diff --git a/.gitignore b/.gitignore index 8e9f9031..b0bf5ae4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ src/build src/dist src/.project src/.pydevproject -src/.settings/ \ No newline at end of file +src/.settings/ +*.dll \ No newline at end of file diff --git a/COPYING b/COPYING index dfa169ea..4fe0f2b0 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ -Copyright (c) 2012-2015 Jonathan Warren -Copyright (c) 2013-2015 The Bitmessage Developers +Copyright (c) 2012-2016 Jonathan Warren +Copyright (c) 2013-2016 The Bitmessage Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSE b/LICENSE index 56ac8e3a..d2afc3c4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2012-2014 Jonathan Warren -Copyright (c) 2013-2014 The Bitmessage Developers +Copyright (c) 2012-2016 Jonathan Warren +Copyright (c) 2013-2016 The Bitmessage Developers 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 diff --git a/Makefile b/Makefile index 3078ee94..fa1c4c91 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ APP=pybitmessage -VERSION=0.4.4 +APPDIR=`basename "\`pwd\`"` +VERSION=0.6.0 RELEASE=1 ARCH_TYPE=`uname -m` PREFIX?=/usr/local @@ -8,7 +9,7 @@ LIBDIR=lib all: debug: source: - tar -cvf ../${APP}_${VERSION}.orig.tar ../${APP}-${VERSION} --exclude-vcs + tar -cvf ../${APP}_${VERSION}.orig.tar ../${APPDIR} --exclude-vcs gzip -f9n ../${APP}_${VERSION}.orig.tar install: mkdir -p ${DESTDIR}/usr @@ -57,5 +58,5 @@ clean: rm -f puppypackage/*.gz puppypackage/*.pet slackpackage/*.txz sourcedeb: - tar -cvf ../${APP}_${VERSION}.orig.tar ../${APP}-${VERSION} --exclude-vcs --exclude 'debian' + tar -cvf ../${APP}_${VERSION}.orig.tar ../${APPDIR} --exclude-vcs --exclude 'debian' gzip -f9n ../${APP}_${VERSION}.orig.tar diff --git a/arch.sh b/arch.sh index 96d2e8d8..5f7982bb 100755 --- a/arch.sh +++ b/arch.sh @@ -2,7 +2,7 @@ APP=pybitmessage PREV_VERSION=0.4.4 -VERSION=0.4.4 +VERSION=0.6.0 RELEASE=1 ARCH_TYPE=any CURRDIR=`pwd` diff --git a/archpackage/PKGBUILD b/archpackage/PKGBUILD index 5c2c78eb..9fd8eadd 100644 --- a/archpackage/PKGBUILD +++ b/archpackage/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Bob Mottram (4096 bits) pkgname=pybitmessage -pkgver=0.4.4 +pkgver=0.6.0 pkgrel=1 pkgdesc="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 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." arch=('any') diff --git a/compiletest.py b/compiletest.py new file mode 100644 index 00000000..91df6c5e --- /dev/null +++ b/compiletest.py @@ -0,0 +1,20 @@ +#!/usr/bin/python2.7 + +import ctypes +import fnmatch +import os +import sys +import traceback + +matches = [] +for root, dirnames, filenames in os.walk('src'): + for filename in fnmatch.filter(filenames, '*.py'): + matches.append(os.path.join(root, filename)) + +for filename in matches: + source = open(filename, 'r').read() + '\n' + try: + compile(source, filename, 'exec') + except Exception as e: + ctypes.windll.user32.MessageBoxA(0, traceback.format_exc(), "Exception in " + filename, 1) + sys.exit(1) \ No newline at end of file diff --git a/debian.sh b/debian.sh index 3a4edbe5..9caed2dc 100755 --- a/debian.sh +++ b/debian.sh @@ -1,11 +1,13 @@ #!/bin/bash APP=pybitmessage -PREV_VERSION=0.4.2 -VERSION=0.4.4 +PREV_VERSION=0.4.4 +VERSION=0.6.0 RELEASE=1 ARCH_TYPE=all DIR=${APP}-${VERSION} +CURDIR=`pwd` +SHORTDIR=`basename ${CURDIR}` if [ $ARCH_TYPE == "x86_64" ]; then ARCH_TYPE="amd64" @@ -30,17 +32,17 @@ make clean make # Change the parent directory name to Debian format -mv ../${APP} ../${DIR} +mv ../${SHORTDIR} ../${DIR} # Create a source archive make sourcedeb # Build the package -dpkg-buildpackage -F +dpkg-buildpackage -F -us -uc # Sign files gpg -ba ../${APP}_${VERSION}-1_${ARCH_TYPE}.deb gpg -ba ../${APP}_${VERSION}.orig.tar.gz # Restore the parent directory name -mv ../${DIR} ../${APP} +mv ../${DIR} ../${SHORTDIR} diff --git a/debian/changelog b/debian/changelog index 415dc400..9fc04ddb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +pybitmessage (0.6.0-1) trusty; urgency=low + + * Bugfixes + * UI improvements + * performance and security improvements + * integration with email gateway (mailchuck.com) + + -- Peter Surda Mon, 2 May 2016 16:25:00 +0200 + pybitmessage (0.4.4-1) utopic; urgency=low * Added ability to limit network transfer rate diff --git a/debian/copyright b/debian/copyright index 55863ba1..b341b873 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,11 +3,11 @@ Upstream-Name: Source: Files: * -Copyright: Copyright 2014 Bob Mottram (4096 bits) +Copyright: Copyright 2016 Bob Mottram (4096 bits) License: MIT Files: debian/* -Copyright: Copyright 2014 Bob Mottram (4096 bits) +Copyright: Copyright 2016 Bob Mottram (4096 bits) License: MIT License: MIT diff --git a/ebuild.sh b/ebuild.sh index 11a6f5be..cd73685b 100755 --- a/ebuild.sh +++ b/ebuild.sh @@ -2,7 +2,7 @@ APP=pybitmessage PREV_VERSION=0.4.4 -VERSION=0.4.4 +VERSION=0.6.0 RELEASE=1 SOURCEDIR=. ARCH_TYPE=`uname -m` diff --git a/ebuildpackage/pybitmessage-0.3.5-1.ebuild b/ebuildpackage/pybitmessage-0.3.5-1.ebuild deleted file mode 100755 index 01eddc4f..00000000 --- a/ebuildpackage/pybitmessage-0.3.5-1.ebuild +++ /dev/null @@ -1,32 +0,0 @@ -# $Header: $ - -EAPI=5 - -inherit git-2 python-r1 - -PYTHON_COMPAT=( python2_7 ) -PYTHON_REQ_USE="sqlite" -REQUIRED_USE="${PYTHON_REQUIRED_USE}" -DESCRIPTION="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 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." -HOMEPAGE="https://github.com/Bitmessage/PyBitmessage" -EGIT_REPO_URI="https://github.com/Bitmessage/PyBitmessage.git" -LICENSE="MIT" -SLOT="0" -KEYWORDS="x86" -DEPEND="dev-libs/popt - ${PYTHON_DEPS}" -RDEPEND="${DEPEND} - dev-libs/openssl - dev-python/PyQt4[]" - -src_configure() { - econf --with-popt -} - -src_compile() { :; } - -src_install() { - emake DESTDIR="${D}" PREFIX="/usr" install - # Install README and (Debian) changelog - dodoc README.md debian/changelog -} diff --git a/osx.sh b/osx.sh index eaa33183..e58a49f4 100755 --- a/osx.sh +++ b/osx.sh @@ -14,6 +14,8 @@ fi echo "Creating OS X packages for Bitmessage." +export PYBITMESSAGEVERSION=$1 + cd src && python2.7 build_osx.py py2app if [[ $? = "0" ]]; then diff --git a/puppy.sh b/puppy.sh index 48832734..a78e021c 100755 --- a/puppy.sh +++ b/puppy.sh @@ -2,7 +2,7 @@ APP=pybitmessage PREV_VERSION=0.4.4 -VERSION=0.4.4 +VERSION=0.6.0 RELEASE=1 BUILDDIR=~/petbuild CURRDIR=`pwd` diff --git a/pyinstaller/bitmessagemain.spec b/pyinstaller/bitmessagemain.spec new file mode 100644 index 00000000..0b41bb00 --- /dev/null +++ b/pyinstaller/bitmessagemain.spec @@ -0,0 +1,58 @@ +srcPath = "C:\\src\\PyBitmessage\\src\\" +qtPath = "C:\\Qt\\4.8.6\\" +openSSLPath = "C:\\OpenSSL-1.0.2e\\" +outPath = "C:\\src\\PyInstaller\\bitmessagemain" + +# -*- mode: python -*- +a = Analysis([srcPath + 'bitmessagemain.py'], + pathex=[outPath], + hiddenimports=[], + hookspath=None, + runtime_hooks=None) + +# fix duplicates +for d in a.datas: + if 'pyconfig' in d[0]: + a.datas.remove(d) + break + +def addTranslations(): + import os + extraDatas = [] + for file in os.listdir(srcPath + 'translations'): + if file[-3:] != ".qm": + continue + extraDatas.append(('translations\\'+file, srcPath + 'translations\\' + file, 'DATA')) + for file in os.listdir(qtPath + 'translations'): + if file[0:3] != "qt_" or file[5:8] != ".qm": + continue + extraDatas.append(('translations\\'+file, qtPath + 'translations\\' + file, 'DATA')) + return extraDatas + +def addUIs(): + import os + extraDatas = [] + for file in os.listdir(srcPath + 'bitmessageqt'): + if file[-3:] != ".ui": + continue + extraDatas.append(('ui\\'+file, srcPath + 'bitmessageqt\\' + file, 'DATA')) + return extraDatas + +# append the translations directory +a.datas += addTranslations() +a.datas += addUIs() + +a.binaries.append(('msvcr120.dll', 'C:\\WINDOWS\\system32\\msvcr120.dll', 'BINARY')) + +pyz = PYZ(a.pure) +exe = EXE(pyz, + a.scripts, + a.binaries, + a.zipfiles, + a.datas, + a.binaries + [('libeay32.dll', openSSLPath + 'libeay32.dll', 'BINARY'), ('bitmsghash\\bitmsghash32.dll', srcPath + 'bitmsghash\\bitmsghash32.dll', 'BINARY'), ('bitmsghash\\bitmsghash.cl', srcPath + 'bitmsghash\\bitmsghash.cl', 'BINARY'), ('sslkeys\\cert.pem', srcPath + 'sslkeys\\cert.pem', 'BINARY'), ('sslkeys\\key.pem', srcPath + 'sslkeys\\key.pem', 'BINARY')], + name='Bitmessage.exe', + debug=False, + strip=None, + upx=False, + console=False, icon= srcPath + 'images\\can-icon.ico') diff --git a/rpmpackage/pybitmessage.spec b/rpmpackage/pybitmessage.spec index 258636f8..1235251a 100644 --- a/rpmpackage/pybitmessage.spec +++ b/rpmpackage/pybitmessage.spec @@ -1,5 +1,5 @@ Name: pybitmessage -Version: 0.4.4 +Version: 0.6.0 Release: 1%{?dist} Summary: Send encrypted messages License: MIT diff --git a/slack.sh b/slack.sh index c19ff954..f7495e46 100755 --- a/slack.sh +++ b/slack.sh @@ -2,7 +2,7 @@ APP=pybitmessage PREV_VERSION=0.4.4 -VERSION=0.4.4 +VERSION=0.6.0 RELEASE=1 ARCH_TYPE=`uname -m` BUILDDIR=~/slackbuild diff --git a/src/addresses.py b/src/addresses.py index f6fbbf73..fa87677a 100644 --- a/src/addresses.py +++ b/src/addresses.py @@ -1,6 +1,7 @@ import hashlib from struct import * from pyelliptic import arithmetic +from binascii import hexlify, unhexlify @@ -10,9 +11,9 @@ def convertIntToString(n): if a[-1:] == 'L': a = a[:-1] if (len(a) % 2) == 0: - return a[2:].decode('hex') + return unhexlify(a[2:]) else: - return ('0'+a[2:]).decode('hex') + return unhexlify('0'+a[2:]) ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" @@ -55,7 +56,7 @@ def decodeBase58(string, alphabet=ALPHABET): def encodeVarint(integer): if integer < 0: - print 'varint cannot be < 0' + logger.error('varint cannot be < 0') raise SystemExit if integer < 253: return pack('>B',integer) @@ -66,7 +67,7 @@ def encodeVarint(integer): if integer >= 4294967296 and integer < 18446744073709551616: return pack('>B',255) + pack('>Q',integer) if integer >= 18446744073709551616: - print 'varint cannot be >= 18446744073709551616' + logger.error('varint cannot be >= 18446744073709551616') raise SystemExit class varintDecodeError(Exception): @@ -142,7 +143,7 @@ def encodeAddress(version,stream,ripe): sha.update(currentHash) checksum = sha.digest()[0:4] - asInt = int(storedBinaryData.encode('hex') + checksum.encode('hex'),16) + asInt = int(hexlify(storedBinaryData) + hexlify(checksum),16) return 'BM-'+ encodeBase58(asInt) def decodeAddress(address): @@ -165,7 +166,7 @@ def decodeAddress(address): #print 'hexdata', hexdata - data = hexdata.decode('hex') + data = unhexlify(hexdata) checksum = data[-4:] sha = hashlib.new('sha512') @@ -185,25 +186,25 @@ def decodeAddress(address): try: addressVersionNumber, bytesUsedByVersionNumber = decodeVarint(data[:9]) except varintDecodeError as e: - print e + logger.error(str(e)) status = 'varintmalformed' return status,0,0,"" #print 'addressVersionNumber', addressVersionNumber #print 'bytesUsedByVersionNumber', bytesUsedByVersionNumber if addressVersionNumber > 4: - print 'cannot decode address version numbers this high' + logger.error('cannot decode address version numbers this high') status = 'versiontoohigh' return status,0,0,"" elif addressVersionNumber == 0: - print 'cannot decode address version numbers of zero.' + logger.error('cannot decode address version numbers of zero.') status = 'versiontoohigh' return status,0,0,"" try: streamNumber, bytesUsedByStreamNumber = decodeVarint(data[bytesUsedByVersionNumber:]) except varintDecodeError as e: - print e + logger.error(str(e)) status = 'varintmalformed' return status,0,0,"" #print streamNumber @@ -268,7 +269,7 @@ if __name__ == "__main__": ripe.update(sha.digest()) addressVersionNumber = 2 streamNumber = 1 - print 'Ripe digest that we will encode in the address:', ripe.digest().encode('hex') + print 'Ripe digest that we will encode in the address:', hexlify(ripe.digest()) returnedAddress = encodeAddress(addressVersionNumber,streamNumber,ripe.digest()) print 'Encoded address:', returnedAddress status,addressVersionNumber,streamNumber,data = decodeAddress(returnedAddress) @@ -277,5 +278,5 @@ if __name__ == "__main__": print 'addressVersionNumber', addressVersionNumber print 'streamNumber', streamNumber print 'length of data(the ripe hash):', len(data) - print 'ripe data:', data.encode('hex') + print 'ripe data:', hexlify(data) diff --git a/src/api.py b/src/api.py index f142953b..a05b1301 100644 --- a/src/api.py +++ b/src/api.py @@ -1,5 +1,5 @@ -# Copyright (c) 2012-2014 Jonathan Warren -# Copyright (c) 2012-2014 The Bitmessage developers +# Copyright (c) 2012-2016 Jonathan Warren +# Copyright (c) 2012-2016 The Bitmessage developers comment= """ This is not what you run to run the Bitmessage API. Instead, enable the API @@ -12,8 +12,9 @@ if __name__ == "__main__": import sys sys.exit(0) -from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler +from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer import json +from binascii import hexlify import shared import time @@ -26,7 +27,7 @@ from pyelliptic.openssl import OpenSSL from struct import pack # Classes -from helper_sql import sqlQuery,sqlExecute,SqlBulkExecute +from helper_sql import sqlQuery,sqlExecute,SqlBulkExecute,sqlStoredProcedure from debug import logger # Helper Functions @@ -43,6 +44,13 @@ class APIError(Exception): def __str__(self): return "API Error %04i: %s" % (self.error_number, self.error_message) + +class StoppableXMLRPCServer(SimpleXMLRPCServer): + def serve_forever(self): + while shared.shutdown == 0: + self.handle_request() + + # This is one of several classes that constitute the API # This class was written by Vaibhav Bhatia. Modified by Jonathan Warren (Atheros). # http://code.activestate.com/recipes/501148-xmlrpc-serverclient-which-does-cookie-handling-and/ @@ -174,7 +182,14 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): return data def HandleListAddressBookEntries(self, params): - queryreturn = sqlQuery('''SELECT label, address from addressbook''') + if len(params) == 1: + label, = params + label = self._decode(label, "base64") + queryreturn = sqlQuery('''SELECT label, address from addressbook WHERE label = ?''', label) + elif len(params) > 1: + raise APIError(0, "Too many paremeters, max 1") + else: + queryreturn = sqlQuery('''SELECT label, address from addressbook''') data = '{"addresses":[' for row in queryreturn: label, address = row @@ -197,8 +212,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): raise APIError(16, 'You already have this address in your address book.') sqlExecute("INSERT INTO addressbook VALUES(?,?)", label, address) - shared.UISignalQueue.put(('rerenderInboxFromLabels','')) - shared.UISignalQueue.put(('rerenderSentToLabels','')) + shared.UISignalQueue.put(('rerenderMessagelistFromLabels','')) + shared.UISignalQueue.put(('rerenderMessagelistToLabels','')) shared.UISignalQueue.put(('rerenderAddressBook','')) return "Added address %s to address book" % address @@ -209,8 +224,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): address = addBMIfNotPresent(address) self._verifyAddress(address) sqlExecute('DELETE FROM addressbook WHERE address=?', address) - shared.UISignalQueue.put(('rerenderInboxFromLabels','')) - shared.UISignalQueue.put(('rerenderSentToLabels','')) + shared.UISignalQueue.put(('rerenderMessagelistFromLabels','')) + shared.UISignalQueue.put(('rerenderMessagelistToLabels','')) shared.UISignalQueue.put(('rerenderAddressBook','')) return "Deleted address book entry for %s if it existed" % address @@ -448,8 +463,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): shared.config.remove_section(address) with open(shared.appdata + 'keys.dat', 'wb') as configfile: shared.config.write(configfile) - shared.UISignalQueue.put(('rerenderInboxFromLabels','')) - shared.UISignalQueue.put(('rerenderSentToLabels','')) + shared.UISignalQueue.put(('rerenderMessagelistFromLabels','')) + shared.UISignalQueue.put(('rerenderMessagelistToLabels','')) shared.reloadMyAddressHashes() return 'success' @@ -463,7 +478,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): message = shared.fixPotentiallyInvalidUTF8Data(message) if len(data) > 25: data += ',' - data += json.dumps({'msgid': msgid.encode('hex'), 'toAddress': toAddress, 'fromAddress': fromAddress, 'subject': subject.encode( + data += json.dumps({'msgid': hexlify(msgid), 'toAddress': toAddress, 'fromAddress': fromAddress, 'subject': subject.encode( 'base64'), 'message': message.encode('base64'), 'encodingType': encodingtype, 'receivedTime': received, 'read': read}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -476,7 +491,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): msgid = row[0] if len(data) > 25: data += ',' - data += json.dumps({'msgid': msgid.encode('hex')}, indent=4, separators=(',', ': ')) + data += json.dumps({'msgid': hexlify(msgid)}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -501,7 +516,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): msgid, toAddress, fromAddress, subject, received, message, encodingtype, read = row subject = shared.fixPotentiallyInvalidUTF8Data(subject) message = shared.fixPotentiallyInvalidUTF8Data(message) - data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'receivedTime':received, 'read': read}, indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':hexlify(msgid), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'receivedTime':received, 'read': read}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -514,7 +529,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): message = shared.fixPotentiallyInvalidUTF8Data(message) if len(data) > 25: data += ',' - data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':hexlify(msgid), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':hexlify(ackdata)}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -525,7 +540,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): msgid = row[0] if len(data) > 25: data += ',' - data += json.dumps({'msgid':msgid.encode('hex')}, indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':hexlify(msgid)}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -541,7 +556,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): message = shared.fixPotentiallyInvalidUTF8Data(message) if len(data) > 25: data += ',' - data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'receivedTime':received}, indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':hexlify(msgid), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'receivedTime':received}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -555,7 +570,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row subject = shared.fixPotentiallyInvalidUTF8Data(subject) message = shared.fixPotentiallyInvalidUTF8Data(message) - data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':hexlify(msgid), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':hexlify(ackdata)}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -572,7 +587,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): message = shared.fixPotentiallyInvalidUTF8Data(message) if len(data) > 25: data += ',' - data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':hexlify(msgid), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':hexlify(ackdata)}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -587,7 +602,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row subject = shared.fixPotentiallyInvalidUTF8Data(subject) message = shared.fixPotentiallyInvalidUTF8Data(message) - data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':hexlify(msgid), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':hexlify(ackdata)}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -680,7 +695,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): shared.workerQueue.put(('sendmessage', toAddress)) - return ackdata.encode('hex') + return hexlify(ackdata) def HandleSendBroadcast(self, params): if len(params) == 0: @@ -737,7 +752,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): toAddress, toLabel, fromAddress, subject, message, ackdata))) shared.workerQueue.put(('sendbroadcast', '')) - return ackdata.encode('hex') + return hexlify(ackdata) def HandleGetStatus(self, params): if len(params) != 1: @@ -779,7 +794,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): raise APIError(16, 'You are already subscribed to that address.') sqlExecute('''INSERT INTO subscriptions VALUES (?,?,?)''',label, address, True) shared.reloadBroadcastSendersForWhichImWatching() - shared.UISignalQueue.put(('rerenderInboxFromLabels', '')) + shared.UISignalQueue.put(('rerenderMessagelistFromLabels', '')) shared.UISignalQueue.put(('rerenderSubscriptions', '')) return 'Added subscription.' @@ -790,7 +805,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): address = addBMIfNotPresent(address) sqlExecute('''DELETE FROM subscriptions WHERE address=?''', address) shared.reloadBroadcastSendersForWhichImWatching() - shared.UISignalQueue.put(('rerenderInboxFromLabels', '')) + shared.UISignalQueue.put(('rerenderMessagelistFromLabels', '')) shared.UISignalQueue.put(('rerenderSubscriptions', '')) return 'Deleted subscription if it existed.' @@ -836,9 +851,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): TTL = 2.5 * 24 * 60 * 60 shared.inventory[inventoryHash] = ( objectType, toStreamNumber, encryptedPayload, int(time.time()) + TTL,'') - shared.inventorySets[toStreamNumber].add(inventoryHash) with shared.printLock: - print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', inventoryHash.encode('hex') + print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', hexlify(inventoryHash) shared.broadcastToSendDataQueues(( toStreamNumber, 'advertiseobject', inventoryHash)) @@ -884,9 +898,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): TTL = 28 * 24 * 60 * 60 shared.inventory[inventoryHash] = ( objectType, pubkeyStreamNumber, payload, int(time.time()) + TTL,'') - shared.inventorySets[pubkeyStreamNumber].add(inventoryHash) with shared.printLock: - print 'broadcasting inv within API command disseminatePubkey with hash:', inventoryHash.encode('hex') + print 'broadcasting inv within API command disseminatePubkey with hash:', hexlify(inventoryHash) shared.broadcastToSendDataQueues(( streamNumber, 'advertiseobject', inventoryHash)) @@ -921,7 +934,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): payload, = row if len(data) > 25: data += ',' - data += json.dumps({'data':payload.encode('hex')}, indent=4, separators=(',', ': ')) + data += json.dumps({'data':hexlify(payload)}, indent=4, separators=(',', ': ')) data += ']}' return data @@ -956,6 +969,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): message, = params shared.UISignalQueue.put(('updateStatusBar', message)) + def HandleDeleteAndVacuum(self, params): + sqlStoredProcedure('deleteandvacuume') + return 'done' handlers = {} handlers['helloWorld'] = HandleHelloWorld @@ -1006,6 +1022,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): handlers['getMessageDataByDestinationTag'] = HandleGetMessageDataByDestinationHash handlers['clientStatus'] = HandleClientStatus handlers['decodeAddress'] = HandleDecodeAddress + handlers['deleteAndVacuum'] = HandleDeleteAndVacuum def _handle_request(self, method, params): if (self.handlers.has_key(method)): diff --git a/src/bitmessagecli.py b/src/bitmessagecli.py new file mode 100644 index 00000000..87d71f05 --- /dev/null +++ b/src/bitmessagecli.py @@ -0,0 +1,1778 @@ +#!/usr/bin/env python2.7.x +# Created by Adam Melton (.dok) referenceing https://bitmessage.org/wiki/API_Reference for API documentation +# Distributed under the MIT/X11 software license. See http://www.opensource.org/licenses/mit-license.php. + +# This is an example of a daemon client for PyBitmessage 0.4.2, by .dok (Version 0.3.0) + + +import ConfigParser +import xmlrpclib +import datetime +import hashlib +import getopt +import imghdr +import ntpath +import json +import time +import sys +import os + +api = '' +keysName = 'keys.dat' +keysPath = 'keys.dat' +usrPrompt = 0 #0 = First Start, 1 = prompt, 2 = no prompt if the program is starting up +knownAddresses = dict() + +def userInput(message): #Checks input for exit or quit. Also formats for input, etc + global usrPrompt + print '\n' + message + uInput = raw_input('> ') + + if (uInput.lower() == 'exit'): #Returns the user to the main menu + usrPrompt = 1 + main() + + elif (uInput.lower() == 'quit'): #Quits the program + print '\n Bye\n' + sys.exit() + os.exit() + else: + return uInput + +def restartBmNotify(): #Prompts the user to restart Bitmessage. + print '\n *******************************************************************' + print ' WARNING: If Bitmessage is running locally, you must restart it now.' + print ' *******************************************************************\n' + +def safeConfigGetBoolean(section,field): + global keysPath + config = ConfigParser.SafeConfigParser() + config.read(keysPath) + + try: + return config.getboolean(section,field) + except: + return False + +#Begin keys.dat interactions +def lookupAppdataFolder(): #gets the appropriate folders for the .dat files depending on the OS. Taken from bitmessagemain.py + APPNAME = "PyBitmessage" + from os import path, environ + if sys.platform == 'darwin': + if "HOME" in environ: + dataFolder = path.join(os.environ["HOME"], "Library/Application support/", APPNAME) + '/' + else: + print ' Could not find home folder, please report this message and your OS X version to the Daemon Github.' + os.exit() + + elif 'win32' in sys.platform or 'win64' in sys.platform: + dataFolder = path.join(environ['APPDATA'], APPNAME) + '\\' + else: + dataFolder = path.expanduser(path.join("~", ".config/" + APPNAME + "/")) + return dataFolder + +def configInit(): + global keysName + config = ConfigParser.SafeConfigParser() + + config.add_section('bitmessagesettings') + config.set('bitmessagesettings', 'port', '8444') #Sets the bitmessage port to stop the warning about the api not properly being setup. This is in the event that the keys.dat is in a different directory or is created locally to connect to a machine remotely. + config.set('bitmessagesettings','apienabled','true') #Sets apienabled to true in keys.dat + + with open(keysName, 'wb') as configfile: + config.write(configfile) + + print '\n ' + str(keysName) + ' Initalized in the same directory as daemon.py' + print ' You will now need to configure the ' + str(keysName) + ' file.\n' + +def apiInit(apiEnabled): + global keysPath + global usrPrompt + config = ConfigParser.SafeConfigParser() + config.read(keysPath) + + + + if (apiEnabled == False): #API information there but the api is disabled. + uInput = userInput("The API is not enabled. Would you like to do that now, (Y)es or (N)o?").lower() + + if uInput == "y": # + config.set('bitmessagesettings','apienabled','true') #Sets apienabled to true in keys.dat + with open(keysPath, 'wb') as configfile: + config.write(configfile) + + print 'Done' + restartBmNotify() + return True + + elif uInput == "n": + print ' \n************************************************************' + print ' Daemon will not work when the API is disabled. ' + print ' Please refer to the Bitmessage Wiki on how to setup the API.' + print ' ************************************************************\n' + usrPrompt = 1 + main() + + else: + print '\n Invalid Entry\n' + usrPrompt = 1 + main() + elif (apiEnabled == True): #API correctly setup + #Everything is as it should be + return True + + else: #API information was not present. + print '\n ' + str(keysPath) + ' not properly configured!\n' + uInput = userInput("Would you like to do this now, (Y)es or (N)o?").lower() + + if uInput == "y": #User said yes, initalize the api by writing these values to the keys.dat file + print ' ' + + apiUsr = userInput("API Username") + apiPwd = userInput("API Password") + apiInterface = userInput("API Interface. (127.0.0.1)") + apiPort = userInput("API Port") + apiEnabled = userInput("API Enabled? (True) or (False)").lower() + daemon = userInput("Daemon mode Enabled? (True) or (False)").lower() + + if (daemon != 'true' and daemon != 'false'): + print '\n Invalid Entry for Daemon.\n' + uInput = 1 + main() + + print ' -----------------------------------\n' + + config.set('bitmessagesettings', 'port', '8444') #sets the bitmessage port to stop the warning about the api not properly being setup. This is in the event that the keys.dat is in a different directory or is created locally to connect to a machine remotely. + config.set('bitmessagesettings','apienabled','true') + config.set('bitmessagesettings', 'apiport', apiPort) + config.set('bitmessagesettings', 'apiinterface', '127.0.0.1') + config.set('bitmessagesettings', 'apiusername', apiUsr) + config.set('bitmessagesettings', 'apipassword', apiPwd) + config.set('bitmessagesettings', 'daemon', daemon) + with open(keysPath, 'wb') as configfile: + config.write(configfile) + + print '\n Finished configuring the keys.dat file with API information.\n' + restartBmNotify() + return True + + elif uInput == "n": + print '\n ***********************************************************' + print ' Please refer to the Bitmessage Wiki on how to setup the API.' + print ' ***********************************************************\n' + usrPrompt = 1 + main() + else: + print ' \nInvalid entry\n' + usrPrompt = 1 + main() + + +def apiData(): + global keysName + global keysPath + global usrPrompt + + config = ConfigParser.SafeConfigParser() + config.read(keysPath) #First try to load the config file (the keys.dat file) from the program directory + + try: + config.get('bitmessagesettings','port') + appDataFolder = '' + except: + #Could not load the keys.dat file in the program directory. Perhaps it is in the appdata directory. + appDataFolder = lookupAppdataFolder() + keysPath = appDataFolder + keysPath + config = ConfigParser.SafeConfigParser() + config.read(keysPath) + + try: + config.get('bitmessagesettings','port') + except: + #keys.dat was not there either, something is wrong. + print '\n ******************************************************************' + print ' There was a problem trying to access the Bitmessage keys.dat file' + print ' or keys.dat is not set up correctly' + print ' Make sure that daemon is in the same directory as Bitmessage. ' + print ' ******************************************************************\n' + + uInput = userInput("Would you like to create a keys.dat in the local directory, (Y)es or (N)o?").lower() + + if (uInput == "y" or uInput == "yes"): + configInit() + keysPath = keysName + usrPrompt = 0 + main() + elif (uInput == "n" or uInput == "no"): + print '\n Trying Again.\n' + usrPrompt = 0 + main() + else: + print '\n Invalid Input.\n' + + usrPrompt = 1 + main() + + try: #checks to make sure that everyting is configured correctly. Excluding apiEnabled, it is checked after + config.get('bitmessagesettings', 'apiport') + config.get('bitmessagesettings', 'apiinterface') + config.get('bitmessagesettings', 'apiusername') + config.get('bitmessagesettings', 'apipassword') + except: + apiInit("") #Initalize the keys.dat file with API information + + #keys.dat file was found or appropriately configured, allow information retrieval + apiEnabled = apiInit(safeConfigGetBoolean('bitmessagesettings','apienabled')) #if false it will prompt the user, if true it will return true + + config.read(keysPath)#read again since changes have been made + apiPort = int(config.get('bitmessagesettings', 'apiport')) + apiInterface = config.get('bitmessagesettings', 'apiinterface') + apiUsername = config.get('bitmessagesettings', 'apiusername') + apiPassword = config.get('bitmessagesettings', 'apipassword') + + print '\n API data successfully imported.\n' + + return "http://" + apiUsername + ":" + apiPassword + "@" + apiInterface+ ":" + str(apiPort) + "/" #Build the api credentials + +#End keys.dat interactions + + +def apiTest(): #Tests the API connection to bitmessage. Returns true if it is connected. + + try: + result = api.add(2,3) + except: + return False + + if (result == 5): + return True + else: + return False + +def bmSettings(): #Allows the viewing and modification of keys.dat settings. + global keysPath + global usrPrompt + config = ConfigParser.SafeConfigParser() + keysPath = 'keys.dat' + + config.read(keysPath)#Read the keys.dat + try: + port = config.get('bitmessagesettings', 'port') + except: + print '\n File not found.\n' + usrPrompt = 0 + main() + + startonlogon = safeConfigGetBoolean('bitmessagesettings', 'startonlogon') + minimizetotray = safeConfigGetBoolean('bitmessagesettings', 'minimizetotray') + showtraynotifications = safeConfigGetBoolean('bitmessagesettings', 'showtraynotifications') + startintray = safeConfigGetBoolean('bitmessagesettings', 'startintray') + defaultnoncetrialsperbyte = config.get('bitmessagesettings', 'defaultnoncetrialsperbyte') + defaultpayloadlengthextrabytes = config.get('bitmessagesettings', 'defaultpayloadlengthextrabytes') + daemon = safeConfigGetBoolean('bitmessagesettings', 'daemon') + + socksproxytype = config.get('bitmessagesettings', 'socksproxytype') + sockshostname = config.get('bitmessagesettings', 'sockshostname') + socksport = config.get('bitmessagesettings', 'socksport') + socksauthentication = safeConfigGetBoolean('bitmessagesettings', 'socksauthentication') + socksusername = config.get('bitmessagesettings', 'socksusername') + sockspassword = config.get('bitmessagesettings', 'sockspassword') + + + print '\n -----------------------------------' + print ' | Current Bitmessage Settings |' + print ' -----------------------------------' + print ' port = ' + port + print ' startonlogon = ' + str(startonlogon) + print ' minimizetotray = ' + str(minimizetotray) + print ' showtraynotifications = ' + str(showtraynotifications) + print ' startintray = ' + str(startintray) + print ' defaultnoncetrialsperbyte = ' + defaultnoncetrialsperbyte + print ' defaultpayloadlengthextrabytes = ' + defaultpayloadlengthextrabytes + print ' daemon = ' + str(daemon) + print '\n ------------------------------------' + print ' | Current Connection Settings |' + print ' -----------------------------------' + print ' socksproxytype = ' + socksproxytype + print ' sockshostname = ' + sockshostname + print ' socksport = ' + socksport + print ' socksauthentication = ' + str(socksauthentication) + print ' socksusername = ' + socksusername + print ' sockspassword = ' + sockspassword + print ' ' + + uInput = userInput("Would you like to modify any of these settings, (Y)es or (N)o?").lower() + + if uInput == "y": + while True: #loops if they mistype the setting name, they can exit the loop with 'exit' + invalidInput = False + uInput = userInput("What setting would you like to modify?").lower() + print ' ' + + if uInput == "port": + print ' Current port number: ' + port + uInput = userInput("Enter the new port number.") + config.set('bitmessagesettings', 'port', str(uInput)) + elif uInput == "startonlogon": + print ' Current status: ' + str(startonlogon) + uInput = userInput("Enter the new status.") + config.set('bitmessagesettings', 'startonlogon', str(uInput)) + elif uInput == "minimizetotray": + print ' Current status: ' + str(minimizetotray) + uInput = userInput("Enter the new status.") + config.set('bitmessagesettings', 'minimizetotray', str(uInput)) + elif uInput == "showtraynotifications": + print ' Current status: ' + str(showtraynotifications) + uInput = userInput("Enter the new status.") + config.set('bitmessagesettings', 'showtraynotifications', str(uInput)) + elif uInput == "startintray": + print ' Current status: ' + str(startintray) + uInput = userInput("Enter the new status.") + config.set('bitmessagesettings', 'startintray', str(uInput)) + elif uInput == "defaultnoncetrialsperbyte": + print ' Current default nonce trials per byte: ' + defaultnoncetrialsperbyte + uInput = userInput("Enter the new defaultnoncetrialsperbyte.") + config.set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(uInput)) + elif uInput == "defaultpayloadlengthextrabytes": + print ' Current default payload length extra bytes: ' + defaultpayloadlengthextrabytes + uInput = userInput("Enter the new defaultpayloadlengthextrabytes.") + config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(uInput)) + elif uInput == "daemon": + print ' Current status: ' + str(daemon) + uInput = userInput("Enter the new status.").lower() + config.set('bitmessagesettings', 'daemon', str(uInput)) + elif uInput == "socksproxytype": + print ' Current socks proxy type: ' + socksproxytype + print "Possibilities: 'none', 'SOCKS4a', 'SOCKS5'." + uInput = userInput("Enter the new socksproxytype.") + config.set('bitmessagesettings', 'socksproxytype', str(uInput)) + elif uInput == "sockshostname": + print ' Current socks host name: ' + sockshostname + uInput = userInput("Enter the new sockshostname.") + config.set('bitmessagesettings', 'sockshostname', str(uInput)) + elif uInput == "socksport": + print ' Current socks port number: ' + socksport + uInput = userInput("Enter the new socksport.") + config.set('bitmessagesettings', 'socksport', str(uInput)) + elif uInput == "socksauthentication": + print ' Current status: ' + str(socksauthentication) + uInput = userInput("Enter the new status.") + config.set('bitmessagesettings', 'socksauthentication', str(uInput)) + elif uInput == "socksusername": + print ' Current socks username: ' + socksusername + uInput = userInput("Enter the new socksusername.") + config.set('bitmessagesettings', 'socksusername', str(uInput)) + elif uInput == "sockspassword": + print ' Current socks password: ' + sockspassword + uInput = userInput("Enter the new password.") + config.set('bitmessagesettings', 'sockspassword', str(uInput)) + else: + print "\n Invalid input. Please try again.\n" + invalidInput = True + + if invalidInput != True: #don't prompt if they made a mistake. + uInput = userInput("Would you like to change another setting, (Y)es or (N)o?").lower() + + if uInput != "y": + print '\n Changes Made.\n' + with open(keysPath, 'wb') as configfile: + config.write(configfile) + restartBmNotify() + break + + + elif uInput == "n": + usrPrompt = 1 + main() + else: + print "Invalid input." + usrPrompt = 1 + main() + +def validAddress(address): + address_information = api.decodeAddress(address) + address_information = eval(address_information) + + if 'success' in str(address_information.get('status')).lower(): + return True + else: + return False + +def getAddress(passphrase,vNumber,sNumber): + passphrase = passphrase.encode('base64')#passphrase must be encoded + + return api.getDeterministicAddress(passphrase,vNumber,sNumber) + +def subscribe(): + global usrPrompt + + while True: + address = userInput("What address would you like to subscribe to?") + + if (address == "c"): + usrPrompt = 1 + print ' ' + main() + elif (validAddress(address)== False): + print '\n Invalid. "c" to cancel. Please try again.\n' + else: + break + + label = userInput("Enter a label for this address.") + label = label.encode('base64') + + api.addSubscription(address,label) + print ('\n You are now subscribed to: ' + address + '\n') + +def unsubscribe(): + global usrPrompt + + while True: + address = userInput("What address would you like to unsubscribe from?") + + if (address == "c"): + usrPrompt = 1 + print ' ' + main() + elif (validAddress(address)== False): + print '\n Invalid. "c" to cancel. Please try again.\n' + else: + break + + + uInput = userInput("Are you sure, (Y)es or (N)o?").lower() + + api.deleteSubscription(address) + print ('\n You are now unsubscribed from: ' + address + '\n') + +def listSubscriptions(): + global usrPrompt + #jsonAddresses = json.loads(api.listSubscriptions()) + #numAddresses = len(jsonAddresses['addresses']) #Number of addresses + print '\nLabel, Address, Enabled\n' + try: + print api.listSubscriptions() + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + '''for addNum in range (0, numAddresses): #processes all of the addresses and lists them out + label = jsonAddresses['addresses'][addNum]['label'] + address = jsonAddresses['addresses'][addNum]['address'] + enabled = jsonAddresses['addresses'][addNum]['enabled'] + + print label, address, enabled + ''' + print ' ' + +def createChan(): + global usrPrompt + password = userInput("Enter channel name") + password = password.encode('base64') + try: + print api.createChan(password) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + +def joinChan(): + global usrPrompt + while True: + address = userInput("Enter channel address") + + if (address == "c"): + usrPrompt = 1 + print ' ' + main() + elif (validAddress(address)== False): + print '\n Invalid. "c" to cancel. Please try again.\n' + else: + break + + password = userInput("Enter channel name") + password = password.encode('base64') + try: + print api.joinChan(password,address) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def leaveChan(): + global usrPrompt + while True: + address = userInput("Enter channel address") + + if (address == "c"): + usrPrompt = 1 + print ' ' + main() + elif (validAddress(address)== False): + print '\n Invalid. "c" to cancel. Please try again.\n' + else: + break + + try: + print api.leaveChan(address) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + +def listAdd(): #Lists all of the addresses and their info + global usrPrompt + try: + jsonAddresses = json.loads(api.listAddresses()) + numAddresses = len(jsonAddresses['addresses']) #Number of addresses + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + #print '\nAddress Number,Label,Address,Stream,Enabled\n' + print '\n --------------------------------------------------------------------------' + print ' | # | Label | Address |S#|Enabled|' + print ' |---|-------------------|-------------------------------------|--|-------|' + for addNum in range (0, numAddresses): #processes all of the addresses and lists them out + label = str(jsonAddresses['addresses'][addNum]['label']) + address = str(jsonAddresses['addresses'][addNum]['address']) + stream = str(jsonAddresses['addresses'][addNum]['stream']) + enabled = str(jsonAddresses['addresses'][addNum]['enabled']) + + if (len(label) > 19): + label = label[:16] + '...' + + print ' |' + str(addNum).ljust(3) + '|' + label.ljust(19) + '|' + address.ljust(37) + '|' + stream.ljust(1), '|' + enabled.ljust(7) + '|' + + print ' --------------------------------------------------------------------------\n' + +def genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe): #Generate address + global usrPrompt + if deterministic == False: #Generates a new address with the user defined label. non-deterministic + addressLabel = lbl.encode('base64') + try: + generatedAddress = api.createRandomAddress(addressLabel) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + return generatedAddress + + elif deterministic == True: #Generates a new deterministic address with the user inputs. + passphrase = passphrase.encode('base64') + try: + generatedAddress = api.createDeterministicAddresses(passphrase, numOfAdd, addVNum, streamNum, ripe) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + return generatedAddress + else: + return 'Entry Error' + +def delMilAddr(): #Generate address + global usrPrompt + try: + response = api.listAddresses2() + # if api is too old just return then fail + if "API Error 0020" in response: return + addresses = json.loads(response) + for entry in addresses['addresses']: + if entry['label'].decode('base64')[:6] == "random": + api.deleteAddress(entry['address']) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def genMilAddr(): #Generate address + global usrPrompt + maxn = 0 + try: + response = api.listAddresses2() + if "API Error 0020" in response: return + addresses = json.loads(response) + for entry in addresses['addresses']: + if entry['label'].decode('base64')[:6] == "random": + newn = int(entry['label'].decode('base64')[6:]) + if maxn < newn: + maxn = newn + except: + print "\n Some error\n" + print "\n Starting at " + str(maxn) + "\n" + for i in range(maxn, 10000): + lbl = "random" + str(i) + addressLabel = lbl.encode('base64') + try: + generatedAddress = api.createRandomAddress(addressLabel) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def saveFile(fileName, fileData): #Allows attachments and messages/broadcats to be saved + + #This section finds all invalid characters and replaces them with ~ + fileName = fileName.replace(" ", "") + fileName = fileName.replace("/", "~") + #fileName = fileName.replace("\\", "~") How do I get this to work...? + fileName = fileName.replace(":", "~") + fileName = fileName.replace("*", "~") + fileName = fileName.replace("?", "~") + fileName = fileName.replace('"', "~") + fileName = fileName.replace("<", "~") + fileName = fileName.replace(">", "~") + fileName = fileName.replace("|", "~") + + directory = 'attachments' + + if not os.path.exists(directory): + os.makedirs(directory) + + filePath = directory +'/'+ fileName + + '''try: #Checks if file already exists + with open(filePath): + print 'File Already Exists' + return + except IOError: pass''' + + + f = open(filePath, 'wb+') #Begin saving to file + f.write(fileData.decode("base64")) + f.close + + print '\n Successfully saved '+ filePath + '\n' + +def attachment(): #Allows users to attach a file to their message or broadcast + theAttachmentS = '' + + while True: + + isImage = False + theAttachment = '' + + while True:#loops until valid path is entered + filePath = userInput('\nPlease enter the path to the attachment or just the attachment name if in this folder.') + + try: + with open(filePath): break + except IOError: + print '\n %s was not found on your filesystem or can not be opened.\n' % filePath + pass + + #print filesize, and encoding estimate with confirmation if file is over X size (1mb?) + invSize = os.path.getsize(filePath) + invSize = (invSize / 1024) #Converts to kilobytes + round(invSize,2) #Rounds to two decimal places + + if (invSize > 500.0):#If over 500KB + print '\n WARNING:The file that you are trying to attach is ', invSize, 'KB and will take considerable time to send.\n' + uInput = userInput('Are you sure you still want to attach it, (Y)es or (N)o?').lower() + + if uInput != "y": + print '\n Attachment discarded.\n' + return '' + elif (invSize > 184320.0): #If larger than 180MB, discard. + print '\n Attachment too big, maximum allowed size:180MB\n' + main() + + pathLen = len(str(ntpath.basename(filePath))) #Gets the length of the filepath excluding the filename + fileName = filePath[(len(str(filePath)) - pathLen):] #reads the filename + + filetype = imghdr.what(filePath) #Tests if it is an image file + if filetype is not None: + print '\n ---------------------------------------------------' + print ' Attachment detected as an Image.' + print ' tags will automatically be included,' + print ' allowing the recipient to view the image' + print ' using the "View HTML code..." option in Bitmessage.' + print ' ---------------------------------------------------\n' + isImage = True + time.sleep(2) + + print '\n Encoding Attachment, Please Wait ...\n' #Alert the user that the encoding process may take some time. + + with open(filePath, 'rb') as f: #Begin the actual encoding + data = f.read(188743680) #Reads files up to 180MB, the maximum size for Bitmessage. + data = data.encode("base64") + + if (isImage == True): #If it is an image, include image tags in the message + theAttachment = """ + + + +Filename:%s +Filesize:%sKB +Encoding:base64 + +
+
+ %s +
+
""" % (fileName,invSize,fileName,filetype,data) + else: #Else it is not an image so do not include the embedded image code. + theAttachment = """ + + + +Filename:%s +Filesize:%sKB +Encoding:base64 + +""" % (fileName,invSize,fileName,fileName,data) + + uInput = userInput('Would you like to add another attachment, (Y)es or (N)o?').lower() + + if (uInput == 'y' or uInput == 'yes'):#Allows multiple attachments to be added to one message + theAttachmentS = str(theAttachmentS) + str(theAttachment)+ '\n\n' + elif (uInput == 'n' or uInput == 'no'): + break + + theAttachmentS = theAttachmentS + theAttachment + return theAttachmentS + +def sendMsg(toAddress, fromAddress, subject, message): #With no arguments sent, sendMsg fills in the blanks. subject and message must be encoded before they are passed. + global usrPrompt + if (validAddress(toAddress)== False): + while True: + toAddress = userInput("What is the To Address?") + + if (toAddress == "c"): + usrPrompt = 1 + print ' ' + main() + elif (validAddress(toAddress)== False): + print '\n Invalid Address. "c" to cancel. Please try again.\n' + else: + break + + + if (validAddress(fromAddress)== False): + try: + jsonAddresses = json.loads(api.listAddresses()) + numAddresses = len(jsonAddresses['addresses']) #Number of addresses + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + if (numAddresses > 1): #Ask what address to send from if multiple addresses + found = False + while True: + print ' ' + fromAddress = userInput("Enter an Address or Address Label to send from.") + + if fromAddress == "exit": + usrPrompt = 1 + main() + + for addNum in range (0, numAddresses): #processes all of the addresses + label = jsonAddresses['addresses'][addNum]['label'] + address = jsonAddresses['addresses'][addNum]['address'] + #stream = jsonAddresses['addresses'][addNum]['stream'] + #enabled = jsonAddresses['addresses'][addNum]['enabled'] + if (fromAddress == label): #address entered was a label and is found + fromAddress = address + found = True + break + + if (found == False): + if(validAddress(fromAddress)== False): + print '\n Invalid Address. Please try again.\n' + + else: + for addNum in range (0, numAddresses): #processes all of the addresses + #label = jsonAddresses['addresses'][addNum]['label'] + address = jsonAddresses['addresses'][addNum]['address'] + #stream = jsonAddresses['addresses'][addNum]['stream'] + #enabled = jsonAddresses['addresses'][addNum]['enabled'] + if (fromAddress == address): #address entered was a found in our addressbook. + found = True + break + + if (found == False): + print '\n The address entered is not one of yours. Please try again.\n' + + if (found == True): + break #Address was found + + else: #Only one address in address book + print '\n Using the only address in the addressbook to send from.\n' + fromAddress = jsonAddresses['addresses'][0]['address'] + + if (subject == ''): + subject = userInput("Enter your Subject.") + subject = subject.encode('base64') + if (message == ''): + message = userInput("Enter your Message.") + + uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower() + if uInput == "y": + message = message + '\n\n' + attachment() + + message = message.encode('base64') + + try: + ackData = api.sendMessage(toAddress, fromAddress, subject, message) + print '\n Message Status:', api.getStatus(ackData), '\n' + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + +def sendBrd(fromAddress, subject, message): #sends a broadcast + global usrPrompt + if (fromAddress == ''): + + try: + jsonAddresses = json.loads(api.listAddresses()) + numAddresses = len(jsonAddresses['addresses']) #Number of addresses + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + if (numAddresses > 1): #Ask what address to send from if multiple addresses + found = False + while True: + fromAddress = userInput("\nEnter an Address or Address Label to send from.") + + if fromAddress == "exit": + usrPrompt = 1 + main() + + for addNum in range (0, numAddresses): #processes all of the addresses + label = jsonAddresses['addresses'][addNum]['label'] + address = jsonAddresses['addresses'][addNum]['address'] + #stream = jsonAddresses['addresses'][addNum]['stream'] + #enabled = jsonAddresses['addresses'][addNum]['enabled'] + if (fromAddress == label): #address entered was a label and is found + fromAddress = address + found = True + break + + if (found == False): + if(validAddress(fromAddress)== False): + print '\n Invalid Address. Please try again.\n' + + else: + for addNum in range (0, numAddresses): #processes all of the addresses + #label = jsonAddresses['addresses'][addNum]['label'] + address = jsonAddresses['addresses'][addNum]['address'] + #stream = jsonAddresses['addresses'][addNum]['stream'] + #enabled = jsonAddresses['addresses'][addNum]['enabled'] + if (fromAddress == address): #address entered was a found in our addressbook. + found = True + break + + if (found == False): + print '\n The address entered is not one of yours. Please try again.\n' + + if (found == True): + break #Address was found + + else: #Only one address in address book + print '\n Using the only address in the addressbook to send from.\n' + fromAddress = jsonAddresses['addresses'][0]['address'] + + if (subject == ''): + subject = userInput("Enter your Subject.") + subject = subject.encode('base64') + if (message == ''): + message = userInput("Enter your Message.") + + uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower() + if uInput == "y": + message = message + '\n\n' + attachment() + + message = message.encode('base64') + + try: + ackData = api.sendBroadcast(fromAddress, subject, message) + print '\n Message Status:', api.getStatus(ackData), '\n' + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def inbox(unreadOnly = False): #Lists the messages by: Message Number, To Address Label, From Address Label, Subject, Received Time) + global usrPrompt + try: + inboxMessages = json.loads(api.getAllInboxMessages()) + numMessages = len(inboxMessages['inboxMessages']) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + messagesPrinted = 0 + messagesUnread = 0 + for msgNum in range (0, numMessages): #processes all of the messages in the inbox + message = inboxMessages['inboxMessages'][msgNum] + # if we are displaying all messages or if this message is unread then display it + if not unreadOnly or not message['read']: + print ' -----------------------------------\n' + print ' Message Number:',msgNum #Message Number + print ' To:', getLabelForAddress(message['toAddress']) #Get the to address + print ' From:', getLabelForAddress(message['fromAddress']) #Get the from address + print ' Subject:', message['subject'].decode('base64') #Get the subject + print ' Received:', datetime.datetime.fromtimestamp(float(message['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S') + messagesPrinted += 1 + if not message['read']: messagesUnread += 1 + + if (messagesPrinted%20 == 0 and messagesPrinted != 0): + uInput = userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() + + print '\n -----------------------------------' + print ' There are %d unread messages of %d messages in the inbox.' % (messagesUnread, numMessages) + print ' -----------------------------------\n' + +def outbox(): + global usrPrompt + try: + outboxMessages = json.loads(api.getAllSentMessages()) + numMessages = len(outboxMessages['sentMessages']) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + for msgNum in range (0, numMessages): #processes all of the messages in the outbox + print '\n -----------------------------------\n' + print ' Message Number:',msgNum #Message Number + #print ' Message ID:', outboxMessages['sentMessages'][msgNum]['msgid'] + print ' To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) #Get the to address + print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']) #Get the from address + print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') #Get the subject + print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] #Get the subject + + print ' Last Action Time:', datetime.datetime.fromtimestamp(float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S') + + if (msgNum%20 == 0 and msgNum != 0): + uInput = userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() + + print '\n -----------------------------------' + print ' There are ',numMessages,' messages in the outbox.' + print ' -----------------------------------\n' + +def readSentMsg(msgNum): #Opens a sent message for reading + global usrPrompt + try: + outboxMessages = json.loads(api.getAllSentMessages()) + numMessages = len(outboxMessages['sentMessages']) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + print ' ' + + if (msgNum >= numMessages): + print '\n Invalid Message Number.\n' + main() + + #Begin attachment detection + message = outboxMessages['sentMessages'][msgNum]['message'].decode('base64') + + while True: #Allows multiple messages to be downloaded/saved + if (';base64,' in message): #Found this text in the message, there is probably an attachment. + attPos= message.index(";base64,") #Finds the attachment position + attEndPos = message.index("' />") #Finds the end of the attachment + #attLen = attEndPos - attPos #Finds the length of the message + + + if ('alt = "' in message): #We can get the filename too + fnPos = message.index('alt = "') #Finds position of the filename + fnEndPos = message.index('" src=') #Finds the end position + #fnLen = fnEndPos - fnPos #Finds the length of the filename + + fileName = message[fnPos+7:fnEndPos] + else: + fnPos = attPos + fileName = 'Attachment' + + uInput = userInput('\n Attachment Detected. Would you like to save the attachment, (Y)es or (N)o?').lower() + if (uInput == "y" or uInput == 'yes'): + + attachment = message[attPos+9:attEndPos] + saveFile(fileName,attachment) + + message = message[:fnPos] + '~~' + message[(attEndPos+4):] + + else: + break + + #End attachment Detection + + print '\n To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) #Get the to address + print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']) #Get the from address + print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') #Get the subject + print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] #Get the subject + print ' Last Action Time:', datetime.datetime.fromtimestamp(float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S') + print ' Message:\n' + print message #inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') + print ' ' + +def readMsg(msgNum): #Opens a message for reading + global usrPrompt + try: + inboxMessages = json.loads(api.getAllInboxMessages()) + numMessages = len(inboxMessages['inboxMessages']) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + if (msgNum >= numMessages): + print '\n Invalid Message Number.\n' + main() + + #Begin attachment detection + message = inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') + + while True: #Allows multiple messages to be downloaded/saved + if (';base64,' in message): #Found this text in the message, there is probably an attachment. + attPos= message.index(";base64,") #Finds the attachment position + attEndPos = message.index("' />") #Finds the end of the attachment + #attLen = attEndPos - attPos #Finds the length of the message + + + if ('alt = "' in message): #We can get the filename too + fnPos = message.index('alt = "') #Finds position of the filename + fnEndPos = message.index('" src=') #Finds the end position + #fnLen = fnEndPos - fnPos #Finds the length of the filename + + fileName = message[fnPos+7:fnEndPos] + else: + fnPos = attPos + fileName = 'Attachment' + + uInput = userInput('\n Attachment Detected. Would you like to save the attachment, (Y)es or (N)o?').lower() + if (uInput == "y" or uInput == 'yes'): + + attachment = message[attPos+9:attEndPos] + saveFile(fileName,attachment) + + message = message[:fnPos] + '~~' + message[(attEndPos+4):] + + else: + break + + #End attachment Detection + print '\n To:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['toAddress']) #Get the to address + print ' From:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['fromAddress']) #Get the from address + print ' Subject:', inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64') #Get the subject + print ' Received:',datetime.datetime.fromtimestamp(float(inboxMessages['inboxMessages'][msgNum]['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S') + print ' Message:\n' + print message #inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') + print ' ' + return inboxMessages['inboxMessages'][msgNum]['msgid'] + +def replyMsg(msgNum,forwardORreply): #Allows you to reply to the message you are currently on. Saves typing in the addresses and subject. + global usrPrompt + forwardORreply = forwardORreply.lower() #makes it lowercase + try: + inboxMessages = json.loads(api.getAllInboxMessages()) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + fromAdd = inboxMessages['inboxMessages'][msgNum]['toAddress']#Address it was sent To, now the From address + message = inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') #Message that you are replying too. + + subject = inboxMessages['inboxMessages'][msgNum]['subject'] + subject = subject.decode('base64') + + if (forwardORreply == 'reply'): + toAdd = inboxMessages['inboxMessages'][msgNum]['fromAddress'] #Address it was From, now the To address + subject = "Re: " + subject + + elif (forwardORreply == 'forward'): + subject = "Fwd: " + subject + + while True: + toAdd = userInput("What is the To Address?") + + if (toAdd == "c"): + usrPrompt = 1 + print ' ' + main() + elif (validAddress(toAdd)== False): + print '\n Invalid Address. "c" to cancel. Please try again.\n' + else: + break + else: + print '\n Invalid Selection. Reply or Forward only' + usrPrompt = 0 + main() + + subject = subject.encode('base64') + + newMessage = userInput("Enter your Message.") + + uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower() + if uInput == "y": + newMessage = newMessage + '\n\n' + attachment() + + newMessage = newMessage + '\n\n------------------------------------------------------\n' + newMessage = newMessage + message + newMessage = newMessage.encode('base64') + + sendMsg(toAdd, fromAdd, subject, newMessage) + + main() + +def delMsg(msgNum): #Deletes a specified message from the inbox + global usrPrompt + try: + inboxMessages = json.loads(api.getAllInboxMessages()) + msgId = inboxMessages['inboxMessages'][int(msgNum)]['msgid'] #gets the message ID via the message index number + + msgAck = api.trashMessage(msgId) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + return msgAck + +def delSentMsg(msgNum): #Deletes a specified message from the outbox + global usrPrompt + try: + outboxMessages = json.loads(api.getAllSentMessages()) + msgId = outboxMessages['sentMessages'][int(msgNum)]['msgid'] #gets the message ID via the message index number + msgAck = api.trashSentMessage(msgId) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + return msgAck + +def getLabelForAddress(address): + global usrPrompt + + if address in knownAddresses: + return knownAddresses[address] + else: + buildKnownAddresses() + if address in knownAddresses: + return knownAddresses[address] + + return address + +def buildKnownAddresses(): + # add from address book + try: + response = api.listAddressBookEntries() + # if api is too old then fail + if "API Error 0020" in response: return + addressBook = json.loads(response) + for entry in addressBook['addresses']: + if entry['address'] not in knownAddresses: + knownAddresses[entry['address']] = "%s (%s)" % (entry['label'].decode('base64'), entry['address']) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + + # add from my addresses + try: + response = api.listAddresses2() + # if api is too old just return then fail + if "API Error 0020" in response: return + addresses = json.loads(response) + for entry in addresses['addresses']: + if entry['address'] not in knownAddresses: + knownAddresses[entry['address']] = "%s (%s)" % (entry['label'].decode('base64'), entry['address']) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def listAddressBookEntries(): + try: + response = api.listAddressBookEntries() + if "API Error" in response: + return getAPIErrorCode(response) + addressBook = json.loads(response) + print + print ' --------------------------------------------------------------' + print ' | Label | Address |' + print ' |--------------------|---------------------------------------|' + for entry in addressBook['addresses']: + label = entry['label'].decode('base64') + address = entry['address'] + if (len(label) > 19): label = label[:16] + '...' + print ' | ' + label.ljust(19) + '| ' + address.ljust(37) + ' |' + print ' --------------------------------------------------------------' + print + + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def addAddressToAddressBook(address, label): + try: + response = api.addAddressBookEntry(address, label.encode('base64')) + if "API Error" in response: + return getAPIErrorCode(response) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def deleteAddressFromAddressBook(address): + try: + response = api.deleteAddressBookEntry(address) + if "API Error" in response: + return getAPIErrorCode(response) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def getAPIErrorCode(response): + if "API Error" in response: + # if we got an API error return the number by getting the number + # after the second space and removing the trailing colon + return int(response.split()[2][:-1]) + +def markMessageRead(messageID): + try: + response = api.getInboxMessageByID(messageID, True) + if "API Error" in response: + return getAPIErrorCode(response) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def markMessageUnread(messageID): + try: + response = api.getInboxMessageByID(messageID, False) + if "API Error" in response: + return getAPIErrorCode(response) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + +def markAllMessagesRead(): + try: + inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages'] + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + for message in inboxMessages: + if not message['read']: + markMessageRead(message['msgid']) + +def markAllMessagesUnread(): + try: + inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages'] + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + for message in inboxMessages: + if message['read']: + markMessageUnread(message['msgid']) + +def clientStatus(): + try: + clientStatus = json.loads(api.clientStatus()) + except: + print '\n Connection Error\n' + usrPrompt = 0 + main() + print "\nnetworkStatus: " + clientStatus['networkStatus'] + "\n" + print "\nnetworkConnections: " + str(clientStatus['networkConnections']) + "\n" + print "\nnumberOfPubkeysProcessed: " + str(clientStatus['numberOfPubkeysProcessed']) + "\n" + print "\nnumberOfMessagesProcessed: " + str(clientStatus['numberOfMessagesProcessed']) + "\n" + print "\nnumberOfBroadcastsProcessed: " + str(clientStatus['numberOfBroadcastsProcessed']) + "\n" + + +def UI(usrInput): #Main user menu + global usrPrompt + + if usrInput == "help" or usrInput == "h" or usrInput == "?": + print ' ' + print ' -------------------------------------------------------------------------' + print ' | https://github.com/Dokument/PyBitmessage-Daemon |' + print ' |-----------------------------------------------------------------------|' + print ' | Command | Description |' + print ' |------------------------|----------------------------------------------|' + print ' | help | This help file. |' + print ' | apiTest | Tests the API |' + print ' | addInfo | Returns address information (If valid) |' + print ' | bmSettings | BitMessage settings |' + print ' | exit | Use anytime to return to main menu |' + print ' | quit | Quits the program |' + print ' |------------------------|----------------------------------------------|' + print ' | listAddresses | Lists all of the users addresses |' + print ' | generateAddress | Generates a new address |' + print ' | getAddress | Get determinist address from passphrase |' + print ' |------------------------|----------------------------------------------|' + print ' | listAddressBookEntries | Lists entries from the Address Book |' + print ' | addAddressBookEntry | Add address to the Address Book |' + print ' | deleteAddressBookEntry | Deletes address from the Address Book |' + print ' |------------------------|----------------------------------------------|' + print ' | subscribe | Subscribes to an address |' + print ' | unsubscribe | Unsubscribes from an address |' + #print ' | listSubscriptions | Lists all of the subscriptions. |' + print ' |------------------------|----------------------------------------------|' + print ' | create | Creates a channel |' + print ' | join | Joins a channel |' + print ' | leave | Leaves a channel |' + print ' |------------------------|----------------------------------------------|' + print ' | inbox | Lists the message information for the inbox |' + print ' | outbox | Lists the message information for the outbox |' + print ' | send | Send a new message or broadcast |' + print ' | unread | Lists all unread inbox messages |' + print ' | read | Reads a message from the inbox or outbox |' + print ' | save | Saves message to text file |' + print ' | delete | Deletes a message or all messages |' + print ' -------------------------------------------------------------------------' + print ' ' + main() + + elif usrInput == "apitest": #tests the API Connection. + if (apiTest() == True): + print '\n API connection test has: PASSED\n' + else: + print '\n API connection test has: FAILED\n' + main() + + elif usrInput == "addinfo": + tmp_address = userInput('\nEnter the Bitmessage Address.') + address_information = api.decodeAddress(tmp_address) + address_information = eval(address_information) + + print '\n------------------------------' + + if 'success' in str(address_information.get('status')).lower(): + print ' Valid Address' + print ' Address Version: %s' % str(address_information.get('addressVersion')) + print ' Stream Number: %s' % str(address_information.get('streamNumber')) + else: + print ' Invalid Address !' + + print '------------------------------\n' + main() + + elif usrInput == "bmsettings": #tests the API Connection. + bmSettings() + print ' ' + main() + + elif usrInput == "quit": #Quits the application + print '\n Bye\n' + sys.exit() + os.exit() + + elif usrInput == "listaddresses": #Lists all of the identities in the addressbook + listAdd() + main() + + elif usrInput == "generateaddress": #Generates a new address + uInput = userInput('\nWould you like to create a (D)eterministic or (R)andom address?').lower() + + if uInput == "d" or uInput == "determinstic": #Creates a deterministic address + deterministic = True + + #lbl = raw_input('Label the new address:') #currently not possible via the api + lbl = '' + passphrase = userInput('Enter the Passphrase.')#.encode('base64') + numOfAdd = int(userInput('How many addresses would you like to generate?')) + #addVNum = int(raw_input('Address version number (default "0"):')) + #streamNum = int(raw_input('Stream number (default "0"):')) + addVNum = 3 + streamNum = 1 + isRipe = userInput('Shorten the address, (Y)es or (N)o?').lower() + + if isRipe == "y": + ripe = True + print genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe) + main() + elif isRipe == "n": + ripe = False + print genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe) + main() + elif isRipe == "exit": + usrPrompt = 1 + main() + else: + print '\n Invalid input\n' + main() + + + elif uInput == "r" or uInput == "random": #Creates a random address with user-defined label + deterministic = False + null = '' + lbl = userInput('Enter the label for the new address.') + + print genAdd(lbl,deterministic, null,null, null, null, null) + main() + + else: + print '\n Invalid input\n' + main() + + elif usrInput == "getaddress": #Gets the address for/from a passphrase + phrase = userInput("Enter the address passphrase.") + print '\n Working...\n' + #vNumber = int(raw_input("Enter the address version number:")) + #sNumber = int(raw_input("Enter the address stream number:")) + + address = getAddress(phrase,4,1)#,vNumber,sNumber) + print ('\n Address: ' + address + '\n') + + usrPrompt = 1 + main() + + elif usrInput == "subscribe": #Subsribe to an address + subscribe() + usrPrompt = 1 + main() + elif usrInput == "unsubscribe": #Unsubscribe from an address + unsubscribe() + usrPrompt = 1 + main() + elif usrInput == "listsubscriptions": #Unsubscribe from an address + listSubscriptions() + usrPrompt = 1 + main() + + elif usrInput == "create": + createChan() + userPrompt = 1 + main() + + elif usrInput == "join": + joinChan() + userPrompt = 1 + main() + + elif usrInput == "leave": + leaveChan() + userPrompt = 1 + main() + + elif usrInput == "inbox": + print '\n Loading...\n' + inbox() + main() + + elif usrInput == "unread": + print '\n Loading...\n' + inbox(True) + main() + + elif usrInput == "outbox": + print '\n Loading...\n' + outbox() + main() + + elif usrInput == 'send': #Sends a message or broadcast + uInput = userInput('Would you like to send a (M)essage or (B)roadcast?').lower() + + if (uInput == 'm' or uInput == 'message'): + null = '' + sendMsg(null,null,null,null) + main() + elif (uInput =='b' or uInput == 'broadcast'): + null = '' + sendBrd(null,null,null) + main() + + + elif usrInput == "read": #Opens a message from the inbox for viewing. + + uInput = userInput("Would you like to read a message from the (I)nbox or (O)utbox?").lower() + + if (uInput != 'i' and uInput != 'inbox' and uInput != 'o' and uInput != 'outbox'): + print '\n Invalid Input.\n' + usrPrompt = 1 + main() + + msgNum = int(userInput("What is the number of the message you wish to open?")) + + if (uInput == 'i' or uInput == 'inbox'): + print '\n Loading...\n' + messageID = readMsg(msgNum) + + uInput = userInput("\nWould you like to keep this message unread, (Y)es or (N)o?").lower() + + if not (uInput == 'y' or uInput == 'yes'): + markMessageRead(messageID) + usrPrompt = 1 + + uInput = userInput("\nWould you like to (D)elete, (F)orward, (R)eply to, or (Exit) this message?").lower() + + if (uInput == 'r' or uInput == 'reply'): + print '\n Loading...\n' + print ' ' + replyMsg(msgNum,'reply') + usrPrompt = 1 + + elif (uInput == 'f' or uInput == 'forward'): + print '\n Loading...\n' + print ' ' + replyMsg(msgNum,'forward') + usrPrompt = 1 + + elif (uInput == "d" or uInput == 'delete'): + uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion + + if uInput == "y": + delMsg(msgNum) + print '\n Message Deleted.\n' + usrPrompt = 1 + else: + usrPrompt = 1 + else: + print '\n Invalid entry\n' + usrPrompt = 1 + + elif (uInput == 'o' or uInput == 'outbox'): + readSentMsg(msgNum) + + uInput = userInput("Would you like to (D)elete, or (Exit) this message?").lower() #Gives the user the option to delete the message + + if (uInput == "d" or uInput == 'delete'): + uInput = userInput('Are you sure, (Y)es or (N)o?').lower() #Prevent accidental deletion + + if uInput == "y": + delSentMsg(msgNum) + print '\n Message Deleted.\n' + usrPrompt = 1 + else: + usrPrompt = 1 + else: + print '\n Invalid Entry\n' + usrPrompt = 1 + + main() + + elif usrInput == "save": + + uInput = userInput("Would you like to save a message from the (I)nbox or (O)utbox?").lower() + + if (uInput != 'i' and uInput == 'inbox' and uInput != 'o' and uInput == 'outbox'): + print '\n Invalid Input.\n' + usrPrompt = 1 + main() + + if (uInput == 'i' or uInput == 'inbox'): + inboxMessages = json.loads(api.getAllInboxMessages()) + numMessages = len(inboxMessages['inboxMessages']) + + while True: + msgNum = int(userInput("What is the number of the message you wish to save?")) + + if (msgNum >= numMessages): + print '\n Invalid Message Number.\n' + else: + break + + subject = inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64') + message = inboxMessages['inboxMessages'][msgNum]['message']#Don't decode since it is done in the saveFile function + + elif (uInput == 'o' or uInput == 'outbox'): + outboxMessages = json.loads(api.getAllSentMessages()) + numMessages = len(outboxMessages['sentMessages']) + + while True: + msgNum = int(userInput("What is the number of the message you wish to save?")) + + if (msgNum >= numMessages): + print '\n Invalid Message Number.\n' + else: + break + + subject = outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') + message = outboxMessages['sentMessages'][msgNum]['message']#Don't decode since it is done in the saveFile function + + subject = subject +'.txt' + saveFile(subject,message) + + usrPrompt = 1 + main() + + elif usrInput == "delete": #will delete a message from the system, not reflected on the UI. + + uInput = userInput("Would you like to delete a message from the (I)nbox or (O)utbox?").lower() + + if (uInput == 'i' or uInput == 'inbox'): + inboxMessages = json.loads(api.getAllInboxMessages()) + numMessages = len(inboxMessages['inboxMessages']) + + while True: + msgNum = userInput('Enter the number of the message you wish to delete or (A)ll to empty the inbox.').lower() + + if (msgNum == 'a' or msgNum == 'all'): + break + elif (int(msgNum) >= numMessages): + print '\n Invalid Message Number.\n' + else: + break + + uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion + + if uInput == "y": + if (msgNum == 'a' or msgNum == 'all'): + print ' ' + for msgNum in range (0, numMessages): #processes all of the messages in the inbox + print ' Deleting message ', msgNum+1, ' of ', numMessages + delMsg(0) + + print '\n Inbox is empty.' + usrPrompt = 1 + else: + delMsg(int(msgNum)) + + print '\n Notice: Message numbers may have changed.\n' + main() + else: + usrPrompt = 1 + elif (uInput == 'o' or uInput == 'outbox'): + outboxMessages = json.loads(api.getAllSentMessages()) + numMessages = len(outboxMessages['sentMessages']) + + while True: + msgNum = userInput('Enter the number of the message you wish to delete or (A)ll to empty the inbox.').lower() + + if (msgNum == 'a' or msgNum == 'all'): + break + elif (int(msgNum) >= numMessages): + print '\n Invalid Message Number.\n' + else: + break + + uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion + + if uInput == "y": + if (msgNum == 'a' or msgNum == 'all'): + print ' ' + for msgNum in range (0, numMessages): #processes all of the messages in the outbox + print ' Deleting message ', msgNum+1, ' of ', numMessages + delSentMsg(0) + + print '\n Outbox is empty.' + usrPrompt = 1 + else: + delSentMsg(int(msgNum)) + print '\n Notice: Message numbers may have changed.\n' + main() + else: + usrPrompt = 1 + else: + print '\n Invalid Entry.\n' + userPrompt = 1 + main() + + elif usrInput == "exit": + print '\n You are already at the main menu. Use "quit" to quit.\n' + usrPrompt = 1 + main() + + elif usrInput == "listaddressbookentries": + res = listAddressBookEntries() + if res == 20: print '\n Error: API function not supported.\n' + usrPrompt = 1 + main() + + elif usrInput == "addaddressbookentry": + address = userInput('Enter address') + label = userInput('Enter label') + res = addAddressToAddressBook(address, label) + if res == 16: print '\n Error: Address already exists in Address Book.\n' + if res == 20: print '\n Error: API function not supported.\n' + usrPrompt = 1 + main() + + elif usrInput == "deleteaddressbookentry": + address = userInput('Enter address') + res = deleteAddressFromAddressBook(address) + if res == 20: print '\n Error: API function not supported.\n' + usrPrompt = 1 + main() + + elif usrInput == "markallmessagesread": + markAllMessagesRead() + usrPrompt = 1 + main() + + elif usrInput == "markallmessagesunread": + markAllMessagesUnread() + usrPrompt = 1 + main() + + elif usrInput == "status": + clientStatus() + usrPrompt = 1 + main() + + elif usrInput == "million+": + genMilAddr() + usrPrompt = 1 + main() + + elif usrInput == "million-": + delMilAddr() + usrPrompt = 1 + main() + + else: + print '\n "',usrInput,'" is not a command.\n' + usrPrompt = 1 + main() + +def main(): + global api + global usrPrompt + + if (usrPrompt == 0): + print '\n ------------------------------' + print ' | Bitmessage Daemon by .dok |' + print ' | Version 0.2.6 for BM 0.3.5 |' + print ' ------------------------------' + api = xmlrpclib.ServerProxy(apiData()) #Connect to BitMessage using these api credentials + + if (apiTest() == False): + print '\n ****************************************************************' + print ' WARNING: You are not connected to the Bitmessage client.' + print ' Either Bitmessage is not running or your settings are incorrect.' + print ' Use the command "apiTest" or "bmSettings" to resolve this issue.' + print ' ****************************************************************\n' + + print 'Type (H)elp for a list of commands.' #Startup message + usrPrompt = 2 + + #if (apiTest() == False):#Preform a connection test #taken out until I get the error handler working + # print '*************************************' + # print 'WARNING: No connection to Bitmessage.' + # print '*************************************' + # print ' ' + elif (usrPrompt == 1): + print '\nType (H)elp for a list of commands.' #Startup message + usrPrompt = 2 + + try: + UI((raw_input('>').lower()).replace(" ", "")) + except EOFError: + UI("quit") + +if __name__ == "__main__": + main() diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index bf1d74f2..02f1396a 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -1,6 +1,6 @@ #!/usr/bin/env python2.7 -# Copyright (c) 2012 Jonathan Warren -# Copyright (c) 2012 The Bitmessage developers +# Copyright (c) 2012-2016 Jonathan Warren +# Copyright (c) 2012-2016 The Bitmessage developers # Distributed under the MIT/X11 software license. See the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -23,8 +23,7 @@ import sys from subprocess import call import time -from SimpleXMLRPCServer import SimpleXMLRPCServer -from api import MySimpleXMLRPCRequestHandler +from api import MySimpleXMLRPCRequestHandler, StoppableXMLRPCServer from helper_startup import isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections import shared @@ -44,22 +43,23 @@ from debug import logger # Helper Functions import helper_bootstrap import helper_generic - +from helper_threading import * def connectToStream(streamNumber): shared.streamsInWhichIAmParticipating[streamNumber] = 'no data' selfInitiatedConnections[streamNumber] = {} - shared.inventorySets[streamNumber] = set() - queryData = sqlQuery('''SELECT hash FROM inventory WHERE streamnumber=?''', streamNumber) - for row in queryData: - shared.inventorySets[streamNumber].add(row[0]) - if isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections(): # Some XP and Vista systems can only have 10 outgoing connections at a time. maximumNumberOfHalfOpenConnections = 9 else: maximumNumberOfHalfOpenConnections = 64 + try: + # don't overload Tor + if shared.config.get('bitmessagesettings', 'socksproxytype') != 'none': + maximumNumberOfHalfOpenConnections = 4 + except: + pass for i in range(maximumNumberOfHalfOpenConnections): a = outgoingSynSender() a.setup(streamNumber, selfInitiatedConnections) @@ -117,13 +117,24 @@ def _fixWinsock(): socket.IPV6_V6ONLY = 27 # This thread, of which there is only one, runs the API. -class singleAPI(threading.Thread): - +class singleAPI(threading.Thread, StoppableThread): def __init__(self): - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="singleAPI") + self.initStop() + + def stopThread(self): + super(singleAPI, self).stopThread() + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect((shared.config.get('bitmessagesettings', 'apiinterface'), shared.config.getint( + 'bitmessagesettings', 'apiport'))) + s.shutdown(socket.SHUT_RDWR) + s.close() + except: + pass def run(self): - se = SimpleXMLRPCServer((shared.config.get('bitmessagesettings', 'apiinterface'), shared.config.getint( + se = StoppableXMLRPCServer((shared.config.get('bitmessagesettings', 'apiinterface'), shared.config.getint( 'bitmessagesettings', 'apiport')), MySimpleXMLRPCRequestHandler, True, True) se.register_introspection_functions() se.serve_forever() @@ -143,7 +154,7 @@ class Main: shared.daemon = daemon # is the application already running? If yes then exit. - thisapp = singleton.singleinstance() + shared.thisapp = singleton.singleinstance("", daemon) # get curses flag curses = False @@ -203,6 +214,11 @@ class Main: singleListenerThread.setup(selfInitiatedConnections) singleListenerThread.daemon = True # close the main program even if there are threads left singleListenerThread.start() + + if shared.safeConfigGetBoolean('bitmessagesettings','upnp'): + import upnp + upnpThread = upnp.uPnPThread() + upnpThread.start() if daemon == False and shared.safeConfigGetBoolean('bitmessagesettings', 'daemon') == False: if curses == False: @@ -246,7 +262,7 @@ class Main: if __name__ == "__main__": mainprogram = Main() - mainprogram.start() + mainprogram.start(shared.safeConfigGetBoolean('bitmessagesettings', 'daemon')) # So far, the creation of and management of the Bitmessage protocol and this diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 1819628b..cae51676 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -1,3 +1,4 @@ +from debug import logger withMessagingMenu = False try: from gi.repository import MessagingMenu @@ -6,21 +7,45 @@ try: except ImportError: MessagingMenu = None +try: + from PyQt4 import QtCore, QtGui + from PyQt4.QtCore import * + from PyQt4.QtGui import * + from PyQt4.QtNetwork import QLocalSocket, QLocalServer + +except Exception as err: + logmsg = 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download it from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\' (without quotes).' + logger.critical(logmsg, exc_info=True) + sys.exit() + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 +except AttributeError: + logger.exception('QtGui.QApplication.UnicodeUTF8 error', exc_info=True) + from addresses import * import shared from bitmessageui import * from namecoin import namecoinConnection, ensureNamecoinOptions from newaddressdialog import * -from addaddressdialog import * +from newaddresswizard import * +from messageview import MessageView +from migrationwizard import * +from foldertree import * from newsubscriptiondialog import * from regenerateaddresses import * from newchandialog import * +from safehtmlparser import * from specialaddressbehavior import * +from emailgateway import * from settings import * +import settingsmixin +import support from about import * from help import * from iconglossary import * from connect import * +import locale as pythonlocale import sys from time import strftime, localtime, gmtime import time @@ -31,143 +56,67 @@ import pickle import platform import textwrap import debug -from debug import logger +import random import subprocess +import string import datetime from helper_sql import * +import helper_search import l10n +import openclpow +import types +from utils import * +from collections import OrderedDict +from account import * +from dialogs import AddAddressDialog +from class_objectHashHolder import objectHashHolder +from class_singleWorker import singleWorker -try: - from PyQt4 import QtCore, QtGui - from PyQt4.QtCore import * - from PyQt4.QtGui import * +def _translate(context, text, disambiguation = None, encoding = None, number = None): + if number is None: + return QtGui.QApplication.translate(context, text) + else: + return QtGui.QApplication.translate(context, text, None, QtCore.QCoreApplication.CodecForTr, number) -except Exception as err: - print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download it from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\' (without quotes).' - print 'Error message:', err - sys.exit() - -try: - _encoding = QtGui.QApplication.UnicodeUTF8 -except AttributeError: - print 'QtGui.QApplication.UnicodeUTF8 error:', err - -def _translate(context, text): - return QtGui.QApplication.translate(context, text) - - -def identiconize(address): - size = 48 - - # If you include another identicon library, please generate an - # example identicon with the following md5 hash: - # 3fd4bf901b9d4ea1394f0fb358725b28 - - try: - identicon_lib = shared.config.get('bitmessagesettings', 'identiconlib') - except: - # default to qidenticon_two_x - identicon_lib = 'qidenticon_two_x' - - # As an 'identiconsuffix' you could put "@bitmessge.ch" or "@bm.addr" to make it compatible with other identicon generators. (Note however, that E-Mail programs might convert the BM-address to lowercase first.) - # It can be used as a pseudo-password to salt the generation of the identicons to decrease the risk - # of attacks where someone creates an address to mimic someone else's identicon. - identiconsuffix = shared.config.get('bitmessagesettings', 'identiconsuffix') - - if not shared.config.getboolean('bitmessagesettings', 'useidenticons'): - idcon = QtGui.QIcon() - return idcon - - if (identicon_lib[:len('qidenticon')] == 'qidenticon'): - # print identicon_lib - # originally by: - # :Author:Shin Adachi - # Licesensed under FreeBSD License. - # stripped from PIL and uses QT instead (by sendiulo, same license) - import qidenticon - hash = hashlib.md5(addBMIfNotPresent(address)+identiconsuffix).hexdigest() - use_two_colors = (identicon_lib[:len('qidenticon_two')] == 'qidenticon_two') - opacity = int(not((identicon_lib == 'qidenticon_x') | (identicon_lib == 'qidenticon_two_x') | (identicon_lib == 'qidenticon_b') | (identicon_lib == 'qidenticon_two_b')))*255 - penwidth = 0 - image = qidenticon.render_identicon(int(hash, 16), size, use_two_colors, opacity, penwidth) - # filename = './images/identicons/'+hash+'.png' - # image.save(filename) - idcon = QtGui.QIcon() - idcon.addPixmap(image, QtGui.QIcon.Normal, QtGui.QIcon.Off) - return idcon - elif identicon_lib == 'pydenticon': - # print identicon_lib - # Here you could load pydenticon.py (just put it in the "src" folder of your Bitmessage source) - from pydenticon import Pydenticon - # It is not included in the source, because it is licensed under GPLv3 - # GPLv3 is a copyleft license that would influence our licensing - # Find the source here: http://boottunes.googlecode.com/svn-history/r302/trunk/src/pydenticon.py - # note that it requires PIL to be installed: http://www.pythonware.com/products/pil/ - idcon_render = Pydenticon(addBMIfNotPresent(address)+identiconsuffix, size*3) - rendering = idcon_render._render() - data = rendering.convert("RGBA").tostring("raw", "RGBA") - qim = QImage(data, size, size, QImage.Format_ARGB32) - pix = QPixmap.fromImage(qim) - idcon = QtGui.QIcon() - idcon.addPixmap(pix, QtGui.QIcon.Normal, QtGui.QIcon.Off) - return idcon - -def avatarize(address): - """ - loads a supported image for the given address' hash form 'avatars' folder - falls back to default avatar if 'default.*' file exists - falls back to identiconize(address) - """ - idcon = QtGui.QIcon() - hash = hashlib.md5(addBMIfNotPresent(address)).hexdigest() - str_broadcast_subscribers = '[Broadcast subscribers]' - if address == str_broadcast_subscribers: - # don't hash [Broadcast subscribers] - hash = address - # http://pyqt.sourceforge.net/Docs/PyQt4/qimagereader.html#supportedImageFormats - # print QImageReader.supportedImageFormats () - # QImageReader.supportedImageFormats () - extensions = ['PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM', 'PGM', 'PPM', 'TIFF', 'XBM', 'XPM', 'TGA'] - # try to find a specific avatar - for ext in extensions: - lower_hash = shared.appdata + 'avatars/' + hash + '.' + ext.lower() - upper_hash = shared.appdata + 'avatars/' + hash + '.' + ext.upper() - if os.path.isfile(lower_hash): - # print 'found avatar of ', address - idcon.addFile(lower_hash) - return idcon - elif os.path.isfile(upper_hash): - # print 'found avatar of ', address - idcon.addFile(upper_hash) - return idcon - # if we haven't found any, try to find a default avatar - for ext in extensions: - lower_default = shared.appdata + 'avatars/' + 'default.' + ext.lower() - upper_default = shared.appdata + 'avatars/' + 'default.' + ext.upper() - if os.path.isfile(lower_default): - default = lower_default - idcon.addFile(lower_default) - return idcon - elif os.path.isfile(upper_default): - default = upper_default - idcon.addFile(upper_default) - return idcon - # If no avatar is found - return identiconize(address) - def change_translation(locale): - global qtranslator - qtranslator = QtCore.QTranslator() - translationpath = os.path.join( - getattr(sys, '_MEIPASS', sys.path[0]), - 'translations', - 'bitmessage_' + locale - ) - qtranslator.load(translationpath) - QtGui.QApplication.installTranslator(qtranslator) + global qmytranslator, qsystranslator + try: + if not qmytranslator.isEmpty(): + QtGui.QApplication.removeTranslator(qmytranslator) + except: + pass + try: + if not qsystranslator.isEmpty(): + QtGui.QApplication.removeTranslator(qsystranslator) + except: + pass + qmytranslator = QtCore.QTranslator() + translationpath = os.path.join (shared.codePath(), 'translations', 'bitmessage_' + locale) + qmytranslator.load(translationpath) + QtGui.QApplication.installTranslator(qmytranslator) -class MyForm(QtGui.QMainWindow): + qsystranslator = QtCore.QTranslator() + if shared.frozen: + translationpath = os.path.join (shared.codePath(), 'translations', 'qt_' + locale) + else: + translationpath = os.path.join (str(QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)), 'qt_' + locale) + qsystranslator.load(translationpath) + QtGui.QApplication.installTranslator(qsystranslator) + + lang = pythonlocale.normalize(l10n.getTranslationLanguage()) + if 'win32' in sys.platform or 'win64' in sys.platform: + lang = l10n.getWindowsLocale(lang) + try: + pythonlocale.setlocale(pythonlocale.LC_ALL, lang) + if 'win32' not in sys.platform and 'win64' not in sys.platform: + l10n.encoding = pythonlocale.nl_langinfo(pythonlocale.CODESET) + else: + l10n.encoding = pythonlocale.getlocale()[1] + except: + logger.error("Failed to set locale to %s", lang, exc_info=True) + +class MyForm(settingsmixin.SMainWindow): # sound type constants SOUND_NONE = 0 @@ -183,8 +132,10 @@ class MyForm(QtGui.QMainWindow): # the maximum frequency of message sounds in seconds maxSoundFrequencySec = 60 - str_broadcast_subscribers = '[Broadcast subscribers]' str_chan = '[chan]' + + REPLY_TYPE_SENDER = 0 + REPLY_TYPE_CHAN = 1 def init_file_menu(self): QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL( @@ -199,39 +150,27 @@ class MyForm(QtGui.QMainWindow): QtCore.SIGNAL( "triggered()"), self.click_actionRegenerateDeterministicAddresses) - QtCore.QObject.connect(self.ui.actionJoinChan, QtCore.SIGNAL( - "triggered()"), + QtCore.QObject.connect(self.ui.pushButtonAddChan, QtCore.SIGNAL( + "clicked()"), self.click_actionJoinChan) # also used for creating chans. QtCore.QObject.connect(self.ui.pushButtonNewAddress, QtCore.SIGNAL( "clicked()"), self.click_NewAddressDialog) - QtCore.QObject.connect(self.ui.comboBoxSendFrom, QtCore.SIGNAL( - "activated(int)"), self.redrawLabelFrom) QtCore.QObject.connect(self.ui.pushButtonAddAddressBook, QtCore.SIGNAL( "clicked()"), self.click_pushButtonAddAddressBook) QtCore.QObject.connect(self.ui.pushButtonAddSubscription, QtCore.SIGNAL( "clicked()"), self.click_pushButtonAddSubscription) - QtCore.QObject.connect(self.ui.pushButtonAddBlacklist, QtCore.SIGNAL( - "clicked()"), self.click_pushButtonAddBlacklist) QtCore.QObject.connect(self.ui.pushButtonTTL, QtCore.SIGNAL( "clicked()"), self.click_pushButtonTTL) QtCore.QObject.connect(self.ui.pushButtonSend, QtCore.SIGNAL( "clicked()"), self.click_pushButtonSend) - QtCore.QObject.connect(self.ui.pushButtonLoadFromAddressBook, - QtCore.SIGNAL( - "clicked()"), - self.click_pushButtonLoadFromAddressBook) QtCore.QObject.connect(self.ui.pushButtonFetchNamecoinID, QtCore.SIGNAL( "clicked()"), self.click_pushButtonFetchNamecoinID) - QtCore.QObject.connect(self.ui.radioButtonBlacklist, QtCore.SIGNAL( - "clicked()"), self.click_radioButtonBlacklist) - QtCore.QObject.connect(self.ui.radioButtonWhitelist, QtCore.SIGNAL( - "clicked()"), self.click_radioButtonWhitelist) - QtCore.QObject.connect(self.ui.pushButtonStatusIcon, QtCore.SIGNAL( - "clicked()"), self.click_pushButtonStatusIcon) QtCore.QObject.connect(self.ui.actionSettings, QtCore.SIGNAL( "triggered()"), self.click_actionSettings) QtCore.QObject.connect(self.ui.actionAbout, QtCore.SIGNAL( "triggered()"), self.click_actionAbout) + QtCore.QObject.connect(self.ui.actionSupport, QtCore.SIGNAL( + "triggered()"), self.click_actionSupport) QtCore.QObject.connect(self.ui.actionHelp, QtCore.SIGNAL( "triggered()"), self.click_actionHelp) @@ -240,14 +179,23 @@ class MyForm(QtGui.QMainWindow): self.ui.inboxContextMenuToolbar = QtGui.QToolBar() # Actions self.actionReply = self.ui.inboxContextMenuToolbar.addAction(_translate( - "MainWindow", "Reply"), self.on_action_InboxReply) + "MainWindow", "Reply to sender"), self.on_action_InboxReply) + self.actionReplyChan = self.ui.inboxContextMenuToolbar.addAction(_translate( + "MainWindow", "Reply to channel"), self.on_action_InboxReplyChan) self.actionAddSenderToAddressBook = self.ui.inboxContextMenuToolbar.addAction( _translate( "MainWindow", "Add sender to your Address Book"), self.on_action_InboxAddSenderToAddressBook) + self.actionAddSenderToBlackList = self.ui.inboxContextMenuToolbar.addAction( + _translate( + "MainWindow", "Add sender to your Blacklist"), + self.on_action_InboxAddSenderToBlackList) self.actionTrashInboxMessage = self.ui.inboxContextMenuToolbar.addAction( _translate("MainWindow", "Move to Trash"), self.on_action_InboxTrash) + self.actionUndeleteTrashedMessage = self.ui.inboxContextMenuToolbar.addAction( + _translate("MainWindow", "Undelete"), + self.on_action_TrashUndelete) self.actionForceHtml = self.ui.inboxContextMenuToolbar.addAction( _translate( "MainWindow", "View HTML code as formatted text"), @@ -259,61 +207,97 @@ class MyForm(QtGui.QMainWindow): self.actionMarkUnread = self.ui.inboxContextMenuToolbar.addAction( _translate( "MainWindow", "Mark Unread"), self.on_action_InboxMarkUnread) + + # contextmenu messagelists self.ui.tableWidgetInbox.setContextMenuPolicy( QtCore.Qt.CustomContextMenu) if connectSignal: self.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL( 'customContextMenuRequested(const QPoint&)'), self.on_context_menuInbox) - self.popMenuInbox = QtGui.QMenu(self) - self.popMenuInbox.addAction(self.actionForceHtml) - self.popMenuInbox.addAction(self.actionMarkUnread) - self.popMenuInbox.addSeparator() - self.popMenuInbox.addAction(self.actionReply) - self.popMenuInbox.addAction(self.actionAddSenderToAddressBook) - self.popMenuInbox.addSeparator() - self.popMenuInbox.addAction(self.actionSaveMessageAs) - self.popMenuInbox.addAction(self.actionTrashInboxMessage) + self.ui.tableWidgetInboxSubscriptions.setContextMenuPolicy( + QtCore.Qt.CustomContextMenu) + if connectSignal: + self.connect(self.ui.tableWidgetInboxSubscriptions, QtCore.SIGNAL( + 'customContextMenuRequested(const QPoint&)'), + self.on_context_menuInbox) + self.ui.tableWidgetInboxChans.setContextMenuPolicy( + QtCore.Qt.CustomContextMenu) + if connectSignal: + self.connect(self.ui.tableWidgetInboxChans, QtCore.SIGNAL( + 'customContextMenuRequested(const QPoint&)'), + self.on_context_menuInbox) def init_identities_popup_menu(self, connectSignal=True): # Popup menu for the Your Identities tab + self.ui.addressContextMenuToolbarYourIdentities = QtGui.QToolBar() + # Actions + self.actionNewYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(_translate( + "MainWindow", "New"), self.on_action_YourIdentitiesNew) + self.actionEnableYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction( + _translate( + "MainWindow", "Enable"), self.on_action_Enable) + self.actionDisableYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction( + _translate( + "MainWindow", "Disable"), self.on_action_Disable) + self.actionSetAvatarYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction( + _translate( + "MainWindow", "Set avatar..."), + self.on_action_TreeWidgetSetAvatar) + self.actionClipboardYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction( + _translate( + "MainWindow", "Copy address to clipboard"), + self.on_action_Clipboard) + self.actionSpecialAddressBehaviorYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction( + _translate( + "MainWindow", "Special address behavior..."), + self.on_action_SpecialAddressBehaviorDialog) + self.actionEmailGateway = self.ui.addressContextMenuToolbarYourIdentities.addAction( + _translate( + "MainWindow", "Email gateway"), + self.on_action_EmailGatewayDialog) + + self.ui.treeWidgetYourIdentities.setContextMenuPolicy( + QtCore.Qt.CustomContextMenu) + if connectSignal: + self.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL( + 'customContextMenuRequested(const QPoint&)'), + self.on_context_menuYourIdentities) + + def init_chan_popup_menu(self, connectSignal=True): + # Popup menu for the Channels tab self.ui.addressContextMenuToolbar = QtGui.QToolBar() # Actions self.actionNew = self.ui.addressContextMenuToolbar.addAction(_translate( "MainWindow", "New"), self.on_action_YourIdentitiesNew) + self.actionDelete = self.ui.addressContextMenuToolbar.addAction( + _translate("MainWindow", "Delete"), + self.on_action_YourIdentitiesDelete) self.actionEnable = self.ui.addressContextMenuToolbar.addAction( _translate( - "MainWindow", "Enable"), self.on_action_YourIdentitiesEnable) + "MainWindow", "Enable"), self.on_action_Enable) self.actionDisable = self.ui.addressContextMenuToolbar.addAction( _translate( - "MainWindow", "Disable"), self.on_action_YourIdentitiesDisable) + "MainWindow", "Disable"), self.on_action_Disable) self.actionSetAvatar = self.ui.addressContextMenuToolbar.addAction( _translate( "MainWindow", "Set avatar..."), - self.on_action_YourIdentitiesSetAvatar) + self.on_action_TreeWidgetSetAvatar) self.actionClipboard = self.ui.addressContextMenuToolbar.addAction( _translate( "MainWindow", "Copy address to clipboard"), - self.on_action_YourIdentitiesClipboard) + self.on_action_Clipboard) self.actionSpecialAddressBehavior = self.ui.addressContextMenuToolbar.addAction( _translate( "MainWindow", "Special address behavior..."), self.on_action_SpecialAddressBehaviorDialog) - self.ui.tableWidgetYourIdentities.setContextMenuPolicy( + + self.ui.treeWidgetChans.setContextMenuPolicy( QtCore.Qt.CustomContextMenu) if connectSignal: - self.connect(self.ui.tableWidgetYourIdentities, QtCore.SIGNAL( + self.connect(self.ui.treeWidgetChans, QtCore.SIGNAL( 'customContextMenuRequested(const QPoint&)'), - self.on_context_menuYourIdentities) - self.popMenu = QtGui.QMenu(self) - self.popMenu.addAction(self.actionNew) - self.popMenu.addSeparator() - self.popMenu.addAction(self.actionClipboard) - self.popMenu.addSeparator() - self.popMenu.addAction(self.actionEnable) - self.popMenu.addAction(self.actionDisable) - self.popMenu.addAction(self.actionSetAvatar) - self.popMenu.addAction(self.actionSpecialAddressBehavior) + self.on_context_menuChan) def init_addressbook_popup_menu(self, connectSignal=True): # Popup menu for the Address Book page @@ -347,14 +331,6 @@ class MyForm(QtGui.QMainWindow): self.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL( 'customContextMenuRequested(const QPoint&)'), self.on_context_menuAddressBook) - self.popMenuAddressBook = QtGui.QMenu(self) - self.popMenuAddressBook.addAction(self.actionAddressBookSend) - self.popMenuAddressBook.addAction(self.actionAddressBookClipboard) - self.popMenuAddressBook.addAction(self.actionAddressBookSubscribe) - self.popMenuAddressBook.addAction(self.actionAddressBookSetAvatar) - self.popMenuAddressBook.addSeparator() - self.popMenuAddressBook.addAction(self.actionAddressBookNew) - self.popMenuAddressBook.addAction(self.actionAddressBookDelete) def init_subscriptions_popup_menu(self, connectSignal=True): # Popup menu for the Subscriptions page @@ -376,22 +352,13 @@ class MyForm(QtGui.QMainWindow): self.on_action_SubscriptionsDisable) self.actionsubscriptionsSetAvatar = self.ui.subscriptionsContextMenuToolbar.addAction( _translate("MainWindow", "Set avatar..."), - self.on_action_SubscriptionsSetAvatar) - self.ui.tableWidgetSubscriptions.setContextMenuPolicy( + self.on_action_TreeWidgetSetAvatar) + self.ui.treeWidgetSubscriptions.setContextMenuPolicy( QtCore.Qt.CustomContextMenu) if connectSignal: - self.connect(self.ui.tableWidgetSubscriptions, QtCore.SIGNAL( + self.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL( 'customContextMenuRequested(const QPoint&)'), self.on_context_menuSubscriptions) - self.popMenuSubscriptions = QtGui.QMenu(self) - self.popMenuSubscriptions.addAction(self.actionsubscriptionsNew) - self.popMenuSubscriptions.addAction(self.actionsubscriptionsDelete) - self.popMenuSubscriptions.addSeparator() - self.popMenuSubscriptions.addAction(self.actionsubscriptionsEnable) - self.popMenuSubscriptions.addAction(self.actionsubscriptionsDisable) - self.popMenuSubscriptions.addAction(self.actionsubscriptionsSetAvatar) - self.popMenuSubscriptions.addSeparator() - self.popMenuSubscriptions.addAction(self.actionsubscriptionsClipboard) def init_sent_popup_menu(self, connectSignal=True): # Popup menu for the Sent page @@ -407,55 +374,203 @@ class MyForm(QtGui.QMainWindow): self.actionForceSend = self.ui.sentContextMenuToolbar.addAction( _translate( "MainWindow", "Force send"), self.on_action_ForceSend) - self.ui.tableWidgetSent.setContextMenuPolicy( - QtCore.Qt.CustomContextMenu) - if connectSignal: - self.connect(self.ui.tableWidgetSent, QtCore.SIGNAL( - 'customContextMenuRequested(const QPoint&)'), - self.on_context_menuSent) # self.popMenuSent = QtGui.QMenu( self ) # self.popMenuSent.addAction( self.actionSentClipboard ) # self.popMenuSent.addAction( self.actionTrashSentMessage ) - def init_blacklist_popup_menu(self, connectSignal=True): - # Popup menu for the Blacklist page - self.ui.blacklistContextMenuToolbar = QtGui.QToolBar() - # Actions - self.actionBlacklistNew = self.ui.blacklistContextMenuToolbar.addAction( - _translate( - "MainWindow", "Add new entry"), self.on_action_BlacklistNew) - self.actionBlacklistDelete = self.ui.blacklistContextMenuToolbar.addAction( - _translate( - "MainWindow", "Delete"), self.on_action_BlacklistDelete) - self.actionBlacklistClipboard = self.ui.blacklistContextMenuToolbar.addAction( - _translate( - "MainWindow", "Copy address to clipboard"), - self.on_action_BlacklistClipboard) - self.actionBlacklistEnable = self.ui.blacklistContextMenuToolbar.addAction( - _translate( - "MainWindow", "Enable"), self.on_action_BlacklistEnable) - self.actionBlacklistDisable = self.ui.blacklistContextMenuToolbar.addAction( - _translate( - "MainWindow", "Disable"), self.on_action_BlacklistDisable) - self.actionBlacklistSetAvatar = self.ui.blacklistContextMenuToolbar.addAction( - _translate( - "MainWindow", "Set avatar..."), - self.on_action_BlacklistSetAvatar) - self.ui.tableWidgetBlacklist.setContextMenuPolicy( - QtCore.Qt.CustomContextMenu) - if connectSignal: - self.connect(self.ui.tableWidgetBlacklist, QtCore.SIGNAL( - 'customContextMenuRequested(const QPoint&)'), - self.on_context_menuBlacklist) - self.popMenuBlacklist = QtGui.QMenu(self) - # self.popMenuBlacklist.addAction( self.actionBlacklistNew ) - self.popMenuBlacklist.addAction(self.actionBlacklistDelete) - self.popMenuBlacklist.addSeparator() - self.popMenuBlacklist.addAction(self.actionBlacklistClipboard) - self.popMenuBlacklist.addSeparator() - self.popMenuBlacklist.addAction(self.actionBlacklistEnable) - self.popMenuBlacklist.addAction(self.actionBlacklistDisable) - self.popMenuBlacklist.addAction(self.actionBlacklistSetAvatar) + def rerenderTabTreeSubscriptions(self): + treeWidget = self.ui.treeWidgetSubscriptions + folders = Ui_FolderWidget.folderWeight.keys() + folders.remove("new") + + # sort ascending when creating + if treeWidget.topLevelItemCount() == 0: + treeWidget.header().setSortIndicator(0, Qt.AscendingOrder) + # init dictionary + + db = getSortedSubscriptions(True) + for address in db: + for folder in folders: + if not folder in db[address]: + db[address][folder] = {} + + if treeWidget.isSortingEnabled(): + treeWidget.setSortingEnabled(False) + + widgets = {} + i = 0 + while i < treeWidget.topLevelItemCount(): + widget = treeWidget.topLevelItem(i) + if widget is not None: + toAddress = widget.address + else: + toAddress = None + + if not toAddress in db: + treeWidget.takeTopLevelItem(i) + # no increment + continue + unread = 0 + j = 0 + while j < widget.childCount(): + subwidget = widget.child(j) + try: + subwidget.setUnreadCount(db[toAddress][subwidget.folderName]['count']) + unread += db[toAddress][subwidget.folderName]['count'] + db[toAddress].pop(subwidget.folderName, None) + except: + widget.takeChild(j) + # no increment + continue + j += 1 + + # add missing folders + if len(db[toAddress]) > 0: + j = 0 + for f, c in db[toAddress].iteritems(): + try: + subwidget = Ui_FolderWidget(widget, j, toAddress, f, c['count']) + except KeyError: + subwidget = Ui_FolderWidget(widget, j, toAddress, f, 0) + j += 1 + widget.setUnreadCount(unread) + db.pop(toAddress, None) + i += 1 + + i = 0 + for toAddress in db: + widget = Ui_SubscriptionWidget(treeWidget, i, toAddress, db[toAddress]["inbox"]['count'], db[toAddress]["inbox"]['label'], db[toAddress]["inbox"]['enabled']) + j = 0 + unread = 0 + for folder in folders: + try: + subwidget = Ui_FolderWidget(widget, j, toAddress, folder, db[toAddress][folder]['count']) + unread += db[toAddress][folder]['count'] + except KeyError: + subwidget = Ui_FolderWidget(widget, j, toAddress, folder, 0) + j += 1 + widget.setUnreadCount(unread) + i += 1 + + treeWidget.setSortingEnabled(True) + + + def rerenderTabTreeMessages(self): + self.rerenderTabTree('messages') + + def rerenderTabTreeChans(self): + self.rerenderTabTree('chan') + + def rerenderTabTree(self, tab): + if tab == 'messages': + treeWidget = self.ui.treeWidgetYourIdentities + elif tab == 'chan': + treeWidget = self.ui.treeWidgetChans + folders = Ui_FolderWidget.folderWeight.keys() + + # sort ascending when creating + if treeWidget.topLevelItemCount() == 0: + treeWidget.header().setSortIndicator(0, Qt.AscendingOrder) + # init dictionary + db = {} + enabled = {} + + for toAddress in getSortedAccounts(): + isEnabled = shared.config.getboolean( + toAddress, 'enabled') + isChan = shared.safeConfigGetBoolean( + toAddress, 'chan') + isMaillinglist = shared.safeConfigGetBoolean( + toAddress, 'mailinglist') + + if treeWidget == self.ui.treeWidgetYourIdentities: + if isChan: + continue + elif treeWidget == self.ui.treeWidgetChans: + if not isChan: + continue + + db[toAddress] = {} + for folder in folders: + db[toAddress][folder] = 0 + + enabled[toAddress] = isEnabled + + # get number of (unread) messages + total = 0 + queryreturn = sqlQuery('SELECT toaddress, folder, count(msgid) as cnt FROM inbox WHERE read = 0 GROUP BY toaddress, folder') + for row in queryreturn: + toaddress, folder, cnt = row + total += cnt + if toaddress in db and folder in db[toaddress]: + db[toaddress][folder] = cnt + if treeWidget == self.ui.treeWidgetYourIdentities: + db[None] = {} + db[None]["inbox"] = total + db[None]["new"] = total + db[None]["sent"] = 0 + db[None]["trash"] = 0 + enabled[None] = True + + if treeWidget.isSortingEnabled(): + treeWidget.setSortingEnabled(False) + + widgets = {} + i = 0 + while i < treeWidget.topLevelItemCount(): + widget = treeWidget.topLevelItem(i) + if widget is not None: + toAddress = widget.address + else: + toAddress = None + + if not toAddress in db: + treeWidget.takeTopLevelItem(i) + # no increment + continue + unread = 0 + j = 0 + while j < widget.childCount(): + subwidget = widget.child(j) + try: + subwidget.setUnreadCount(db[toAddress][subwidget.folderName]) + if subwidget.folderName not in ["new", "trash", "sent"]: + unread += db[toAddress][subwidget.folderName] + db[toAddress].pop(subwidget.folderName, None) + except: + widget.takeChild(j) + # no increment + continue + j += 1 + + # add missing folders + if len(db[toAddress]) > 0: + j = 0 + for f, c in db[toAddress].iteritems(): + subwidget = Ui_FolderWidget(widget, j, toAddress, f, c) + if subwidget.folderName not in ["new", "trash", "sent"]: + unread += c + j += 1 + widget.setUnreadCount(unread) + db.pop(toAddress, None) + i += 1 + + i = 0 + for toAddress in db: + widget = Ui_AddressWidget(treeWidget, i, toAddress, db[toAddress]["inbox"], enabled[toAddress]) + j = 0 + unread = 0 + for folder in folders: + if toAddress is not None and folder == "new": + continue + subwidget = Ui_FolderWidget(widget, j, toAddress, folder, db[toAddress][folder]) + if subwidget.folderName not in ["new", "trash", "sent"]: + unread += db[toAddress][folder] + j += 1 + widget.setUnreadCount(unread) + i += 1 + + treeWidget.setSortingEnabled(True) def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) @@ -464,20 +579,18 @@ class MyForm(QtGui.QMainWindow): # Ask the user if we may delete their old version 1 addresses if they # have any. - configSections = shared.config.sections() - for addressInKeysFile in configSections: - if addressInKeysFile != 'bitmessagesettings': - status, addressVersionNumber, streamNumber, hash = decodeAddress( - addressInKeysFile) - if addressVersionNumber == 1: - displayMsg = _translate( - "MainWindow", "One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. " - + "May we delete it now?").arg(addressInKeysFile) - reply = QtGui.QMessageBox.question( - self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) - if reply == QtGui.QMessageBox.Yes: - shared.config.remove_section(addressInKeysFile) - shared.writeKeysFile() + for addressInKeysFile in getSortedAccounts(): + status, addressVersionNumber, streamNumber, hash = decodeAddress( + addressInKeysFile) + if addressVersionNumber == 1: + displayMsg = _translate( + "MainWindow", "One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. " + + "May we delete it now?").arg(addressInKeysFile) + reply = QtGui.QMessageBox.question( + self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) + if reply == QtGui.QMessageBox.Yes: + shared.config.remove_section(addressInKeysFile) + shared.writeKeysFile() # Configure Bitmessage to start on startup (or remove the # configuration) based on the setting in the keys.dat file @@ -496,63 +609,35 @@ class MyForm(QtGui.QMainWindow): # startup for linux pass - - self.totalNumberOfBytesReceived = 0 - self.totalNumberOfBytesSent = 0 + # e.g. for editing labels + self.recurDepth = 0 + + # switch back to this when replying + self.replyFromTab = None - self.ui.labelSendBroadcastWarning.setVisible(False) - - self.timer = QtCore.QTimer() - self.timer.start(2000) # milliseconds - QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.runEveryTwoSeconds) - self.init_file_menu() self.init_inbox_popup_menu() self.init_identities_popup_menu() self.init_addressbook_popup_menu() self.init_subscriptions_popup_menu() + self.init_chan_popup_menu() self.init_sent_popup_menu() - self.init_blacklist_popup_menu() - # Initialize the user's list of addresses on the 'Your Identities' tab. - configSections = shared.config.sections() - for addressInKeysFile in configSections: - if addressInKeysFile != 'bitmessagesettings': - isEnabled = shared.config.getboolean( - addressInKeysFile, 'enabled') - newItem = QtGui.QTableWidgetItem(unicode( - shared.config.get(addressInKeysFile, 'label'), 'utf-8)')) - if not isEnabled: - newItem.setTextColor(QtGui.QColor(128, 128, 128)) - self.ui.tableWidgetYourIdentities.insertRow(0) - newItem.setIcon(avatarize(addressInKeysFile)) - self.ui.tableWidgetYourIdentities.setItem(0, 0, newItem) - newItem = QtGui.QTableWidgetItem(addressInKeysFile) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if shared.safeConfigGetBoolean(addressInKeysFile, 'chan'): - newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange - if not isEnabled: - newItem.setTextColor(QtGui.QColor(128, 128, 128)) - if shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist'): - newItem.setTextColor(QtGui.QColor(137, 04, 177)) # magenta - self.ui.tableWidgetYourIdentities.setItem(0, 1, newItem) - newItem = QtGui.QTableWidgetItem(str( - decodeAddress(addressInKeysFile)[2])) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if not isEnabled: - newItem.setTextColor(QtGui.QColor(128, 128, 128)) - self.ui.tableWidgetYourIdentities.setItem(0, 2, newItem) - if isEnabled: - status, addressVersionNumber, streamNumber, hash = decodeAddress( - addressInKeysFile) + # Initialize the user's list of addresses on the 'Chan' tab. + self.rerenderTabTreeChans() - # Load inbox from messages database file - self.loadInbox() + # Initialize the user's list of addresses on the 'Messages' tab. + self.rerenderTabTreeMessages() - # Load Sent items from database - self.loadSent() + # Set welcome message + self.ui.textEditInboxMessage.setText( + """ + Welcome to easy and secure Bitmessage + * send messages to other people + * send broadcast messages like twitter or + * discuss in chan(nel)s with other people + """ + ) # Initialize the address book self.rerenderAddressBook() @@ -562,49 +647,73 @@ class MyForm(QtGui.QMainWindow): # Initialize the inbox search QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL( - "returnPressed()"), self.inboxSearchLineEditPressed) + "returnPressed()"), self.inboxSearchLineEditReturnPressed) + QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL( + "returnPressed()"), self.inboxSearchLineEditReturnPressed) + QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL( + "returnPressed()"), self.inboxSearchLineEditReturnPressed) + QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL( + "textChanged(QString)"), self.inboxSearchLineEditUpdated) + QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL( + "textChanged(QString)"), self.inboxSearchLineEditUpdated) + QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL( + "textChanged(QString)"), self.inboxSearchLineEditUpdated) - # Initialize the sent search - QtCore.QObject.connect(self.ui.sentSearchLineEdit, QtCore.SIGNAL( - "returnPressed()"), self.sentSearchLineEditPressed) - - # Initialize the Blacklist or Whitelist - if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white': - self.ui.tabWidget.setTabText(6, 'Whitelist') - self.ui.radioButtonWhitelist.click() - self.rerenderBlackWhiteList() - - QtCore.QObject.connect(self.ui.tableWidgetYourIdentities, QtCore.SIGNAL( - "itemChanged(QTableWidgetItem *)"), self.tableWidgetYourIdentitiesItemChanged) + # Initialize addressbook QtCore.QObject.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL( "itemChanged(QTableWidgetItem *)"), self.tableWidgetAddressBookItemChanged) - QtCore.QObject.connect(self.ui.tableWidgetSubscriptions, QtCore.SIGNAL( - "itemChanged(QTableWidgetItem *)"), self.tableWidgetSubscriptionsItemChanged) + # This is necessary for the completer to work if multiple recipients + QtCore.QObject.connect(self.ui.lineEditTo, QtCore.SIGNAL( + "cursorPositionChanged(int, int)"), self.ui.lineEditTo.completer().onCursorPositionChanged) + + # show messages from message list QtCore.QObject.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL( "itemSelectionChanged ()"), self.tableWidgetInboxItemClicked) - QtCore.QObject.connect(self.ui.tableWidgetSent, QtCore.SIGNAL( - "itemSelectionChanged ()"), self.tableWidgetSentItemClicked) + QtCore.QObject.connect(self.ui.tableWidgetInboxSubscriptions, QtCore.SIGNAL( + "itemSelectionChanged ()"), self.tableWidgetInboxItemClicked) + QtCore.QObject.connect(self.ui.tableWidgetInboxChans, QtCore.SIGNAL( + "itemSelectionChanged ()"), self.tableWidgetInboxItemClicked) + + # tree address lists + QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL( + "itemSelectionChanged ()"), self.treeWidgetItemClicked) + QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL( + "itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged) + QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL( + "itemSelectionChanged ()"), self.treeWidgetItemClicked) + QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL( + "itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged) + QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL( + "itemSelectionChanged ()"), self.treeWidgetItemClicked) + QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL( + "itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged) # Put the colored icon on the status bar - # self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png")) + # self.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png")) self.statusbar = self.statusBar() - self.statusbar.insertPermanentWidget(0, self.ui.pushButtonStatusIcon) - self.ui.labelStartupTime.setText(_translate("MainWindow", "Since startup on %1").arg( - l10n.formatTimestamp())) + + self.pushButtonStatusIcon = QtGui.QPushButton(self) + self.pushButtonStatusIcon.setText('') + self.pushButtonStatusIcon.setIcon(QIcon(':/newPrefix/images/redicon.png')) + self.pushButtonStatusIcon.setFlat(True) + self.statusbar.insertPermanentWidget(0, self.pushButtonStatusIcon) + QtCore.QObject.connect(self.pushButtonStatusIcon, QtCore.SIGNAL( + "clicked()"), self.click_pushButtonStatusIcon) + self.numberOfMessagesProcessed = 0 self.numberOfBroadcastsProcessed = 0 self.numberOfPubkeysProcessed = 0 + self.unreadCount = 0 # Set the icon sizes for the identicons identicon_size = 3*7 self.ui.tableWidgetInbox.setIconSize(QtCore.QSize(identicon_size, identicon_size)) - self.ui.tableWidgetSent.setIconSize(QtCore.QSize(identicon_size, identicon_size)) - self.ui.tableWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size)) - self.ui.tableWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size)) + self.ui.treeWidgetChans.setIconSize(QtCore.QSize(identicon_size, identicon_size)) + self.ui.treeWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size)) + self.ui.treeWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.ui.tableWidgetAddressBook.setIconSize(QtCore.QSize(identicon_size, identicon_size)) - self.ui.tableWidgetBlacklist.setIconSize(QtCore.QSize(identicon_size, identicon_size)) - self.UISignalThread = UISignaler() + self.UISignalThread = UISignaler.get() QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( @@ -617,38 +726,46 @@ class MyForm(QtGui.QMainWindow): "displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewInboxMessage) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewSentMessage) - QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( - "updateNetworkStatusTab()"), self.updateNetworkStatusTab) - QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( - "updateNumberOfMessagesProcessed()"), self.updateNumberOfMessagesProcessed) - QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( - "updateNumberOfPubkeysProcessed()"), self.updateNumberOfPubkeysProcessed) - QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( - "updateNumberOfBroadcastsProcessed()"), self.updateNumberOfBroadcastsProcessed) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "setStatusIcon(PyQt_PyObject)"), self.setStatusIcon) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "changedInboxUnread(PyQt_PyObject)"), self.changedInboxUnread) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( - "rerenderInboxFromLabels()"), self.rerenderInboxFromLabels) + "rerenderMessagelistFromLabels()"), self.rerenderMessagelistFromLabels) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( - "rerenderSentToLabels()"), self.rerenderSentToLabels) + "rerenderMessgelistToLabels()"), self.rerenderMessagelistToLabels) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "rerenderAddressBook()"), self.rerenderAddressBook) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "rerenderSubscriptions()"), self.rerenderSubscriptions) - QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( - "rerenderBlackWhiteList()"), self.rerenderBlackWhiteList) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "removeInboxRowByMsgid(PyQt_PyObject)"), self.removeInboxRowByMsgid) + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "newVersionAvailable(PyQt_PyObject)"), self.newVersionAvailable) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "displayAlert(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayAlert) self.UISignalThread.start() + # Key press in tree view + self.ui.treeWidgetYourIdentities.keyPressEvent = self.treeWidgetKeyPressEvent + self.ui.treeWidgetSubscriptions.keyPressEvent = self.treeWidgetKeyPressEvent + self.ui.treeWidgetChans.keyPressEvent = self.treeWidgetKeyPressEvent + + # Key press in messagelist + self.ui.tableWidgetInbox.keyPressEvent = self.tableWidgetKeyPressEvent + self.ui.tableWidgetInboxSubscriptions.keyPressEvent = self.tableWidgetKeyPressEvent + self.ui.tableWidgetInboxChans.keyPressEvent = self.tableWidgetKeyPressEvent + + # Key press in messageview + self.ui.textEditInboxMessage.keyPressEvent = self.textEditKeyPressEvent + self.ui.textEditInboxMessageSubscriptions.keyPressEvent = self.textEditKeyPressEvent + self.ui.textEditInboxMessageChans.keyPressEvent = self.textEditKeyPressEvent + # Below this point, it would be good if all of the necessary global data # structures were initialized. self.rerenderComboBoxSendFrom() + self.rerenderComboBoxSendFromBroadcast() # Put the TTL slider in the correct spot TTL = shared.config.getint('bitmessagesettings', 'ttl') @@ -661,7 +778,9 @@ class MyForm(QtGui.QMainWindow): QtCore.QObject.connect(self.ui.horizontalSliderTTL, QtCore.SIGNAL( "valueChanged(int)"), self.updateTTL) - + + self.initSettings() + # Check to see whether we can connect to namecoin. Hide the 'Fetch Namecoin ID' button if we can't. try: options = {} @@ -674,7 +793,7 @@ class MyForm(QtGui.QMainWindow): if nc.test()[0] == 'failed': self.ui.pushButtonFetchNamecoinID.hide() except: - print 'There was a problem testing for a Namecoin daemon. Hiding the Fetch Namecoin ID button' + logger.error('There was a problem testing for a Namecoin daemon. Hiding the Fetch Namecoin ID button') self.ui.pushButtonFetchNamecoinID.hide() def updateTTL(self, sliderPosition): @@ -686,13 +805,10 @@ class MyForm(QtGui.QMainWindow): def updateHumanFriendlyTTLDescription(self, TTL): numberOfHours = int(round(TTL / (60*60))) if numberOfHours < 48: - if numberOfHours == 1: - self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "1 hour")) - else: - self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%1 hours").arg(numberOfHours)) + self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfHours)) else: numberOfDays = int(round(TTL / (24*60*60))) - self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%1 days").arg(numberOfDays)) + self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n day(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfDays)) # Show or hide the application window after clicking an item within the # tray icon or, on Windows, the try icon itself. @@ -700,13 +816,10 @@ class MyForm(QtGui.QMainWindow): if not self.actionShow.isChecked(): self.hide() else: - if sys.platform[0:3] == 'win': - self.setWindowFlags(Qt.Window) - # else: - # self.showMaximized() self.show() self.setWindowState( self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) + self.raise_() self.activateWindow() # pointer to the application @@ -723,7 +836,7 @@ class MyForm(QtGui.QMainWindow): return if not self.actionShow.isChecked(): self.actionShow.setChecked(True) - self.appIndicatorShowOrHideWindow() + self.appIndicatorShowOrHideWindow() # unchecks the show item on the application indicator def appIndicatorHide(self): @@ -781,250 +894,237 @@ class MyForm(QtGui.QMainWindow): # Show the program window and select subscriptions tab def appIndicatorSubscribe(self): self.appIndicatorShow() - self.ui.tabWidget.setCurrentIndex(4) + self.ui.tabWidget.setCurrentIndex(2) - # Show the program window and select the address book tab - def appIndicatorAddressBook(self): + # Show the program window and select channels tab + def appIndicatorChannel(self): self.appIndicatorShow() - self.ui.tabWidget.setCurrentIndex(5) - - # Load Sent items from database - def loadSent(self, where="", what=""): - what = "%" + what + "%" - if where == "To": - where = "toaddress" - elif where == "From": - where = "fromaddress" - elif where == "Subject": - where = "subject" - elif where == "Message": - where = "message" - else: - where = "toaddress || fromaddress || subject || message" - - sqlStatement = ''' - SELECT toaddress, fromaddress, subject, status, ackdata, lastactiontime - FROM sent WHERE folder="sent" AND %s LIKE ? - ORDER BY lastactiontime - ''' % (where,) - - while self.ui.tableWidgetSent.rowCount() > 0: - self.ui.tableWidgetSent.removeRow(0) - - queryreturn = sqlQuery(sqlStatement, what) - for row in queryreturn: - toAddress, fromAddress, subject, status, ackdata, lastactiontime = row - subject = shared.fixPotentiallyInvalidUTF8Data(subject) - - if shared.config.has_section(fromAddress): - fromLabel = shared.config.get(fromAddress, 'label') - else: - fromLabel = fromAddress - - toLabel = '' - queryreturn = sqlQuery( - '''select label from addressbook where address=?''', toAddress) - if queryreturn != []: + self.ui.tabWidget.setCurrentIndex(3) + + def propagateUnreadCount(self, address = None, folder = "inbox", widget = None, type = 1): + def updateUnreadCount(item): + # if refreshing the account root, we need to rescan folders + if type == 0 or (folder is None and isinstance(item, Ui_FolderWidget)): + if addressItem.type in [AccountMixin.SUBSCRIPTION, AccountMixin.MAILINGLIST]: + xAddress = "fromaddress" + else: + xAddress = "toaddress" + xFolder = folder + if isinstance(item, Ui_FolderWidget): + xFolder = item.folderName + if xFolder == "new": + xFolder = "inbox" + if addressItem.type == AccountMixin.ALL: + if xFolder: + queryreturn = sqlQuery("SELECT COUNT(*) FROM inbox WHERE folder = ? AND read = 0", xFolder) + else: + queryreturn = sqlQuery("SELECT COUNT(*) FROM inbox WHERE read = 0") + else: + if address and xFolder: + queryreturn = sqlQuery("SELECT COUNT(*) FROM inbox WHERE " + xAddress + " = ? AND folder = ? AND read = 0", address, xFolder) + elif address: + queryreturn = sqlQuery("SELECT COUNT(*) FROM inbox WHERE " + xAddress + " = ? AND read = 0", address) for row in queryreturn: - toLabel, = row - if toLabel == '': - # It might be a broadcast message. We should check for that - # label. - queryreturn = sqlQuery( - '''select label from subscriptions where address=?''', toAddress) + item.setUnreadCount(int(row[0])) + if isinstance(item, Ui_AddressWidget) and item.type == AccountMixin.ALL: + self.drawTrayIcon(self.currentTrayIconFileName, self.findInboxUnreadCount()) + elif type == 1: + item.setUnreadCount(item.unreadCount + 1) + if isinstance(item, Ui_AddressWidget) and item.type == AccountMixin.ALL: + self.drawTrayIcon(self.currentTrayIconFileName, self.findInboxUnreadCount(self.unreadCount + 1)) + elif type == -1: + item.setUnreadCount(item.unreadCount - 1) + if isinstance(item, Ui_AddressWidget) and item.type == AccountMixin.ALL: + self.drawTrayIcon(self.currentTrayIconFileName, self.findInboxUnreadCount(self.unreadCount -1)) + + widgets = [self.ui.treeWidgetYourIdentities, self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans] + for treeWidget in widgets: + root = treeWidget.invisibleRootItem() + for i in range(root.childCount()): + addressItem = root.child(i) + if addressItem.type != AccountMixin.ALL and address is not None and addressItem.data(0, QtCore.Qt.UserRole) != address: + continue + if folder not in ["trash"]: + updateUnreadCount(addressItem) + if addressItem.childCount == 0: + continue + for j in range(addressItem.childCount()): + folderItem = addressItem.child(j) + if folderItem.folderName == "new" and (folder is None or folder in ["inbox", "new"]): + updateUnreadCount(folderItem) + continue + if folder is None and folderItem.folderName != "inbox": + continue + if folder is not None and ((folder == "new" and folderItem.folderName != "inbox") or \ + (folder != "new" and folderItem.folderName != folder)): + continue + if folder in ["sent", "trash"] and folderItem.folderName != folder: + continue + updateUnreadCount(folderItem) - if queryreturn != []: - for row in queryreturn: - toLabel, = row - - if toLabel == '': - if shared.config.has_section(toAddress): - toLabel = shared.config.get(toAddress, 'label') - if toLabel == '': - toLabel = toAddress + def addMessageListItem(self, tableWidget, items): + sortingEnabled = tableWidget.isSortingEnabled() + if sortingEnabled: + tableWidget.setSortingEnabled(False) + tableWidget.insertRow(0) + for i in range(len(items)): + tableWidget.setItem(0, i, items[i]) + if sortingEnabled: + tableWidget.setSortingEnabled(True) - self.ui.tableWidgetSent.insertRow(0) - toAddressItem = QtGui.QTableWidgetItem(unicode(toLabel, 'utf-8')) - toAddressItem.setToolTip(unicode(toLabel, 'utf-8')) - toAddressItem.setIcon(avatarize(toAddress)) - toAddressItem.setData(Qt.UserRole, str(toAddress)) - toAddressItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetSent.setItem(0, 0, toAddressItem) + def addMessageListItemSent(self, tableWidget, toAddress, fromAddress, subject, status, ackdata, lastactiontime): + acct = accountClass(fromAddress) + if acct is None: + acct = BMAccount(fromAddress) + acct.parseMessage(toAddress, fromAddress, subject, "") - if fromLabel == '': - fromLabel = fromAddress - fromAddressItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8')) - fromAddressItem.setToolTip(unicode(fromLabel, 'utf-8')) - fromAddressItem.setIcon(avatarize(fromAddress)) - fromAddressItem.setData(Qt.UserRole, str(fromAddress)) - fromAddressItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetSent.setItem(0, 1, fromAddressItem) + items = [] + MessageList_AddressWidget(items, str(toAddress), unicode(acct.toLabel, 'utf-8')) + MessageList_AddressWidget(items, str(fromAddress), unicode(acct.fromLabel, 'utf-8')) + MessageList_SubjectWidget(items, str(subject), unicode(acct.subject, 'utf-8', 'replace')) - subjectItem = QtGui.QTableWidgetItem(unicode(subject, 'utf-8')) - subjectItem.setToolTip(unicode(subject, 'utf-8')) - subjectItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetSent.setItem(0, 2, subjectItem) - - if status == 'awaitingpubkey': - statusText = _translate( - "MainWindow", "Waiting for their encryption key. Will request it again soon.") - elif status == 'doingpowforpubkey': - statusText = _translate( - "MainWindow", "Encryption key request queued.") - elif status == 'msgqueued': - statusText = _translate( - "MainWindow", "Queued.") - elif status == 'msgsent': - statusText = _translate("MainWindow", "Message sent. Waiting for acknowledgement. Sent at %1").arg( - l10n.formatTimestamp(lastactiontime)) - elif status == 'msgsentnoackexpected': - statusText = _translate("MainWindow", "Message sent. Sent at %1").arg( - l10n.formatTimestamp(lastactiontime)) - elif status == 'doingmsgpow': - statusText = _translate( - "MainWindow", "Need to do work to send message. Work is queued.") - elif status == 'ackreceived': - statusText = _translate("MainWindow", "Acknowledgement of the message received %1").arg( - l10n.formatTimestamp(lastactiontime)) - elif status == 'broadcastqueued': - statusText = _translate( - "MainWindow", "Broadcast queued.") - elif status == 'broadcastsent': - statusText = _translate("MainWindow", "Broadcast on %1").arg( - l10n.formatTimestamp(lastactiontime)) - elif status == 'toodifficult': - statusText = _translate("MainWindow", "Problem: The work demanded by the recipient is more difficult than you are willing to do. %1").arg( - l10n.formatTimestamp(lastactiontime)) - elif status == 'badkey': - statusText = _translate("MainWindow", "Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1").arg( - l10n.formatTimestamp(lastactiontime)) - elif status == 'forcepow': - statusText = _translate( - "MainWindow", "Forced difficulty override. Send should start soon.") - else: - statusText = _translate("MainWindow", "Unknown status: %1 %2").arg(status).arg( - l10n.formatTimestamp(lastactiontime)) - newItem = myTableWidgetItem(statusText) - newItem.setToolTip(statusText) - newItem.setData(Qt.UserRole, QByteArray(ackdata)) - newItem.setData(33, int(lastactiontime)) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetSent.setItem(0, 3, newItem) - self.ui.tableWidgetSent.sortItems(3, Qt.DescendingOrder) - self.ui.tableWidgetSent.keyPressEvent = self.tableWidgetSentKeyPressEvent - - # Load inbox from messages database file - def loadInbox(self, where="", what=""): - what = "%" + what + "%" - if where == "To": - where = "toaddress" - elif where == "From": - where = "fromaddress" - elif where == "Subject": - where = "subject" - elif where == "Message": - where = "message" + if status == 'awaitingpubkey': + statusText = _translate( + "MainWindow", "Waiting for their encryption key. Will request it again soon.") + elif status == 'doingpowforpubkey': + statusText = _translate( + "MainWindow", "Encryption key request queued.") + elif status == 'msgqueued': + statusText = _translate( + "MainWindow", "Queued.") + elif status == 'msgsent': + statusText = _translate("MainWindow", "Message sent. Waiting for acknowledgement. Sent at %1").arg( + l10n.formatTimestamp(lastactiontime)) + elif status == 'msgsentnoackexpected': + statusText = _translate("MainWindow", "Message sent. Sent at %1").arg( + l10n.formatTimestamp(lastactiontime)) + elif status == 'doingmsgpow': + statusText = _translate( + "MainWindow", "Need to do work to send message. Work is queued.") + elif status == 'ackreceived': + statusText = _translate("MainWindow", "Acknowledgement of the message received %1").arg( + l10n.formatTimestamp(lastactiontime)) + elif status == 'broadcastqueued': + statusText = _translate( + "MainWindow", "Broadcast queued.") + elif status == 'broadcastsent': + statusText = _translate("MainWindow", "Broadcast on %1").arg( + l10n.formatTimestamp(lastactiontime)) + elif status == 'toodifficult': + statusText = _translate("MainWindow", "Problem: The work demanded by the recipient is more difficult than you are willing to do. %1").arg( + l10n.formatTimestamp(lastactiontime)) + elif status == 'badkey': + statusText = _translate("MainWindow", "Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1").arg( + l10n.formatTimestamp(lastactiontime)) + elif status == 'forcepow': + statusText = _translate( + "MainWindow", "Forced difficulty override. Send should start soon.") else: - where = "toaddress || fromaddress || subject || message" - - sqlStatement = ''' - SELECT msgid, toaddress, fromaddress, subject, received, read - FROM inbox WHERE folder="inbox" AND %s LIKE ? - ORDER BY received - ''' % (where,) - - while self.ui.tableWidgetInbox.rowCount() > 0: - self.ui.tableWidgetInbox.removeRow(0) + statusText = _translate("MainWindow", "Unknown status: %1 %2").arg(status).arg( + l10n.formatTimestamp(lastactiontime)) + newItem = myTableWidgetItem(statusText) + newItem.setToolTip(statusText) + newItem.setData(Qt.UserRole, QByteArray(ackdata)) + newItem.setData(33, int(lastactiontime)) + newItem.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + items.append(newItem) + self.addMessageListItem(tableWidget, items) + return acct + def addMessageListItemInbox(self, tableWidget, msgfolder, msgid, toAddress, fromAddress, subject, received, read): font = QFont() font.setBold(True) - queryreturn = sqlQuery(sqlStatement, what) + if toAddress == str_broadcast_subscribers: + acct = accountClass(fromAddress) + else: + acct = accountClass(toAddress) + if acct is None: + acct = accountClass(fromAddress) + if acct is None: + acct = BMAccount(fromAddress) + acct.parseMessage(toAddress, fromAddress, subject, "") + + items = [] + #to + MessageList_AddressWidget(items, toAddress, unicode(acct.toLabel, 'utf-8'), not read) + # from + MessageList_AddressWidget(items, fromAddress, unicode(acct.fromLabel, 'utf-8'), not read) + # subject + MessageList_SubjectWidget(items, str(subject), unicode(acct.subject, 'utf-8', 'replace'), not read) + # time received + time_item = myTableWidgetItem(l10n.formatTimestamp(received)) + time_item.setToolTip(l10n.formatTimestamp(received)) + time_item.setData(Qt.UserRole, QByteArray(msgid)) + time_item.setData(33, int(received)) + time_item.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + if not read: + time_item.setFont(font) + items.append(time_item) + self.addMessageListItem(tableWidget, items) + return acct + + # Load Sent items from database + def loadSent(self, tableWidget, account, where="", what=""): + if tableWidget == self.ui.tableWidgetInboxSubscriptions: + tableWidget.setColumnHidden(0, True) + tableWidget.setColumnHidden(1, False) + xAddress = 'toaddress' + elif tableWidget == self.ui.tableWidgetInboxChans: + tableWidget.setColumnHidden(0, False) + tableWidget.setColumnHidden(1, True) + xAddress = 'both' + else: + tableWidget.setColumnHidden(0, False) + if account is None: + tableWidget.setColumnHidden(1, False) + else: + tableWidget.setColumnHidden(1, True) + xAddress = 'fromaddress' + + tableWidget.setSortingEnabled(False) + tableWidget.setRowCount(0) + queryreturn = helper_search.search_sql(xAddress, account, "sent", where, what, False) + for row in queryreturn: - msgid, toAddress, fromAddress, subject, received, read = row - subject = shared.fixPotentiallyInvalidUTF8Data(subject) - try: - if toAddress == self.str_broadcast_subscribers: - toLabel = self.str_broadcast_subscribers - else: - toLabel = shared.config.get(toAddress, 'label') - except: - toLabel = '' - if toLabel == '': - toLabel = toAddress + toAddress, fromAddress, subject, status, ackdata, lastactiontime = row + self.addMessageListItemSent(tableWidget, toAddress, fromAddress, subject, status, ackdata, lastactiontime) - fromLabel = '' - if shared.config.has_section(fromAddress): - fromLabel = shared.config.get(fromAddress, 'label') - - if fromLabel == '': # If the fromAddress isn't one of our addresses and isn't a chan - queryreturn = sqlQuery( - '''select label from addressbook where address=?''', fromAddress) - if queryreturn != []: - for row in queryreturn: - fromLabel, = row + tableWidget.setSortingEnabled(False) + tableWidget.horizontalHeader().setSortIndicator(3, Qt.DescendingOrder) + tableWidget.horizontalHeaderItem(3).setText(_translate("MainWindow", "Sent", None)) - if fromLabel == '': # If this address wasn't in our address book... - queryreturn = sqlQuery( - '''select label from subscriptions where address=?''', fromAddress) - if queryreturn != []: - for row in queryreturn: - fromLabel, = row - if fromLabel == '': - fromLabel = fromAddress - - # message row - self.ui.tableWidgetInbox.insertRow(0) - # to - to_item = QtGui.QTableWidgetItem(unicode(toLabel, 'utf-8')) - to_item.setToolTip(unicode(toLabel, 'utf-8')) - to_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if not read: - to_item.setFont(font) - to_item.setData(Qt.UserRole, str(toAddress)) - if shared.safeConfigGetBoolean(toAddress, 'mailinglist'): - to_item.setTextColor(QtGui.QColor(137, 04, 177)) # magenta - if shared.safeConfigGetBoolean(str(toAddress), 'chan'): - to_item.setTextColor(QtGui.QColor(216, 119, 0)) # orange - to_item.setIcon(avatarize(toAddress)) - self.ui.tableWidgetInbox.setItem(0, 0, to_item) - # from - from_item = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8')) - from_item.setToolTip(unicode(fromLabel, 'utf-8')) - from_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if not read: - from_item.setFont(font) - from_item.setData(Qt.UserRole, str(fromAddress)) - if shared.safeConfigGetBoolean(str(fromAddress), 'chan'): - from_item.setTextColor(QtGui.QColor(216, 119, 0)) # orange - from_item.setIcon(avatarize(fromAddress)) - self.ui.tableWidgetInbox.setItem(0, 1, from_item) - # subject - subject_item = QtGui.QTableWidgetItem(unicode(subject, 'utf-8')) - subject_item.setToolTip(unicode(subject, 'utf-8')) - subject_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if not read: - subject_item.setFont(font) - self.ui.tableWidgetInbox.setItem(0, 2, subject_item) - # time received - time_item = myTableWidgetItem(l10n.formatTimestamp(received)) - time_item.setToolTip(l10n.formatTimestamp(received)) - time_item.setData(Qt.UserRole, QByteArray(msgid)) - time_item.setData(33, int(received)) - time_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if not read: - time_item.setFont(font) - self.ui.tableWidgetInbox.setItem(0, 3, time_item) + # Load messages from database file + def loadMessagelist(self, tableWidget, account, folder="inbox", where="", what="", unreadOnly = False): + if folder == 'sent': + self.loadSent(tableWidget, account, where, what) + return - self.ui.tableWidgetInbox.sortItems(3, Qt.DescendingOrder) - self.ui.tableWidgetInbox.keyPressEvent = self.tableWidgetInboxKeyPressEvent + if tableWidget == self.ui.tableWidgetInboxSubscriptions: + xAddress = "fromaddress" + else: + xAddress = "toaddress" + if account is not None: + tableWidget.setColumnHidden(0, True) + tableWidget.setColumnHidden(1, False) + else: + tableWidget.setColumnHidden(0, False) + tableWidget.setColumnHidden(1, False) + + tableWidget.setSortingEnabled(False) + tableWidget.setRowCount(0) + + queryreturn = helper_search.search_sql(xAddress, account, folder, where, what, unreadOnly) + + for row in queryreturn: + msgfolder, msgid, toAddress, fromAddress, subject, received, read = row + self.addMessageListItemInbox(tableWidget, msgfolder, msgid, toAddress, fromAddress, subject, received, read) + + tableWidget.horizontalHeader().setSortIndicator(3, Qt.DescendingOrder) + tableWidget.setSortingEnabled(True) + tableWidget.selectRow(0) + tableWidget.horizontalHeaderItem(3).setText(_translate("MainWindow", "Received", None)) # create application indicator def appIndicatorInit(self, app): @@ -1065,11 +1165,11 @@ class MyForm(QtGui.QMainWindow): actionSubscribe.triggered.connect(self.appIndicatorSubscribe) m.addAction(actionSubscribe) - # Address book - actionAddressBook = QtGui.QAction(_translate( - "MainWindow", "Address Book"), m, checkable=False) - actionAddressBook.triggered.connect(self.appIndicatorAddressBook) - m.addAction(actionAddressBook) + # Channels + actionSubscribe = QtGui.QAction(_translate( + "MainWindow", "Channel"), m, checkable=False) + actionSubscribe.triggered.connect(self.appIndicatorChannel) + m.addAction(actionSubscribe) # separator actionSeparator = QtGui.QAction('', m, checkable=False) @@ -1115,7 +1215,7 @@ class MyForm(QtGui.QMainWindow): for row in queryreturn: toAddress, read = row if not read: - if toAddress == self.str_broadcast_subscribers: + if toAddress == str_broadcast_subscribers: if self.mmapp.has_source("Subscriptions"): self.mmapp.remove_source("Subscriptions") else: @@ -1133,8 +1233,8 @@ class MyForm(QtGui.QMainWindow): msgid, toAddress, read = row try: - if toAddress == self.str_broadcast_subscribers: - toLabel = self.str_broadcast_subscribers + if toAddress == str_broadcast_subscribers: + toLabel = str_broadcast_subscribers else: toLabel = shared.config.get(toAddress, 'label') except: @@ -1143,7 +1243,7 @@ class MyForm(QtGui.QMainWindow): toLabel = toAddress if not read: - if toLabel == self.str_broadcast_subscribers: + if toLabel == str_broadcast_subscribers: # increment the unread subscriptions unreadSubscriptions = unreadSubscriptions + 1 else: @@ -1179,7 +1279,7 @@ class MyForm(QtGui.QMainWindow): # has messageing menu been installed if not withMessagingMenu: - print 'WARNING: MessagingMenu is not available. Is libmessaging-menu-dev installed?' + logger.warning('WARNING: MessagingMenu is not available. Is libmessaging-menu-dev installed?') return # create the menu server @@ -1192,7 +1292,7 @@ class MyForm(QtGui.QMainWindow): self.ubuntuMessagingMenuUnread(True) except Exception: withMessagingMenu = False - print 'WARNING: messaging menu disabled' + logger.warning('WARNING: messaging menu disabled') # update the Ubuntu messaging menu def ubuntuMessagingMenuUpdate(self, drawAttention, newItem, toLabel): @@ -1204,11 +1304,11 @@ class MyForm(QtGui.QMainWindow): # has messageing menu been installed if not withMessagingMenu: - print 'WARNING: messaging menu disabled or libmessaging-menu-dev not installed' + logger.warning('WARNING: messaging menu disabled or libmessaging-menu-dev not installed') return # remember this item to that the messaging menu can find it - if toLabel == self.str_broadcast_subscribers: + if toLabel == str_broadcast_subscribers: self.newBroadcastItem = newItem else: self.newMessageItem = newItem @@ -1298,7 +1398,7 @@ class MyForm(QtGui.QMainWindow): stdout=subprocess.PIPE) gst_available=True except: - print "WARNING: gst123 must be installed in order to play mp3 sounds" + logger.warning("WARNING: gst123 must be installed in order to play mp3 sounds") if not gst_available: try: subprocess.call(["mpg123", soundFilename], @@ -1306,14 +1406,14 @@ class MyForm(QtGui.QMainWindow): stdout=subprocess.PIPE) gst_available=True except: - print "WARNING: mpg123 must be installed in order to play mp3 sounds" + logger.warning("WARNING: mpg123 must be installed in order to play mp3 sounds") else: try: subprocess.call(["aplay", soundFilename], stdin=subprocess.PIPE, stdout=subprocess.PIPE) except: - print "WARNING: aplay must be installed in order to play WAV sounds" + logger.warning("WARNING: aplay must be installed in order to play WAV sounds") elif sys.platform[0:3] == 'win': # use winsound on Windows import winsound @@ -1346,16 +1446,68 @@ class MyForm(QtGui.QMainWindow): else: self.tray.showMessage(title, subtitle, 1, 2000) - def tableWidgetInboxKeyPressEvent(self, event): - if event.key() == QtCore.Qt.Key_Delete: - self.on_action_InboxTrash() - return QtGui.QTableWidget.keyPressEvent(self.ui.tableWidgetInbox, event) + # tree + def treeWidgetKeyPressEvent(self, event): + return self.handleKeyPress(event, self.getCurrentTreeWidget()) - def tableWidgetSentKeyPressEvent(self, event): - if event.key() == QtCore.Qt.Key_Delete: - self.on_action_SentTrash() - return QtGui.QTableWidget.keyPressEvent(self.ui.tableWidgetSent, event) + # inbox / sent + def tableWidgetKeyPressEvent(self, event): + return self.handleKeyPress(event, self.getCurrentMessagelist()) + # messageview + def textEditKeyPressEvent(self, event): + return self.handleKeyPress(event, self.getCurrentMessageTextedit()) + + def handleKeyPress(self, event, focus = None): + messagelist = self.getCurrentMessagelist() + folder = self.getCurrentFolder() + if event.key() == QtCore.Qt.Key_Delete: + if isinstance (focus, MessageView) or isinstance(focus, QtGui.QTableWidget): + if folder == "sent": + self.on_action_SentTrash() + else: + self.on_action_InboxTrash() + event.ignore() + elif QtGui.QApplication.queryKeyboardModifiers() == QtCore.Qt.NoModifier: + if event.key() == QtCore.Qt.Key_N: + currentRow = messagelist.currentRow() + if currentRow < messagelist.rowCount() - 1: + messagelist.selectRow(currentRow + 1) + event.ignore() + elif event.key() == QtCore.Qt.Key_P: + currentRow = messagelist.currentRow() + if currentRow > 0: + messagelist.selectRow(currentRow - 1) + event.ignore() + elif event.key() == QtCore.Qt.Key_R: + if messagelist == self.ui.tableWidgetInboxChans: + self.on_action_InboxReplyChan() + else: + self.on_action_InboxReply() + event.ignore() + elif event.key() == QtCore.Qt.Key_C: + currentAddress = self.getCurrentAccount() + if currentAddress: + self.setSendFromComboBox(currentAddress) + self.ui.tabWidgetSend.setCurrentIndex(0) + self.ui.tabWidget.setCurrentIndex(1) + self.ui.lineEditTo.setFocus() + event.ignore() + elif event.key() == QtCore.Qt.Key_F: + searchline = self.getCurrentSearchLine(retObj = True) + if searchline: + searchline.setFocus() + event.ignore() + if not event.isAccepted(): + return + if isinstance (focus, MessageView): + return MessageView.keyPressEvent(focus, event) + elif isinstance (focus, QtGui.QTableWidget): + return QtGui.QTableWidget.keyPressEvent(focus, event) + elif isinstance (focus, QtGui.QTreeWidget): + return QtGui.QTreeWidget.keyPressEvent(focus, event) + + # menu button 'manage keys' def click_actionManageKeys(self): if 'darwin' in sys.platform or 'linux' in sys.platform: if shared.appdata == '': @@ -1379,11 +1531,23 @@ class MyForm(QtGui.QMainWindow): if reply == QtGui.QMessageBox.Yes: shared.openKeysFile() + # menu button 'delete all treshed messages' def click_actionDeleteAllTrashedMessages(self): if QtGui.QMessageBox.question(self, _translate("MainWindow", "Delete trash?"), _translate("MainWindow", "Are you sure you want to delete all trashed messages?"), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) == QtGui.QMessageBox.No: return sqlStoredProcedure('deleteandvacuume') + self.rerenderTabTreeMessages() + self.rerenderTabTreeSubscriptions() + self.rerenderTabTreeChans() + if self.getCurrentFolder(self.ui.treeWidgetYourIdentities) == "trash": + self.loadMessagelist(self.ui.tableWidgetInbox, self.getCurrentAccount(self.ui.treeWidgetYourIdentities), "trash") + elif self.getCurrentFolder(self.ui.treeWidgetSubscriptions) == "trash": + self.loadMessagelist(self.ui.tableWidgetInboxSubscriptions, self.getCurrentAccount(self.ui.treeWidgetSubscriptions), "trash") + elif self.getCurrentFolder(self.ui.treeWidgetChans) == "trash": + self.loadMessagelist(self.ui.tableWidgetInboxChans, self.getCurrentAccount(self.ui.treeWidgetChans), "trash") + + # menu botton 'regenerate deterministic addresses' def click_actionRegenerateDeterministicAddresses(self): self.regenerateAddressesDialogInstance = regenerateAddressesDialog( self) @@ -1409,6 +1573,7 @@ class MyForm(QtGui.QMainWindow): ), self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(), self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked())) self.ui.tabWidget.setCurrentIndex(3) + # opens 'join chan' dialog def click_actionJoinChan(self): self.newChanDialogInstance = newChanDialog(self) if self.newChanDialogInstance.exec_(): @@ -1420,7 +1585,7 @@ class MyForm(QtGui.QMainWindow): shared.apiAddressGeneratorReturnQueue.queue.clear() shared.addressGeneratorQueue.put(('createChan', 4, 1, self.str_chan + ' ' + str(self.newChanDialogInstance.ui.lineEditChanNameCreate.text().toUtf8()), self.newChanDialogInstance.ui.lineEditChanNameCreate.text().toUtf8())) addressGeneratorReturnValue = shared.apiAddressGeneratorReturnQueue.get() - print 'addressGeneratorReturnValue', addressGeneratorReturnValue + logger.debug('addressGeneratorReturnValue ' + str(addressGeneratorReturnValue)) if len(addressGeneratorReturnValue) == 0: QMessageBox.about(self, _translate("MainWindow", "Address already present"), _translate( "MainWindow", "Could not add chan because it appears to already be one of your identities.")) @@ -1445,7 +1610,7 @@ class MyForm(QtGui.QMainWindow): shared.apiAddressGeneratorReturnQueue.queue.clear() shared.addressGeneratorQueue.put(('joinChan', addBMIfNotPresent(self.newChanDialogInstance.ui.lineEditChanBitmessageAddress.text()), self.str_chan + ' ' + str(self.newChanDialogInstance.ui.lineEditChanNameJoin.text().toUtf8()), self.newChanDialogInstance.ui.lineEditChanNameJoin.text().toUtf8())) addressGeneratorReturnValue = shared.apiAddressGeneratorReturnQueue.get() - print 'addressGeneratorReturnValue', addressGeneratorReturnValue + logger.debug('addressGeneratorReturnValue ' + str(addressGeneratorReturnValue)) if addressGeneratorReturnValue == 'chan name does not match address': QMessageBox.about(self, _translate("MainWindow", "Address does not match chan name"), _translate( "MainWindow", "Although the Bitmessage address you entered was valid, it doesn\'t match the chan name.")) @@ -1458,6 +1623,7 @@ class MyForm(QtGui.QMainWindow): QMessageBox.about(self, _translate("MainWindow", "Success"), _translate( "MainWindow", "Successfully joined chan. ")) self.ui.tabWidget.setCurrentIndex(3) + self.rerenderAddressBook() def showConnectDialog(self): self.connectDialogInstance = connectDialog(self) @@ -1468,21 +1634,27 @@ class MyForm(QtGui.QMainWindow): else: self.click_actionSettings() + def showMigrationWizard(self, level): + self.migrationWizardInstance = Ui_MigrationWizard(["a"]) + if self.migrationWizardInstance.exec_(): + pass + else: + pass + def changeEvent(self, event): if event.type() == QtCore.QEvent.LanguageChange: self.ui.retranslateUi(self) self.init_inbox_popup_menu(False) self.init_identities_popup_menu(False) + self.init_chan_popup_menu(False) self.init_addressbook_popup_menu(False) self.init_subscriptions_popup_menu(False) self.init_sent_popup_menu(False) - self.init_blacklist_popup_menu(False) + self.ui.blackwhitelist.init_blacklist_popup_menu(False) if event.type() == QtCore.QEvent.WindowStateChange: if self.windowState() & QtCore.Qt.WindowMinimized: if shared.config.getboolean('bitmessagesettings', 'minimizetotray') and not 'darwin' in sys.platform: - self.appIndicatorHide() - if 'win32' in sys.platform or 'win64' in sys.platform: - self.setWindowFlags(Qt.ToolTip) + QTimer.singleShot(0, self.appIndicatorHide) elif event.oldState() & QtCore.Qt.WindowMinimized: # The window state has just been changed to # Normal/Maximised/FullScreen @@ -1495,98 +1667,6 @@ class MyForm(QtGui.QMainWindow): self.actionShow.setChecked(not self.actionShow.isChecked()) self.appIndicatorShowOrHideWindow() - def updateNumberOfMessagesProcessed(self): - self.ui.labelMessageCount.setText(_translate( - "MainWindow", "Processed %1 person-to-person messages.").arg(str(shared.numberOfMessagesProcessed))) - - def updateNumberOfBroadcastsProcessed(self): - self.ui.labelBroadcastCount.setText(_translate( - "MainWindow", "Processed %1 broadcast messages.").arg(str(shared.numberOfBroadcastsProcessed))) - - def updateNumberOfPubkeysProcessed(self): - self.ui.labelPubkeyCount.setText(_translate( - "MainWindow", "Processed %1 public keys.").arg(str(shared.numberOfPubkeysProcessed))) - - def formatBytes(self, num): - for x in ['bytes','KB','MB','GB']: - if num < 1000.0: - return "%3.0f %s" % (num, x) - num /= 1000.0 - return "%3.0f %s" % (num, 'TB') - - def formatByteRate(self, num): - num /= 1000 - return "%4.0f KB" % num - - def updateNumberOfBytes(self): - """ - This function is run every two seconds, so we divide the rate of bytes - sent and received by 2. - """ - self.ui.labelBytesRecvCount.setText(_translate( - "MainWindow", "Down: %1/s Total: %2").arg(self.formatByteRate(shared.numberOfBytesReceived/2), self.formatBytes(self.totalNumberOfBytesReceived))) - self.ui.labelBytesSentCount.setText(_translate( - "MainWindow", "Up: %1/s Total: %2").arg(self.formatByteRate(shared.numberOfBytesSent/2), self.formatBytes(self.totalNumberOfBytesSent))) - self.totalNumberOfBytesReceived += shared.numberOfBytesReceived - self.totalNumberOfBytesSent += shared.numberOfBytesSent - shared.numberOfBytesReceived = 0 - shared.numberOfBytesSent = 0 - - def updateNetworkStatusTab(self): - # print 'updating network status tab' - totalNumberOfConnectionsFromAllStreams = 0 # One would think we could use len(sendDataQueues) for this but the number doesn't always match: just because we have a sendDataThread running doesn't mean that the connection has been fully established (with the exchange of version messages). - streamNumberTotals = {} - for host, streamNumber in shared.connectedHostsList.items(): - if not streamNumber in streamNumberTotals: - streamNumberTotals[streamNumber] = 1 - else: - streamNumberTotals[streamNumber] += 1 - - while self.ui.tableWidgetConnectionCount.rowCount() > 0: - self.ui.tableWidgetConnectionCount.removeRow(0) - for streamNumber, connectionCount in streamNumberTotals.items(): - self.ui.tableWidgetConnectionCount.insertRow(0) - if streamNumber == 0: - newItem = QtGui.QTableWidgetItem("?") - else: - newItem = QtGui.QTableWidgetItem(str(streamNumber)) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetConnectionCount.setItem(0, 0, newItem) - newItem = QtGui.QTableWidgetItem(str(connectionCount)) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetConnectionCount.setItem(0, 1, newItem) - """for currentRow in range(self.ui.tableWidgetConnectionCount.rowCount()): - rowStreamNumber = int(self.ui.tableWidgetConnectionCount.item(currentRow,0).text()) - if streamNumber == rowStreamNumber: - foundTheRowThatNeedsUpdating = True - self.ui.tableWidgetConnectionCount.item(currentRow,1).setText(str(connectionCount)) - #totalNumberOfConnectionsFromAllStreams += connectionCount - if foundTheRowThatNeedsUpdating == False: - #Add a line to the table for this stream number and update its count with the current connection count. - self.ui.tableWidgetConnectionCount.insertRow(0) - newItem = QtGui.QTableWidgetItem(str(streamNumber)) - newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) - self.ui.tableWidgetConnectionCount.setItem(0,0,newItem) - newItem = QtGui.QTableWidgetItem(str(connectionCount)) - newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) - self.ui.tableWidgetConnectionCount.setItem(0,1,newItem) - totalNumberOfConnectionsFromAllStreams += connectionCount""" - self.ui.labelTotalConnections.setText(_translate( - "MainWindow", "Total Connections: %1").arg(str(len(shared.connectedHostsList)))) - if len(shared.connectedHostsList) > 0 and shared.statusIconColor == 'red': # FYI: The 'singlelistener' thread sets the icon color to green when it receives an incoming connection, meaning that the user's firewall is configured correctly. - self.setStatusIcon('yellow') - elif len(shared.connectedHostsList) == 0: - self.setStatusIcon('red') - - # timer driven - def runEveryTwoSeconds(self): - self.ui.labelLookupsPerSecond.setText(_translate( - "MainWindow", "Inventory lookups per second: %1").arg(str(shared.numberOfInventoryLookupsPerformed/2))) - shared.numberOfInventoryLookupsPerformed = 0 - self.updateNumberOfBytes() - # Indicates whether or not there is a connection to the Bitmessage network connected = False @@ -1594,7 +1674,7 @@ class MyForm(QtGui.QMainWindow): global withMessagingMenu # print 'setting status icon color' if color == 'red': - self.ui.pushButtonStatusIcon.setIcon( + self.pushButtonStatusIcon.setIcon( QIcon(":/newPrefix/images/redicon.png")) shared.statusIconColor = 'red' # if the connection is lost then show a notification @@ -1611,7 +1691,7 @@ class MyForm(QtGui.QMainWindow): if color == 'yellow': if self.statusBar().currentMessage() == 'Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won\'t send until you connect.': self.statusBar().showMessage('') - self.ui.pushButtonStatusIcon.setIcon(QIcon( + self.pushButtonStatusIcon.setIcon(QIcon( ":/newPrefix/images/yellowicon.png")) shared.statusIconColor = 'yellow' # if a new connection has been established then show a notification @@ -1628,7 +1708,7 @@ class MyForm(QtGui.QMainWindow): if color == 'green': if self.statusBar().currentMessage() == 'Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won\'t send until you connect.': self.statusBar().showMessage('') - self.ui.pushButtonStatusIcon.setIcon( + self.pushButtonStatusIcon.setIcon( QIcon(":/newPrefix/images/greenicon.png")) shared.statusIconColor = 'green' if not self.connected: @@ -1684,60 +1764,87 @@ class MyForm(QtGui.QMainWindow): def drawTrayIcon(self, iconFileName, inboxUnreadCount): self.tray.setIcon(self.calcTrayIcon(iconFileName, inboxUnreadCount)) - def changedInboxUnread(self): + def changedInboxUnread(self, row = None): self.drawTrayIcon(self.currentTrayIconFileName, self.findInboxUnreadCount()) + self.rerenderTabTreeMessages() + self.rerenderTabTreeSubscriptions() + self.rerenderTabTreeChans() - def findInboxUnreadCount(self): - queryreturn = sqlQuery('''SELECT count(*) from inbox WHERE folder='inbox' and read=0''') - cnt = 0 - for row in queryreturn: - cnt, = row - return int(cnt) + def findInboxUnreadCount(self, count = None): + if count is None: + queryreturn = sqlQuery('''SELECT count(*) from inbox WHERE folder='inbox' and read=0''') + cnt = 0 + for row in queryreturn: + cnt, = row + self.unreadCount = int(cnt) + else: + self.unreadCount = count + return self.unreadCount def updateSentItemStatusByToAddress(self, toAddress, textToDisplay): - for i in range(self.ui.tableWidgetSent.rowCount()): - rowAddress = str(self.ui.tableWidgetSent.item( - i, 0).data(Qt.UserRole).toPyObject()) - if toAddress == rowAddress: - self.ui.tableWidgetSent.item(i, 3).setToolTip(textToDisplay) - try: - newlinePosition = textToDisplay.indexOf('\n') - except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception. - newlinePosition = 0 - if newlinePosition > 1: - self.ui.tableWidgetSent.item(i, 3).setText( - textToDisplay[:newlinePosition]) - else: - self.ui.tableWidgetSent.item(i, 3).setText(textToDisplay) + for sent in [self.ui.tableWidgetInbox, self.ui.tableWidgetInboxSubscriptions, self.ui.tableWidgetInboxChans]: + treeWidget = self.widgetConvert(sent) + if self.getCurrentFolder(treeWidget) != "sent": + continue + if treeWidget in [self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans] and self.getCurrentAccount(treeWidget) != toAddress: + continue + + for i in range(sent.rowCount()): + rowAddress = sent.item( + i, 0).data(Qt.UserRole) + if toAddress == rowAddress: + sent.item(i, 3).setToolTip(textToDisplay) + try: + newlinePosition = textToDisplay.indexOf('\n') + except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception. + newlinePosition = 0 + if newlinePosition > 1: + sent.item(i, 3).setText( + textToDisplay[:newlinePosition]) + else: + sent.item(i, 3).setText(textToDisplay) def updateSentItemStatusByAckdata(self, ackdata, textToDisplay): - for i in range(self.ui.tableWidgetSent.rowCount()): - toAddress = str(self.ui.tableWidgetSent.item( - i, 0).data(Qt.UserRole).toPyObject()) - tableAckdata = self.ui.tableWidgetSent.item( - i, 3).data(Qt.UserRole).toPyObject() - status, addressVersionNumber, streamNumber, ripe = decodeAddress( - toAddress) - if ackdata == tableAckdata: - self.ui.tableWidgetSent.item(i, 3).setToolTip(textToDisplay) - try: - newlinePosition = textToDisplay.indexOf('\n') - except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception. - newlinePosition = 0 - if newlinePosition > 1: - self.ui.tableWidgetSent.item(i, 3).setText( - textToDisplay[:newlinePosition]) - else: - self.ui.tableWidgetSent.item(i, 3).setText(textToDisplay) + for sent in [self.ui.tableWidgetInbox, self.ui.tableWidgetInboxSubscriptions, self.ui.tableWidgetInboxChans]: + treeWidget = self.widgetConvert(sent) + if self.getCurrentFolder(treeWidget) != "sent": + continue + for i in range(sent.rowCount()): + toAddress = sent.item( + i, 0).data(Qt.UserRole) + tableAckdata = sent.item( + i, 3).data(Qt.UserRole).toPyObject() + status, addressVersionNumber, streamNumber, ripe = decodeAddress( + toAddress) + if ackdata == tableAckdata: + sent.item(i, 3).setToolTip(textToDisplay) + try: + newlinePosition = textToDisplay.indexOf('\n') + except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception. + newlinePosition = 0 + if newlinePosition > 1: + sent.item(i, 3).setText( + textToDisplay[:newlinePosition]) + else: + sent.item(i, 3).setText(textToDisplay) def removeInboxRowByMsgid(self, msgid): # msgid and inventoryHash are the same thing - for i in range(self.ui.tableWidgetInbox.rowCount()): - if msgid == str(self.ui.tableWidgetInbox.item(i, 3).data(Qt.UserRole).toPyObject()): - self.statusBar().showMessage(_translate( - "MainWindow", "Message trashed")) - self.ui.tableWidgetInbox.removeRow(i) - break - self.changedInboxUnread() + for inbox in ([ + self.ui.tableWidgetInbox, + self.ui.tableWidgetInboxSubscriptions, + self.ui.tableWidgetInboxChans]): + for i in range(inbox.rowCount()): + if msgid == str(inbox.item(i, 3).data(Qt.UserRole).toPyObject()): + self.statusBar().showMessage(_translate( + "MainWindow", "Message trashed")) + treeWidget = self.widgetConvert(inbox) + self.propagateUnreadCount(inbox.item(i, 1 if inbox.item(i, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), self.getCurrentFolder(treeWidget), treeWidget, 0) + inbox.removeRow(i) + break + + def newVersionAvailable(self, version): + self.notifiedNewVersion = ".".join(str(n) for n in version) + self.statusBar().showMessage(_translate("MainWindow", "New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest").arg(self.notifiedNewVersion)) def displayAlert(self, title, text, exitAfterUserClicksOk): self.statusBar().showMessage(text) @@ -1745,171 +1852,101 @@ class MyForm(QtGui.QMainWindow): if exitAfterUserClicksOk: os._exit(0) - def rerenderInboxFromLabels(self): - for i in range(self.ui.tableWidgetInbox.rowCount()): - addressToLookup = str(self.ui.tableWidgetInbox.item( - i, 1).data(Qt.UserRole).toPyObject()) - fromLabel = '' - queryreturn = sqlQuery( - '''select label from addressbook where address=?''', addressToLookup) + def rerenderMessagelistFromLabels(self): + for messagelist in (self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans, self.ui.tableWidgetInboxSubscriptions): + for i in range(messagelist.rowCount()): + messagelist.item(i, 1).setLabel() - if queryreturn != []: - for row in queryreturn: - fromLabel, = row - - if fromLabel == '': - # It might be a broadcast message. We should check for that - # label. - queryreturn = sqlQuery( - '''select label from subscriptions where address=?''', addressToLookup) - - if queryreturn != []: - for row in queryreturn: - fromLabel, = row - if fromLabel == '': - # Message might be from an address we own like a chan address. Let's look for that label. - if shared.config.has_section(addressToLookup): - fromLabel = shared.config.get(addressToLookup, 'label') - if fromLabel == '': - fromLabel = addressToLookup - self.ui.tableWidgetInbox.item( - i, 1).setText(unicode(fromLabel, 'utf-8')) - self.ui.tableWidgetInbox.item( - i, 1).setIcon(avatarize(addressToLookup)) - # Set the color according to whether it is the address of a mailing - # list or not. - if shared.safeConfigGetBoolean(addressToLookup, 'chan'): - self.ui.tableWidgetInbox.item(i, 1).setTextColor(QtGui.QColor(216, 119, 0)) # orange - else: - self.ui.tableWidgetInbox.item( - i, 1).setTextColor(QApplication.palette().text().color()) - - - def rerenderInboxToLabels(self): - for i in range(self.ui.tableWidgetInbox.rowCount()): - toAddress = str(self.ui.tableWidgetInbox.item( - i, 0).data(Qt.UserRole).toPyObject()) - # Message might be to an address we own like a chan address. Let's look for that label. - if shared.config.has_section(toAddress): - toLabel = shared.config.get(toAddress, 'label') - else: - toLabel = toAddress - self.ui.tableWidgetInbox.item( - i, 0).setText(unicode(toLabel, 'utf-8')) - self.ui.tableWidgetInbox.item( - i, 0).setIcon(avatarize(toAddress)) - # Set the color according to whether it is the address of a mailing - # list, a chan or neither. - if shared.safeConfigGetBoolean(toAddress, 'chan'): - self.ui.tableWidgetInbox.item(i, 0).setTextColor(QtGui.QColor(216, 119, 0)) # orange - elif shared.safeConfigGetBoolean(toAddress, 'mailinglist'): - self.ui.tableWidgetInbox.item(i, 0).setTextColor(QtGui.QColor(137, 04, 177)) # magenta - else: - self.ui.tableWidgetInbox.item( - i, 0).setTextColor(QApplication.palette().text().color()) - - def rerenderSentFromLabels(self): - for i in range(self.ui.tableWidgetSent.rowCount()): - fromAddress = str(self.ui.tableWidgetSent.item( - i, 1).data(Qt.UserRole).toPyObject()) - # Message might be from an address we own like a chan address. Let's look for that label. - if shared.config.has_section(fromAddress): - fromLabel = shared.config.get(fromAddress, 'label') - else: - fromLabel = fromAddress - self.ui.tableWidgetSent.item( - i, 1).setText(unicode(fromLabel, 'utf-8')) - self.ui.tableWidgetSent.item( - i, 1).setIcon(avatarize(fromAddress)) - - def rerenderSentToLabels(self): - for i in range(self.ui.tableWidgetSent.rowCount()): - addressToLookup = str(self.ui.tableWidgetSent.item( - i, 0).data(Qt.UserRole).toPyObject()) - toLabel = '' - queryreturn = sqlQuery( - '''select label from addressbook where address=?''', addressToLookup) - if queryreturn != []: - for row in queryreturn: - toLabel, = row - - if toLabel == '': - # Message might be to an address we own like a chan address. Let's look for that label. - if shared.config.has_section(addressToLookup): - toLabel = shared.config.get(addressToLookup, 'label') - if toLabel == '': - toLabel = addressToLookup - self.ui.tableWidgetSent.item( - i, 0).setText(unicode(toLabel, 'utf-8')) + def rerenderMessagelistToLabels(self): + for messagelist in (self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans, self.ui.tableWidgetInboxSubscriptions): + for i in range(messagelist.rowCount()): + messagelist.item(i, 0).setLabel() def rerenderAddressBook(self): - self.ui.tableWidgetAddressBook.setRowCount(0) + def addRow (address, label, type): + self.ui.tableWidgetAddressBook.insertRow(0) + newItem = Ui_AddressBookWidgetItemLabel(address, unicode(label, 'utf-8'), type) + self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) + newItem = Ui_AddressBookWidgetItemAddress(address, unicode(label, 'utf-8'), type) + self.ui.tableWidgetAddressBook.setItem(0, 1, newItem) + + oldRows = {} + for i in range(self.ui.tableWidgetAddressBook.rowCount()): + item = self.ui.tableWidgetAddressBook.item(i, 0) + oldRows[item.address] = [item.label, item.type, i] + + if self.ui.tableWidgetAddressBook.rowCount() == 0: + self.ui.tableWidgetAddressBook.horizontalHeader().setSortIndicator(0, Qt.AscendingOrder) + if self.ui.tableWidgetAddressBook.isSortingEnabled(): + self.ui.tableWidgetAddressBook.setSortingEnabled(False) + + newRows = {} + # subscriptions + queryreturn = sqlQuery('SELECT label, address FROM subscriptions WHERE enabled = 1') + for row in queryreturn: + label, address = row + newRows[address] = [label, AccountMixin.SUBSCRIPTION] + # chans + addresses = getSortedAccounts() + for address in addresses: + account = accountClass(address) + if (account.type == AccountMixin.CHAN and shared.safeConfigGetBoolean(address, 'enabled')): + newRows[address] = [account.getLabel(), AccountMixin.CHAN] + # normal accounts queryreturn = sqlQuery('SELECT * FROM addressbook') for row in queryreturn: label, address = row - self.ui.tableWidgetAddressBook.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) - newItem.setIcon(avatarize(address)) - self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) - newItem = QtGui.QTableWidgetItem(address) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetAddressBook.setItem(0, 1, newItem) + newRows[address] = [label, AccountMixin.NORMAL] + + completerList = [] + for address in sorted(oldRows, key = lambda x: oldRows[x][2], reverse = True): + if address in newRows: + completerList.append(unicode(newRows[address][0], encoding="UTF-8") + " <" + address + ">") + newRows.pop(address) + else: + self.ui.tableWidgetAddressBook.removeRow(oldRows[address][2]) + for address in newRows: + addRow(address, newRows[address][0], newRows[address][1]) + completerList.append(unicode(newRows[address][0], encoding="UTF-8") + " <" + address + ">") + + # sort + self.ui.tableWidgetAddressBook.sortByColumn(0, Qt.AscendingOrder) + self.ui.tableWidgetAddressBook.setSortingEnabled(True) + self.ui.lineEditTo.completer().model().setStringList(completerList) def rerenderSubscriptions(self): - self.ui.tableWidgetSubscriptions.setRowCount(0) - queryreturn = sqlQuery('SELECT label, address, enabled FROM subscriptions') - for row in queryreturn: - label, address, enabled = row - self.ui.tableWidgetSubscriptions.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) - if not enabled: - newItem.setTextColor(QtGui.QColor(128, 128, 128)) - newItem.setIcon(avatarize(address)) - self.ui.tableWidgetSubscriptions.setItem(0, 0, newItem) - newItem = QtGui.QTableWidgetItem(address) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if not enabled: - newItem.setTextColor(QtGui.QColor(128, 128, 128)) - self.ui.tableWidgetSubscriptions.setItem(0, 1, newItem) + self.rerenderTabTreeSubscriptions() - def rerenderBlackWhiteList(self): - self.ui.tableWidgetBlacklist.setRowCount(0) - listType = shared.config.get('bitmessagesettings', 'blackwhitelist') - if listType == 'black': - queryreturn = sqlQuery('''SELECT label, address, enabled FROM blacklist''') - else: - queryreturn = sqlQuery('''SELECT label, address, enabled FROM whitelist''') - for row in queryreturn: - label, address, enabled = row - self.ui.tableWidgetBlacklist.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) - if not enabled: - newItem.setTextColor(QtGui.QColor(128, 128, 128)) - newItem.setIcon(avatarize(address)) - self.ui.tableWidgetBlacklist.setItem(0, 0, newItem) - newItem = QtGui.QTableWidgetItem(address) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if not enabled: - newItem.setTextColor(QtGui.QColor(128, 128, 128)) - self.ui.tableWidgetBlacklist.setItem(0, 1, newItem) def click_pushButtonTTL(self): QtGui.QMessageBox.information(self, 'Time To Live', _translate( - "MainWindow", "The TTL, or Time-To-Live is the length of time that the network will hold the message. \ -The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it \ -will resend the message automatically. The longer the Time-To-Live, the \ -more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate."), QMessageBox.Ok) + "MainWindow", """The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate."""), QMessageBox.Ok) def click_pushButtonSend(self): self.statusBar().showMessage('') - toAddresses = str(self.ui.lineEditTo.text()) - fromAddress = str(self.ui.labelFrom.text()) - subject = str(self.ui.lineEditSubject.text().toUtf8()) - message = str( - self.ui.textEditMessage.document().toPlainText().toUtf8()) + + if self.ui.tabWidgetSend.currentIndex() == 0: + # message to specific people + sendMessageToPeople = True + fromAddress = str(self.ui.comboBoxSendFrom.itemData( + self.ui.comboBoxSendFrom.currentIndex(), + Qt.UserRole).toString()) + toAddresses = str(self.ui.lineEditTo.text()) + subject = str(self.ui.lineEditSubject.text().toUtf8()) + message = str( + self.ui.textEditMessage.document().toPlainText().toUtf8()) + else: + # broadcast message + sendMessageToPeople = False + fromAddress = str(self.ui.comboBoxSendFromBroadcast.itemData( + self.ui.comboBoxSendFromBroadcast.currentIndex(), + Qt.UserRole).toString()) + subject = str(self.ui.lineEditSubjectBroadcast.text().toUtf8()) + message = str( + self.ui.textEditMessageBroadcast.document().toPlainText().toUtf8()) """ The whole network message must fit in 2^18 bytes. Let's assume 500 bytes of overhead. If someone wants to get that too an exact @@ -1921,18 +1958,42 @@ more work your computer must do to send the message. A Time-To-Live of four or f QMessageBox.about(self, _translate("MainWindow", "Message too long"), _translate( "MainWindow", "The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending.").arg(len(message) - (2 ** 18 - 500))) return - if self.ui.radioButtonSpecific.isChecked(): # To send a message to specific people (rather than broadcast) + + acct = accountClass(fromAddress) + + if sendMessageToPeople: # To send a message to specific people (rather than broadcast) toAddressesList = [s.strip() for s in toAddresses.replace(',', ';').split(';')] toAddressesList = list(set( toAddressesList)) # remove duplicate addresses. If the user has one address with a BM- and the same address without the BM-, this will not catch it. They'll send the message to the person twice. for toAddress in toAddressesList: if toAddress != '': + # label plus address + if "<" in toAddress and ">" in toAddress: + toAddress = toAddress.split('<')[1].split('>')[0] + # email address + elif toAddress.find("@") >= 0: + if isinstance(acct, GatewayAccount): + acct.createMessage(toAddress, fromAddress, subject, message) + subject = acct.subject + toAddress = acct.toAddress + else: + email = acct.getLabel() + if email[-14:] != "@mailchuck.com": #attempt register + # 12 character random email address + email = ''.join(random.SystemRandom().choice(string.ascii_lowercase) for _ in range(12)) + "@mailchuck.com" + acct = MailchuckAccount(fromAddress) + acct.register(email) + shared.config.set(fromAddress, 'label', email) + shared.config.set(fromAddress, 'gateway', 'mailchuck') + shared.writeKeysFile() + self.statusBar().showMessage(_translate( + "MainWindow", "Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending.").arg(email)) + return status, addressVersionNumber, streamNumber, ripe = decodeAddress( toAddress) if status != 'success': - with shared.printLock: - print 'Error: Could not decode', toAddress, ':', status + logger.error('Error: Could not decode ' + toAddress + ':' + status) if status == 'missingbm': self.statusBar().showMessage(_translate( @@ -1963,6 +2024,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f "MainWindow", "Error: You must specify a From address. If you don\'t have one, go to the \'Your Identities\' tab.")) else: toAddress = addBMIfNotPresent(toAddress) + if addressVersionNumber > 4 or addressVersionNumber <= 1: QMessageBox.about(self, _translate("MainWindow", "Address version number"), _translate( "MainWindow", "Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version.").arg(toAddress).arg(str(addressVersionNumber))) @@ -2008,12 +2070,15 @@ more work your computer must do to send the message. A Time-To-Live of four or f shared.workerQueue.put(('sendmessage', toAddress)) self.ui.comboBoxSendFrom.setCurrentIndex(0) - self.ui.labelFrom.setText('') self.ui.lineEditTo.setText('') self.ui.lineEditSubject.setText('') - self.ui.textEditMessage.setText('') - self.ui.tabWidget.setCurrentIndex(2) - self.ui.tableWidgetSent.setCurrentCell(0, 0) + self.ui.textEditMessage.reset() + if self.replyFromTab is not None: + self.ui.tabWidget.setCurrentIndex(self.replyFromTab) + self.replyFromTab = None + self.statusBar().showMessage(_translate( + "MainWindow", "Message queued.")) + #self.ui.tableWidgetInbox.setCurrentCell(0, 0) else: self.statusBar().showMessage(_translate( "MainWindow", "Your \'To\' field is empty.")) @@ -2027,7 +2092,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f # this is a broadcast message, but we can use it to update the # user interface when the POW is done generating. ackdata = OpenSSL.rand(32) - toAddress = self.str_broadcast_subscribers + toAddress = str_broadcast_subscribers ripe = '' t = ('', # msgid. We don't know what this will be until the POW is done. toAddress, @@ -2048,20 +2113,20 @@ more work your computer must do to send the message. A Time-To-Live of four or f sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', *t) - toLabel = self.str_broadcast_subscribers + toLabel = str_broadcast_subscribers self.displayNewSentMessage( toAddress, toLabel, fromAddress, subject, message, ackdata) shared.workerQueue.put(('sendbroadcast', '')) - self.ui.comboBoxSendFrom.setCurrentIndex(0) - self.ui.labelFrom.setText('') - self.ui.lineEditTo.setText('') - self.ui.lineEditSubject.setText('') - self.ui.textEditMessage.setText('') - self.ui.tabWidget.setCurrentIndex(2) - self.ui.tableWidgetSent.setCurrentCell(0, 0) + self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0) + self.ui.lineEditSubjectBroadcast.setText('') + self.ui.textEditMessageBroadcast.reset() + self.ui.tabWidget.setCurrentIndex(1) + self.ui.tableWidgetInboxSubscriptions.setCurrentCell(0, 0) + self.statusBar().showMessage(_translate( + "MainWindow", "Broadcast queued.")) def click_pushButtonLoadFromAddressBook(self): self.ui.tabWidget.setCurrentIndex(5) @@ -2083,155 +2148,120 @@ more work your computer must do to send the message. A Time-To-Live of four or f self.statusBar().showMessage(_translate( "MainWindow", "Fetched address from namecoin identity.")) - def redrawLabelFrom(self, index): - self.ui.labelFrom.setText( - self.ui.comboBoxSendFrom.itemData(index).toPyObject()) - self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(self.ui.comboBoxSendFrom.itemData(index).toPyObject()) - - def setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(self, address): + def setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(self, address): # If this is a chan then don't let people broadcast because no one # should subscribe to chan addresses. - if shared.safeConfigGetBoolean(str(address), 'chan'): - self.ui.radioButtonSpecific.click() - self.ui.radioButtonBroadcast.setEnabled(False) + if shared.safeConfigGetBoolean(str(address), 'mailinglist'): + self.ui.tabWidgetSend.setCurrentIndex(1) else: - self.ui.radioButtonBroadcast.setEnabled(True) + self.ui.tabWidgetSend.setCurrentIndex(0) def rerenderComboBoxSendFrom(self): self.ui.comboBoxSendFrom.clear() - self.ui.labelFrom.setText('') - configSections = shared.config.sections() - for addressInKeysFile in configSections: - if addressInKeysFile != 'bitmessagesettings': - isEnabled = shared.config.getboolean( - addressInKeysFile, 'enabled') # I realize that this is poor programming practice but I don't care. It's easier for others to read. - if isEnabled: - self.ui.comboBoxSendFrom.insertItem(0, avatarize(addressInKeysFile), unicode(shared.config.get( - addressInKeysFile, 'label'), 'utf-8'), addressInKeysFile) + for addressInKeysFile in getSortedAccounts(): + isEnabled = shared.config.getboolean( + addressInKeysFile, 'enabled') # I realize that this is poor programming practice but I don't care. It's easier for others to read. + isMaillinglist = shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist') + if isEnabled and not isMaillinglist: + self.ui.comboBoxSendFrom.addItem(avatarize(addressInKeysFile), unicode(shared.config.get( + addressInKeysFile, 'label'), 'utf-8'), addressInKeysFile) +# self.ui.comboBoxSendFrom.model().sort(1, Qt.AscendingOrder) + for i in range(self.ui.comboBoxSendFrom.count()): + address = str(self.ui.comboBoxSendFrom.itemData(i, Qt.UserRole).toString()) + self.ui.comboBoxSendFrom.setItemData(i, AccountColor(address).accountColor(), Qt.ForegroundRole) self.ui.comboBoxSendFrom.insertItem(0, '', '') if(self.ui.comboBoxSendFrom.count() == 2): self.ui.comboBoxSendFrom.setCurrentIndex(1) - self.redrawLabelFrom(self.ui.comboBoxSendFrom.currentIndex()) else: self.ui.comboBoxSendFrom.setCurrentIndex(0) + def rerenderComboBoxSendFromBroadcast(self): + self.ui.comboBoxSendFromBroadcast.clear() + for addressInKeysFile in getSortedAccounts(): + isEnabled = shared.config.getboolean( + addressInKeysFile, 'enabled') # I realize that this is poor programming practice but I don't care. It's easier for others to read. + isChan = shared.safeConfigGetBoolean(addressInKeysFile, 'chan') + if isEnabled and not isChan: + self.ui.comboBoxSendFromBroadcast.addItem(avatarize(addressInKeysFile), unicode(shared.config.get( + addressInKeysFile, 'label'), 'utf-8'), addressInKeysFile) + for i in range(self.ui.comboBoxSendFromBroadcast.count()): + address = str(self.ui.comboBoxSendFromBroadcast.itemData(i, Qt.UserRole).toString()) + self.ui.comboBoxSendFromBroadcast.setItemData(i, AccountColor(address).accountColor(), Qt.ForegroundRole) + self.ui.comboBoxSendFromBroadcast.insertItem(0, '', '') + if(self.ui.comboBoxSendFromBroadcast.count() == 2): + self.ui.comboBoxSendFromBroadcast.setCurrentIndex(1) + else: + self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0) + # This function is called by the processmsg function when that function # receives a message to an address that is acting as a # pseudo-mailing-list. The message will be broadcast out. This function # puts the message on the 'Sent' tab. def displayNewSentMessage(self, toAddress, toLabel, fromAddress, subject, message, ackdata): - subject = shared.fixPotentiallyInvalidUTF8Data(subject) - message = shared.fixPotentiallyInvalidUTF8Data(message) - try: - fromLabel = shared.config.get(fromAddress, 'label') - except: - fromLabel = '' - if fromLabel == '': - fromLabel = fromAddress - - self.ui.tableWidgetSent.setSortingEnabled(False) - self.ui.tableWidgetSent.insertRow(0) - if toLabel == '': - newItem = QtGui.QTableWidgetItem(unicode(toAddress, 'utf-8')) - newItem.setToolTip(unicode(toAddress, 'utf-8')) - else: - newItem = QtGui.QTableWidgetItem(unicode(toLabel, 'utf-8')) - newItem.setToolTip(unicode(toLabel, 'utf-8')) - newItem.setData(Qt.UserRole, str(toAddress)) - newItem.setIcon(avatarize(toAddress)) - self.ui.tableWidgetSent.setItem(0, 0, newItem) - if fromLabel == '': - newItem = QtGui.QTableWidgetItem(unicode(fromAddress, 'utf-8')) - newItem.setToolTip(unicode(fromAddress, 'utf-8')) - else: - newItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8')) - newItem.setToolTip(unicode(fromLabel, 'utf-8')) - newItem.setData(Qt.UserRole, str(fromAddress)) - newItem.setIcon(avatarize(fromAddress)) - self.ui.tableWidgetSent.setItem(0, 1, newItem) - newItem = QtGui.QTableWidgetItem(unicode(subject, 'utf-8)')) - newItem.setToolTip(unicode(subject, 'utf-8)')) - #newItem.setData(Qt.UserRole, unicode(message, 'utf-8)')) # No longer hold the message in the table; we'll use a SQL query to display it as needed. - self.ui.tableWidgetSent.setItem(0, 2, newItem) - # newItem = QtGui.QTableWidgetItem('Doing work necessary to send - # broadcast...'+ - # l10n.formatTimestamp()) - newItem = myTableWidgetItem(_translate("MainWindow", "Work is queued. %1").arg(l10n.formatTimestamp())) - newItem.setToolTip(_translate("MainWindow", "Work is queued. %1").arg(l10n.formatTimestamp())) - newItem.setData(Qt.UserRole, QByteArray(ackdata)) - newItem.setData(33, int(time.time())) - self.ui.tableWidgetSent.setItem(0, 3, newItem) - self.ui.textEditSentMessage.setPlainText(unicode(message, 'utf-8)')) - self.ui.tableWidgetSent.setSortingEnabled(True) + acct = accountClass(fromAddress) + acct.parseMessage(toAddress, fromAddress, subject, message) + tab = -1 + for sent in [self.ui.tableWidgetInbox, self.ui.tableWidgetInboxSubscriptions, self.ui.tableWidgetInboxChans]: + tab += 1 + if tab == 1: + tab = 2 + treeWidget = self.widgetConvert(sent) + if self.getCurrentFolder(treeWidget) != "sent": + continue + if treeWidget == self.ui.treeWidgetYourIdentities and self.getCurrentAccount(treeWidget) != fromAddress: + continue + elif treeWidget in [self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans] and self.getCurrentAccount(treeWidget) != toAddress: + continue + elif not helper_search.check_match(toAddress, fromAddress, subject, message, self.getCurrentSearchOption(tab), self.getCurrentSearchLine(tab)): + continue + + self.addMessageListItemSent(sent, toAddress, fromAddress, subject, "msgqueued", ackdata, time.time()) + self.getAccountTextedit(acct).setPlainText(unicode(message, 'utf-8)', 'replace')) + sent.setCurrentCell(0, 0) def displayNewInboxMessage(self, inventoryHash, toAddress, fromAddress, subject, message): - subject = shared.fixPotentiallyInvalidUTF8Data(subject) - fromLabel = '' - queryreturn = sqlQuery( - '''select label from addressbook where address=?''', fromAddress) - if queryreturn != []: - for row in queryreturn: - fromLabel, = row + if toAddress == str_broadcast_subscribers: + acct = accountClass(fromAddress) else: - # There might be a label in the subscriptions table - queryreturn = sqlQuery( - '''select label from subscriptions where address=?''', fromAddress) - if queryreturn != []: - for row in queryreturn: - fromLabel, = row - - try: - if toAddress == self.str_broadcast_subscribers: - toLabel = self.str_broadcast_subscribers - else: - toLabel = shared.config.get(toAddress, 'label') - except: - toLabel = '' - if toLabel == '': - toLabel = toAddress - - font = QFont() - font.setBold(True) - self.ui.tableWidgetInbox.setSortingEnabled(False) - newItem = QtGui.QTableWidgetItem(unicode(toLabel, 'utf-8')) - newItem.setToolTip(unicode(toLabel, 'utf-8')) - newItem.setFont(font) - newItem.setData(Qt.UserRole, str(toAddress)) - if shared.safeConfigGetBoolean(str(toAddress), 'mailinglist'): - newItem.setTextColor(QtGui.QColor(137, 04, 177)) # magenta - if shared.safeConfigGetBoolean(str(toAddress), 'chan'): - newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange - self.ui.tableWidgetInbox.insertRow(0) - newItem.setIcon(avatarize(toAddress)) - self.ui.tableWidgetInbox.setItem(0, 0, newItem) - - if fromLabel == '': - newItem = QtGui.QTableWidgetItem(unicode(fromAddress, 'utf-8')) - newItem.setToolTip(unicode(fromAddress, 'utf-8')) - if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'): - self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(fromAddress, 'utf-8'), self.SOUND_UNKNOWN, None) + acct = accountClass(toAddress) + inbox = self.getAccountMessagelist(acct) + ret = None + tab = -1 + for treeWidget in [self.ui.treeWidgetYourIdentities, self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans]: + tab += 1 + if tab == 1: + tab = 2 + tableWidget = self.widgetConvert(treeWidget) + if not helper_search.check_match(toAddress, fromAddress, subject, message, self.getCurrentSearchOption(tab), self.getCurrentSearchLine(tab)): + continue + if tableWidget == inbox and self.getCurrentAccount(treeWidget) == acct.address and self.getCurrentFolder(treeWidget) in ["inbox", None]: + ret = self.addMessageListItemInbox(inbox, "inbox", inventoryHash, toAddress, fromAddress, subject, time.time(), 0) + elif treeWidget == self.ui.treeWidgetYourIdentities and self.getCurrentAccount(treeWidget) is None and self.getCurrentFolder(treeWidget) in ["inbox", "new", None]: + ret = self.addMessageListItemInbox(tableWidget, "inbox", inventoryHash, toAddress, fromAddress, subject, time.time(), 0) + if ret is None: + acct.parseMessage(toAddress, fromAddress, subject, "") else: - newItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8')) - newItem.setToolTip(unicode(unicode(fromLabel, 'utf-8'))) - if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'): - self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(fromLabel, 'utf-8'), self.SOUND_KNOWN, unicode(fromLabel, 'utf-8')) - newItem.setData(Qt.UserRole, str(fromAddress)) - newItem.setFont(font) - newItem.setIcon(avatarize(fromAddress)) - self.ui.tableWidgetInbox.setItem(0, 1, newItem) - newItem = QtGui.QTableWidgetItem(unicode(subject, 'utf-8)')) - newItem.setToolTip(unicode(subject, 'utf-8)')) - #newItem.setData(Qt.UserRole, unicode(message, 'utf-8)')) # No longer hold the message in the table; we'll use a SQL query to display it as needed. - newItem.setFont(font) - self.ui.tableWidgetInbox.setItem(0, 2, newItem) - newItem = myTableWidgetItem(l10n.formatTimestamp()) - newItem.setToolTip(l10n.formatTimestamp()) - newItem.setData(Qt.UserRole, QByteArray(inventoryHash)) - newItem.setData(33, int(time.time())) - newItem.setFont(font) - self.ui.tableWidgetInbox.setItem(0, 3, newItem) - self.ui.tableWidgetInbox.setSortingEnabled(True) - self.ubuntuMessagingMenuUpdate(True, newItem, toLabel) + acct = ret + self.propagateUnreadCount(acct.address) + if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'): + self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(acct.fromLabel, 'utf-8'), self.SOUND_UNKNOWN, None) + if self.getCurrentAccount() is not None and ((self.getCurrentFolder(treeWidget) != "inbox" and self.getCurrentFolder(treeWidget) is not None) or self.getCurrentAccount(treeWidget) != acct.address): + # Ubuntu should notify of new message irespective of whether it's in current message list or not + self.ubuntuMessagingMenuUpdate(True, None, acct.toLabel) + if hasattr(acct, "feedback") and acct.feedback != GatewayAccount.ALL_OK: + if acct.feedback == GatewayAccount.REGISTRATION_DENIED: + self.dialog = EmailGatewayRegistrationDialog(self, _translate("EmailGatewayRegistrationDialog", "Registration failed:"), + _translate("EmailGatewayRegistrationDialog", "The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below:") + ) + if self.dialog.exec_(): + email = str(self.dialog.ui.lineEditEmail.text().toUtf8()) + # register resets address variables + acct.register(email) + shared.config.set(acct.fromAddress, 'label', email) + shared.config.set(acct.fromAddress, 'gateway', 'mailchuck') + shared.writeKeysFile() + self.statusBar().showMessage(_translate( + "MainWindow", "Sending email gateway registration request")) def click_pushButtonAddAddressBook(self): self.AddAddressDialogInstance = AddAddressDialog(self) @@ -2251,19 +2281,10 @@ more work your computer must do to send the message. A Time-To-Live of four or f def addEntryToAddressBook(self,address,label): queryreturn = sqlQuery('''select * from addressbook where address=?''', address) if queryreturn == []: - self.ui.tableWidgetAddressBook.setSortingEnabled(False) - self.ui.tableWidgetAddressBook.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) - newItem.setIcon(avatarize(address)) - self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) - newItem = QtGui.QTableWidgetItem(address) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetAddressBook.setItem(0, 1, newItem) - self.ui.tableWidgetAddressBook.setSortingEnabled(True) sqlExecute('''INSERT INTO addressbook VALUES (?,?)''', str(label), address) - self.rerenderInboxFromLabels() - self.rerenderSentToLabels() + self.rerenderMessagelistFromLabels() + self.rerenderMessagelistToLabels() + self.rerenderAddressBook() else: self.statusBar().showMessage(_translate( "MainWindow", "Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want.")) @@ -2273,20 +2294,12 @@ more work your computer must do to send the message. A Time-To-Live of four or f #This should be handled outside of this function, for error displaying and such, but it must also be checked here. if shared.isAddressInMySubscriptionsList(address): return - #Add to UI list - self.ui.tableWidgetSubscriptions.setSortingEnabled(False) - self.ui.tableWidgetSubscriptions.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) - newItem.setIcon(avatarize(address)) - self.ui.tableWidgetSubscriptions.setItem(0,0,newItem) - newItem = QtGui.QTableWidgetItem(address) - newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) - self.ui.tableWidgetSubscriptions.setItem(0,1,newItem) - self.ui.tableWidgetSubscriptions.setSortingEnabled(True) #Add to database (perhaps this should be separated from the MyForm class) sqlExecute('''INSERT INTO subscriptions VALUES (?,?,?)''',str(label),address,True) - self.rerenderInboxFromLabels() + self.rerenderMessagelistFromLabels() shared.reloadBroadcastSendersForWhichImWatching() + self.rerenderAddressBook() + self.rerenderTabTreeSubscriptions() def click_pushButtonAddSubscription(self): self.NewSubscriptionDialogInstance = NewSubscriptionDialog(self) @@ -2297,7 +2310,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f address = addBMIfNotPresent(str(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())) # We must check to see if the address is already in the subscriptions list. The user cannot add it again or else it will cause problems when updating and deleting the entry. if shared.isAddressInMySubscriptionsList(address): - self.statusBar().showMessage(_translate("MainWindow", "Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want.")) + self.statusBar().showMessage(_translate("MainWindow", "Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want.")) return label = self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8() self.addSubscription(address, label) @@ -2305,21 +2318,15 @@ more work your computer must do to send the message. A Time-To-Live of four or f # in the objectProcessorQueue to be processed if self.NewSubscriptionDialogInstance.ui.checkBoxDisplayMessagesAlreadyInInventory.isChecked(): status, addressVersion, streamNumber, ripe = decodeAddress(address) - shared.flushInventory() + shared.inventory.flush() doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(encodeVarint( addressVersion) + encodeVarint(streamNumber) + ripe).digest()).digest() tag = doubleHashOfAddressData[32:] - queryreturn = sqlQuery( - '''select payload from inventory where objecttype=3 and tag=?''', tag) - for row in queryreturn: - payload, = row - objectType = 3 - with shared.objectProcessorQueueSizeLock: - shared.objectProcessorQueueSize += len(payload) - shared.objectProcessorQueue.put((objectType,payload)) + for value in shared.inventory.by_type_and_tag(3, tag): + shared.objectProcessorQueue.put((value.type, value.payload)) def click_pushButtonStatusIcon(self): - print 'click_pushButtonStatusIcon' + logger.debug('click_pushButtonStatusIcon') self.iconGlossaryInstance = iconGlossaryDialog(self) if self.iconGlossaryInstance.exec_(): pass @@ -2328,6 +2335,9 @@ more work your computer must do to send the message. A Time-To-Live of four or f self.helpDialogInstance = helpDialog(self) self.helpDialogInstance.exec_() + def click_actionSupport(self): + support.createSupportMessage(self) + def click_actionAbout(self): self.aboutDialogInstance = aboutDialog(self) self.aboutDialogInstance.exec_() @@ -2339,6 +2349,8 @@ more work your computer must do to send the message. A Time-To-Live of four or f self.settingsDialogInstance.ui.checkBoxStartOnLogon.isChecked())) shared.config.set('bitmessagesettings', 'minimizetotray', str( self.settingsDialogInstance.ui.checkBoxMinimizeToTray.isChecked())) + shared.config.set('bitmessagesettings', 'trayonclose', str( + self.settingsDialogInstance.ui.checkBoxTrayOnClose.isChecked())) shared.config.set('bitmessagesettings', 'showtraynotifications', str( self.settingsDialogInstance.ui.checkBoxShowTrayNotifications.isChecked())) shared.config.set('bitmessagesettings', 'startintray', str( @@ -2350,10 +2362,10 @@ more work your computer must do to send the message. A Time-To-Live of four or f 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': - shared.config.set('bitmessagesettings', 'userlocale', languages[lang_ind]) - change_translation(languages[lang_ind]) + lang = str(self.settingsDialogInstance.ui.languageComboBox.itemData(self.settingsDialogInstance.ui.languageComboBox.currentIndex()).toString()) + shared.config.set('bitmessagesettings', 'userlocale', lang) + logger.debug("Setting locale to %s", lang) + change_translation(lang) if int(shared.config.get('bitmessagesettings', 'port')) != int(self.settingsDialogInstance.ui.lineEditTCPPort.text()): if not shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'): @@ -2361,6 +2373,12 @@ more work your computer must do to send the message. A Time-To-Live of four or f "MainWindow", "You must restart Bitmessage for the port number change to take effect.")) shared.config.set('bitmessagesettings', 'port', str( self.settingsDialogInstance.ui.lineEditTCPPort.text())) + if self.settingsDialogInstance.ui.checkBoxUPnP.isChecked() != shared.safeConfigGetBoolean('bitmessagesettings', 'upnp'): + shared.config.set('bitmessagesettings', 'upnp', str(self.settingsDialogInstance.ui.checkBoxUPnP.isChecked())) + if self.settingsDialogInstance.ui.checkBoxUPnP.isChecked(): + import upnp + upnpThread = upnp.uPnPThread() + upnpThread.start() #print 'self.settingsDialogInstance.ui.comboBoxProxyType.currentText()', self.settingsDialogInstance.ui.comboBoxProxyType.currentText() #print 'self.settingsDialogInstance.ui.comboBoxProxyType.currentText())[0:5]', self.settingsDialogInstance.ui.comboBoxProxyType.currentText()[0:5] if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none' and self.settingsDialogInstance.ui.comboBoxProxyType.currentText()[0:5] == 'SOCKS': @@ -2415,6 +2433,9 @@ more work your computer must do to send the message. A Time-To-Live of four or f shared.config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(int(float( self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()) * shared.networkDefaultPayloadLengthExtraBytes))) + if openclpow.has_opencl() and self.settingsDialogInstance.ui.checkBoxOpenCL.isChecked() != shared.safeConfigGetBoolean("bitmessagesettings", "opencl"): + shared.config.set('bitmessagesettings', 'opencl', str(self.settingsDialogInstance.ui.checkBoxOpenCL.isChecked())) + acceptableDifficultyChanged = False if float(self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) >= 1 or float(self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) == 0: @@ -2491,21 +2512,21 @@ more work your computer must do to send the message. A Time-To-Live of four or f # startup for linux pass - if shared.appdata != '' and self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): # If we are NOT using portable mode now but the user selected that we should... + if shared.appdata != shared.lookupExeFolder() and self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): # If we are NOT using portable mode now but the user selected that we should... # Write the keys.dat file to disk in the new location sqlStoredProcedure('movemessagstoprog') - with open('keys.dat', 'wb') as configfile: + with open(shared.lookupExeFolder() + 'keys.dat', 'wb') as configfile: shared.config.write(configfile) # Write the knownnodes.dat file to disk in the new location shared.knownNodesLock.acquire() - output = open('knownnodes.dat', 'wb') + output = open(shared.lookupExeFolder() + 'knownnodes.dat', 'wb') pickle.dump(shared.knownNodes, output) output.close() shared.knownNodesLock.release() os.remove(shared.appdata + 'keys.dat') os.remove(shared.appdata + 'knownnodes.dat') previousAppdataLocation = shared.appdata - shared.appdata = '' + shared.appdata = shared.lookupExeFolder() debug.restartLoggingInUpdatedAppdataLocation() try: os.remove(previousAppdataLocation + 'debug.log') @@ -2513,7 +2534,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f except: pass - if shared.appdata == '' and not self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): # If we ARE using portable mode now but the user selected that we shouldn't... + if shared.appdata == shared.lookupExeFolder() and not self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): # If we ARE using portable mode now but the user selected that we shouldn't... shared.appdata = shared.lookupAppdataFolder() if not os.path.exists(shared.appdata): os.makedirs(shared.appdata) @@ -2526,80 +2547,20 @@ more work your computer must do to send the message. A Time-To-Live of four or f pickle.dump(shared.knownNodes, output) output.close() shared.knownNodesLock.release() - os.remove('keys.dat') - os.remove('knownnodes.dat') + os.remove(shared.lookupExeFolder() + 'keys.dat') + os.remove(shared.lookupExeFolder() + 'knownnodes.dat') debug.restartLoggingInUpdatedAppdataLocation() try: - os.remove('debug.log') - os.remove('debug.log.1') + os.remove(shared.lookupExeFolder() + 'debug.log') + os.remove(shared.lookupExeFolder() + 'debug.log.1') except: pass - def click_radioButtonBlacklist(self): - if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white': - shared.config.set('bitmessagesettings', 'blackwhitelist', 'black') - shared.writeKeysFile() - # self.ui.tableWidgetBlacklist.clearContents() - self.ui.tableWidgetBlacklist.setRowCount(0) - self.rerenderBlackWhiteList() - self.ui.tabWidget.setTabText(6, 'Blacklist') - - def click_radioButtonWhitelist(self): - if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': - shared.config.set('bitmessagesettings', 'blackwhitelist', 'white') - shared.writeKeysFile() - # self.ui.tableWidgetBlacklist.clearContents() - self.ui.tableWidgetBlacklist.setRowCount(0) - self.rerenderBlackWhiteList() - self.ui.tabWidget.setTabText(6, 'Whitelist') - - def click_pushButtonAddBlacklist(self): - self.NewBlacklistDialogInstance = AddAddressDialog(self) - if self.NewBlacklistDialogInstance.exec_(): - if self.NewBlacklistDialogInstance.ui.labelAddressCheck.text() == _translate("MainWindow", "Address is valid."): - address = addBMIfNotPresent(str( - self.NewBlacklistDialogInstance.ui.lineEditAddress.text())) - # First we must check to see if the address is already in the - # address book. The user cannot add it again or else it will - # cause problems when updating and deleting the entry. - t = (address,) - if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': - sql = '''select * from blacklist where address=?''' - else: - sql = '''select * from whitelist where address=?''' - queryreturn = sqlQuery(sql,*t) - if queryreturn == []: - self.ui.tableWidgetBlacklist.setSortingEnabled(False) - self.ui.tableWidgetBlacklist.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode( - self.NewBlacklistDialogInstance.ui.newAddressLabel.text().toUtf8(), 'utf-8')) - newItem.setIcon(avatarize(address)) - self.ui.tableWidgetBlacklist.setItem(0, 0, newItem) - newItem = QtGui.QTableWidgetItem(address) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetBlacklist.setItem(0, 1, newItem) - self.ui.tableWidgetBlacklist.setSortingEnabled(True) - t = (str(self.NewBlacklistDialogInstance.ui.newAddressLabel.text().toUtf8()), address, True) - if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': - sql = '''INSERT INTO blacklist VALUES (?,?,?)''' - else: - sql = '''INSERT INTO whitelist VALUES (?,?,?)''' - sqlExecute(sql, *t) - else: - self.statusBar().showMessage(_translate( - "MainWindow", "Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want.")) - else: - self.statusBar().showMessage(_translate( - "MainWindow", "The address you entered was invalid. Ignoring it.")) - def on_action_SpecialAddressBehaviorDialog(self): self.dialog = SpecialAddressBehaviorDialog(self) # For Modal dialogs if self.dialog.exec_(): - currentRow = self.ui.tableWidgetYourIdentities.currentRow() - addressAtCurrentRow = str( - self.ui.tableWidgetYourIdentities.item(currentRow, 1).text()) + addressAtCurrentRow = self.getCurrentAccount() if shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'): return if self.dialog.ui.radioButtonBehaveNormalAddress.isChecked(): @@ -2607,22 +2568,78 @@ more work your computer must do to send the message. A Time-To-Live of four or f addressAtCurrentRow), 'mailinglist', 'false') # Set the color to either black or grey if shared.config.getboolean(addressAtCurrentRow, 'enabled'): - self.ui.tableWidgetYourIdentities.item( - currentRow, 1).setTextColor(QApplication.palette() + self.setCurrentItemColor(QApplication.palette() .text().color()) else: - self.ui.tableWidgetYourIdentities.item( - currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) + self.setCurrentItemColor(QtGui.QColor(128, 128, 128)) else: shared.config.set(str( addressAtCurrentRow), 'mailinglist', 'true') shared.config.set(str(addressAtCurrentRow), 'mailinglistname', str( self.dialog.ui.lineEditMailingListName.text().toUtf8())) - self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) # magenta + self.setCurrentItemColor(QtGui.QColor(137, 04, 177)) #magenta + self.rerenderComboBoxSendFrom() + self.rerenderComboBoxSendFromBroadcast() shared.writeKeysFile() - self.rerenderInboxToLabels() + self.rerenderMessagelistToLabels() + def on_action_EmailGatewayDialog(self): + self.dialog = EmailGatewayDialog(self) + # For Modal dialogs + if self.dialog.exec_(): + addressAtCurrentRow = self.getCurrentAccount() + acct = accountClass(addressAtCurrentRow) + # no chans / mailinglists + if acct.type != AccountMixin.NORMAL: + return + if self.dialog.ui.radioButtonUnregister.isChecked() and isinstance(acct, GatewayAccount): + acct.unregister() + shared.config.remove_option(addressAtCurrentRow, 'gateway') + shared.writeKeysFile() + self.statusBar().showMessage(_translate( + "MainWindow", "Sending email gateway unregistration request")) + elif self.dialog.ui.radioButtonStatus.isChecked() and isinstance(acct, GatewayAccount): + acct.status() + self.statusBar().showMessage(_translate( + "MainWindow", "Sending email gateway status request")) + elif self.dialog.ui.radioButtonSettings.isChecked() and isinstance(acct, GatewayAccount): + acct.settings() + listOfAddressesInComboBoxSendFrom = [str(self.ui.comboBoxSendFrom.itemData(i).toPyObject()) for i in range(self.ui.comboBoxSendFrom.count())] + if acct.fromAddress in listOfAddressesInComboBoxSendFrom: + currentIndex = listOfAddressesInComboBoxSendFrom.index(acct.fromAddress) + self.ui.comboBoxSendFrom.setCurrentIndex(currentIndex) + else: + self.ui.comboBoxSendFrom.setCurrentIndex(0) + self.ui.lineEditTo.setText(acct.toAddress) + self.ui.lineEditSubject.setText(acct.subject) + self.ui.textEditMessage.setText(acct.message) + self.ui.tabWidgetSend.setCurrentIndex(0) + self.ui.tabWidget.setCurrentIndex(1) + self.ui.textEditMessage.setFocus() + elif self.dialog.ui.radioButtonRegister.isChecked(): + email = str(self.dialog.ui.lineEditEmail.text().toUtf8()) + acct = MailchuckAccount(addressAtCurrentRow) + acct.register(email) + shared.config.set(addressAtCurrentRow, 'label', email) + shared.config.set(addressAtCurrentRow, 'gateway', 'mailchuck') + shared.writeKeysFile() + self.statusBar().showMessage(_translate( + "MainWindow", "Sending email gateway registration request")) + else: + pass + #print "well nothing" +# shared.writeKeysFile() +# self.rerenderInboxToLabels() + def click_NewAddressDialog(self): + addresses = [] + for addressInKeysFile in getSortedAccounts(): + addresses.append(addressInKeysFile) +# self.dialog = Ui_NewAddressWizard(addresses) +# self.dialog.exec_() +# print "Name: " + self.dialog.field("name").toString() +# print "Email: " + self.dialog.field("email").toString() +# return self.dialog = NewAddressDialog(self) # For Modal dialogs if self.dialog.exec_(): @@ -2649,7 +2666,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f shared.addressGeneratorQueue.put(('createDeterministicAddresses', 4, streamNumberForAddress, "unused deterministic address", self.dialog.ui.spinBoxNumberOfAddressesToMake.value( ), self.dialog.ui.lineEditPassphrase.text().toUtf8(), self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) else: - print 'new address dialog box rejected' + logger.debug('new address dialog box rejected') # Quit selected from menu or application indicator def quit(self): @@ -2660,27 +2677,97 @@ more work your computer must do to send the message. A Time-To-Live of four or f if reply is QtGui.QMessageBox.No: return ''' + + self.statusBar().showMessage(_translate( + "MainWindow", "Shutting down PyBitmessage... %1%").arg(str(0))) + + # check if PoW queue empty + maxWorkerQueue = 0 + curWorkerQueue = 1 + while curWorkerQueue > 0: + # worker queue size + curWorkerQueue = shared.workerQueue.qsize() + # if worker is busy add 1 + for thread in threading.enumerate(): + try: + if isinstance(thread, singleWorker): + curWorkerQueue += thread.busy + except: + pass + if curWorkerQueue > maxWorkerQueue: + maxWorkerQueue = curWorkerQueue + if curWorkerQueue > 0: + self.statusBar().showMessage(_translate("MainWindow", "Waiting for PoW to finish... %1%").arg(str(50 * (maxWorkerQueue - curWorkerQueue) / maxWorkerQueue))) + time.sleep(0.5) + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000) + + self.statusBar().showMessage(_translate("MainWindow", "Shutting down Pybitmessage... %1%").arg(str(50))) + + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000) + if maxWorkerQueue > 0: + time.sleep(0.5) # a bit of time so that the hashHolder is populated + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000) + + # check if objectHashHolder empty + self.statusBar().showMessage(_translate("MainWindow", "Waiting for objects to be sent... %1%").arg(str(50))) + maxWaitingObjects = 0 + curWaitingObjects = 1 + while curWaitingObjects > 0: + curWaitingObjects = 0 + for thread in threading.enumerate(): + try: + if isinstance(thread, objectHashHolder): + curWaitingObjects += thread.hashCount() + except: + pass + if curWaitingObjects > maxWaitingObjects: + maxWaitingObjects = curWaitingObjects + if curWaitingObjects > 0: + self.statusBar().showMessage(_translate("MainWindow", "Waiting for objects to be sent... %1%").arg(str(50 + 20 * (maxWaitingObjects - curWaitingObjects) / maxWaitingObjects))) + time.sleep(0.5) + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000) + + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000) + if maxWorkerQueue > 0 or maxWaitingObjects > 0: + time.sleep(10) # a bit of time so that the other nodes retrieve the objects + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000) + + # save state and geometry self and all widgets + self.statusBar().showMessage(_translate("MainWindow", "Saving settings... %1%").arg(str(70))) + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000) + self.saveSettings() + for attr, obj in self.ui.__dict__.iteritems(): + if hasattr(obj, "__class__") and isinstance(obj, settingsmixin.SettingsMixin): + saveMethod = getattr(obj, "saveSettings", None) + if callable (saveMethod): + obj.saveSettings() + + self.statusBar().showMessage(_translate("MainWindow", "Shutting down core... %1%").arg(str(80))) + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000) shared.doCleanShutdown() + self.statusBar().showMessage(_translate("MainWindow", "Stopping notifications... %1%").arg(str(90))) self.tray.hide() # unregister the messaging system if self.mmapp is not None: self.mmapp.unregister() - self.statusBar().showMessage(_translate( - "MainWindow", "All done. Closing user interface...")) + + self.statusBar().showMessage(_translate("MainWindow", "Shutdown imminent... %1%").arg(str(100))) + shared.thisapp.cleanup() + logger.info("Shutdown complete") os._exit(0) # window close event def closeEvent(self, event): self.appIndicatorHide() - minimizeonclose = False + trayonclose = False try: - minimizeonclose = shared.config.getboolean( - 'bitmessagesettings', 'minimizeonclose') + trayonclose = shared.config.getboolean( + 'bitmessagesettings', 'trayonclose') except Exception: pass - if minimizeonclose: + if trayonclose: # minimize the application event.ignore() else: @@ -2689,10 +2776,10 @@ more work your computer must do to send the message. A Time-To-Live of four or f self.quit() def on_action_InboxMessageForceHtml(self): - currentInboxRow = self.ui.tableWidgetInbox.currentRow() - - msgid = str(self.ui.tableWidgetInbox.item( - currentInboxRow, 3).data(Qt.UserRole).toPyObject()) + msgid = self.getCurrentMessageId() + textEdit = self.getCurrentMessageTextedit() + if not msgid: + return queryreturn = sqlQuery( '''select message from inbox where msgid=?''', msgid) if queryreturn != []: @@ -2713,29 +2800,42 @@ more work your computer must do to send the message. A Time-To-Live of four or f content = ' '.join(lines) # To keep the whitespace between lines content = shared.fixPotentiallyInvalidUTF8Data(content) content = unicode(content, 'utf-8)') - self.ui.textEditInboxMessage.setHtml(QtCore.QString(content)) + textEdit.setHtml(QtCore.QString(content)) def on_action_InboxMarkUnread(self): + tableWidget = self.getCurrentMessagelist() + if not tableWidget: + return font = QFont() font.setBold(True) inventoryHashesToMarkUnread = [] - for row in self.ui.tableWidgetInbox.selectedIndexes(): + modified = 0 + for row in tableWidget.selectedIndexes(): currentRow = row.row() - inventoryHashToMarkUnread = str(self.ui.tableWidgetInbox.item( + inventoryHashToMarkUnread = str(tableWidget.item( currentRow, 3).data(Qt.UserRole).toPyObject()) + if inventoryHashToMarkUnread in inventoryHashesToMarkUnread: + # it returns columns as separate items, so we skip dupes + continue + if not tableWidget.item(currentRow, 0).unread: + modified += 1 inventoryHashesToMarkUnread.append(inventoryHashToMarkUnread) - self.ui.tableWidgetInbox.item(currentRow, 0).setFont(font) - self.ui.tableWidgetInbox.item(currentRow, 1).setFont(font) - self.ui.tableWidgetInbox.item(currentRow, 2).setFont(font) - self.ui.tableWidgetInbox.item(currentRow, 3).setFont(font) + tableWidget.item(currentRow, 0).setUnread(True) + tableWidget.item(currentRow, 1).setUnread(True) + tableWidget.item(currentRow, 2).setUnread(True) + tableWidget.item(currentRow, 3).setFont(font) #sqlite requires the exact number of ?s to prevent injection - sqlExecute('''UPDATE inbox SET read=0 WHERE msgid IN (%s)''' % ( + rowcount = sqlExecute('''UPDATE inbox SET read=0 WHERE msgid IN (%s) AND read=1''' % ( "?," * len(inventoryHashesToMarkUnread))[:-1], *inventoryHashesToMarkUnread) - self.changedInboxUnread() - # self.ui.tableWidgetInbox.selectRow(currentRow + 1) + if rowcount == 1: + # performance optimisation + self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), self.getCurrentFolder()) + else: + self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), self.getCurrentFolder(), self.getCurrentTreeWidget(), 0) + # tableWidget.selectRow(currentRow + 1) # This doesn't de-select the last message if you try to mark it unread, but that doesn't interfere. Might not be necessary. # We could also select upwards, but then our problem would be with the topmost message. - # self.ui.tableWidgetInbox.clearSelection() manages to mark the message as read again. + # tableWidget.clearSelection() manages to mark the message as read again. # Format predefined text on message reply. def quoted_text(self, message): @@ -2759,113 +2859,229 @@ more work your computer must do to send the message. A Time-To-Live of four or f 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( - currentInboxRow, 0).data(Qt.UserRole).toPyObject()) - fromAddressAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item( - currentInboxRow, 1).data(Qt.UserRole).toPyObject()) - msgid = str(self.ui.tableWidgetInbox.item( + def setSendFromComboBox(self, address = None): + if address is None: + messagelist = self.getCurrentMessagelist() + if messagelist: + currentInboxRow = messagelist.currentRow() + address = messagelist.item( + currentInboxRow, 0).address + for box in [self.ui.comboBoxSendFrom, self.ui.comboBoxSendFromBroadcast]: + listOfAddressesInComboBoxSendFrom = [str(box.itemData(i).toPyObject()) for i in range(box.count())] + if address in listOfAddressesInComboBoxSendFrom: + currentIndex = listOfAddressesInComboBoxSendFrom.index(address) + box.setCurrentIndex(currentIndex) + else: + box.setCurrentIndex(0) + + def on_action_InboxReplyChan(self): + self.on_action_InboxReply(self.REPLY_TYPE_CHAN) + + def on_action_InboxReply(self, replyType = None): + tableWidget = self.getCurrentMessagelist() + if not tableWidget: + return + + if replyType is None: + replyType = self.REPLY_TYPE_SENDER + + # save this to return back after reply is done + self.replyFromTab = self.ui.tabWidget.currentIndex() + + currentInboxRow = tableWidget.currentRow() + toAddressAtCurrentInboxRow = tableWidget.item( + currentInboxRow, 0).address + acct = accountClass(toAddressAtCurrentInboxRow) + fromAddressAtCurrentInboxRow = tableWidget.item( + currentInboxRow, 1).address + msgid = str(tableWidget.item( currentInboxRow, 3).data(Qt.UserRole).toPyObject()) queryreturn = sqlQuery( '''select message from inbox where msgid=?''', msgid) if queryreturn != []: for row in queryreturn: messageAtCurrentInboxRow, = row - if toAddressAtCurrentInboxRow == self.str_broadcast_subscribers: - self.ui.labelFrom.setText('') + acct.parseMessage(toAddressAtCurrentInboxRow, fromAddressAtCurrentInboxRow, tableWidget.item(currentInboxRow, 2).subject, messageAtCurrentInboxRow) + widget = { + 'subject': self.ui.lineEditSubject, + 'from': self.ui.comboBoxSendFrom, + 'message': self.ui.textEditMessage + } + if toAddressAtCurrentInboxRow == str_broadcast_subscribers: + self.ui.tabWidgetSend.setCurrentIndex(0) +# toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow elif not shared.config.has_section(toAddressAtCurrentInboxRow): QtGui.QMessageBox.information(self, _translate("MainWindow", "Address is gone"), _translate( "MainWindow", "Bitmessage cannot find your address %1. Perhaps you removed it?").arg(toAddressAtCurrentInboxRow), QMessageBox.Ok) - self.ui.labelFrom.setText('') elif not shared.config.getboolean(toAddressAtCurrentInboxRow, 'enabled'): QtGui.QMessageBox.information(self, _translate("MainWindow", "Address disabled"), _translate( "MainWindow", "Error: The address from which you are trying to send is disabled. You\'ll have to enable it on the \'Your Identities\' tab before using it."), QMessageBox.Ok) - self.ui.labelFrom.setText('') else: - self.ui.labelFrom.setText(toAddressAtCurrentInboxRow) - self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(toAddressAtCurrentInboxRow) - - self.ui.lineEditTo.setText(str(fromAddressAtCurrentInboxRow)) + self.setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(toAddressAtCurrentInboxRow) + if self.ui.tabWidgetSend.currentIndex() == 1: + widget = { + 'subject': self.ui.lineEditSubjectBroadcast, + 'from': self.ui.comboBoxSendFromBroadcast, + 'message': self.ui.textEditMessageBroadcast + } + self.ui.tabWidgetSend.setCurrentIndex(1) + toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow + if fromAddressAtCurrentInboxRow == tableWidget.item(currentInboxRow, 1).label or ( + isinstance(acct, GatewayAccount) and fromAddressAtCurrentInboxRow == acct.relayAddress): + self.ui.lineEditTo.setText(str(acct.fromAddress)) + else: + self.ui.lineEditTo.setText(tableWidget.item(currentInboxRow, 1).label + " <" + str(acct.fromAddress) + ">") # If the previous message was to a chan then we should send our reply to the chan rather than to the particular person who sent the message. - if shared.config.has_section(toAddressAtCurrentInboxRow): - if shared.safeConfigGetBoolean(toAddressAtCurrentInboxRow, 'chan'): - print 'original sent to a chan. Setting the to address in the reply to the chan address.' + if acct.type == AccountMixin.CHAN and replyType == self.REPLY_TYPE_CHAN: + logger.debug('original sent to a chan. Setting the to address in the reply to the chan address.') + if toAddressAtCurrentInboxRow == tableWidget.item(currentInboxRow, 0).label: self.ui.lineEditTo.setText(str(toAddressAtCurrentInboxRow)) + else: + self.ui.lineEditTo.setText(tableWidget.item(currentInboxRow, 0).label + " <" + str(acct.toAddress) + ">") - listOfAddressesInComboBoxSendFrom = [str(self.ui.comboBoxSendFrom.itemData(i).toPyObject()) for i in range(self.ui.comboBoxSendFrom.count())] - if toAddressAtCurrentInboxRow in listOfAddressesInComboBoxSendFrom: - currentIndex = listOfAddressesInComboBoxSendFrom.index(toAddressAtCurrentInboxRow) - self.ui.comboBoxSendFrom.setCurrentIndex(currentIndex) - else: - self.ui.comboBoxSendFrom.setCurrentIndex(0) + self.setSendFromComboBox(toAddressAtCurrentInboxRow) - 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()) + quotedText = self.quoted_text(unicode(messageAtCurrentInboxRow, 'utf-8', 'replace')) + widget['message'].setPlainText(quotedText) + if acct.subject[0:3] in ['Re:', 'RE:']: + widget['subject'].setText(tableWidget.item(currentInboxRow, 2).label) else: - self.ui.lineEditSubject.setText( - 'Re: ' + self.ui.tableWidgetInbox.item(currentInboxRow, 2).text()) - self.ui.radioButtonSpecific.setChecked(True) + widget['subject'].setText('Re: ' + tableWidget.item(currentInboxRow, 2).label) self.ui.tabWidget.setCurrentIndex(1) + widget['message'].setFocus() def on_action_InboxAddSenderToAddressBook(self): - currentInboxRow = self.ui.tableWidgetInbox.currentRow() - # self.ui.tableWidgetInbox.item(currentRow,1).data(Qt.UserRole).toPyObject() - addressAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item( - currentInboxRow, 1).data(Qt.UserRole).toPyObject()) + tableWidget = self.getCurrentMessagelist() + if not tableWidget: + return + currentInboxRow = tableWidget.currentRow() + # tableWidget.item(currentRow,1).data(Qt.UserRole).toPyObject() + addressAtCurrentInboxRow = tableWidget.item( + currentInboxRow, 1).data(Qt.UserRole) # Let's make sure that it isn't already in the address book queryreturn = sqlQuery('''select * from addressbook where address=?''', addressAtCurrentInboxRow) if queryreturn == []: - self.ui.tableWidgetAddressBook.insertRow(0) - newItem = QtGui.QTableWidgetItem( - '--New entry. Change label in Address Book.--') - self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) - newItem.setIcon(avatarize(addressAtCurrentInboxRow)) - newItem = QtGui.QTableWidgetItem(addressAtCurrentInboxRow) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetAddressBook.setItem(0, 1, newItem) sqlExecute('''INSERT INTO addressbook VALUES (?,?)''', '--New entry. Change label in Address Book.--', addressAtCurrentInboxRow) - self.ui.tabWidget.setCurrentIndex(5) - self.ui.tableWidgetAddressBook.setCurrentCell(0, 0) + self.rerenderAddressBook() self.statusBar().showMessage(_translate( "MainWindow", "Entry added to the Address Book. Edit the label to your liking.")) else: self.statusBar().showMessage(_translate( "MainWindow", "Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want.")) + def on_action_InboxAddSenderToBlackList(self): + tableWidget = self.getCurrentMessagelist() + if not tableWidget: + return + currentInboxRow = tableWidget.currentRow() + # tableWidget.item(currentRow,1).data(Qt.UserRole).toPyObject() + addressAtCurrentInboxRow = tableWidget.item( + currentInboxRow, 1).data(Qt.UserRole) + recipientAddress = tableWidget.item( + currentInboxRow, 0).data(Qt.UserRole) + # Let's make sure that it isn't already in the address book + queryreturn = sqlQuery('''select * from blacklist where address=?''', + addressAtCurrentInboxRow) + if queryreturn == []: + label = "\"" + tableWidget.item(currentInboxRow, 2).subject + "\" in " + shared.config.get(recipientAddress, "label") + sqlExecute('''INSERT INTO blacklist VALUES (?,?, ?)''', + label, + addressAtCurrentInboxRow, True) + self.ui.blackwhitelist.rerenderBlackWhiteList() + self.statusBar().showMessage(_translate( + "MainWindow", "Entry added to the blacklist. Edit the label to your liking.")) + else: + self.statusBar().showMessage(_translate( + "MainWindow", "Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want.")) + + def deleteRowFromMessagelist(row = None, inventoryHash = None, ackData = None, messageLists = None): + if messageLists is None: + messageLists = (self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans, self.ui.tableWidgetInboxSubscriptions) + elif type(messageLists) not in (list, tuple): + messageLists = (messageLists) + for messageList in messageLists: + if row is not None: + inventoryHash = str(messageList.item(row, 3).data(Qt.UserRole).toPyObject()) + messageList.removeRow(row) + elif inventoryHash is not None: + for i in range(messageList.rowCount() - 1, -1, -1): + if messageList.item(i, 3).data(Qt.UserRole).toPyObject() == inventoryHash: + messageList.removeRow(i) + elif ackData is not None: + for i in range(messageList.rowCount() - 1, -1, -1): + if messageList.item(i, 3).data(Qt.UserRole).toPyObject() == ackData: + messageList.removeRow(i) + # Send item on the Inbox tab to trash def on_action_InboxTrash(self): - while self.ui.tableWidgetInbox.selectedIndexes() != []: - currentRow = self.ui.tableWidgetInbox.selectedIndexes()[0].row() - inventoryHashToTrash = str(self.ui.tableWidgetInbox.item( + tableWidget = self.getCurrentMessagelist() + if not tableWidget: + return + unread = False + currentRow = 0 + folder = self.getCurrentFolder() + shifted = QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier + while tableWidget.selectedIndexes(): + currentRow = tableWidget.selectedIndexes()[0].row() + inventoryHashToTrash = str(tableWidget.item( currentRow, 3).data(Qt.UserRole).toPyObject()) - sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', inventoryHashToTrash) - self.ui.textEditInboxMessage.setText("") - self.ui.tableWidgetInbox.removeRow(currentRow) + if folder == "trash" or shifted: + sqlExecute('''DELETE FROM inbox WHERE msgid=?''', inventoryHashToTrash) + else: + sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', inventoryHashToTrash) + if tableWidget.item(currentRow, 0).unread: + self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), folder, self.getCurrentTreeWidget(), -1) + if folder != "trash" and not shifted: + self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), "trash", self.getCurrentTreeWidget(), 1) + + self.getCurrentMessageTextedit().setText("") + tableWidget.removeRow(currentRow) self.statusBar().showMessage(_translate( - "MainWindow", "Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back.")) + "MainWindow", "Moved items to trash.")) if currentRow == 0: - self.ui.tableWidgetInbox.selectRow(currentRow) + tableWidget.selectRow(currentRow) else: - self.ui.tableWidgetInbox.selectRow(currentRow - 1) + tableWidget.selectRow(currentRow - 1) + + def on_action_TrashUndelete(self): + tableWidget = self.getCurrentMessagelist() + if not tableWidget: + return + unread = False + currentRow = 0 + while tableWidget.selectedIndexes(): + currentRow = tableWidget.selectedIndexes()[0].row() + inventoryHashToTrash = str(tableWidget.item( + currentRow, 3).data(Qt.UserRole).toPyObject()) + sqlExecute('''UPDATE inbox SET folder='inbox' WHERE msgid=?''', inventoryHashToTrash) + if tableWidget.item(currentRow, 0).unread: + self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), "inbox", self.getCurrentTreeWidget(), 1) + self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), "trash", self.getCurrentTreeWidget(), -1) + self.getCurrentMessageTextedit().setText("") + tableWidget.removeRow(currentRow) + self.statusBar().showMessage(_translate( + "MainWindow", "Undeleted item.")) + if currentRow == 0: + tableWidget.selectRow(currentRow) + else: + tableWidget.selectRow(currentRow - 1) def on_action_InboxSaveMessageAs(self): - currentInboxRow = self.ui.tableWidgetInbox.currentRow() + tableWidget = self.getCurrentMessagelist() + if not tableWidget: + return + currentInboxRow = tableWidget.currentRow() try: - subjectAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item(currentInboxRow,2).text()) + subjectAtCurrentInboxRow = str(tableWidget.item(currentInboxRow,2).data(Qt.UserRole)) except: subjectAtCurrentInboxRow = '' # Retrieve the message data out of the SQL database - msgid = str(self.ui.tableWidgetInbox.item( + msgid = str(tableWidget.item( currentInboxRow, 3).data(Qt.UserRole).toPyObject()) queryreturn = sqlQuery( '''select message from inbox where msgid=?''', msgid) @@ -2882,29 +3098,41 @@ more work your computer must do to send the message. A Time-To-Live of four or f f.write(message) f.close() except Exception, e: - sys.stderr.write('Write error: '+ e) + logger.exception('Message not saved', exc_info=True) self.statusBar().showMessage(_translate("MainWindow", "Write error.")) # Send item on the Sent tab to trash def on_action_SentTrash(self): - while self.ui.tableWidgetSent.selectedIndexes() != []: - currentRow = self.ui.tableWidgetSent.selectedIndexes()[0].row() - ackdataToTrash = str(self.ui.tableWidgetSent.item( + currentRow = 0 + unread = False + tableWidget = self.getCurrentMessagelist() + if not tableWidget: + return + folder = self.getCurrentFolder() + shifted = (QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier) > 0 + while tableWidget.selectedIndexes() != []: + currentRow = tableWidget.selectedIndexes()[0].row() + ackdataToTrash = str(tableWidget.item( currentRow, 3).data(Qt.UserRole).toPyObject()) - sqlExecute('''UPDATE sent SET folder='trash' WHERE ackdata=?''', ackdataToTrash) - self.ui.textEditSentMessage.setPlainText("") - self.ui.tableWidgetSent.removeRow(currentRow) + if folder == "trash" or shifted: + sqlExecute('''DELETE FROM sent WHERE ackdata=?''', ackdataToTrash) + else: + sqlExecute('''UPDATE sent SET folder='trash' WHERE ackdata=?''', ackdataToTrash) + if tableWidget.item(currentRow, 0).unread: + self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), folder, self.getCurrentTreeWidget(), -1) + self.getCurrentMessageTextedit().setPlainText("") + tableWidget.removeRow(currentRow) self.statusBar().showMessage(_translate( - "MainWindow", "Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back.")) + "MainWindow", "Moved items to trash.")) if currentRow == 0: - self.ui.tableWidgetSent.selectRow(currentRow) + self.ui.tableWidgetInbox.selectRow(currentRow) else: - self.ui.tableWidgetSent.selectRow(currentRow - 1) + self.ui.tableWidgetInbox.selectRow(currentRow - 1) def on_action_ForceSend(self): - currentRow = self.ui.tableWidgetSent.currentRow() - addressAtCurrentRow = str(self.ui.tableWidgetSent.item( - currentRow, 0).data(Qt.UserRole).toPyObject()) + currentRow = self.ui.tableWidgetInbox.currentRow() + addressAtCurrentRow = self.ui.tableWidgetInbox.item( + currentRow, 0).data(Qt.UserRole) toRipe = decodeAddress(addressAtCurrentRow)[3] sqlExecute( '''UPDATE sent SET status='forcepow' WHERE toripe=? AND status='toodifficult' and folder='sent' ''', @@ -2917,9 +3145,9 @@ more work your computer must do to send the message. A Time-To-Live of four or f shared.workerQueue.put(('sendmessage', '')) def on_action_SentClipboard(self): - currentRow = self.ui.tableWidgetSent.currentRow() - addressAtCurrentRow = str(self.ui.tableWidgetSent.item( - currentRow, 0).data(Qt.UserRole).toPyObject()) + currentRow = self.ui.tableWidgetInbox.currentRow() + addressAtCurrentRow = self.ui.tableWidgetInbox.item( + currentRow, 0).data(Qt.UserRole) clipboard = QtGui.QApplication.clipboard() clipboard.setText(str(addressAtCurrentRow)) @@ -2938,8 +3166,8 @@ more work your computer must do to send the message. A Time-To-Live of four or f sqlExecute('''DELETE FROM addressbook WHERE label=? AND address=?''', str(labelAtCurrentRow), str(addressAtCurrentRow)) self.ui.tableWidgetAddressBook.removeRow(currentRow) - self.rerenderInboxFromLabels() - self.rerenderSentToLabels() + self.rerenderMessagelistFromLabels() + self.rerenderMessagelistToLabels() def on_action_AddressBookClipboard(self): fullStringOfAddresses = '' @@ -2964,12 +3192,15 @@ more work your computer must do to send the message. A Time-To-Live of four or f self.ui.tableWidgetAddressBook.selectedIndexes()[i].row()] = 0 for currentRow in listOfSelectedRows: addressAtCurrentRow = self.ui.tableWidgetAddressBook.item( - currentRow, 1).text() + currentRow, 0).address + labelAtCurrentRow = self.ui.tableWidgetAddressBook.item( + currentRow, 0).label + stringToAdd = labelAtCurrentRow + " <" + addressAtCurrentRow + ">" if self.ui.lineEditTo.text() == '': - self.ui.lineEditTo.setText(str(addressAtCurrentRow)) + self.ui.lineEditTo.setText(stringToAdd) else: - self.ui.lineEditTo.setText(str( - self.ui.lineEditTo.text()) + '; ' + str(addressAtCurrentRow)) + self.ui.lineEditTo.setText(unicode( + self.ui.lineEditTo.text().toUtf8(), encoding="UTF-8") + '; ' + stringToAdd) if listOfSelectedRows == {}: self.statusBar().showMessage(_translate( "MainWindow", "No addresses selected.")) @@ -2985,13 +3216,30 @@ more work your computer must do to send the message. A Time-To-Live of four or f addressAtCurrentRow = str(self.ui.tableWidgetAddressBook.item(currentRow,1).text()) # Then subscribe to it... provided it's not already in the address book if shared.isAddressInMySubscriptionsList(addressAtCurrentRow): - self.statusBar().showMessage(QtGui.QApplication.translate("MainWindow", "Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want.")) + self.statusBar().showMessage(QtGui.QApplication.translate("MainWindow", "Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want.")) continue labelAtCurrentRow = self.ui.tableWidgetAddressBook.item(currentRow,0).text().toUtf8() self.addSubscription(addressAtCurrentRow, labelAtCurrentRow) self.ui.tabWidget.setCurrentIndex(4) def on_context_menuAddressBook(self, point): + self.popMenuAddressBook = QtGui.QMenu(self) + self.popMenuAddressBook.addAction(self.actionAddressBookSend) + self.popMenuAddressBook.addAction(self.actionAddressBookClipboard) + self.popMenuAddressBook.addAction(self.actionAddressBookSubscribe) + self.popMenuAddressBook.addAction(self.actionAddressBookSetAvatar) + self.popMenuAddressBook.addSeparator() + self.popMenuAddressBook.addAction(self.actionAddressBookNew) + normal = True + for row in self.ui.tableWidgetAddressBook.selectedIndexes(): + currentRow = row.row() + type = self.ui.tableWidgetAddressBook.item( + currentRow, 0).type + if type != AccountMixin.NORMAL: + normal = False + if normal: + # only if all selected addressbook items are normal, allow delete + self.popMenuAddressBook.addAction(self.actionAddressBookDelete) self.popMenuAddressBook.exec_( self.ui.tableWidgetAddressBook.mapToGlobal(point)) @@ -3000,186 +3248,324 @@ more work your computer must do to send the message. A Time-To-Live of four or f self.click_pushButtonAddSubscription() def on_action_SubscriptionsDelete(self): - print 'clicked Delete' - currentRow = self.ui.tableWidgetSubscriptions.currentRow() - labelAtCurrentRow = self.ui.tableWidgetSubscriptions.item( - currentRow, 0).text().toUtf8() - addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item( - currentRow, 1).text() - sqlExecute('''DELETE FROM subscriptions WHERE label=? AND address=?''', - str(labelAtCurrentRow), str(addressAtCurrentRow)) - self.ui.tableWidgetSubscriptions.removeRow(currentRow) - self.rerenderInboxFromLabels() + if QtGui.QMessageBox.question(self, "Delete subscription?", _translate("MainWindow", "If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received.\n\nAre you sure you want to delete the subscription?"), QMessageBox.Yes|QMessageBox.No) != QMessageBox.Yes: + return + address = self.getCurrentAccount() + sqlExecute('''DELETE FROM subscriptions WHERE address=?''', + address) + self.rerenderTabTreeSubscriptions() + self.rerenderMessagelistFromLabels() + self.rerenderAddressBook() shared.reloadBroadcastSendersForWhichImWatching() def on_action_SubscriptionsClipboard(self): - currentRow = self.ui.tableWidgetSubscriptions.currentRow() - addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item( - currentRow, 1).text() + address = self.getCurrentAccount() clipboard = QtGui.QApplication.clipboard() - clipboard.setText(str(addressAtCurrentRow)) + clipboard.setText(str(address)) def on_action_SubscriptionsEnable(self): - currentRow = self.ui.tableWidgetSubscriptions.currentRow() - labelAtCurrentRow = self.ui.tableWidgetSubscriptions.item( - currentRow, 0).text().toUtf8() - addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item( - currentRow, 1).text() + address = self.getCurrentAccount() sqlExecute( - '''update subscriptions set enabled=1 WHERE label=? AND address=?''', - str(labelAtCurrentRow), str(addressAtCurrentRow)) - self.ui.tableWidgetSubscriptions.item( - currentRow, 0).setTextColor(QApplication.palette().text().color()) - self.ui.tableWidgetSubscriptions.item( - currentRow, 1).setTextColor(QApplication.palette().text().color()) + '''update subscriptions set enabled=1 WHERE address=?''', + address) + account = self.getCurrentItem() + account.setEnabled(True) + self.rerenderAddressBook() shared.reloadBroadcastSendersForWhichImWatching() def on_action_SubscriptionsDisable(self): - currentRow = self.ui.tableWidgetSubscriptions.currentRow() - labelAtCurrentRow = self.ui.tableWidgetSubscriptions.item( - currentRow, 0).text().toUtf8() - addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item( - currentRow, 1).text() + address = self.getCurrentAccount() sqlExecute( - '''update subscriptions set enabled=0 WHERE label=? AND address=?''', - str(labelAtCurrentRow), str(addressAtCurrentRow)) - self.ui.tableWidgetSubscriptions.item( - currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128)) - self.ui.tableWidgetSubscriptions.item( - currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) + '''update subscriptions set enabled=0 WHERE address=?''', + address) + account = self.getCurrentItem() + account.setEnabled(False) + self.rerenderAddressBook() shared.reloadBroadcastSendersForWhichImWatching() def on_context_menuSubscriptions(self, point): + currentItem = self.getCurrentItem() + if not isinstance(currentItem, Ui_AddressWidget): + return + self.popMenuSubscriptions = QtGui.QMenu(self) + self.popMenuSubscriptions.addAction(self.actionsubscriptionsNew) + self.popMenuSubscriptions.addAction(self.actionsubscriptionsDelete) + self.popMenuSubscriptions.addSeparator() + if currentItem.isEnabled: + self.popMenuSubscriptions.addAction(self.actionsubscriptionsDisable) + else: + self.popMenuSubscriptions.addAction(self.actionsubscriptionsEnable) + self.popMenuSubscriptions.addAction(self.actionsubscriptionsSetAvatar) + self.popMenuSubscriptions.addSeparator() + self.popMenuSubscriptions.addAction(self.actionsubscriptionsClipboard) self.popMenuSubscriptions.exec_( - self.ui.tableWidgetSubscriptions.mapToGlobal(point)) + self.ui.treeWidgetSubscriptions.mapToGlobal(point)) - # Group of functions for the Blacklist dialog box - def on_action_BlacklistNew(self): - self.click_pushButtonAddBlacklist() - - def on_action_BlacklistDelete(self): - currentRow = self.ui.tableWidgetBlacklist.currentRow() - labelAtCurrentRow = self.ui.tableWidgetBlacklist.item( - currentRow, 0).text().toUtf8() - addressAtCurrentRow = self.ui.tableWidgetBlacklist.item( - currentRow, 1).text() - if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': - sqlExecute( - '''DELETE FROM blacklist WHERE label=? AND address=?''', - str(labelAtCurrentRow), str(addressAtCurrentRow)) + def widgetConvert (self, widget): + if widget == self.ui.tableWidgetInbox: + return self.ui.treeWidgetYourIdentities + elif widget == self.ui.tableWidgetInboxSubscriptions: + return self.ui.treeWidgetSubscriptions + elif widget == self.ui.tableWidgetInboxChans: + return self.ui.treeWidgetChans + elif widget == self.ui.treeWidgetYourIdentities: + return self.ui.tableWidgetInbox + elif widget == self.ui.treeWidgetSubscriptions: + return self.ui.tableWidgetInboxSubscriptions + elif widget == self.ui.treeWidgetChans: + return self.ui.tableWidgetInboxChans else: - sqlExecute( - '''DELETE FROM whitelist WHERE label=? AND address=?''', - str(labelAtCurrentRow), str(addressAtCurrentRow)) - self.ui.tableWidgetBlacklist.removeRow(currentRow) + return None - def on_action_BlacklistClipboard(self): - currentRow = self.ui.tableWidgetBlacklist.currentRow() - addressAtCurrentRow = self.ui.tableWidgetBlacklist.item( - currentRow, 1).text() - clipboard = QtGui.QApplication.clipboard() - clipboard.setText(str(addressAtCurrentRow)) - - def on_context_menuBlacklist(self, point): - self.popMenuBlacklist.exec_( - self.ui.tableWidgetBlacklist.mapToGlobal(point)) - - def on_action_BlacklistEnable(self): - currentRow = self.ui.tableWidgetBlacklist.currentRow() - addressAtCurrentRow = self.ui.tableWidgetBlacklist.item( - currentRow, 1).text() - self.ui.tableWidgetBlacklist.item( - currentRow, 0).setTextColor(QApplication.palette().text().color()) - self.ui.tableWidgetBlacklist.item( - currentRow, 1).setTextColor(QApplication.palette().text().color()) - if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': - sqlExecute( - '''UPDATE blacklist SET enabled=1 WHERE address=?''', - str(addressAtCurrentRow)) + def getCurrentTreeWidget(self): + currentIndex = self.ui.tabWidget.currentIndex(); + treeWidgetList = [ + self.ui.treeWidgetYourIdentities, + False, + self.ui.treeWidgetSubscriptions, + self.ui.treeWidgetChans + ] + if currentIndex >= 0 and currentIndex < len(treeWidgetList): + return treeWidgetList[currentIndex] else: - sqlExecute( - '''UPDATE whitelist SET enabled=1 WHERE address=?''', - str(addressAtCurrentRow)) + return False - def on_action_BlacklistDisable(self): - currentRow = self.ui.tableWidgetBlacklist.currentRow() - addressAtCurrentRow = self.ui.tableWidgetBlacklist.item( - currentRow, 1).text() - self.ui.tableWidgetBlacklist.item( - currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128)) - self.ui.tableWidgetBlacklist.item( - currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) - if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': - sqlExecute( - '''UPDATE blacklist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow)) + def getAccountTreeWidget(self, account): + try: + if account.type == AccountMixin.CHAN: + return self.ui.treeWidgetChans + elif account.type == AccountMixin.SUBSCRIPTION: + return self.ui.treeWidgetSubscriptions + else: + return self.ui.treeWidgetYourIdentities + except: + return self.ui.treeWidgetYourIdentities + + def getCurrentMessagelist(self): + currentIndex = self.ui.tabWidget.currentIndex(); + messagelistList = [ + self.ui.tableWidgetInbox, + False, + self.ui.tableWidgetInboxSubscriptions, + self.ui.tableWidgetInboxChans, + ] + if currentIndex >= 0 and currentIndex < len(messagelistList): + return messagelistList[currentIndex] else: - sqlExecute( - '''UPDATE whitelist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow)) + return False + + def getAccountMessagelist(self, account): + try: + if account.type == AccountMixin.CHAN: + return self.ui.tableWidgetInboxChans + elif account.type == AccountMixin.SUBSCRIPTION: + return self.ui.tableWidgetInboxSubscriptions + else: + return self.ui.tableWidgetInbox + except: + return self.ui.tableWidgetInbox + + def getCurrentMessageId(self): + messagelist = self.getCurrentMessagelist() + if messagelist: + currentRow = messagelist.currentRow() + if currentRow >= 0: + msgid = str(messagelist.item( + currentRow, 3).data(Qt.UserRole).toPyObject()) # data is saved at the 4. column of the table... + return msgid + return False + + def getCurrentMessageTextedit(self): + currentIndex = self.ui.tabWidget.currentIndex(); + messagelistList = [ + self.ui.textEditInboxMessage, + False, + self.ui.textEditInboxMessageSubscriptions, + self.ui.textEditInboxMessageChans, + ] + if currentIndex >= 0 and currentIndex < len(messagelistList): + return messagelistList[currentIndex] + else: + return False + + def getAccountTextedit(self, account): + try: + if account.type == AccountMixin.CHAN: + return self.ui.textEditInboxMessageChans + elif account.type == AccountMixin.SUBSCRIPTION: + return self.ui.textEditInboxSubscriptions + else: + return self.ui.textEditInboxMessage + except: + return self.ui.textEditInboxMessage + + def getCurrentSearchLine(self, currentIndex = None, retObj = False): + if currentIndex is None: + currentIndex = self.ui.tabWidget.currentIndex(); + messagelistList = [ + self.ui.inboxSearchLineEdit, + False, + self.ui.inboxSearchLineEditSubscriptions, + self.ui.inboxSearchLineEditChans, + ] + if currentIndex >= 0 and currentIndex < len(messagelistList): + if retObj: + return messagelistList[currentIndex] + else: + return messagelistList[currentIndex].text().toUtf8().data() + else: + return None + + def getCurrentSearchOption(self, currentIndex = None): + if currentIndex is None: + currentIndex = self.ui.tabWidget.currentIndex(); + messagelistList = [ + self.ui.inboxSearchOption, + False, + self.ui.inboxSearchOptionSubscriptions, + self.ui.inboxSearchOptionChans, + ] + if currentIndex >= 0 and currentIndex < len(messagelistList): + return messagelistList[currentIndex].currentText().toUtf8().data() + else: + return None # Group of functions for the Your Identities dialog box + def getCurrentItem(self, treeWidget = None): + if treeWidget is None: + treeWidget = self.getCurrentTreeWidget() + if treeWidget: + currentItem = treeWidget.currentItem() + if currentItem: + return currentItem + return False + + def getCurrentAccount(self, treeWidget = None): + currentItem = self.getCurrentItem(treeWidget) + if currentItem: + account = currentItem.address + return account + else: + # TODO need debug msg? + return False + + def getCurrentFolder(self, treeWidget = None): + if treeWidget is None: + treeWidget = self.getCurrentTreeWidget() + #treeWidget = self.ui.treeWidgetYourIdentities + if treeWidget: + currentItem = treeWidget.currentItem() + if currentItem and hasattr(currentItem, 'folderName'): + return currentItem.folderName + else: + return None + + def setCurrentItemColor(self, color): + treeWidget = self.getCurrentTreeWidget() + if treeWidget: + brush = QtGui.QBrush() + brush.setStyle(QtCore.Qt.NoBrush) + brush.setColor(color) + currentItem = treeWidget.currentItem() + currentItem.setForeground(0, brush) + def on_action_YourIdentitiesNew(self): self.click_NewAddressDialog() - def on_action_YourIdentitiesEnable(self): - currentRow = self.ui.tableWidgetYourIdentities.currentRow() - addressAtCurrentRow = str( - self.ui.tableWidgetYourIdentities.item(currentRow, 1).text()) - shared.config.set(addressAtCurrentRow, 'enabled', 'true') - shared.writeKeysFile() - self.ui.tableWidgetYourIdentities.item( - currentRow, 0).setTextColor(QApplication.palette().text().color()) - self.ui.tableWidgetYourIdentities.item( - currentRow, 1).setTextColor(QApplication.palette().text().color()) - self.ui.tableWidgetYourIdentities.item( - currentRow, 2).setTextColor(QApplication.palette().text().color()) - if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'): - self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) # magenta - if shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'): - self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(216, 119, 0)) # orange - shared.reloadMyAddressHashes() - - def on_action_YourIdentitiesDisable(self): - currentRow = self.ui.tableWidgetYourIdentities.currentRow() - addressAtCurrentRow = str( - self.ui.tableWidgetYourIdentities.item(currentRow, 1).text()) - shared.config.set(str(addressAtCurrentRow), 'enabled', 'false') - self.ui.tableWidgetYourIdentities.item( - currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128)) - self.ui.tableWidgetYourIdentities.item( - currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) - self.ui.tableWidgetYourIdentities.item( - currentRow, 2).setTextColor(QtGui.QColor(128, 128, 128)) - if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'): - self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) # magenta + def on_action_YourIdentitiesDelete(self): + account = self.getCurrentItem() + if account.type == AccountMixin.NORMAL: + return # maybe in the future + elif account.type == AccountMixin.CHAN: + if QtGui.QMessageBox.question(self, "Delete channel?", _translate("MainWindow", "If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received.\n\nAre you sure you want to delete the channel?"), QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes: + shared.config.remove_section(str(account.address)) + else: + return + else: + return shared.writeKeysFile() shared.reloadMyAddressHashes() + self.rerenderAddressBook() + if account.type == AccountMixin.NORMAL: + self.rerenderTabTreeMessages() + elif account.type == AccountMixin.CHAN: + self.rerenderTabTreeChans() - def on_action_YourIdentitiesClipboard(self): - currentRow = self.ui.tableWidgetYourIdentities.currentRow() - addressAtCurrentRow = self.ui.tableWidgetYourIdentities.item( - currentRow, 1).text() + def on_action_Enable(self): + addressAtCurrentRow = self.getCurrentAccount() + self.enableIdentity(addressAtCurrentRow) + account = self.getCurrentItem() + account.setEnabled(True) + + def enableIdentity(self, address): + shared.config.set(address, 'enabled', 'true') + shared.writeKeysFile() + shared.reloadMyAddressHashes() + self.rerenderAddressBook() + + def on_action_Disable(self): + address = self.getCurrentAccount() + self.disableIdentity(address) + account = self.getCurrentItem() + account.setEnabled(False) + + def disableIdentity(self, address): + shared.config.set(str(address), 'enabled', 'false') + shared.writeKeysFile() + shared.reloadMyAddressHashes() + self.rerenderAddressBook() + + def on_action_Clipboard(self): + address = self.getCurrentAccount() clipboard = QtGui.QApplication.clipboard() - clipboard.setText(str(addressAtCurrentRow)) - - def on_action_YourIdentitiesSetAvatar(self): - self.on_action_SetAvatar(self.ui.tableWidgetYourIdentities) + clipboard.setText(str(address)) + def on_action_ClipboardMessagelist(self): + tableWidget = self.getCurrentMessagelist() + currentColumn = tableWidget.currentColumn() + currentRow = tableWidget.currentRow() + if currentColumn not in [0, 1, 2]: # to, from, subject + if self.getCurrentFolder() == "sent": + currentColumn = 0 + else: + currentColumn = 1 + if self.getCurrentFolder() == "sent": + myAddress = tableWidget.item(currentRow, 1).data(Qt.UserRole) + otherAddress = tableWidget.item(currentRow, 0).data(Qt.UserRole) + else: + myAddress = tableWidget.item(currentRow, 0).data(Qt.UserRole) + otherAddress = tableWidget.item(currentRow, 1).data(Qt.UserRole) + account = accountClass(myAddress) + if isinstance(account, GatewayAccount) and otherAddress == account.relayAddress and ( + (currentColumn in [0, 2] and self.getCurrentFolder() == "sent") or + (currentColumn in [1, 2] and self.getCurrentFolder() != "sent")): + text = str(tableWidget.item(currentRow, currentColumn).label) + else: + text = tableWidget.item(currentRow, currentColumn).data(Qt.UserRole) + text = unicode(str(text), 'utf-8', 'ignore') + clipboard = QtGui.QApplication.clipboard() + clipboard.setText(text) + + #set avatar functions + def on_action_TreeWidgetSetAvatar(self): + address = self.getCurrentAccount() + self.setAvatar(address) + def on_action_AddressBookSetAvatar(self): self.on_action_SetAvatar(self.ui.tableWidgetAddressBook) - def on_action_SubscriptionsSetAvatar(self): - self.on_action_SetAvatar(self.ui.tableWidgetSubscriptions) - - def on_action_BlacklistSetAvatar(self): - self.on_action_SetAvatar(self.ui.tableWidgetBlacklist) - def on_action_SetAvatar(self, thisTableWidget): - # thisTableWidget = self.ui.tableWidgetYourIdentities - if not os.path.exists(shared.appdata + 'avatars/'): - os.makedirs(shared.appdata + 'avatars/') currentRow = thisTableWidget.currentRow() addressAtCurrentRow = thisTableWidget.item( currentRow, 1).text() + setToIdenticon = not self.setAvatar(addressAtCurrentRow) + if setToIdenticon: + thisTableWidget.item( + currentRow, 0).setIcon(avatarize(addressAtCurrentRow)) + + def setAvatar(self, addressAtCurrentRow): + if not os.path.exists(shared.appdata + 'avatars/'): + os.makedirs(shared.appdata + 'avatars/') hash = hashlib.md5(addBMIfNotPresent(addressAtCurrentRow)).hexdigest() extensions = ['PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM', 'PGM', 'PPM', 'TIFF', 'XBM', 'XPM', 'TGA'] # http://pyqt.sourceforge.net/Docs/PyQt4/qimagereader.html#supportedImageFormats @@ -3229,25 +3615,94 @@ more work your computer must do to send the message. A Time-To-Live of four or f if sourcefile != '': copied = QtCore.QFile.copy(sourcefile, destination) if not copied: - print 'couldn\'t copy :(' - return False + logger.error('couldn\'t copy :(') # set the icon - thisTableWidget.item( - currentRow, 0).setIcon(avatarize(addressAtCurrentRow)) - self.rerenderSubscriptions() + self.rerenderTabTreeMessages() + self.rerenderTabTreeSubscriptions() + self.rerenderTabTreeChans() self.rerenderComboBoxSendFrom() - self.rerenderInboxFromLabels() - self.rerenderInboxToLabels() - self.rerenderSentFromLabels() - self.rerenderSentToLabels() - self.rerenderBlackWhiteList() + self.rerenderComboBoxSendFromBroadcast() + self.rerenderMessagelistFromLabels() + self.rerenderMessagelistToLabels() + self.ui.blackwhitelist.rerenderBlackWhiteList() + # generate identicon + return False + + return True def on_context_menuYourIdentities(self, point): + currentItem = self.getCurrentItem() + if not isinstance(currentItem, Ui_AddressWidget): + return + self.popMenuYourIdentities = QtGui.QMenu(self) + self.popMenuYourIdentities.addAction(self.actionNewYourIdentities) + self.popMenuYourIdentities.addSeparator() + self.popMenuYourIdentities.addAction(self.actionClipboardYourIdentities) + self.popMenuYourIdentities.addSeparator() + if currentItem.isEnabled: + self.popMenuYourIdentities.addAction(self.actionDisableYourIdentities) + else: + self.popMenuYourIdentities.addAction(self.actionEnableYourIdentities) + self.popMenuYourIdentities.addAction(self.actionSetAvatarYourIdentities) + self.popMenuYourIdentities.addAction(self.actionSpecialAddressBehaviorYourIdentities) + self.popMenuYourIdentities.addAction(self.actionEmailGateway) + self.popMenuYourIdentities.exec_( + self.ui.treeWidgetYourIdentities.mapToGlobal(point)) + + # TODO make one popMenu + def on_context_menuChan(self, point): + currentItem = self.getCurrentItem() + if not isinstance(currentItem, Ui_AddressWidget): + return + self.popMenu = QtGui.QMenu(self) + self.popMenu.addAction(self.actionNew) + self.popMenu.addAction(self.actionDelete) + self.popMenu.addSeparator() + self.popMenu.addAction(self.actionClipboard) + self.popMenu.addSeparator() + if currentItem.isEnabled: + self.popMenu.addAction(self.actionDisable) + else: + self.popMenu.addAction(self.actionEnable) + self.popMenu.addAction(self.actionSetAvatar) self.popMenu.exec_( - self.ui.tableWidgetYourIdentities.mapToGlobal(point)) + self.ui.treeWidgetChans.mapToGlobal(point)) def on_context_menuInbox(self, point): - self.popMenuInbox.exec_(self.ui.tableWidgetInbox.mapToGlobal(point)) + tableWidget = self.getCurrentMessagelist() + if tableWidget: + currentFolder = self.getCurrentFolder() + if currentFolder is None: + pass + if currentFolder == 'sent': + self.on_context_menuSent(point) + else: + self.popMenuInbox = QtGui.QMenu(self) + self.popMenuInbox.addAction(self.actionForceHtml) + self.popMenuInbox.addAction(self.actionMarkUnread) + self.popMenuInbox.addSeparator() + address = tableWidget.item( + tableWidget.currentRow(), 0).data(Qt.UserRole) + account = accountClass(address) + if account.type == AccountMixin.CHAN: + self.popMenuInbox.addAction(self.actionReplyChan) + self.popMenuInbox.addAction(self.actionReply) + self.popMenuInbox.addAction(self.actionAddSenderToAddressBook) + self.actionClipboardMessagelist = self.ui.inboxContextMenuToolbar.addAction( + _translate("MainWindow", + "Copy subject to clipboard" if tableWidget.currentColumn() == 2 else "Copy address to clipboard" + ), + self.on_action_ClipboardMessagelist) + self.popMenuInbox.addAction(self.actionClipboardMessagelist) + self.popMenuInbox.addSeparator() + self.popMenuInbox.addAction(self.actionAddSenderToBlackList) + self.popMenuInbox.addSeparator() + self.popMenuInbox.addAction(self.actionSaveMessageAs) + if currentFolder == "trash": + self.popMenuInbox.addAction(self.actionUndeleteTrashedMessage) + else: + self.popMenuInbox.addAction(self.actionTrashInboxMessage) + self.popMenuInbox.exec_(tableWidget.mapToGlobal(point)) def on_context_menuSent(self, point): self.popMenuSent = QtGui.QMenu(self) @@ -3256,155 +3711,180 @@ more work your computer must do to send the message. A Time-To-Live of four or f # Check to see if this item is toodifficult and display an additional # menu option (Force Send) if it is. - currentRow = self.ui.tableWidgetSent.currentRow() - ackData = str(self.ui.tableWidgetSent.item( - currentRow, 3).data(Qt.UserRole).toPyObject()) - queryreturn = sqlQuery('''SELECT status FROM sent where ackdata=?''', ackData) - for row in queryreturn: - status, = row - if status == 'toodifficult': - self.popMenuSent.addAction(self.actionForceSend) - self.popMenuSent.exec_(self.ui.tableWidgetSent.mapToGlobal(point)) - - def inboxSearchLineEditPressed(self): - searchKeyword = self.ui.inboxSearchLineEdit.text().toUtf8().data() - searchOption = self.ui.inboxSearchOptionCB.currentText().toUtf8().data() - self.ui.inboxSearchLineEdit.setText(QString("")) - self.ui.textEditInboxMessage.setPlainText(QString("")) - self.loadInbox(searchOption, searchKeyword) - - def sentSearchLineEditPressed(self): - searchKeyword = self.ui.sentSearchLineEdit.text().toUtf8().data() - searchOption = self.ui.sentSearchOptionCB.currentText().toUtf8().data() - self.ui.sentSearchLineEdit.setText(QString("")) - self.ui.textEditInboxMessage.setPlainText(QString("")) - self.loadSent(searchOption, searchKeyword) - - def tableWidgetInboxItemClicked(self): currentRow = self.ui.tableWidgetInbox.currentRow() if currentRow >= 0: - font = QFont() - font.setBold(False) - self.ui.textEditInboxMessage.setCurrentFont(font) - - fromAddress = str(self.ui.tableWidgetInbox.item( - currentRow, 1).data(Qt.UserRole).toPyObject()) - msgid = str(self.ui.tableWidgetInbox.item( + ackData = str(self.ui.tableWidgetInbox.item( currentRow, 3).data(Qt.UserRole).toPyObject()) - queryreturn = sqlQuery( - '''select message from inbox where msgid=?''', msgid) - if queryreturn != []: - for row in queryreturn: - messageText, = row - messageText = shared.fixPotentiallyInvalidUTF8Data(messageText) - messageText = unicode(messageText, 'utf-8)') - if len(messageText) > 30000: - messageText = ( - messageText[:30000] + '\n' + - '--- Display of the remainder of the message ' + - 'truncated because it is too long.\n' + - '--- To see the full message, right-click in the ' + - 'Inbox view and select "View HTML code as formatted ' + - 'text",\n' + - '--- or select "Save message as..." to save it to a ' + - 'file, or select "Reply" and ' + - 'view the full message in the quote.') - # If we have received this message from either a broadcast address - # or from someone in our address book, display as HTML - if decodeAddress(fromAddress)[3] in shared.broadcastSendersForWhichImWatching or shared.isAddressInMyAddressBook(fromAddress): - self.ui.textEditInboxMessage.setText(messageText) - else: - self.ui.textEditInboxMessage.setPlainText(messageText) + queryreturn = sqlQuery('''SELECT status FROM sent where ackdata=?''', ackData) + for row in queryreturn: + status, = row + if status == 'toodifficult': + self.popMenuSent.addAction(self.actionForceSend) - self.ui.tableWidgetInbox.item(currentRow, 0).setFont(font) - self.ui.tableWidgetInbox.item(currentRow, 1).setFont(font) - self.ui.tableWidgetInbox.item(currentRow, 2).setFont(font) - self.ui.tableWidgetInbox.item(currentRow, 3).setFont(font) + self.popMenuSent.exec_(self.ui.tableWidgetInbox.mapToGlobal(point)) - inventoryHash = str(self.ui.tableWidgetInbox.item( - currentRow, 3).data(Qt.UserRole).toPyObject()) - self.ubuntuMessagingMenuClear(inventoryHash) - sqlExecute('''update inbox set read=1 WHERE msgid=?''', inventoryHash) - self.changedInboxUnread() + def inboxSearchLineEditUpdated(self, text): + # dynamic search for too short text is slow + if len(str(text)) < 3: + return + messagelist = self.getCurrentMessagelist() + searchOption = self.getCurrentSearchOption() + if messagelist: + account = self.getCurrentAccount() + folder = self.getCurrentFolder() + self.loadMessagelist(messagelist, account, folder, searchOption, str(text)) - def tableWidgetSentItemClicked(self): - currentRow = self.ui.tableWidgetSent.currentRow() - if currentRow >= 0: - ackdata = str(self.ui.tableWidgetSent.item( - currentRow, 3).data(Qt.UserRole).toPyObject()) - queryreturn = sqlQuery( - '''select message from sent where ackdata=?''', ackdata) - if queryreturn != []: - for row in queryreturn: - message, = row - else: - message = "Error occurred: could not load message from disk." - message = unicode(message, 'utf-8)') - self.ui.textEditSentMessage.setPlainText(message) + def inboxSearchLineEditReturnPressed(self): + logger.debug("Search return pressed") + searchLine = self.getCurrentSearchLine() + messagelist = self.getCurrentMessagelist() + if len(str(searchLine)) < 3: + searchOption = self.getCurrentSearchOption() + account = self.getCurrentAccount() + folder = self.getCurrentFolder() + self.loadMessagelist(messagelist, account, folder, searchOption, searchLine) + if messagelist: + messagelist.setFocus() - def tableWidgetYourIdentitiesItemChanged(self): - currentRow = self.ui.tableWidgetYourIdentities.currentRow() - if currentRow >= 0: - addressAtCurrentRow = self.ui.tableWidgetYourIdentities.item( - currentRow, 1).text() - shared.config.set(str(addressAtCurrentRow), 'label', str( - self.ui.tableWidgetYourIdentities.item(currentRow, 0).text().toUtf8())) - shared.writeKeysFile() + def treeWidgetItemClicked(self): + searchLine = self.getCurrentSearchLine() + searchOption = self.getCurrentSearchOption() + messageTextedit = self.getCurrentMessageTextedit() + if messageTextedit: + messageTextedit.setPlainText(QString("")) + messagelist = self.getCurrentMessagelist() + if messagelist: + account = self.getCurrentAccount() + folder = self.getCurrentFolder() + self.loadMessagelist(messagelist, account, folder, searchOption, searchLine) + + def treeWidgetItemChanged(self, item, column): + # only for manual edits. automatic edits (setText) are ignored + if column != 0: + return + # only account names of normal addresses (no chans/mailinglists) + if (not isinstance(item, Ui_AddressWidget)) or (not self.getCurrentTreeWidget()) or self.getCurrentTreeWidget().currentItem() is None: + return + # not visible + if (not self.getCurrentItem()) or (not isinstance (self.getCurrentItem(), Ui_AddressWidget)): + return + # only currently selected item + if item.address != self.getCurrentAccount(): + return + # "All accounts" can't be renamed + if item.type == AccountMixin.ALL: + return + + newLabel = unicode(item.text(0), 'utf-8', 'ignore') + oldLabel = item.defaultLabel() + + # unchanged, do not do anything either + if newLabel == oldLabel: + return + + # recursion prevention + if self.recurDepth > 0: + return + + self.recurDepth += 1 + if item.type == AccountMixin.NORMAL or item.type == AccountMixin.MAILINGLIST: + self.rerenderComboBoxSendFromBroadcast() + if item.type == AccountMixin.NORMAL or item.type == AccountMixin.CHAN: self.rerenderComboBoxSendFrom() - # self.rerenderInboxFromLabels() - self.rerenderInboxToLabels() - self.rerenderSentFromLabels() - # self.rerenderSentToLabels() + self.rerenderMessagelistFromLabels() + if item.type != AccountMixin.SUBSCRIPTION: + self.rerenderMessagelistToLabels() + if item.type in (AccountMixin.NORMAL, AccountMixin.CHAN, AccountMixin.SUBSCRIPTION): + self.rerenderAddressBook() + self.recurDepth -= 1 - def tableWidgetAddressBookItemChanged(self): - currentRow = self.ui.tableWidgetAddressBook.currentRow() - if currentRow >= 0: - addressAtCurrentRow = self.ui.tableWidgetAddressBook.item( - currentRow, 1).text() - sqlExecute('''UPDATE addressbook set label=? WHERE address=?''', - str(self.ui.tableWidgetAddressBook.item(currentRow, 0).text().toUtf8()), - str(addressAtCurrentRow)) - self.rerenderInboxFromLabels() - self.rerenderSentToLabels() + def tableWidgetInboxItemClicked(self): + folder = self.getCurrentFolder() + messageTextedit = self.getCurrentMessageTextedit() + if not messageTextedit: + return + queryreturn = [] + message = "" - def tableWidgetSubscriptionsItemChanged(self): - currentRow = self.ui.tableWidgetSubscriptions.currentRow() - if currentRow >= 0: - addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item( - currentRow, 1).text() - sqlExecute('''UPDATE subscriptions set label=? WHERE address=?''', - str(self.ui.tableWidgetSubscriptions.item(currentRow, 0).text().toUtf8()), - str(addressAtCurrentRow)) - self.rerenderInboxFromLabels() - self.rerenderSentToLabels() + if folder == 'sent': + ackdata = self.getCurrentMessageId() + if ackdata and messageTextedit: + queryreturn = sqlQuery( + '''select message, 1 from sent where ackdata=?''', ackdata) + else: + msgid = self.getCurrentMessageId() + if msgid and messageTextedit: + queryreturn = sqlQuery( + '''select message, read from inbox where msgid=?''', msgid) + + if queryreturn != []: + refresh = False + propagate = False + tableWidget = self.getCurrentMessagelist() + currentRow = tableWidget.currentRow() + for row in queryreturn: + message, read = row + if tableWidget.item(currentRow, 0).unread == True: + refresh = True + if folder != 'sent': + markread = sqlExecute( + '''UPDATE inbox SET read = 1 WHERE msgid = ? AND read=0''', msgid) + if markread > 0: + propagate = True + if refresh: + if not tableWidget: + return + font = QFont() + font.setBold(False) +# inventoryHashesToMarkRead = [] +# inventoryHashToMarkRead = str(tableWidget.item( +# currentRow, 3).data(Qt.UserRole).toPyObject()) +# inventoryHashesToMarkRead.append(inventoryHashToMarkRead) + tableWidget.item(currentRow, 0).setUnread(False) + tableWidget.item(currentRow, 1).setUnread(False) + tableWidget.item(currentRow, 2).setUnread(False) + tableWidget.item(currentRow, 3).setFont(font) + if propagate: + self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(Qt.UserRole), folder, self.getCurrentTreeWidget(), -1) + + else: + data = self.getCurrentMessageId() + if data != False: + message = "Error occurred: could not load message from disk." + messageTextedit.setCurrentFont(QtGui.QFont()) + messageTextedit.setTextColor(QtGui.QColor()) + messageTextedit.setContent(message) + + def tableWidgetAddressBookItemChanged(self, item): + if item.type == AccountMixin.CHAN: + self.rerenderComboBoxSendFrom() + self.rerenderMessagelistFromLabels() + self.rerenderMessagelistToLabels() def writeNewAddressToTable(self, label, address, streamNumber): - self.ui.tableWidgetYourIdentities.setSortingEnabled(False) - self.ui.tableWidgetYourIdentities.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) - newItem.setIcon(avatarize(address)) - self.ui.tableWidgetYourIdentities.setItem( - 0, 0, newItem) - newItem = QtGui.QTableWidgetItem(address) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - if shared.safeConfigGetBoolean(address, 'chan'): - newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange - self.ui.tableWidgetYourIdentities.setItem(0, 1, newItem) - newItem = QtGui.QTableWidgetItem(streamNumber) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetYourIdentities.setItem(0, 2, newItem) - # self.ui.tableWidgetYourIdentities.setSortingEnabled(True) + self.rerenderTabTreeMessages() + self.rerenderTabTreeSubscriptions() + self.rerenderTabTreeChans() self.rerenderComboBoxSendFrom() + self.rerenderComboBoxSendFromBroadcast() def updateStatusBar(self, data): if data != "": - with shared.printLock: - print 'Status bar:', data + logger.info('Status bar: ' + data) self.statusBar().showMessage(data) + def initSettings(self): + QtCore.QCoreApplication.setOrganizationName("PyBitmessage") + QtCore.QCoreApplication.setOrganizationDomain("bitmessage.org") + QtCore.QCoreApplication.setApplicationName("pybitmessageqt") + self.loadSettings() + for attr, obj in self.ui.__dict__.iteritems(): + if hasattr(obj, "__class__") and isinstance(obj, settingsmixin.SettingsMixin): + loadMethod = getattr(obj, "loadSettings", None) + if callable (loadMethod): + obj.loadSettings() + class helpDialog(QtGui.QDialog): @@ -3455,6 +3935,8 @@ class settingsDialog(QtGui.QDialog): shared.config.getboolean('bitmessagesettings', 'startonlogon')) self.ui.checkBoxMinimizeToTray.setChecked( shared.config.getboolean('bitmessagesettings', 'minimizetotray')) + self.ui.checkBoxTrayOnClose.setChecked( + shared.safeConfigGetBoolean('bitmessagesettings', 'trayonclose')) self.ui.checkBoxShowTrayNotifications.setChecked( shared.config.getboolean('bitmessagesettings', 'showtraynotifications')) self.ui.checkBoxStartInTray.setChecked( @@ -3466,17 +3948,16 @@ class settingsDialog(QtGui.QDialog): self.ui.checkBoxReplyBelow.setChecked( shared.safeConfigGetBoolean('bitmessagesettings', 'replybelow')) - global languages - languages = ['system','en','eo','fr','de','es','ru','no','ar','zh_cn','ja','nl','cs','en_pirate','other'] - user_countrycode = str(shared.config.get('bitmessagesettings', 'userlocale')) - if user_countrycode in languages: - curr_index = languages.index(user_countrycode) - else: - curr_index = languages.index('other') - self.ui.languageComboBox.setCurrentIndex(curr_index) - - if shared.appdata == '': + if shared.appdata == shared.lookupExeFolder(): self.ui.checkBoxPortableMode.setChecked(True) + else: + try: + import tempfile + file = tempfile.NamedTemporaryFile(dir=shared.lookupExeFolder(), delete=True) + file.close # should autodelete + except: + self.ui.checkBoxPortableMode.setDisabled(True) + if 'darwin' in sys.platform: self.ui.checkBoxStartOnLogon.setDisabled(True) self.ui.checkBoxStartOnLogon.setText(_translate( @@ -3494,6 +3975,8 @@ class settingsDialog(QtGui.QDialog): # On the Network settings tab: self.ui.lineEditTCPPort.setText(str( shared.config.get('bitmessagesettings', 'port'))) + self.ui.checkBoxUPnP.setChecked( + shared.safeConfigGetBoolean('bitmessagesettings', 'upnp')) self.ui.checkBoxAuthentication.setChecked(shared.config.getboolean( 'bitmessagesettings', 'socksauthentication')) self.ui.checkBoxSocksListen.setChecked(shared.config.getboolean( @@ -3540,6 +4023,16 @@ class settingsDialog(QtGui.QDialog): self.ui.lineEditMaxAcceptableSmallMessageDifficulty.setText(str((float(shared.config.getint( 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')) / shared.networkDefaultPayloadLengthExtraBytes))) + # OpenCL + if openclpow.has_opencl(): + self.ui.checkBoxOpenCL.setEnabled(True) + else: + self.ui.checkBoxOpenCL.setEnabled(False) + if shared.safeConfigGetBoolean("bitmessagesettings", "opencl"): + self.ui.checkBoxOpenCL.setChecked(True) + else: + self.ui.checkBoxOpenCL.setChecked(False) + # Namecoin integration tab nmctype = shared.config.get('bitmessagesettings', 'namecoinrpctype') self.ui.lineEditNamecoinHost.setText(str( @@ -3666,9 +4159,7 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog): self.ui = Ui_SpecialAddressBehaviorDialog() self.ui.setupUi(self) self.parent = parent - currentRow = parent.ui.tableWidgetYourIdentities.currentRow() - addressAtCurrentRow = str( - parent.ui.tableWidgetYourIdentities.item(currentRow, 1).text()) + addressAtCurrentRow = parent.getCurrentAccount() if not shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'): if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'): self.ui.radioButtonBehaviorMailingList.click() @@ -3688,44 +4179,44 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog): QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) - -class AddAddressDialog(QtGui.QDialog): +class EmailGatewayDialog(QtGui.QDialog): def __init__(self, parent): QtGui.QWidget.__init__(self, parent) - self.ui = Ui_AddAddressDialog() + self.ui = Ui_EmailGatewayDialog() self.ui.setupUi(self) self.parent = parent - QtCore.QObject.connect(self.ui.lineEditAddress, QtCore.SIGNAL( - "textChanged(QString)"), self.addressChanged) + addressAtCurrentRow = parent.getCurrentAccount() + acct = accountClass(addressAtCurrentRow) + if isinstance(acct, GatewayAccount): + self.ui.radioButtonUnregister.setEnabled(True) + self.ui.radioButtonStatus.setEnabled(True) + self.ui.radioButtonStatus.setChecked(True) + self.ui.radioButtonSettings.setEnabled(True) + else: + self.ui.radioButtonStatus.setEnabled(False) + self.ui.radioButtonSettings.setEnabled(False) + self.ui.radioButtonUnregister.setEnabled(False) + label = shared.config.get(addressAtCurrentRow, 'label') + if label.find("@mailchuck.com") > -1: + self.ui.lineEditEmail.setText(label) + + QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) + + +class EmailGatewayRegistrationDialog(QtGui.QDialog): + + def __init__(self, parent, title, label): + QtGui.QWidget.__init__(self, parent) + self.ui = Ui_EmailGatewayRegistrationDialog() + self.ui.setupUi(self) + self.parent = parent + self.setWindowTitle(title) + self.ui.label.setText(label) + + QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) + - def addressChanged(self, QString): - status, a, b, c = decodeAddress(str(QString)) - if status == 'missingbm': - self.ui.labelAddressCheck.setText(_translate( - "MainWindow", "The address should start with ''BM-''")) - elif status == 'checksumfailed': - self.ui.labelAddressCheck.setText(_translate( - "MainWindow", "The address is not typed or copied correctly (the checksum failed).")) - elif status == 'versiontoohigh': - self.ui.labelAddressCheck.setText(_translate( - "MainWindow", "The version number of this address is higher than this software can support. Please upgrade Bitmessage.")) - elif status == 'invalidcharacters': - self.ui.labelAddressCheck.setText(_translate( - "MainWindow", "The address contains invalid characters.")) - elif status == 'ripetooshort': - self.ui.labelAddressCheck.setText(_translate( - "MainWindow", "Some data encoded in the address is too short.")) - elif status == 'ripetoolong': - self.ui.labelAddressCheck.setText(_translate( - "MainWindow", "Some data encoded in the address is too long.")) - elif status == 'varintmalformed': - self.ui.labelAddressCheck.setText(_translate( - "MainWindow", "Some data encoded in the address is malformed.")) - elif status == 'success': - self.ui.labelAddressCheck.setText( - _translate("MainWindow", "Address is valid.")) - class NewSubscriptionDialog(QtGui.QDialog): def __init__(self, parent): @@ -3770,23 +4261,18 @@ class NewSubscriptionDialog(QtGui.QDialog): self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText( _translate("MainWindow", "Address is an old type. We cannot display its past broadcasts.")) else: - shared.flushInventory() + shared.inventory.flush() doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(encodeVarint( addressVersion) + encodeVarint(streamNumber) + ripe).digest()).digest() tag = doubleHashOfAddressData[32:] - queryreturn = sqlQuery( - '''select hash from inventory where objecttype=3 and tag=?''', tag) - if len(queryreturn) == 0: + count = len(shared.inventory.by_type_and_tag(3, tag)) + if count == 0: self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText( _translate("MainWindow", "There are no recent broadcasts from this address to display.")) - elif len(queryreturn) == 1: - self.ui.checkBoxDisplayMessagesAlreadyInInventory.setEnabled(True) - self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText( - _translate("MainWindow", "Display the %1 recent broadcast from this address.").arg(str(len(queryreturn)))) else: self.ui.checkBoxDisplayMessagesAlreadyInInventory.setEnabled(True) self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText( - _translate("MainWindow", "Display the %1 recent broadcasts from this address.").arg(str(len(queryreturn)))) + _translate("MainWindow", "Display the %1 recent broadcast(s) from this address.").arg(count)) class NewAddressDialog(QtGui.QDialog): @@ -3799,10 +4285,10 @@ class NewAddressDialog(QtGui.QDialog): row = 1 # Let's fill out the 'existing address' combo box with addresses from # the 'Your Identities' tab. - while self.parent.ui.tableWidgetYourIdentities.item(row - 1, 1): + for addressInKeysFile in getSortedAccounts(): self.ui.radioButtonExisting.click() self.ui.comboBoxExisting.addItem( - self.parent.ui.tableWidgetYourIdentities.item(row - 1, 1).text()) + addressInKeysFile) row += 1 self.ui.groupBoxDeterministic.setHidden(True) QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) @@ -3838,81 +4324,90 @@ class myTableWidgetItem(QTableWidgetItem): def __lt__(self, other): return int(self.data(33).toPyObject()) < int(other.data(33).toPyObject()) -class UISignaler(QThread): +from uisignaler import UISignaler - def __init__(self, parent=None): - QThread.__init__(self, parent) - def run(self): - while True: - command, data = shared.UISignalQueue.get() - if command == 'writeNewAddressToTable': - label, address, streamNumber = data - self.emit(SIGNAL( - "writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), label, address, str(streamNumber)) - elif command == 'updateStatusBar': - self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"), data) - elif command == 'updateSentItemStatusByToAddress': - toAddress, message = data - self.emit(SIGNAL( - "updateSentItemStatusByToAddress(PyQt_PyObject,PyQt_PyObject)"), toAddress, message) - elif command == 'updateSentItemStatusByAckdata': - ackData, message = data - self.emit(SIGNAL( - "updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), ackData, message) - elif command == 'displayNewInboxMessage': - inventoryHash, toAddress, fromAddress, subject, body = data - self.emit(SIGNAL( - "displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), - inventoryHash, toAddress, fromAddress, subject, body) - elif command == 'displayNewSentMessage': - toAddress, fromLabel, fromAddress, subject, message, ackdata = data - self.emit(SIGNAL( - "displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), - toAddress, fromLabel, fromAddress, subject, message, ackdata) - elif command == 'updateNetworkStatusTab': - self.emit(SIGNAL("updateNetworkStatusTab()")) - elif command == 'updateNumberOfMessagesProcessed': - self.emit(SIGNAL("updateNumberOfMessagesProcessed()")) - elif command == 'updateNumberOfPubkeysProcessed': - self.emit(SIGNAL("updateNumberOfPubkeysProcessed()")) - elif command == 'updateNumberOfBroadcastsProcessed': - self.emit(SIGNAL("updateNumberOfBroadcastsProcessed()")) - elif command == 'setStatusIcon': - self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"), data) - elif command == 'changedInboxUnread': - self.emit(SIGNAL("changedInboxUnread(PyQt_PyObject)"), data) - elif command == 'rerenderInboxFromLabels': - self.emit(SIGNAL("rerenderInboxFromLabels()")) - elif command == 'rerenderSentToLabels': - self.emit(SIGNAL("rerenderSentToLabels()")) - elif command == 'rerenderAddressBook': - self.emit(SIGNAL("rerenderAddressBook()")) - elif command == 'rerenderSubscriptions': - self.emit(SIGNAL("rerenderSubscriptions()")) - elif command == 'rerenderBlackWhiteList': - self.emit(SIGNAL("rerenderBlackWhiteList()")) - elif command == 'removeInboxRowByMsgid': - self.emit(SIGNAL("removeInboxRowByMsgid(PyQt_PyObject)"), data) - elif command == 'alert': - title, text, exitAfterUserClicksOk = data - self.emit(SIGNAL("displayAlert(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), title, text, exitAfterUserClicksOk) - else: - sys.stderr.write( - 'Command sent to UISignaler not recognized: %s\n' % command) +app = None +myapp = None + +class MySingleApplication(QApplication): + """ + Listener to allow our Qt form to get focus when another instance of the + application is open. + + Based off this nice reimplmentation of MySingleApplication: + http://stackoverflow.com/a/12712362/2679626 + """ + + # Unique identifier for this application + uuid = '6ec0149b-96e1-4be1-93ab-1465fb3ebf7c' + + def __init__(self, *argv): + super(MySingleApplication, self).__init__(*argv) + id = MySingleApplication.uuid + + self.server = None + self.is_running = False + + socket = QLocalSocket() + socket.connectToServer(id) + self.is_running = socket.waitForConnected() + + # Cleanup past crashed servers + if not self.is_running: + if socket.error() == QLocalSocket.ConnectionRefusedError: + socket.disconnectFromServer() + QLocalServer.removeServer(id) + + socket.abort() + + # Checks if there's an instance of the local server id running + if self.is_running: + # This should be ignored, singleton.py will take care of exiting me. + pass + else: + # Nope, create a local server with this id and assign on_new_connection + # for whenever a second instance tries to run focus the application. + self.server = QLocalServer() + self.server.listen(id) + self.server.newConnection.connect(self.on_new_connection) + + def __del__(self): + if self.server: + self.server.close() + + def on_new_connection(self): + global myapp + if myapp: + myapp.appIndicatorShow() + +def init(): + global app + if not app: + app = MySingleApplication(sys.argv) + return app def run(): - app = QtGui.QApplication(sys.argv) + global myapp + app = init() change_translation(l10n.getTranslationLanguage()) app.setStyleSheet("QStatusBar::item { border: 0px solid black }") myapp = MyForm() - if not shared.config.getboolean('bitmessagesettings', 'startintray'): - myapp.show() - myapp.appIndicatorInit(app) myapp.ubuntuMessagingMenuInit() myapp.notifierInit() if shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'): myapp.showConnectDialog() # ask the user if we may connect + +# try: +# if shared.config.get('bitmessagesettings', 'mailchuck') < 1: +# myapp.showMigrationWizard(shared.config.get('bitmessagesettings', 'mailchuck')) +# except: +# myapp.showMigrationWizard(0) + + # only show after wizards and connect dialogs have completed + if not shared.config.getboolean('bitmessagesettings', 'startintray'): + myapp.show() + sys.exit(app.exec_()) diff --git a/src/bitmessageqt/about.py b/src/bitmessageqt/about.py index d2687532..7ddec7a0 100644 --- a/src/bitmessageqt/about.py +++ b/src/bitmessageqt/about.py @@ -66,7 +66,7 @@ class Ui_aboutDialog(object): aboutDialog.setWindowTitle(_translate("aboutDialog", "About", None)) self.label.setText(_translate("aboutDialog", "PyBitmessage", None)) self.labelVersion.setText(_translate("aboutDialog", "version ?", None)) - self.label_2.setText(_translate("aboutDialog", "

Copyright © 2012-2014 Jonathan Warren
Copyright © 2013-2014 The Bitmessage Developers

", None)) + self.label_2.setText(_translate("aboutDialog", "

Copyright © 2012-2016 Jonathan Warren
Copyright © 2013-2016 The Bitmessage Developers

", None)) self.label_3.setText(_translate("aboutDialog", "

Distributed under the MIT/X11 software license; see http://www.opensource.org/licenses/mit-license.php

", None)) self.label_5.setText(_translate("aboutDialog", "This is Beta software.", None)) diff --git a/src/bitmessageqt/account.py b/src/bitmessageqt/account.py new file mode 100644 index 00000000..35a3b91c --- /dev/null +++ b/src/bitmessageqt/account.py @@ -0,0 +1,287 @@ +from PyQt4 import QtCore, QtGui + +import shared +import re +import sys +import inspect +from helper_sql import * +from addresses import decodeAddress +from foldertree import AccountMixin +from pyelliptic.openssl import OpenSSL +from utils import str_broadcast_subscribers +import time + +def getSortedAccounts(): + configSections = filter(lambda x: x != 'bitmessagesettings', shared.config.sections()) + configSections.sort(cmp = + lambda x,y: cmp(unicode(shared.config.get(x, 'label'), 'utf-8').lower(), unicode(shared.config.get(y, 'label'), 'utf-8').lower()) + ) + return configSections + +def getSortedSubscriptions(count = False): + queryreturn = sqlQuery('SELECT label, address, enabled FROM subscriptions ORDER BY label COLLATE NOCASE ASC') + ret = {} + for row in queryreturn: + label, address, enabled = row + ret[address] = {} + ret[address]["inbox"] = {} + ret[address]["inbox"]['label'] = label + ret[address]["inbox"]['enabled'] = enabled + ret[address]["inbox"]['count'] = 0 + if count: + queryreturn = sqlQuery('''SELECT fromaddress, folder, count(msgid) as cnt + FROM inbox, subscriptions + WHERE read = 0 AND subscriptions.address = inbox.fromaddress + GROUP BY inbox.fromaddress, folder''') + for row in queryreturn: + address, folder, cnt = row + if not folder in ret[address]: + ret[address][folder] = { + 'label': ret[address]['inbox']['label'], + 'enabled': ret[address]['inbox']['enabled'] + } + ret[address][folder]['count'] = cnt + return ret + +def accountClass(address): + if not shared.config.has_section(address): + # FIXME: This BROADCAST section makes no sense + if address == str_broadcast_subscribers: + subscription = BroadcastAccount(address) + if subscription.type != AccountMixin.BROADCAST: + return None + else: + subscription = SubscriptionAccount(address) + if subscription.type != AccountMixin.SUBSCRIPTION: + return None + return subscription + try: + gateway = shared.config.get(address, "gateway") + for name, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass): +# obj = g(address) + if issubclass(cls, GatewayAccount) and cls.gatewayName == gateway: + return cls(address) + # general gateway + return GatewayAccount(address) + except: + pass + # no gateway + return BMAccount(address) + +class AccountColor(AccountMixin): + def __init__(self, address, type = None): + self.isEnabled = True + self.address = address + if type is None: + if address is None: + self.type = AccountMixin.ALL + elif shared.safeConfigGetBoolean(self.address, 'mailinglist'): + self.type = AccountMixin.MAILINGLIST + elif shared.safeConfigGetBoolean(self.address, 'chan'): + self.type = AccountMixin.CHAN + elif sqlQuery( + '''select label from subscriptions where address=?''', self.address): + self.type = AccountMixin.SUBSCRIPTION + else: + self.type = AccountMixin.NORMAL + else: + self.type = type + + +class BMAccount(object): + def __init__(self, address = None): + self.address = address + self.type = AccountMixin.NORMAL + if shared.config.has_section(address): + if shared.safeConfigGetBoolean(self.address, 'chan'): + self.type = AccountMixin.CHAN + elif shared.safeConfigGetBoolean(self.address, 'mailinglist'): + self.type = AccountMixin.MAILINGLIST + elif self.address == str_broadcast_subscribers: + self.type = AccountMixin.BROADCAST + else: + queryreturn = sqlQuery( + '''select label from subscriptions where address=?''', self.address) + if queryreturn: + self.type = AccountMixin.SUBSCRIPTION + + def getLabel(self, address = None): + if address is None: + address = self.address + label = address + if shared.config.has_section(address): + label = shared.config.get(address, 'label') + queryreturn = sqlQuery( + '''select label from addressbook where address=?''', address) + if queryreturn != []: + for row in queryreturn: + label, = row + else: + queryreturn = sqlQuery( + '''select label from subscriptions where address=?''', address) + if queryreturn != []: + for row in queryreturn: + label, = row + return label + + def parseMessage(self, toAddress, fromAddress, subject, message): + self.toAddress = toAddress + self.fromAddress = fromAddress + self.subject = subject + self.message = message + self.fromLabel = self.getLabel(fromAddress) + self.toLabel = self.getLabel(toAddress) + + +class SubscriptionAccount(BMAccount): + pass + + +class BroadcastAccount(BMAccount): + pass + + +class GatewayAccount(BMAccount): + gatewayName = None + ALL_OK = 0 + REGISTRATION_DENIED = 1 + def __init__(self, address): + super(BMAccount, self).__init__(address) + + def send(self): + status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.toAddress) + ackdata = OpenSSL.rand(32) + t = () + sqlExecute( + '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', + '', + self.toAddress, + ripe, + self.fromAddress, + 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. + 'msgqueued', + 0, # retryNumber + 'sent', # folder + 2, # encodingtype + min(shared.config.getint('bitmessagesettings', 'ttl'), 86400 * 2) # not necessary to have a TTL higher than 2 days + ) + + shared.workerQueue.put(('sendmessage', self.toAddress)) + + def parseMessage(self, toAddress, fromAddress, subject, message): + super(BMAccount, self).parseMessage(toAddress, fromAddress, subject, message) + +class MailchuckAccount(GatewayAccount): + # 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+) (.*)") + def __init__(self, address): + super(GatewayAccount, self).__init__(address) + self.feedback = self.ALL_OK + + def createMessage(self, toAddress, fromAddress, subject, message): + self.subject = toAddress + " " + subject + self.toAddress = self.relayAddress + self.fromAddress = fromAddress + self.message = message + + def register(self, email): + self.toAddress = self.registrationAddress + self.subject = email + self.message = "" + self.fromAddress = self.address + self.send() + + def unregister(self): + self.toAddress = self.unregistrationAddress + self.subject = "" + self.message = "" + self.fromAddress = self.address + self.send() + + def status(self): + self.toAddress = self.registrationAddress + self.subject = "status" + self.message = "" + self.fromAddress = self.address + self.send() + + def settings(self): + self.toAddress = self.registrationAddress + self.subject = "config" + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. +""") + self.fromAddress = self.address + + def parseMessage(self, toAddress, fromAddress, subject, message): + super(GatewayAccount, self).parseMessage(toAddress, fromAddress, subject, message) + if fromAddress == self.relayAddress: + matches = self.regExpIncoming.search(subject) + if not matches is None: + self.subject = "" + if not matches.group(1) is None: + self.subject += matches.group(1) + if not matches.group(3) is None: + self.subject += matches.group(3) + if not matches.group(2) is None: + self.fromLabel = matches.group(2) + self.fromAddress = matches.group(2) + if toAddress == self.relayAddress: + matches = self.regExpOutgoing.search(subject) + if not matches is None: + if not matches.group(2) is None: + self.subject = matches.group(2) + if not matches.group(1) is None: + self.toLabel = matches.group(1) + self.toAddress = matches.group(1) + self.feedback = self.ALL_OK + if fromAddress == self.registrationAddress and self.subject == "Registration Request Denied": + self.feedback = self.REGISTRATION_DENIED + return self.feedback diff --git a/src/bitmessageqt/bitmessageui.py b/src/bitmessageqt/bitmessageui.py index e35b30cd..1761dfe3 100644 --- a/src/bitmessageqt/bitmessageui.py +++ b/src/bitmessageqt/bitmessageui.py @@ -2,12 +2,19 @@ # Form implementation generated from reading ui file 'bitmessageui.ui' # -# Created: Sun Mar 08 22:07:43 2015 -# by: PyQt4 UI code generator 4.10.3 +# Created: Mon Mar 23 22:18:07 2015 +# by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! from PyQt4 import QtCore, QtGui +from foldertree import AddressBookCompleter +from messageview import MessageView +from messagecompose import MessageCompose +import settingsmixin +from networkstatus import NetworkStatus +from blacklist import Blacklist +import shared try: _fromUtf8 = QtCore.QString.fromUtf8 @@ -17,11 +24,17 @@ except AttributeError: try: _encoding = QtGui.QApplication.UnicodeUTF8 - def _translate(context, text, disambig): - return QtGui.QApplication.translate(context, text, disambig, _encoding) + def _translate(context, text, disambig, encoding = QtCore.QCoreApplication.CodecForTr, n = None): + if n is None: + return QtGui.QApplication.translate(context, text, disambig, _encoding) + else: + return QtGui.QApplication.translate(context, text, disambig, _encoding, n) except AttributeError: - def _translate(context, text, disambig): - return QtGui.QApplication.translate(context, text, disambig) + def _translate(context, text, disambig, encoding = QtCore.QCoreApplication.CodecForTr, n = None): + if n is None: + return QtGui.QApplication.translate(context, text, disambig) + else: + return QtGui.QApplication.translate(context, text, disambig, QtCore.QCoreApplication.CodecForTr, n) class Ui_MainWindow(object): def setupUi(self, MainWindow): @@ -33,9 +46,8 @@ class Ui_MainWindow(object): MainWindow.setTabShape(QtGui.QTabWidget.Rounded) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) - self.gridLayout = QtGui.QGridLayout(self.centralwidget) - self.gridLayout.setMargin(0) - self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.gridLayout_10 = QtGui.QGridLayout(self.centralwidget) + self.gridLayout_10.setObjectName(_fromUtf8("gridLayout_10")) self.tabWidget = QtGui.QTabWidget(self.centralwidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) @@ -52,27 +64,52 @@ class Ui_MainWindow(object): self.tabWidget.setObjectName(_fromUtf8("tabWidget")) self.inbox = QtGui.QWidget() self.inbox.setObjectName(_fromUtf8("inbox")) - self.verticalLayout_2 = QtGui.QVBoxLayout(self.inbox) - self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2")) - self.horizontalLayoutSearch = QtGui.QHBoxLayout() - self.horizontalLayoutSearch.setContentsMargins(-1, 0, -1, -1) - self.horizontalLayoutSearch.setObjectName(_fromUtf8("horizontalLayoutSearch")) + self.gridLayout = QtGui.QGridLayout(self.inbox) + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.horizontalSplitter_3 = settingsmixin.SSplitter() + self.horizontalSplitter_3.setObjectName(_fromUtf8("horizontalSplitter_3")) + self.verticalSplitter_12 = settingsmixin.SSplitter() + self.verticalSplitter_12.setObjectName(_fromUtf8("verticalSplitter_12")) + self.verticalSplitter_12.setOrientation(QtCore.Qt.Vertical) + self.treeWidgetYourIdentities = settingsmixin.STreeWidget(self.inbox) + self.treeWidgetYourIdentities.setObjectName(_fromUtf8("treeWidgetYourIdentities")) + self.treeWidgetYourIdentities.resize(200, self.treeWidgetYourIdentities.height()) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/identities.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off) + self.treeWidgetYourIdentities.headerItem().setIcon(0, icon1) + self.verticalSplitter_12.addWidget(self.treeWidgetYourIdentities) + self.pushButtonNewAddress = QtGui.QPushButton(self.inbox) + self.pushButtonNewAddress.setObjectName(_fromUtf8("pushButtonNewAddress")) + self.pushButtonNewAddress.resize(200, self.pushButtonNewAddress.height()) + self.verticalSplitter_12.addWidget(self.pushButtonNewAddress) + self.verticalSplitter_12.setStretchFactor(0, 1) + self.verticalSplitter_12.setStretchFactor(1, 0) + self.verticalSplitter_12.setCollapsible(0, False) + self.verticalSplitter_12.setCollapsible(1, False) + self.verticalSplitter_12.handle(1).setEnabled(False) + self.horizontalSplitter_3.addWidget(self.verticalSplitter_12) + self.verticalSplitter_7 = settingsmixin.SSplitter() + self.verticalSplitter_7.setObjectName(_fromUtf8("verticalSplitter_7")) + self.verticalSplitter_7.setOrientation(QtCore.Qt.Vertical) + self.horizontalSplitterSearch = QtGui.QSplitter() + self.horizontalSplitterSearch.setObjectName(_fromUtf8("horizontalSplitterSearch")) self.inboxSearchLineEdit = QtGui.QLineEdit(self.inbox) self.inboxSearchLineEdit.setObjectName(_fromUtf8("inboxSearchLineEdit")) - self.horizontalLayoutSearch.addWidget(self.inboxSearchLineEdit) - self.inboxSearchOptionCB = QtGui.QComboBox(self.inbox) - self.inboxSearchOptionCB.setObjectName(_fromUtf8("inboxSearchOptionCB")) - self.inboxSearchOptionCB.addItem(_fromUtf8("")) - self.inboxSearchOptionCB.addItem(_fromUtf8("")) - self.inboxSearchOptionCB.addItem(_fromUtf8("")) - self.inboxSearchOptionCB.addItem(_fromUtf8("")) - self.inboxSearchOptionCB.addItem(_fromUtf8("")) - self.horizontalLayoutSearch.addWidget(self.inboxSearchOptionCB) - self.verticalLayout_2.addLayout(self.horizontalLayoutSearch) - self.splitter = QtGui.QSplitter(self.inbox) - self.splitter.setOrientation(QtCore.Qt.Vertical) - self.splitter.setObjectName(_fromUtf8("splitter")) - self.tableWidgetInbox = QtGui.QTableWidget(self.splitter) + self.horizontalSplitterSearch.addWidget(self.inboxSearchLineEdit) + self.inboxSearchOption = QtGui.QComboBox(self.inbox) + self.inboxSearchOption.setObjectName(_fromUtf8("inboxSearchOption")) + self.inboxSearchOption.addItem(_fromUtf8("")) + self.inboxSearchOption.addItem(_fromUtf8("")) + self.inboxSearchOption.addItem(_fromUtf8("")) + self.inboxSearchOption.addItem(_fromUtf8("")) + self.inboxSearchOption.addItem(_fromUtf8("")) + self.inboxSearchOption.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) + self.horizontalSplitterSearch.addWidget(self.inboxSearchOption) + self.horizontalSplitterSearch.handle(1).setEnabled(False) + self.horizontalSplitterSearch.setStretchFactor(0, 1) + self.horizontalSplitterSearch.setStretchFactor(1, 0) + self.verticalSplitter_7.addWidget(self.horizontalSplitterSearch) + self.tableWidgetInbox = settingsmixin.STableWidget(self.inbox) self.tableWidgetInbox.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) self.tableWidgetInbox.setAlternatingRowColors(True) self.tableWidgetInbox.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) @@ -97,84 +134,179 @@ class Ui_MainWindow(object): self.tableWidgetInbox.horizontalHeader().setStretchLastSection(True) self.tableWidgetInbox.verticalHeader().setVisible(False) self.tableWidgetInbox.verticalHeader().setDefaultSectionSize(26) - self.textEditInboxMessage = QtGui.QTextEdit(self.splitter) + self.verticalSplitter_7.addWidget(self.tableWidgetInbox) + self.textEditInboxMessage = MessageView(self.inbox) self.textEditInboxMessage.setBaseSize(QtCore.QSize(0, 500)) self.textEditInboxMessage.setReadOnly(True) self.textEditInboxMessage.setObjectName(_fromUtf8("textEditInboxMessage")) - self.verticalLayout_2.addWidget(self.splitter) - icon1 = QtGui.QIcon() - icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/inbox.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.tabWidget.addTab(self.inbox, icon1, _fromUtf8("")) + self.verticalSplitter_7.addWidget(self.textEditInboxMessage) + self.verticalSplitter_7.setStretchFactor(0, 0) + self.verticalSplitter_7.setStretchFactor(1, 1) + self.verticalSplitter_7.setStretchFactor(2, 2) + self.verticalSplitter_7.setCollapsible(0, False) + self.verticalSplitter_7.setCollapsible(1, False) + self.verticalSplitter_7.setCollapsible(2, False) + self.verticalSplitter_7.handle(1).setEnabled(False) + self.horizontalSplitter_3.addWidget(self.verticalSplitter_7) + self.horizontalSplitter_3.setStretchFactor(0, 0) + self.horizontalSplitter_3.setStretchFactor(1, 1) + self.horizontalSplitter_3.setCollapsible(0, False) + self.horizontalSplitter_3.setCollapsible(1, False) + self.gridLayout.addWidget(self.horizontalSplitter_3) + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/inbox.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.tabWidget.addTab(self.inbox, icon2, _fromUtf8("")) self.send = QtGui.QWidget() self.send.setObjectName(_fromUtf8("send")) - self.gridLayout_2 = QtGui.QGridLayout(self.send) - self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) - self.pushButtonLoadFromAddressBook = QtGui.QPushButton(self.send) + self.gridLayout_7 = QtGui.QGridLayout(self.send) + self.gridLayout_7.setObjectName(_fromUtf8("gridLayout_7")) + self.horizontalSplitter = settingsmixin.SSplitter() + self.horizontalSplitter.setObjectName(_fromUtf8("horizontalSplitter")) + self.verticalSplitter_2 = settingsmixin.SSplitter() + self.verticalSplitter_2.setObjectName(_fromUtf8("verticalSplitter_2")) + self.verticalSplitter_2.setOrientation(QtCore.Qt.Vertical) + self.tableWidgetAddressBook = settingsmixin.STableWidget(self.send) + self.tableWidgetAddressBook.setAlternatingRowColors(True) + self.tableWidgetAddressBook.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) + self.tableWidgetAddressBook.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.tableWidgetAddressBook.setObjectName(_fromUtf8("tableWidgetAddressBook")) + self.tableWidgetAddressBook.setColumnCount(2) + self.tableWidgetAddressBook.setRowCount(0) + self.tableWidgetAddressBook.resize(200, self.tableWidgetAddressBook.height()) + item = QtGui.QTableWidgetItem() + icon3 = QtGui.QIcon() + icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/addressbook.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off) + item.setIcon(icon3) + self.tableWidgetAddressBook.setHorizontalHeaderItem(0, item) + item = QtGui.QTableWidgetItem() + self.tableWidgetAddressBook.setHorizontalHeaderItem(1, item) + self.tableWidgetAddressBook.horizontalHeader().setCascadingSectionResizes(True) + self.tableWidgetAddressBook.horizontalHeader().setDefaultSectionSize(200) + self.tableWidgetAddressBook.horizontalHeader().setHighlightSections(False) + self.tableWidgetAddressBook.horizontalHeader().setStretchLastSection(True) + self.tableWidgetAddressBook.verticalHeader().setVisible(False) + self.verticalSplitter_2.addWidget(self.tableWidgetAddressBook) + self.addressBookCompleter = AddressBookCompleter() + self.addressBookCompleter.setCompletionMode(QtGui.QCompleter.PopupCompletion) + self.addressBookCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive) + self.addressBookCompleterModel = QtGui.QStringListModel() + self.addressBookCompleter.setModel(self.addressBookCompleterModel) + self.pushButtonAddAddressBook = QtGui.QPushButton(self.send) + self.pushButtonAddAddressBook.setObjectName(_fromUtf8("pushButtonAddAddressBook")) + self.pushButtonAddAddressBook.resize(200, self.pushButtonAddAddressBook.height()) + self.verticalSplitter_2.addWidget(self.pushButtonAddAddressBook) + self.pushButtonFetchNamecoinID = QtGui.QPushButton(self.send) + self.pushButtonFetchNamecoinID.resize(200, self.pushButtonFetchNamecoinID.height()) font = QtGui.QFont() - font.setPointSize(7) - self.pushButtonLoadFromAddressBook.setFont(font) - self.pushButtonLoadFromAddressBook.setObjectName(_fromUtf8("pushButtonLoadFromAddressBook")) - self.gridLayout_2.addWidget(self.pushButtonLoadFromAddressBook, 3, 2, 1, 1) - self.label_3 = QtGui.QLabel(self.send) + font.setPointSize(9) + self.pushButtonFetchNamecoinID.setFont(font) + self.pushButtonFetchNamecoinID.setObjectName(_fromUtf8("pushButtonFetchNamecoinID")) + self.verticalSplitter_2.addWidget(self.pushButtonFetchNamecoinID) + self.verticalSplitter_2.setStretchFactor(0, 1) + self.verticalSplitter_2.setStretchFactor(1, 0) + self.verticalSplitter_2.setStretchFactor(2, 0) + self.verticalSplitter_2.setCollapsible(0, False) + self.verticalSplitter_2.setCollapsible(1, False) + self.verticalSplitter_2.setCollapsible(2, False) + self.verticalSplitter_2.handle(1).setEnabled(False) + self.verticalSplitter_2.handle(2).setEnabled(False) + self.horizontalSplitter.addWidget(self.verticalSplitter_2) + self.verticalSplitter = settingsmixin.SSplitter() + self.verticalSplitter.setObjectName(_fromUtf8("verticalSplitter")) + self.verticalSplitter.setOrientation(QtCore.Qt.Vertical) + self.tabWidgetSend = QtGui.QTabWidget(self.send) + self.tabWidgetSend.setObjectName(_fromUtf8("tabWidgetSend")) + self.sendDirect = QtGui.QWidget() + self.sendDirect.setObjectName(_fromUtf8("sendDirect")) + self.gridLayout_8 = QtGui.QGridLayout(self.sendDirect) + self.gridLayout_8.setObjectName(_fromUtf8("gridLayout_8")) + self.verticalSplitter_5 = settingsmixin.SSplitter() + self.verticalSplitter_5.setObjectName(_fromUtf8("verticalSplitter_5")) + self.verticalSplitter_5.setOrientation(QtCore.Qt.Vertical) + self.gridLayout_2 = QtGui.QGridLayout() + self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) + self.label_3 = QtGui.QLabel(self.sendDirect) self.label_3.setObjectName(_fromUtf8("label_3")) - self.gridLayout_2.addWidget(self.label_3, 4, 0, 1, 1) - self.pushButtonSend = QtGui.QPushButton(self.send) - self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend")) - self.gridLayout_2.addWidget(self.pushButtonSend, 7, 8, 1, 1) - self.horizontalSliderTTL = QtGui.QSlider(self.send) - self.horizontalSliderTTL.setMinimumSize(QtCore.QSize(35, 0)) - self.horizontalSliderTTL.setMaximumSize(QtCore.QSize(70, 16777215)) - self.horizontalSliderTTL.setOrientation(QtCore.Qt.Horizontal) - self.horizontalSliderTTL.setInvertedAppearance(False) - self.horizontalSliderTTL.setInvertedControls(False) - self.horizontalSliderTTL.setObjectName(_fromUtf8("horizontalSliderTTL")) - self.gridLayout_2.addWidget(self.horizontalSliderTTL, 7, 6, 1, 1) - spacerItem = QtGui.QSpacerItem(20, 297, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.gridLayout_2.addItem(spacerItem, 6, 0, 1, 1) - self.comboBoxSendFrom = QtGui.QComboBox(self.send) + self.gridLayout_2.addWidget(self.label_3, 2, 0, 1, 1) + self.label_2 = QtGui.QLabel(self.sendDirect) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1) + self.lineEditSubject = QtGui.QLineEdit(self.sendDirect) + self.lineEditSubject.setText(_fromUtf8("")) + self.lineEditSubject.setObjectName(_fromUtf8("lineEditSubject")) + self.gridLayout_2.addWidget(self.lineEditSubject, 2, 1, 1, 1) + self.label = QtGui.QLabel(self.sendDirect) + self.label.setObjectName(_fromUtf8("label")) + self.gridLayout_2.addWidget(self.label, 1, 0, 1, 1) + self.comboBoxSendFrom = QtGui.QComboBox(self.sendDirect) self.comboBoxSendFrom.setMinimumSize(QtCore.QSize(300, 0)) self.comboBoxSendFrom.setObjectName(_fromUtf8("comboBoxSendFrom")) - self.gridLayout_2.addWidget(self.comboBoxSendFrom, 2, 1, 1, 1) - self.labelHumanFriendlyTTLDescription = QtGui.QLabel(self.send) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.labelHumanFriendlyTTLDescription.sizePolicy().hasHeightForWidth()) - self.labelHumanFriendlyTTLDescription.setSizePolicy(sizePolicy) - self.labelHumanFriendlyTTLDescription.setMinimumSize(QtCore.QSize(45, 0)) - self.labelHumanFriendlyTTLDescription.setMaximumSize(QtCore.QSize(45, 16777215)) - self.labelHumanFriendlyTTLDescription.setObjectName(_fromUtf8("labelHumanFriendlyTTLDescription")) - self.gridLayout_2.addWidget(self.labelHumanFriendlyTTLDescription, 7, 7, 1, 1) - self.label_4 = QtGui.QLabel(self.send) - self.label_4.setObjectName(_fromUtf8("label_4")) - self.gridLayout_2.addWidget(self.label_4, 5, 0, 1, 1) - self.label = QtGui.QLabel(self.send) - self.label.setObjectName(_fromUtf8("label")) - self.gridLayout_2.addWidget(self.label, 3, 0, 1, 1) - self.radioButtonSpecific = QtGui.QRadioButton(self.send) - self.radioButtonSpecific.setChecked(True) - self.radioButtonSpecific.setObjectName(_fromUtf8("radioButtonSpecific")) - self.gridLayout_2.addWidget(self.radioButtonSpecific, 0, 1, 1, 1) - self.labelSendBroadcastWarning = QtGui.QLabel(self.send) - self.labelSendBroadcastWarning.setEnabled(True) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.labelSendBroadcastWarning.sizePolicy().hasHeightForWidth()) - self.labelSendBroadcastWarning.setSizePolicy(sizePolicy) - self.labelSendBroadcastWarning.setIndent(-1) - self.labelSendBroadcastWarning.setObjectName(_fromUtf8("labelSendBroadcastWarning")) - self.gridLayout_2.addWidget(self.labelSendBroadcastWarning, 7, 1, 1, 4) - self.radioButtonBroadcast = QtGui.QRadioButton(self.send) - self.radioButtonBroadcast.setObjectName(_fromUtf8("radioButtonBroadcast")) - self.gridLayout_2.addWidget(self.radioButtonBroadcast, 1, 1, 1, 2) + self.gridLayout_2.addWidget(self.comboBoxSendFrom, 0, 1, 1, 1) + self.lineEditTo = QtGui.QLineEdit(self.sendDirect) + self.lineEditTo.setObjectName(_fromUtf8("lineEditTo")) + self.gridLayout_2.addWidget(self.lineEditTo, 1, 1, 1, 1) + self.lineEditTo.setCompleter(self.addressBookCompleter) + self.gridLayout_2_Widget = QtGui.QWidget() + self.gridLayout_2_Widget.setLayout(self.gridLayout_2) + self.verticalSplitter_5.addWidget(self.gridLayout_2_Widget) + self.textEditMessage = MessageCompose(self.sendDirect) + self.textEditMessage.setObjectName(_fromUtf8("textEditMessage")) + self.verticalSplitter_5.addWidget(self.textEditMessage) + self.verticalSplitter_5.setStretchFactor(0, 0) + self.verticalSplitter_5.setStretchFactor(1, 1) + self.verticalSplitter_5.setCollapsible(0, False) + self.verticalSplitter_5.setCollapsible(1, False) + self.verticalSplitter_5.handle(1).setEnabled(False) + self.gridLayout_8.addWidget(self.verticalSplitter_5, 0, 0, 1, 1) + self.tabWidgetSend.addTab(self.sendDirect, _fromUtf8("")) + self.sendBroadcast = QtGui.QWidget() + self.sendBroadcast.setObjectName(_fromUtf8("sendBroadcast")) + self.gridLayout_9 = QtGui.QGridLayout(self.sendBroadcast) + self.gridLayout_9.setObjectName(_fromUtf8("gridLayout_9")) + self.verticalSplitter_6 = settingsmixin.SSplitter() + self.verticalSplitter_6.setObjectName(_fromUtf8("verticalSplitter_6")) + self.verticalSplitter_6.setOrientation(QtCore.Qt.Vertical) + self.gridLayout_5 = QtGui.QGridLayout() + self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5")) + self.label_8 = QtGui.QLabel(self.sendBroadcast) + self.label_8.setObjectName(_fromUtf8("label_8")) + self.gridLayout_5.addWidget(self.label_8, 0, 0, 1, 1) + self.lineEditSubjectBroadcast = QtGui.QLineEdit(self.sendBroadcast) + self.lineEditSubjectBroadcast.setText(_fromUtf8("")) + self.lineEditSubjectBroadcast.setObjectName(_fromUtf8("lineEditSubjectBroadcast")) + self.gridLayout_5.addWidget(self.lineEditSubjectBroadcast, 1, 1, 1, 1) + self.label_7 = QtGui.QLabel(self.sendBroadcast) + self.label_7.setObjectName(_fromUtf8("label_7")) + self.gridLayout_5.addWidget(self.label_7, 1, 0, 1, 1) + self.comboBoxSendFromBroadcast = QtGui.QComboBox(self.sendBroadcast) + self.comboBoxSendFromBroadcast.setMinimumSize(QtCore.QSize(300, 0)) + self.comboBoxSendFromBroadcast.setObjectName(_fromUtf8("comboBoxSendFromBroadcast")) + self.gridLayout_5.addWidget(self.comboBoxSendFromBroadcast, 0, 1, 1, 1) + self.gridLayout_5_Widget = QtGui.QWidget() + self.gridLayout_5_Widget.setLayout(self.gridLayout_5) + self.verticalSplitter_6.addWidget(self.gridLayout_5_Widget) + self.textEditMessageBroadcast = MessageCompose(self.sendBroadcast) + self.textEditMessageBroadcast.setObjectName(_fromUtf8("textEditMessageBroadcast")) + self.verticalSplitter_6.addWidget(self.textEditMessageBroadcast) + self.verticalSplitter_6.setStretchFactor(0, 0) + self.verticalSplitter_6.setStretchFactor(1, 1) + self.verticalSplitter_6.setCollapsible(0, False) + self.verticalSplitter_6.setCollapsible(1, False) + self.verticalSplitter_6.handle(1).setEnabled(False) + self.gridLayout_9.addWidget(self.verticalSplitter_6, 0, 0, 1, 1) + self.tabWidgetSend.addTab(self.sendBroadcast, _fromUtf8("")) + self.verticalSplitter.addWidget(self.tabWidgetSend) + self.tTLContainer = QtGui.QWidget() + self.tTLContainer.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) + self.horizontalLayout_5 = QtGui.QHBoxLayout() + self.tTLContainer.setLayout(self.horizontalLayout_5) + self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5")) self.pushButtonTTL = QtGui.QPushButton(self.send) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.pushButtonTTL.sizePolicy().hasHeightForWidth()) self.pushButtonTTL.setSizePolicy(sizePolicy) - self.pushButtonTTL.setMaximumSize(QtCore.QSize(32, 16777215)) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(0, 0, 255)) brush.setStyle(QtCore.Qt.SolidPattern) @@ -191,301 +323,252 @@ class Ui_MainWindow(object): self.pushButtonTTL.setFont(font) self.pushButtonTTL.setFlat(True) self.pushButtonTTL.setObjectName(_fromUtf8("pushButtonTTL")) - self.gridLayout_2.addWidget(self.pushButtonTTL, 7, 5, 1, 1) - self.label_2 = QtGui.QLabel(self.send) - self.label_2.setObjectName(_fromUtf8("label_2")) - self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1) - self.lineEditTo = QtGui.QLineEdit(self.send) - self.lineEditTo.setObjectName(_fromUtf8("lineEditTo")) - self.gridLayout_2.addWidget(self.lineEditTo, 3, 1, 1, 1) - self.textEditMessage = QtGui.QTextEdit(self.send) - self.textEditMessage.setObjectName(_fromUtf8("textEditMessage")) - self.gridLayout_2.addWidget(self.textEditMessage, 5, 1, 2, 8) - self.pushButtonFetchNamecoinID = QtGui.QPushButton(self.send) - font = QtGui.QFont() - font.setPointSize(7) - self.pushButtonFetchNamecoinID.setFont(font) - self.pushButtonFetchNamecoinID.setObjectName(_fromUtf8("pushButtonFetchNamecoinID")) - self.gridLayout_2.addWidget(self.pushButtonFetchNamecoinID, 3, 3, 1, 1) - self.labelFrom = QtGui.QLabel(self.send) - self.labelFrom.setText(_fromUtf8("")) - self.labelFrom.setObjectName(_fromUtf8("labelFrom")) - self.gridLayout_2.addWidget(self.labelFrom, 2, 2, 1, 7) - self.lineEditSubject = QtGui.QLineEdit(self.send) - self.lineEditSubject.setText(_fromUtf8("")) - self.lineEditSubject.setObjectName(_fromUtf8("lineEditSubject")) - self.gridLayout_2.addWidget(self.lineEditSubject, 4, 1, 1, 8) - icon2 = QtGui.QIcon() - icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/send.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.tabWidget.addTab(self.send, icon2, _fromUtf8("")) - self.sent = QtGui.QWidget() - self.sent.setObjectName(_fromUtf8("sent")) - self.verticalLayout = QtGui.QVBoxLayout(self.sent) - self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) - self.horizontalLayout = QtGui.QHBoxLayout() - self.horizontalLayout.setContentsMargins(-1, 0, -1, -1) - self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) - self.sentSearchLineEdit = QtGui.QLineEdit(self.sent) - self.sentSearchLineEdit.setObjectName(_fromUtf8("sentSearchLineEdit")) - self.horizontalLayout.addWidget(self.sentSearchLineEdit) - self.sentSearchOptionCB = QtGui.QComboBox(self.sent) - self.sentSearchOptionCB.setObjectName(_fromUtf8("sentSearchOptionCB")) - self.sentSearchOptionCB.addItem(_fromUtf8("")) - self.sentSearchOptionCB.addItem(_fromUtf8("")) - self.sentSearchOptionCB.addItem(_fromUtf8("")) - self.sentSearchOptionCB.addItem(_fromUtf8("")) - self.sentSearchOptionCB.addItem(_fromUtf8("")) - self.horizontalLayout.addWidget(self.sentSearchOptionCB) - self.verticalLayout.addLayout(self.horizontalLayout) - self.splitter_2 = QtGui.QSplitter(self.sent) - self.splitter_2.setOrientation(QtCore.Qt.Vertical) - self.splitter_2.setObjectName(_fromUtf8("splitter_2")) - self.tableWidgetSent = QtGui.QTableWidget(self.splitter_2) - self.tableWidgetSent.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) - self.tableWidgetSent.setDragDropMode(QtGui.QAbstractItemView.DragDrop) - self.tableWidgetSent.setAlternatingRowColors(True) - self.tableWidgetSent.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) - self.tableWidgetSent.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) - self.tableWidgetSent.setWordWrap(False) - self.tableWidgetSent.setObjectName(_fromUtf8("tableWidgetSent")) - self.tableWidgetSent.setColumnCount(4) - self.tableWidgetSent.setRowCount(0) - item = QtGui.QTableWidgetItem() - self.tableWidgetSent.setHorizontalHeaderItem(0, item) - item = QtGui.QTableWidgetItem() - self.tableWidgetSent.setHorizontalHeaderItem(1, item) - item = QtGui.QTableWidgetItem() - self.tableWidgetSent.setHorizontalHeaderItem(2, item) - item = QtGui.QTableWidgetItem() - self.tableWidgetSent.setHorizontalHeaderItem(3, item) - self.tableWidgetSent.horizontalHeader().setCascadingSectionResizes(True) - self.tableWidgetSent.horizontalHeader().setDefaultSectionSize(130) - self.tableWidgetSent.horizontalHeader().setHighlightSections(False) - self.tableWidgetSent.horizontalHeader().setSortIndicatorShown(False) - self.tableWidgetSent.horizontalHeader().setStretchLastSection(True) - self.tableWidgetSent.verticalHeader().setVisible(False) - self.tableWidgetSent.verticalHeader().setStretchLastSection(False) - self.textEditSentMessage = QtGui.QTextEdit(self.splitter_2) - self.textEditSentMessage.setReadOnly(True) - self.textEditSentMessage.setObjectName(_fromUtf8("textEditSentMessage")) - self.verticalLayout.addWidget(self.splitter_2) - icon3 = QtGui.QIcon() - icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/sent.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.tabWidget.addTab(self.sent, icon3, _fromUtf8("")) - self.youridentities = QtGui.QWidget() - self.youridentities.setObjectName(_fromUtf8("youridentities")) - self.gridLayout_3 = QtGui.QGridLayout(self.youridentities) - self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) - self.pushButtonNewAddress = QtGui.QPushButton(self.youridentities) - self.pushButtonNewAddress.setObjectName(_fromUtf8("pushButtonNewAddress")) - self.gridLayout_3.addWidget(self.pushButtonNewAddress, 0, 0, 1, 1) - spacerItem1 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.gridLayout_3.addItem(spacerItem1, 0, 1, 1, 1) - self.tableWidgetYourIdentities = QtGui.QTableWidget(self.youridentities) - self.tableWidgetYourIdentities.setFrameShadow(QtGui.QFrame.Sunken) - self.tableWidgetYourIdentities.setLineWidth(1) - self.tableWidgetYourIdentities.setAlternatingRowColors(True) - self.tableWidgetYourIdentities.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) - self.tableWidgetYourIdentities.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) - self.tableWidgetYourIdentities.setObjectName(_fromUtf8("tableWidgetYourIdentities")) - self.tableWidgetYourIdentities.setColumnCount(3) - self.tableWidgetYourIdentities.setRowCount(0) - item = QtGui.QTableWidgetItem() - font = QtGui.QFont() - font.setKerning(True) - item.setFont(font) - self.tableWidgetYourIdentities.setHorizontalHeaderItem(0, item) - item = QtGui.QTableWidgetItem() - self.tableWidgetYourIdentities.setHorizontalHeaderItem(1, item) - item = QtGui.QTableWidgetItem() - self.tableWidgetYourIdentities.setHorizontalHeaderItem(2, item) - self.tableWidgetYourIdentities.horizontalHeader().setCascadingSectionResizes(True) - self.tableWidgetYourIdentities.horizontalHeader().setDefaultSectionSize(346) - self.tableWidgetYourIdentities.horizontalHeader().setMinimumSectionSize(52) - self.tableWidgetYourIdentities.horizontalHeader().setSortIndicatorShown(True) - self.tableWidgetYourIdentities.horizontalHeader().setStretchLastSection(True) - self.tableWidgetYourIdentities.verticalHeader().setVisible(False) - self.tableWidgetYourIdentities.verticalHeader().setDefaultSectionSize(26) - self.tableWidgetYourIdentities.verticalHeader().setSortIndicatorShown(False) - self.tableWidgetYourIdentities.verticalHeader().setStretchLastSection(False) - self.gridLayout_3.addWidget(self.tableWidgetYourIdentities, 1, 0, 1, 2) + self.horizontalLayout_5.addWidget(self.pushButtonTTL, 0, QtCore.Qt.AlignRight) + self.horizontalSliderTTL = QtGui.QSlider(self.send) + self.horizontalSliderTTL.setMinimumSize(QtCore.QSize(35, 0)) + self.horizontalSliderTTL.setOrientation(QtCore.Qt.Horizontal) + self.horizontalSliderTTL.setInvertedAppearance(False) + self.horizontalSliderTTL.setInvertedControls(False) + self.horizontalSliderTTL.setObjectName(_fromUtf8("horizontalSliderTTL")) + self.horizontalLayout_5.addWidget(self.horizontalSliderTTL, 0, QtCore.Qt.AlignLeft) + self.labelHumanFriendlyTTLDescription = QtGui.QLabel(self.send) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.labelHumanFriendlyTTLDescription.sizePolicy().hasHeightForWidth()) + self.labelHumanFriendlyTTLDescription.setSizePolicy(sizePolicy) + self.labelHumanFriendlyTTLDescription.setMinimumSize(QtCore.QSize(45, 0)) + self.labelHumanFriendlyTTLDescription.setObjectName(_fromUtf8("labelHumanFriendlyTTLDescription")) + self.horizontalLayout_5.addWidget(self.labelHumanFriendlyTTLDescription, 1, QtCore.Qt.AlignLeft) + self.pushButtonSend = QtGui.QPushButton(self.send) + self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend")) + self.horizontalLayout_5.addWidget(self.pushButtonSend, 0, QtCore.Qt.AlignRight) + self.horizontalSliderTTL.setMaximumSize(QtCore.QSize(70, self.pushButtonSend.height())) + self.verticalSplitter.addWidget(self.tTLContainer) + self.tTLContainer.adjustSize() + self.verticalSplitter.setStretchFactor(1, 0) + self.verticalSplitter.setStretchFactor(0, 1) + self.verticalSplitter.setCollapsible(0, False) + self.verticalSplitter.setCollapsible(1, False) + self.verticalSplitter.handle(1).setEnabled(False) + self.horizontalSplitter.addWidget(self.verticalSplitter) + self.horizontalSplitter.setStretchFactor(0, 0) + self.horizontalSplitter.setStretchFactor(1, 1) + self.horizontalSplitter.setCollapsible(0, False) + self.horizontalSplitter.setCollapsible(1, False) + self.gridLayout_7.addWidget(self.horizontalSplitter, 0, 0, 1, 1) icon4 = QtGui.QIcon() - icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/identities.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.tabWidget.addTab(self.youridentities, icon4, _fromUtf8("")) + icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/send.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.tabWidget.addTab(self.send, icon4, _fromUtf8("")) self.subscriptions = QtGui.QWidget() self.subscriptions.setObjectName(_fromUtf8("subscriptions")) - self.gridLayout_4 = QtGui.QGridLayout(self.subscriptions) - self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4")) - self.label_5 = QtGui.QLabel(self.subscriptions) - self.label_5.setWordWrap(True) - self.label_5.setObjectName(_fromUtf8("label_5")) - self.gridLayout_4.addWidget(self.label_5, 0, 0, 1, 2) + self.gridLayout_3 = QtGui.QGridLayout(self.subscriptions) + self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) + self.horizontalSplitter_4 = settingsmixin.SSplitter() + self.horizontalSplitter_4.setObjectName(_fromUtf8("horizontalSplitter_4")) + self.verticalSplitter_3 = settingsmixin.SSplitter() + self.verticalSplitter_3.setObjectName(_fromUtf8("verticalSplitter_3")) + self.verticalSplitter_3.setOrientation(QtCore.Qt.Vertical) + self.treeWidgetSubscriptions = settingsmixin.STreeWidget(self.subscriptions) + self.treeWidgetSubscriptions.setAlternatingRowColors(True) + self.treeWidgetSubscriptions.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) + self.treeWidgetSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.treeWidgetSubscriptions.setObjectName(_fromUtf8("treeWidgetSubscriptions")) + self.treeWidgetSubscriptions.resize(200, self.treeWidgetSubscriptions.height()) + icon5 = QtGui.QIcon() + icon5.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off) + self.treeWidgetSubscriptions.headerItem().setIcon(0, icon5) + self.verticalSplitter_3.addWidget(self.treeWidgetSubscriptions) self.pushButtonAddSubscription = QtGui.QPushButton(self.subscriptions) self.pushButtonAddSubscription.setObjectName(_fromUtf8("pushButtonAddSubscription")) - self.gridLayout_4.addWidget(self.pushButtonAddSubscription, 1, 0, 1, 1) - spacerItem2 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.gridLayout_4.addItem(spacerItem2, 1, 1, 1, 1) - self.tableWidgetSubscriptions = QtGui.QTableWidget(self.subscriptions) - self.tableWidgetSubscriptions.setAlternatingRowColors(True) - self.tableWidgetSubscriptions.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) - self.tableWidgetSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) - self.tableWidgetSubscriptions.setObjectName(_fromUtf8("tableWidgetSubscriptions")) - self.tableWidgetSubscriptions.setColumnCount(2) - self.tableWidgetSubscriptions.setRowCount(0) + self.pushButtonAddSubscription.resize(200, self.pushButtonAddSubscription.height()) + self.verticalSplitter_3.addWidget(self.pushButtonAddSubscription) + self.verticalSplitter_3.setStretchFactor(0, 1) + self.verticalSplitter_3.setStretchFactor(1, 0) + self.verticalSplitter_3.setCollapsible(0, False) + self.verticalSplitter_3.setCollapsible(1, False) + self.verticalSplitter_3.handle(1).setEnabled(False) + self.horizontalSplitter_4.addWidget(self.verticalSplitter_3) + self.verticalSplitter_4 = settingsmixin.SSplitter() + self.verticalSplitter_4.setObjectName(_fromUtf8("verticalSplitter_4")) + self.verticalSplitter_4.setOrientation(QtCore.Qt.Vertical) + self.horizontalSplitter_2 = QtGui.QSplitter() + self.horizontalSplitter_2.setObjectName(_fromUtf8("horizontalSplitter_2")) + self.inboxSearchLineEditSubscriptions = QtGui.QLineEdit(self.subscriptions) + self.inboxSearchLineEditSubscriptions.setObjectName(_fromUtf8("inboxSearchLineEditSubscriptions")) + self.horizontalSplitter_2.addWidget(self.inboxSearchLineEditSubscriptions) + self.inboxSearchOptionSubscriptions = QtGui.QComboBox(self.subscriptions) + self.inboxSearchOptionSubscriptions.setObjectName(_fromUtf8("inboxSearchOptionSubscriptions")) + self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) + self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) + self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) + self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) + self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) + self.inboxSearchOptionSubscriptions.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) + self.horizontalSplitter_2.addWidget(self.inboxSearchOptionSubscriptions) + self.horizontalSplitter_2.handle(1).setEnabled(False) + self.horizontalSplitter_2.setStretchFactor(0, 1) + self.horizontalSplitter_2.setStretchFactor(1, 0) + self.verticalSplitter_4.addWidget(self.horizontalSplitter_2) + self.tableWidgetInboxSubscriptions = settingsmixin.STableWidget(self.subscriptions) + self.tableWidgetInboxSubscriptions.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) + self.tableWidgetInboxSubscriptions.setAlternatingRowColors(True) + self.tableWidgetInboxSubscriptions.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) + self.tableWidgetInboxSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.tableWidgetInboxSubscriptions.setWordWrap(False) + self.tableWidgetInboxSubscriptions.setObjectName(_fromUtf8("tableWidgetInboxSubscriptions")) + self.tableWidgetInboxSubscriptions.setColumnCount(4) + self.tableWidgetInboxSubscriptions.setRowCount(0) item = QtGui.QTableWidgetItem() - self.tableWidgetSubscriptions.setHorizontalHeaderItem(0, item) + self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(0, item) item = QtGui.QTableWidgetItem() - self.tableWidgetSubscriptions.setHorizontalHeaderItem(1, item) - self.tableWidgetSubscriptions.horizontalHeader().setCascadingSectionResizes(True) - self.tableWidgetSubscriptions.horizontalHeader().setDefaultSectionSize(400) - self.tableWidgetSubscriptions.horizontalHeader().setHighlightSections(False) - self.tableWidgetSubscriptions.horizontalHeader().setSortIndicatorShown(False) - self.tableWidgetSubscriptions.horizontalHeader().setStretchLastSection(True) - self.tableWidgetSubscriptions.verticalHeader().setVisible(False) - self.gridLayout_4.addWidget(self.tableWidgetSubscriptions, 2, 0, 1, 2) - icon5 = QtGui.QIcon() - icon5.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.tabWidget.addTab(self.subscriptions, icon5, _fromUtf8("")) - self.addressbook = QtGui.QWidget() - self.addressbook.setObjectName(_fromUtf8("addressbook")) - self.gridLayout_5 = QtGui.QGridLayout(self.addressbook) - self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5")) - self.label_6 = QtGui.QLabel(self.addressbook) - self.label_6.setWordWrap(True) - self.label_6.setObjectName(_fromUtf8("label_6")) - self.gridLayout_5.addWidget(self.label_6, 0, 0, 1, 2) - self.pushButtonAddAddressBook = QtGui.QPushButton(self.addressbook) - self.pushButtonAddAddressBook.setObjectName(_fromUtf8("pushButtonAddAddressBook")) - self.gridLayout_5.addWidget(self.pushButtonAddAddressBook, 1, 0, 1, 1) - spacerItem3 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.gridLayout_5.addItem(spacerItem3, 1, 1, 1, 1) - self.tableWidgetAddressBook = QtGui.QTableWidget(self.addressbook) - self.tableWidgetAddressBook.setAlternatingRowColors(True) - self.tableWidgetAddressBook.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) - self.tableWidgetAddressBook.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) - self.tableWidgetAddressBook.setObjectName(_fromUtf8("tableWidgetAddressBook")) - self.tableWidgetAddressBook.setColumnCount(2) - self.tableWidgetAddressBook.setRowCount(0) + self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(1, item) item = QtGui.QTableWidgetItem() - self.tableWidgetAddressBook.setHorizontalHeaderItem(0, item) + self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(2, item) item = QtGui.QTableWidgetItem() - self.tableWidgetAddressBook.setHorizontalHeaderItem(1, item) - self.tableWidgetAddressBook.horizontalHeader().setCascadingSectionResizes(True) - self.tableWidgetAddressBook.horizontalHeader().setDefaultSectionSize(400) - self.tableWidgetAddressBook.horizontalHeader().setHighlightSections(False) - self.tableWidgetAddressBook.horizontalHeader().setStretchLastSection(True) - self.tableWidgetAddressBook.verticalHeader().setVisible(False) - self.gridLayout_5.addWidget(self.tableWidgetAddressBook, 2, 0, 1, 2) + self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(3, item) + self.tableWidgetInboxSubscriptions.horizontalHeader().setCascadingSectionResizes(True) + self.tableWidgetInboxSubscriptions.horizontalHeader().setDefaultSectionSize(200) + self.tableWidgetInboxSubscriptions.horizontalHeader().setHighlightSections(False) + self.tableWidgetInboxSubscriptions.horizontalHeader().setMinimumSectionSize(27) + self.tableWidgetInboxSubscriptions.horizontalHeader().setSortIndicatorShown(False) + self.tableWidgetInboxSubscriptions.horizontalHeader().setStretchLastSection(True) + self.tableWidgetInboxSubscriptions.verticalHeader().setVisible(False) + self.tableWidgetInboxSubscriptions.verticalHeader().setDefaultSectionSize(26) + self.verticalSplitter_4.addWidget(self.tableWidgetInboxSubscriptions) + self.textEditInboxMessageSubscriptions = MessageView(self.subscriptions) + self.textEditInboxMessageSubscriptions.setBaseSize(QtCore.QSize(0, 500)) + self.textEditInboxMessageSubscriptions.setReadOnly(True) + self.textEditInboxMessageSubscriptions.setObjectName(_fromUtf8("textEditInboxMessageSubscriptions")) + self.verticalSplitter_4.addWidget(self.textEditInboxMessageSubscriptions) + self.verticalSplitter_4.setStretchFactor(0, 0) + self.verticalSplitter_4.setStretchFactor(1, 1) + self.verticalSplitter_4.setStretchFactor(2, 2) + self.verticalSplitter_4.setCollapsible(0, False) + self.verticalSplitter_4.setCollapsible(1, False) + self.verticalSplitter_4.setCollapsible(2, False) + self.verticalSplitter_4.handle(1).setEnabled(False) + self.horizontalSplitter_4.addWidget(self.verticalSplitter_4) + self.horizontalSplitter_4.setStretchFactor(0, 0) + self.horizontalSplitter_4.setStretchFactor(1, 1) + self.horizontalSplitter_4.setCollapsible(0, False) + self.horizontalSplitter_4.setCollapsible(1, False) + self.gridLayout_3.addWidget(self.horizontalSplitter_4, 0, 0, 1, 1) icon6 = QtGui.QIcon() - icon6.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/addressbook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.tabWidget.addTab(self.addressbook, icon6, _fromUtf8("")) - self.blackwhitelist = QtGui.QWidget() - self.blackwhitelist.setObjectName(_fromUtf8("blackwhitelist")) - self.gridLayout_6 = QtGui.QGridLayout(self.blackwhitelist) - self.gridLayout_6.setObjectName(_fromUtf8("gridLayout_6")) - self.radioButtonBlacklist = QtGui.QRadioButton(self.blackwhitelist) - self.radioButtonBlacklist.setChecked(True) - self.radioButtonBlacklist.setObjectName(_fromUtf8("radioButtonBlacklist")) - self.gridLayout_6.addWidget(self.radioButtonBlacklist, 0, 0, 1, 2) - self.radioButtonWhitelist = QtGui.QRadioButton(self.blackwhitelist) - self.radioButtonWhitelist.setObjectName(_fromUtf8("radioButtonWhitelist")) - self.gridLayout_6.addWidget(self.radioButtonWhitelist, 1, 0, 1, 2) - self.pushButtonAddBlacklist = QtGui.QPushButton(self.blackwhitelist) - self.pushButtonAddBlacklist.setObjectName(_fromUtf8("pushButtonAddBlacklist")) - self.gridLayout_6.addWidget(self.pushButtonAddBlacklist, 2, 0, 1, 1) - spacerItem4 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.gridLayout_6.addItem(spacerItem4, 2, 1, 1, 1) - self.tableWidgetBlacklist = QtGui.QTableWidget(self.blackwhitelist) - self.tableWidgetBlacklist.setAlternatingRowColors(True) - self.tableWidgetBlacklist.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) - self.tableWidgetBlacklist.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) - self.tableWidgetBlacklist.setObjectName(_fromUtf8("tableWidgetBlacklist")) - self.tableWidgetBlacklist.setColumnCount(2) - self.tableWidgetBlacklist.setRowCount(0) - item = QtGui.QTableWidgetItem() - self.tableWidgetBlacklist.setHorizontalHeaderItem(0, item) - item = QtGui.QTableWidgetItem() - self.tableWidgetBlacklist.setHorizontalHeaderItem(1, item) - self.tableWidgetBlacklist.horizontalHeader().setCascadingSectionResizes(True) - self.tableWidgetBlacklist.horizontalHeader().setDefaultSectionSize(400) - self.tableWidgetBlacklist.horizontalHeader().setHighlightSections(False) - self.tableWidgetBlacklist.horizontalHeader().setSortIndicatorShown(False) - self.tableWidgetBlacklist.horizontalHeader().setStretchLastSection(True) - self.tableWidgetBlacklist.verticalHeader().setVisible(False) - self.gridLayout_6.addWidget(self.tableWidgetBlacklist, 3, 0, 1, 2) + icon6.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.tabWidget.addTab(self.subscriptions, icon6, _fromUtf8("")) + self.chans = QtGui.QWidget() + self.chans.setObjectName(_fromUtf8("chans")) + self.gridLayout_4 = QtGui.QGridLayout(self.chans) + self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4")) + self.horizontalSplitter_7 = settingsmixin.SSplitter() + self.horizontalSplitter_7.setObjectName(_fromUtf8("horizontalSplitter_7")) + self.verticalSplitter_17 = settingsmixin.SSplitter() + self.verticalSplitter_17.setObjectName(_fromUtf8("verticalSplitter_17")) + self.verticalSplitter_17.setOrientation(QtCore.Qt.Vertical) + self.treeWidgetChans = settingsmixin.STreeWidget(self.chans) + self.treeWidgetChans.setFrameShadow(QtGui.QFrame.Sunken) + self.treeWidgetChans.setLineWidth(1) + self.treeWidgetChans.setAlternatingRowColors(True) + self.treeWidgetChans.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) + self.treeWidgetChans.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.treeWidgetChans.setObjectName(_fromUtf8("treeWidgetChans")) + self.treeWidgetChans.resize(200, self.treeWidgetChans.height()) icon7 = QtGui.QIcon() - icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/blacklist.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.tabWidget.addTab(self.blackwhitelist, icon7, _fromUtf8("")) - self.networkstatus = QtGui.QWidget() - self.networkstatus.setObjectName(_fromUtf8("networkstatus")) - self.pushButtonStatusIcon = QtGui.QPushButton(self.networkstatus) - self.pushButtonStatusIcon.setGeometry(QtCore.QRect(680, 440, 21, 23)) - self.pushButtonStatusIcon.setText(_fromUtf8("")) + icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-16px.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off) + self.treeWidgetChans.headerItem().setIcon(0, icon7) + self.verticalSplitter_17.addWidget(self.treeWidgetChans) + self.pushButtonAddChan = QtGui.QPushButton(self.chans) + self.pushButtonAddChan.setObjectName(_fromUtf8("pushButtonAddChan")) + self.pushButtonAddChan.resize(200, self.pushButtonAddChan.height()) + self.verticalSplitter_17.addWidget(self.pushButtonAddChan) + self.verticalSplitter_17.setStretchFactor(0, 1) + self.verticalSplitter_17.setStretchFactor(1, 0) + self.verticalSplitter_17.setCollapsible(0, False) + self.verticalSplitter_17.setCollapsible(1, False) + self.verticalSplitter_17.handle(1).setEnabled(False) + self.horizontalSplitter_7.addWidget(self.verticalSplitter_17) + self.verticalSplitter_8 = settingsmixin.SSplitter() + self.verticalSplitter_8.setObjectName(_fromUtf8("verticalSplitter_8")) + self.verticalSplitter_8.setOrientation(QtCore.Qt.Vertical) + self.horizontalSplitter_6 = QtGui.QSplitter() + self.horizontalSplitter_6.setObjectName(_fromUtf8("horizontalSplitter_6")) + self.inboxSearchLineEditChans = QtGui.QLineEdit(self.chans) + self.inboxSearchLineEditChans.setObjectName(_fromUtf8("inboxSearchLineEditChans")) + self.horizontalSplitter_6.addWidget(self.inboxSearchLineEditChans) + self.inboxSearchOptionChans = QtGui.QComboBox(self.chans) + self.inboxSearchOptionChans.setObjectName(_fromUtf8("inboxSearchOptionChans")) + self.inboxSearchOptionChans.addItem(_fromUtf8("")) + self.inboxSearchOptionChans.addItem(_fromUtf8("")) + self.inboxSearchOptionChans.addItem(_fromUtf8("")) + self.inboxSearchOptionChans.addItem(_fromUtf8("")) + self.inboxSearchOptionChans.addItem(_fromUtf8("")) + self.inboxSearchOptionChans.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) + self.horizontalSplitter_6.addWidget(self.inboxSearchOptionChans) + self.horizontalSplitter_6.handle(1).setEnabled(False) + self.horizontalSplitter_6.setStretchFactor(0, 1) + self.horizontalSplitter_6.setStretchFactor(1, 0) + self.verticalSplitter_8.addWidget(self.horizontalSplitter_6) + self.tableWidgetInboxChans = settingsmixin.STableWidget(self.chans) + self.tableWidgetInboxChans.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) + self.tableWidgetInboxChans.setAlternatingRowColors(True) + self.tableWidgetInboxChans.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) + self.tableWidgetInboxChans.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.tableWidgetInboxChans.setWordWrap(False) + self.tableWidgetInboxChans.setObjectName(_fromUtf8("tableWidgetInboxChans")) + self.tableWidgetInboxChans.setColumnCount(4) + self.tableWidgetInboxChans.setRowCount(0) + item = QtGui.QTableWidgetItem() + self.tableWidgetInboxChans.setHorizontalHeaderItem(0, item) + item = QtGui.QTableWidgetItem() + self.tableWidgetInboxChans.setHorizontalHeaderItem(1, item) + item = QtGui.QTableWidgetItem() + self.tableWidgetInboxChans.setHorizontalHeaderItem(2, item) + item = QtGui.QTableWidgetItem() + self.tableWidgetInboxChans.setHorizontalHeaderItem(3, item) + self.tableWidgetInboxChans.horizontalHeader().setCascadingSectionResizes(True) + self.tableWidgetInboxChans.horizontalHeader().setDefaultSectionSize(200) + self.tableWidgetInboxChans.horizontalHeader().setHighlightSections(False) + self.tableWidgetInboxChans.horizontalHeader().setMinimumSectionSize(27) + self.tableWidgetInboxChans.horizontalHeader().setSortIndicatorShown(False) + self.tableWidgetInboxChans.horizontalHeader().setStretchLastSection(True) + self.tableWidgetInboxChans.verticalHeader().setVisible(False) + self.tableWidgetInboxChans.verticalHeader().setDefaultSectionSize(26) + self.verticalSplitter_8.addWidget(self.tableWidgetInboxChans) + self.textEditInboxMessageChans = MessageView(self.chans) + self.textEditInboxMessageChans.setBaseSize(QtCore.QSize(0, 500)) + self.textEditInboxMessageChans.setReadOnly(True) + self.textEditInboxMessageChans.setObjectName(_fromUtf8("textEditInboxMessageChans")) + self.verticalSplitter_8.addWidget(self.textEditInboxMessageChans) + self.verticalSplitter_8.setStretchFactor(0, 0) + self.verticalSplitter_8.setStretchFactor(1, 1) + self.verticalSplitter_8.setStretchFactor(2, 2) + self.verticalSplitter_8.setCollapsible(0, False) + self.verticalSplitter_8.setCollapsible(1, False) + self.verticalSplitter_8.setCollapsible(2, False) + self.verticalSplitter_8.handle(1).setEnabled(False) + self.horizontalSplitter_7.addWidget(self.verticalSplitter_8) + self.horizontalSplitter_7.setStretchFactor(0, 0) + self.horizontalSplitter_7.setStretchFactor(1, 1) + self.horizontalSplitter_7.setCollapsible(0, False) + self.horizontalSplitter_7.setCollapsible(1, False) + self.gridLayout_4.addWidget(self.horizontalSplitter_7, 0, 0, 1, 1) icon8 = QtGui.QIcon() - icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/redicon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.pushButtonStatusIcon.setIcon(icon8) - self.pushButtonStatusIcon.setFlat(True) - self.pushButtonStatusIcon.setObjectName(_fromUtf8("pushButtonStatusIcon")) - self.tableWidgetConnectionCount = QtGui.QTableWidget(self.networkstatus) - self.tableWidgetConnectionCount.setGeometry(QtCore.QRect(20, 70, 241, 241)) - palette = QtGui.QPalette() - brush = QtGui.QBrush(QtGui.QColor(212, 208, 200)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush) - brush = QtGui.QBrush(QtGui.QColor(212, 208, 200)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush) - brush = QtGui.QBrush(QtGui.QColor(212, 208, 200)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush) - self.tableWidgetConnectionCount.setPalette(palette) - self.tableWidgetConnectionCount.setFrameShape(QtGui.QFrame.Box) - self.tableWidgetConnectionCount.setFrameShadow(QtGui.QFrame.Plain) - self.tableWidgetConnectionCount.setProperty("showDropIndicator", False) - self.tableWidgetConnectionCount.setAlternatingRowColors(True) - self.tableWidgetConnectionCount.setSelectionMode(QtGui.QAbstractItemView.NoSelection) - self.tableWidgetConnectionCount.setObjectName(_fromUtf8("tableWidgetConnectionCount")) - self.tableWidgetConnectionCount.setColumnCount(2) - self.tableWidgetConnectionCount.setRowCount(0) - item = QtGui.QTableWidgetItem() - self.tableWidgetConnectionCount.setHorizontalHeaderItem(0, item) - item = QtGui.QTableWidgetItem() - self.tableWidgetConnectionCount.setHorizontalHeaderItem(1, item) - self.tableWidgetConnectionCount.horizontalHeader().setCascadingSectionResizes(True) - self.tableWidgetConnectionCount.horizontalHeader().setHighlightSections(False) - self.tableWidgetConnectionCount.horizontalHeader().setStretchLastSection(True) - self.tableWidgetConnectionCount.verticalHeader().setVisible(False) - self.labelTotalConnections = QtGui.QLabel(self.networkstatus) - self.labelTotalConnections.setGeometry(QtCore.QRect(20, 30, 401, 16)) - self.labelTotalConnections.setObjectName(_fromUtf8("labelTotalConnections")) - self.labelStartupTime = QtGui.QLabel(self.networkstatus) - self.labelStartupTime.setGeometry(QtCore.QRect(320, 110, 331, 20)) - self.labelStartupTime.setObjectName(_fromUtf8("labelStartupTime")) - self.labelMessageCount = QtGui.QLabel(self.networkstatus) - self.labelMessageCount.setGeometry(QtCore.QRect(350, 130, 361, 16)) - self.labelMessageCount.setObjectName(_fromUtf8("labelMessageCount")) - self.labelPubkeyCount = QtGui.QLabel(self.networkstatus) - self.labelPubkeyCount.setGeometry(QtCore.QRect(350, 170, 331, 16)) - self.labelPubkeyCount.setObjectName(_fromUtf8("labelPubkeyCount")) - self.labelBroadcastCount = QtGui.QLabel(self.networkstatus) - self.labelBroadcastCount.setGeometry(QtCore.QRect(350, 150, 351, 16)) - self.labelBroadcastCount.setObjectName(_fromUtf8("labelBroadcastCount")) - self.labelLookupsPerSecond = QtGui.QLabel(self.networkstatus) - self.labelLookupsPerSecond.setGeometry(QtCore.QRect(320, 250, 291, 16)) - self.labelLookupsPerSecond.setObjectName(_fromUtf8("labelLookupsPerSecond")) - self.labelBytesRecvCount = QtGui.QLabel(self.networkstatus) - self.labelBytesRecvCount.setGeometry(QtCore.QRect(350, 210, 251, 16)) - self.labelBytesRecvCount.setObjectName(_fromUtf8("labelBytesRecvCount")) - self.labelBytesSentCount = QtGui.QLabel(self.networkstatus) - self.labelBytesSentCount.setGeometry(QtCore.QRect(350, 230, 251, 16)) - self.labelBytesSentCount.setObjectName(_fromUtf8("labelBytesSentCount")) - icon9 = QtGui.QIcon() - icon9.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/networkstatus.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.tabWidget.addTab(self.networkstatus, icon9, _fromUtf8("")) - self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) + icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-16px.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.tabWidget.addTab(self.chans, icon8, _fromUtf8("")) + self.blackwhitelist = Blacklist() + self.tabWidget.addTab(self.blackwhitelist, QtGui.QIcon(":/newPrefix/images/blacklist.png"), "") + # Initialize the Blacklist or Whitelist + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white': + self.blackwhitelist.radioButtonWhitelist.click() + self.blackwhitelist.rerenderBlackWhiteList() + + self.networkstatus = NetworkStatus() + self.tabWidget.addTab(self.networkstatus, QtGui.QIcon(":/newPrefix/images/networkstatus.png"), "") + self.gridLayout_10.addWidget(self.tabWidget, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 21)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 27)) self.menubar.setObjectName(_fromUtf8("menubar")) self.menuFile = QtGui.QMenu(self.menubar) self.menuFile.setObjectName(_fromUtf8("menuFile")) @@ -514,6 +597,10 @@ class Ui_MainWindow(object): icon = QtGui.QIcon.fromTheme(_fromUtf8("help-contents")) self.actionHelp.setIcon(icon) self.actionHelp.setObjectName(_fromUtf8("actionHelp")) + self.actionSupport = QtGui.QAction(MainWindow) + icon = QtGui.QIcon.fromTheme(_fromUtf8("help-support")) + self.actionSupport.setIcon(icon) + self.actionSupport.setObjectName(_fromUtf8("actionSupport")) self.actionAbout = QtGui.QAction(MainWindow) icon = QtGui.QIcon.fromTheme(_fromUtf8("help-about")) self.actionAbout.setIcon(icon) @@ -537,10 +624,10 @@ class Ui_MainWindow(object): self.menuFile.addAction(self.actionManageKeys) self.menuFile.addAction(self.actionDeleteAllTrashedMessages) self.menuFile.addAction(self.actionRegenerateDeterministicAddresses) - self.menuFile.addAction(self.actionJoinChan) self.menuFile.addAction(self.actionExit) self.menuSettings.addAction(self.actionSettings) self.menuHelp.addAction(self.actionHelp) + self.menuHelp.addAction(self.actionSupport) self.menuHelp.addAction(self.actionAbout) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuSettings.menuAction()) @@ -548,43 +635,25 @@ class Ui_MainWindow(object): self.retranslateUi(MainWindow) self.tabWidget.setCurrentIndex(0) - QtCore.QObject.connect(self.radioButtonSpecific, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.lineEditTo.setEnabled) - QtCore.QObject.connect(self.radioButtonSpecific, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.labelSendBroadcastWarning.hide) - QtCore.QObject.connect(self.radioButtonBroadcast, QtCore.SIGNAL(_fromUtf8("clicked()")), self.labelSendBroadcastWarning.show) + self.tabWidgetSend.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) - MainWindow.setTabOrder(self.tabWidget, self.tableWidgetInbox) MainWindow.setTabOrder(self.tableWidgetInbox, self.textEditInboxMessage) - MainWindow.setTabOrder(self.textEditInboxMessage, self.radioButtonSpecific) - MainWindow.setTabOrder(self.radioButtonSpecific, self.radioButtonBroadcast) - MainWindow.setTabOrder(self.radioButtonBroadcast, self.comboBoxSendFrom) + MainWindow.setTabOrder(self.textEditInboxMessage, self.comboBoxSendFrom) MainWindow.setTabOrder(self.comboBoxSendFrom, self.lineEditTo) - MainWindow.setTabOrder(self.lineEditTo, self.pushButtonLoadFromAddressBook) - MainWindow.setTabOrder(self.pushButtonLoadFromAddressBook, self.lineEditSubject) + MainWindow.setTabOrder(self.lineEditTo, self.lineEditSubject) MainWindow.setTabOrder(self.lineEditSubject, self.textEditMessage) - MainWindow.setTabOrder(self.textEditMessage, self.pushButtonSend) - MainWindow.setTabOrder(self.pushButtonSend, self.tableWidgetSent) - MainWindow.setTabOrder(self.tableWidgetSent, self.textEditSentMessage) - MainWindow.setTabOrder(self.textEditSentMessage, self.pushButtonNewAddress) - MainWindow.setTabOrder(self.pushButtonNewAddress, self.tableWidgetYourIdentities) - MainWindow.setTabOrder(self.tableWidgetYourIdentities, self.pushButtonAddSubscription) - MainWindow.setTabOrder(self.pushButtonAddSubscription, self.tableWidgetSubscriptions) - MainWindow.setTabOrder(self.tableWidgetSubscriptions, self.pushButtonAddAddressBook) - MainWindow.setTabOrder(self.pushButtonAddAddressBook, self.tableWidgetAddressBook) - MainWindow.setTabOrder(self.tableWidgetAddressBook, self.radioButtonBlacklist) - MainWindow.setTabOrder(self.radioButtonBlacklist, self.radioButtonWhitelist) - MainWindow.setTabOrder(self.radioButtonWhitelist, self.pushButtonAddBlacklist) - MainWindow.setTabOrder(self.pushButtonAddBlacklist, self.tableWidgetBlacklist) - MainWindow.setTabOrder(self.tableWidgetBlacklist, self.tableWidgetConnectionCount) - MainWindow.setTabOrder(self.tableWidgetConnectionCount, self.pushButtonStatusIcon) + MainWindow.setTabOrder(self.textEditMessage, self.pushButtonAddSubscription) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(_translate("MainWindow", "Bitmessage", None)) + self.treeWidgetYourIdentities.headerItem().setText(0, _translate("MainWindow", "Identities", None)) + self.pushButtonNewAddress.setText(_translate("MainWindow", "New Identity", None)) self.inboxSearchLineEdit.setPlaceholderText(_translate("MainWindow", "Search", None)) - self.inboxSearchOptionCB.setItemText(0, _translate("MainWindow", "All", None)) - self.inboxSearchOptionCB.setItemText(1, _translate("MainWindow", "To", None)) - self.inboxSearchOptionCB.setItemText(2, _translate("MainWindow", "From", None)) - self.inboxSearchOptionCB.setItemText(3, _translate("MainWindow", "Subject", None)) - self.inboxSearchOptionCB.setItemText(4, _translate("MainWindow", "Message", None)) + self.inboxSearchOption.setItemText(0, _translate("MainWindow", "All", None)) + self.inboxSearchOption.setItemText(1, _translate("MainWindow", "To", None)) + self.inboxSearchOption.setItemText(2, _translate("MainWindow", "From", None)) + self.inboxSearchOption.setItemText(3, _translate("MainWindow", "Subject", None)) + self.inboxSearchOption.setItemText(4, _translate("MainWindow", "Message", None)) self.tableWidgetInbox.setSortingEnabled(True) item = self.tableWidgetInbox.horizontalHeaderItem(0) item.setText(_translate("MainWindow", "To", None)) @@ -594,88 +663,72 @@ class Ui_MainWindow(object): item.setText(_translate("MainWindow", "Subject", None)) item = self.tableWidgetInbox.horizontalHeaderItem(3) item.setText(_translate("MainWindow", "Received", None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.inbox), _translate("MainWindow", "Inbox", None)) - self.pushButtonLoadFromAddressBook.setText(_translate("MainWindow", "Load from Address book", None)) - self.label_3.setText(_translate("MainWindow", "Subject:", None)) - self.pushButtonSend.setText(_translate("MainWindow", "Send", None)) - self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "X days", None)) - self.label_4.setText(_translate("MainWindow", "Message:", None)) - self.label.setText(_translate("MainWindow", "To:", None)) - self.radioButtonSpecific.setText(_translate("MainWindow", "Send to one or more specific people", None)) - self.labelSendBroadcastWarning.setText(_translate("MainWindow", "Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them.", None)) - self.radioButtonBroadcast.setText(_translate("MainWindow", "Broadcast to everyone who is subscribed to your address", None)) - self.pushButtonTTL.setText(_translate("MainWindow", "TTL:", None)) - self.label_2.setText(_translate("MainWindow", "From:", None)) - self.textEditMessage.setHtml(_translate("MainWindow", "\n" -"\n" -"


", None)) - self.pushButtonFetchNamecoinID.setText(_translate("MainWindow", "Fetch Namecoin ID", None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None)) - self.sentSearchLineEdit.setPlaceholderText(_translate("MainWindow", "Search", None)) - self.sentSearchOptionCB.setItemText(0, _translate("MainWindow", "All", None)) - self.sentSearchOptionCB.setItemText(1, _translate("MainWindow", "To", None)) - self.sentSearchOptionCB.setItemText(2, _translate("MainWindow", "From", None)) - self.sentSearchOptionCB.setItemText(3, _translate("MainWindow", "Subject", None)) - self.sentSearchOptionCB.setItemText(4, _translate("MainWindow", "Message", None)) - self.tableWidgetSent.setSortingEnabled(True) - item = self.tableWidgetSent.horizontalHeaderItem(0) - item.setText(_translate("MainWindow", "To", None)) - item = self.tableWidgetSent.horizontalHeaderItem(1) - item.setText(_translate("MainWindow", "From", None)) - item = self.tableWidgetSent.horizontalHeaderItem(2) - item.setText(_translate("MainWindow", "Subject", None)) - item = self.tableWidgetSent.horizontalHeaderItem(3) - item.setText(_translate("MainWindow", "Status", None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.sent), _translate("MainWindow", "Sent", None)) - self.pushButtonNewAddress.setText(_translate("MainWindow", "New", None)) - self.tableWidgetYourIdentities.setSortingEnabled(True) - item = self.tableWidgetYourIdentities.horizontalHeaderItem(0) - item.setText(_translate("MainWindow", "Label (not shown to anyone)", None)) - item = self.tableWidgetYourIdentities.horizontalHeaderItem(1) - item.setText(_translate("MainWindow", "Address", None)) - item = self.tableWidgetYourIdentities.horizontalHeaderItem(2) - item.setText(_translate("MainWindow", "Stream", None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.youridentities), _translate("MainWindow", "Your Identities", None)) - self.label_5.setText(_translate("MainWindow", "Here you can subscribe to \'broadcast messages\' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab.", None)) - self.pushButtonAddSubscription.setText(_translate("MainWindow", "Add new Subscription", None)) - self.tableWidgetSubscriptions.setSortingEnabled(True) - item = self.tableWidgetSubscriptions.horizontalHeaderItem(0) - item.setText(_translate("MainWindow", "Label", None)) - item = self.tableWidgetSubscriptions.horizontalHeaderItem(1) - item.setText(_translate("MainWindow", "Address", None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.subscriptions), _translate("MainWindow", "Subscriptions", None)) - self.label_6.setText(_translate("MainWindow", "The Address book is useful for adding names or labels to other people\'s Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the \'Add\' button, or from your inbox by right-clicking on a message.", None)) - self.pushButtonAddAddressBook.setText(_translate("MainWindow", "Add new entry", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.inbox), _translate("MainWindow", "Messages", None)) self.tableWidgetAddressBook.setSortingEnabled(True) item = self.tableWidgetAddressBook.horizontalHeaderItem(0) - item.setText(_translate("MainWindow", "Name or Label", None)) + item.setText(_translate("MainWindow", "Address book", None)) item = self.tableWidgetAddressBook.horizontalHeaderItem(1) item.setText(_translate("MainWindow", "Address", None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.addressbook), _translate("MainWindow", "Address Book", None)) - self.radioButtonBlacklist.setText(_translate("MainWindow", "Use a Blacklist (Allow all incoming messages except those on the Blacklist)", None)) - self.radioButtonWhitelist.setText(_translate("MainWindow", "Use a Whitelist (Block all incoming messages except those on the Whitelist)", None)) - self.pushButtonAddBlacklist.setText(_translate("MainWindow", "Add new entry", None)) - self.tableWidgetBlacklist.setSortingEnabled(True) - item = self.tableWidgetBlacklist.horizontalHeaderItem(0) - item.setText(_translate("MainWindow", "Name or Label", None)) - item = self.tableWidgetBlacklist.horizontalHeaderItem(1) - item.setText(_translate("MainWindow", "Address", None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.blackwhitelist), _translate("MainWindow", "Blacklist", None)) - item = self.tableWidgetConnectionCount.horizontalHeaderItem(0) - item.setText(_translate("MainWindow", "Stream #", None)) - item = self.tableWidgetConnectionCount.horizontalHeaderItem(1) - item.setText(_translate("MainWindow", "Connections", None)) - self.labelTotalConnections.setText(_translate("MainWindow", "Total connections:", None)) - self.labelStartupTime.setText(_translate("MainWindow", "Since startup:", None)) - self.labelMessageCount.setText(_translate("MainWindow", "Processed 0 person-to-person messages.", None)) - self.labelPubkeyCount.setText(_translate("MainWindow", "Processed 0 public keys.", None)) - self.labelBroadcastCount.setText(_translate("MainWindow", "Processed 0 broadcasts.", None)) - self.labelLookupsPerSecond.setText(_translate("MainWindow", "Inventory lookups per second: 0", None)) - self.labelBytesRecvCount.setText(_translate("MainWindow", "Down: 0 KB/s", None)) - self.labelBytesSentCount.setText(_translate("MainWindow", "Up: 0 KB/s", None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.networkstatus), _translate("MainWindow", "Network Status", None)) + self.pushButtonAddAddressBook.setText(_translate("MainWindow", "Add Contact", None)) + self.pushButtonFetchNamecoinID.setText(_translate("MainWindow", "Fetch Namecoin ID", None)) + self.label_3.setText(_translate("MainWindow", "Subject:", None)) + self.label_2.setText(_translate("MainWindow", "From:", None)) + self.label.setText(_translate("MainWindow", "To:", None)) + #self.textEditMessage.setHtml("") + self.tabWidgetSend.setTabText(self.tabWidgetSend.indexOf(self.sendDirect), _translate("MainWindow", "Send ordinary Message", None)) + self.label_8.setText(_translate("MainWindow", "From:", None)) + self.label_7.setText(_translate("MainWindow", "Subject:", None)) + #self.textEditMessageBroadcast.setHtml("") + self.tabWidgetSend.setTabText(self.tabWidgetSend.indexOf(self.sendBroadcast), _translate("MainWindow", "Send Message to your Subscribers", None)) + self.pushButtonTTL.setText(_translate("MainWindow", "TTL:", None)) + hours = 48 + try: + hours = int(shared.config.getint('bitmessagesettings', 'ttl')/60/60) + except: + pass + self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, hours)) + self.pushButtonSend.setText(_translate("MainWindow", "Send", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None)) + self.treeWidgetSubscriptions.headerItem().setText(0, _translate("MainWindow", "Subscriptions", None)) + self.pushButtonAddSubscription.setText(_translate("MainWindow", "Add new Subscription", None)) + self.inboxSearchLineEditSubscriptions.setPlaceholderText(_translate("MainWindow", "Search", None)) + self.inboxSearchOptionSubscriptions.setItemText(0, _translate("MainWindow", "All", None)) + self.inboxSearchOptionSubscriptions.setItemText(1, _translate("MainWindow", "To", None)) + self.inboxSearchOptionSubscriptions.setItemText(2, _translate("MainWindow", "From", None)) + self.inboxSearchOptionSubscriptions.setItemText(3, _translate("MainWindow", "Subject", None)) + self.inboxSearchOptionSubscriptions.setItemText(4, _translate("MainWindow", "Message", None)) + self.tableWidgetInboxSubscriptions.setSortingEnabled(True) + item = self.tableWidgetInboxSubscriptions.horizontalHeaderItem(0) + item.setText(_translate("MainWindow", "To", None)) + item = self.tableWidgetInboxSubscriptions.horizontalHeaderItem(1) + item.setText(_translate("MainWindow", "From", None)) + item = self.tableWidgetInboxSubscriptions.horizontalHeaderItem(2) + item.setText(_translate("MainWindow", "Subject", None)) + item = self.tableWidgetInboxSubscriptions.horizontalHeaderItem(3) + item.setText(_translate("MainWindow", "Received", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.subscriptions), _translate("MainWindow", "Subscriptions", None)) + self.treeWidgetChans.headerItem().setText(0, _translate("MainWindow", "Chans", None)) + self.pushButtonAddChan.setText(_translate("MainWindow", "Add Chan", None)) + self.inboxSearchLineEditChans.setPlaceholderText(_translate("MainWindow", "Search", None)) + self.inboxSearchOptionChans.setItemText(0, _translate("MainWindow", "All", None)) + self.inboxSearchOptionChans.setItemText(1, _translate("MainWindow", "To", None)) + self.inboxSearchOptionChans.setItemText(2, _translate("MainWindow", "From", None)) + self.inboxSearchOptionChans.setItemText(3, _translate("MainWindow", "Subject", None)) + self.inboxSearchOptionChans.setItemText(4, _translate("MainWindow", "Message", None)) + self.tableWidgetInboxChans.setSortingEnabled(True) + item = self.tableWidgetInboxChans.horizontalHeaderItem(0) + item.setText(_translate("MainWindow", "To", None)) + item = self.tableWidgetInboxChans.horizontalHeaderItem(1) + item.setText(_translate("MainWindow", "From", None)) + item = self.tableWidgetInboxChans.horizontalHeaderItem(2) + item.setText(_translate("MainWindow", "Subject", None)) + item = self.tableWidgetInboxChans.horizontalHeaderItem(3) + item.setText(_translate("MainWindow", "Received", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.chans), _translate("MainWindow", "Chans", None)) + self.blackwhitelist.retranslateUi() + self.tabWidget.setTabText(self.tabWidget.indexOf(self.blackwhitelist), _translate("blacklist", "Blacklist", None)) + self.networkstatus.retranslateUi() + self.tabWidget.setTabText(self.tabWidget.indexOf(self.networkstatus), _translate("networkstatus", "Network Status", None)) self.menuFile.setTitle(_translate("MainWindow", "File", None)) self.menuSettings.setTitle(_translate("MainWindow", "Settings", None)) self.menuHelp.setTitle(_translate("MainWindow", "Help", None)) @@ -685,6 +738,7 @@ class Ui_MainWindow(object): self.actionExit.setShortcut(_translate("MainWindow", "Ctrl+Q", None)) self.actionHelp.setText(_translate("MainWindow", "Help", None)) self.actionHelp.setShortcut(_translate("MainWindow", "F1", None)) + self.actionSupport.setText(_translate("MainWindow", "Contact support", None)) self.actionAbout.setText(_translate("MainWindow", "About", None)) self.actionSettings.setText(_translate("MainWindow", "Settings", None)) self.actionRegenerateDeterministicAddresses.setText(_translate("MainWindow", "Regenerate deterministic addresses", None)) @@ -692,3 +746,14 @@ class Ui_MainWindow(object): self.actionJoinChan.setText(_translate("MainWindow", "Join / Create chan", None)) import bitmessage_icons_rc + +if __name__ == "__main__": + import sys + + app = QtGui.QApplication(sys.argv) + MainWindow = settingsmixin.SMainWindow() + ui = Ui_MainWindow() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) + diff --git a/src/bitmessageqt/bitmessageui.ui b/src/bitmessageqt/bitmessageui.ui index e45cc22d..fef40be6 100644 --- a/src/bitmessageqt/bitmessageui.ui +++ b/src/bitmessageqt/bitmessageui.ui @@ -21,10 +21,7 @@ QTabWidget::Rounded - - - 0 - + @@ -65,134 +62,176 @@ :/newPrefix/images/inbox.png:/newPrefix/images/inbox.png - Inbox + Messages - - - - - 0 - + + + - - - Search - - + + + + + + 200 + 16777215 + + + + + Identities + + + + :/newPrefix/images/identities.png + + + + + + + + + + 200 + 16777215 + + + + New Indentitiy + + + + - + - - All - + + + 0 + + + + + Search + + + + + + + + All + + + + + To + + + + + From + + + + + Subject + + + + + Message + + + + + - - To - + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + true + + + 200 + + + false + + + 27 + + + false + + + true + + + false + + + 26 + + + + To + + + + + From + + + + + Subject + + + + + Received + + + - - From - + + + + 0 + 500 + + + + true + + - - - Subject - - - - - Message - - - + - - - - Qt::Vertical - - - - QAbstractItemView::NoEditTriggers - - - true - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::SelectRows - - - true - - - false - - - true - - - 200 - - - false - - - 27 - - - false - - - true - - - false - - - 26 - - - - To - - - - - From - - - - - Subject - - - - - Received - - - - - - - 0 - 500 - - - - true - - - - @@ -203,498 +242,366 @@ Send - - - - - - 7 - - - - Load from Address book - - - - - - - Subject: - - - - - - - Send - - - - - - - - 35 - 0 - - - - - 70 - 16777215 - - - - Qt::Horizontal - - - false - - - false - - - - - - - Qt::Vertical - - - - 20 - 297 - - - - - - - - - 300 - 0 - - - - - - - - - 0 - 0 - - - - - 45 - 0 - - - - - 45 - 16777215 - - - - X days - - - - - - - Message: - - - - - - - To: - - - - - - - Send to one or more specific people - - - true - - - - - - - true - - - - 0 - 0 - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - - - -1 - - - - - - - Broadcast to everyone who is subscribed to your address - - - - - - - - 0 - 0 - - - - - 32 - 16777215 - - - - - - - - - 0 - 0 - 255 - - - - - - - - - 0 - 0 - 255 - - - - - - - - - 120 - 120 - 120 - - - - - - - - - true - - - - TTL: - - - true - - - - - - - From: - - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - - - - - 7 - - - - Fetch Namecoin ID - - - - - - - - - - - - - - - - - - - - - - - :/newPrefix/images/sent.png:/newPrefix/images/sent.png - - - Sent - - - + + - - 0 - - - - Search - - + + + + + + 200 + 16777215 + + + + true + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + true + + + true + + + 200 + + + false + + + true + + + false + + + + Address book + + + + :/newPrefix/images/addressbook.png + + + + + + Address + + + + + + + + + 200 + 16777215 + + + + Add Contact + + + + + + + + 200 + 16777215 + + + + + 9 + + + + Fetch Namecoin ID + + + + - + - - All - + + + 0 + + + + Send ordinary Message + + + + + + + + + + Subject: + + + + + + + From: + + + + + + + + + + + + + + To: + + + + + + + + 300 + 0 + + + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Droid Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> + + + + + + + + + + Send Message to your Subscribers + + + + + + + + + + From: + + + + + + + + + + + + + + Subject: + + + + + + + + 300 + 0 + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Droid Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> + + + + + + + + - - To - + + + + + + 0 + 0 + + + + + 32 + 16777215 + + + + + + + + + 0 + 0 + 255 + + + + + + + + + 0 + 0 + 255 + + + + + + + + + 120 + 120 + 120 + + + + + + + + + true + + + + TTL: + + + true + + + + + + + + 35 + 0 + + + + + 70 + 16777215 + + + + Qt::Horizontal + + + false + + + false + + + + + + + + 0 + 0 + + + + + 45 + 0 + + + + + 45 + 16777215 + + + + X days + + + + + + + + 16777215 + 16777215 + + + + Send + + + + - - - From - - - - - Subject - - - - - Message - - - + - - - - Qt::Vertical - - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::DragDrop - - - true - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::SelectRows - - - true - - - false - - - true - - - 130 - - - false - - - false - - - true - - - false - - - false - - - - To - - - - - From - - - - - Subject - - - - - Status - - - - - - true - - - - - - - - - - :/newPrefix/images/identities.png:/newPrefix/images/identities.png - - - Your Identities - - - - - - New - - - - - - - Qt::Horizontal - - - - 689 - 20 - - - - - - - - QFrame::Sunken - - - 1 - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - true - - - true - - - 346 - - - 52 - - - true - - - true - - - false - - - 26 - - - false - - - false - - - - Label (not shown to anyone) - - - - true - - - - - - Address - - - - - Stream - - - - + @@ -704,162 +611,369 @@ p, li { white-space: pre-wrap; } Subscriptions - - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - - - true - - - - - - - Add new Subscription - - - - - - - Qt::Horizontal - - - - 689 - 20 - - - - - - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - true - - - true - - - 400 - - - false - - - false - - - true - - - false - - - - Label - - - - - Address - - - + + + + + + + + + + 200 + 16777215 + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + Subscriptions + + + + :/newPrefix/images/subscriptions.png + + + + + + + + + + 200 + 16777215 + + + + Add new Subscription + + + + + + + + + + + + + Search + + + + + + + + All + + + + + To + + + + + From + + + + + Subject + + + + + Message + + + + + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + true + + + 200 + + + false + + + 27 + + + false + + + true + + + false + + + 26 + + + + To + + + + + From + + + + + Subject + + + + + Received + + + + + + + + + 0 + 500 + + + + true + + + + + + - + - :/newPrefix/images/addressbook.png:/newPrefix/images/addressbook.png + :/newPrefix/images/can-icon-16px.png:/newPrefix/images/can-icon-16px.png - Address Book + Chans - - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - - - true - - - - - - - Add new entry - - - - - - - Qt::Horizontal - - - - 689 - 20 - - - - - - - - true - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::SelectRows - - - true - - - true - - - 400 - - - false - - - true - - - false - - - - Name or Label - - - - - Address - - - + + + + + + + + + + 200 + 16777215 + + + + QFrame::Sunken + + + 1 + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + Chans + + + + :/newPrefix/images/can-icon-16px.png + + + + + + + + + + 200 + 16777215 + + + + Add Chan + + + + + + + + + + + + + Search + + + + + + + + All + + + + + To + + + + + From + + + + + Subject + + + + + Message + + + + + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + true + + + 200 + + + false + + + 27 + + + false + + + true + + + false + + + 26 + + + + To + + + + + From + + + + + Subject + + + + + Received + + + + + + + + + 0 + 500 + + + + true + + + + + + @@ -1182,7 +1296,7 @@ p, li { white-space: pre-wrap; } 0 0 885 - 21 + 27 @@ -1192,7 +1306,6 @@ p, li { white-space: pre-wrap; } - @@ -1319,25 +1432,14 @@ p, li { white-space: pre-wrap; } - tabWidget tableWidgetInbox textEditInboxMessage - radioButtonSpecific - radioButtonBroadcast comboBoxSendFrom lineEditTo - pushButtonLoadFromAddressBook lineEditSubject textEditMessage pushButtonSend - tableWidgetSent - textEditSentMessage - pushButtonNewAddress - tableWidgetYourIdentities pushButtonAddSubscription - tableWidgetSubscriptions - pushButtonAddAddressBook - tableWidgetAddressBook radioButtonBlacklist radioButtonWhitelist pushButtonAddBlacklist @@ -1348,54 +1450,5 @@ p, li { white-space: pre-wrap; } - - - radioButtonSpecific - toggled(bool) - lineEditTo - setEnabled(bool) - - - 121 - 60 - - - 175 - 147 - - - - - radioButtonSpecific - clicked(bool) - labelSendBroadcastWarning - hide() - - - 95 - 59 - - - 129 - 528 - - - - - radioButtonBroadcast - clicked() - labelSendBroadcastWarning - show() - - - 108 - 84 - - - 177 - 519 - - - - + diff --git a/src/bitmessageqt/blacklist.py b/src/bitmessageqt/blacklist.py new file mode 100644 index 00000000..1e4be35a --- /dev/null +++ b/src/bitmessageqt/blacklist.py @@ -0,0 +1,242 @@ +from PyQt4 import QtCore, QtGui +import shared +from tr import _translate +import l10n +from uisignaler import UISignaler +import widgets +from addresses import addBMIfNotPresent +from dialogs import AddAddressDialog +from helper_sql import sqlExecute, sqlQuery +from retranslateui import RetranslateMixin +from utils import avatarize +from uisignaler import UISignaler + + +class Blacklist(QtGui.QWidget, RetranslateMixin): + def __init__(self, parent=None): + super(Blacklist, self).__init__(parent) + widgets.load('blacklist.ui', self) + + QtCore.QObject.connect(self.radioButtonBlacklist, QtCore.SIGNAL( + "clicked()"), self.click_radioButtonBlacklist) + QtCore.QObject.connect(self.radioButtonWhitelist, QtCore.SIGNAL( + "clicked()"), self.click_radioButtonWhitelist) + QtCore.QObject.connect(self.pushButtonAddBlacklist, QtCore.SIGNAL( + "clicked()"), self.click_pushButtonAddBlacklist) + + self.init_blacklist_popup_menu() + + # Initialize blacklist + QtCore.QObject.connect(self.tableWidgetBlacklist, QtCore.SIGNAL( + "itemChanged(QTableWidgetItem *)"), self.tableWidgetBlacklistItemChanged) + + # Set the icon sizes for the identicons + identicon_size = 3*7 + self.tableWidgetBlacklist.setIconSize(QtCore.QSize(identicon_size, identicon_size)) + + self.UISignalThread = UISignaler.get() + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "rerenderBlackWhiteList()"), self.rerenderBlackWhiteList) + + def click_radioButtonBlacklist(self): + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white': + shared.config.set('bitmessagesettings', 'blackwhitelist', 'black') + shared.writeKeysFile() + # self.tableWidgetBlacklist.clearContents() + self.tableWidgetBlacklist.setRowCount(0) + self.rerenderBlackWhiteList() + + def click_radioButtonWhitelist(self): + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': + shared.config.set('bitmessagesettings', 'blackwhitelist', 'white') + shared.writeKeysFile() + # self.tableWidgetBlacklist.clearContents() + self.tableWidgetBlacklist.setRowCount(0) + self.rerenderBlackWhiteList() + + def click_pushButtonAddBlacklist(self): + self.NewBlacklistDialogInstance = AddAddressDialog(self) + if self.NewBlacklistDialogInstance.exec_(): + if self.NewBlacklistDialogInstance.ui.labelAddressCheck.text() == _translate("MainWindow", "Address is valid."): + address = addBMIfNotPresent(str( + self.NewBlacklistDialogInstance.ui.lineEditAddress.text())) + # First we must check to see if the address is already in the + # address book. The user cannot add it again or else it will + # cause problems when updating and deleting the entry. + t = (address,) + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': + sql = '''select * from blacklist where address=?''' + else: + sql = '''select * from whitelist where address=?''' + queryreturn = sqlQuery(sql,*t) + if queryreturn == []: + self.tableWidgetBlacklist.setSortingEnabled(False) + self.tableWidgetBlacklist.insertRow(0) + newItem = QtGui.QTableWidgetItem(unicode( + self.NewBlacklistDialogInstance.ui.newAddressLabel.text().toUtf8(), 'utf-8')) + newItem.setIcon(avatarize(address)) + self.tableWidgetBlacklist.setItem(0, 0, newItem) + newItem = QtGui.QTableWidgetItem(address) + newItem.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.tableWidgetBlacklist.setItem(0, 1, newItem) + self.tableWidgetBlacklist.setSortingEnabled(True) + t = (str(self.NewBlacklistDialogInstance.ui.newAddressLabel.text().toUtf8()), address, True) + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': + sql = '''INSERT INTO blacklist VALUES (?,?,?)''' + else: + sql = '''INSERT INTO whitelist VALUES (?,?,?)''' + sqlExecute(sql, *t) + else: + self.statusBar().showMessage(_translate( + "MainWindow", "Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want.")) + else: + self.statusBar().showMessage(_translate( + "MainWindow", "The address you entered was invalid. Ignoring it.")) + + def tableWidgetBlacklistItemChanged(self, item): + if item.column() == 0: + addressitem = self.tableWidgetBlacklist.item(item.row(), 1) + if isinstance(addressitem, QtGui.QTableWidgetItem): + if self.radioButtonBlacklist.isChecked(): + sqlExecute('''UPDATE blacklist SET label=? WHERE address=?''', + str(item.text()), str(addressitem.text())) + else: + sqlExecute('''UPDATE whitelist SET label=? WHERE address=?''', + str(item.text()), str(addressitem.text())) + + def init_blacklist_popup_menu(self, connectSignal=True): + # Popup menu for the Blacklist page + self.blacklistContextMenuToolbar = QtGui.QToolBar() + # Actions + self.actionBlacklistNew = self.blacklistContextMenuToolbar.addAction( + _translate( + "MainWindow", "Add new entry"), self.on_action_BlacklistNew) + self.actionBlacklistDelete = self.blacklistContextMenuToolbar.addAction( + _translate( + "MainWindow", "Delete"), self.on_action_BlacklistDelete) + self.actionBlacklistClipboard = self.blacklistContextMenuToolbar.addAction( + _translate( + "MainWindow", "Copy address to clipboard"), + self.on_action_BlacklistClipboard) + self.actionBlacklistEnable = self.blacklistContextMenuToolbar.addAction( + _translate( + "MainWindow", "Enable"), self.on_action_BlacklistEnable) + self.actionBlacklistDisable = self.blacklistContextMenuToolbar.addAction( + _translate( + "MainWindow", "Disable"), self.on_action_BlacklistDisable) + self.actionBlacklistSetAvatar = self.blacklistContextMenuToolbar.addAction( + _translate( + "MainWindow", "Set avatar..."), + self.on_action_BlacklistSetAvatar) + self.tableWidgetBlacklist.setContextMenuPolicy( + QtCore.Qt.CustomContextMenu) + if connectSignal: + self.connect(self.tableWidgetBlacklist, QtCore.SIGNAL( + 'customContextMenuRequested(const QPoint&)'), + self.on_context_menuBlacklist) + self.popMenuBlacklist = QtGui.QMenu(self) + # self.popMenuBlacklist.addAction( self.actionBlacklistNew ) + self.popMenuBlacklist.addAction(self.actionBlacklistDelete) + self.popMenuBlacklist.addSeparator() + self.popMenuBlacklist.addAction(self.actionBlacklistClipboard) + self.popMenuBlacklist.addSeparator() + self.popMenuBlacklist.addAction(self.actionBlacklistEnable) + self.popMenuBlacklist.addAction(self.actionBlacklistDisable) + self.popMenuBlacklist.addAction(self.actionBlacklistSetAvatar) + + def rerenderBlackWhiteList(self): + tabs = self.parent().parent() + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': + tabs.setTabText(tabs.indexOf(self), _translate('blacklist', 'Blacklist')) + else: + tabs.setTabText(tabs.indexOf(self), _translate('blacklist', 'Whitelist')) + self.tableWidgetBlacklist.setRowCount(0) + listType = shared.config.get('bitmessagesettings', 'blackwhitelist') + if listType == 'black': + queryreturn = sqlQuery('''SELECT label, address, enabled FROM blacklist''') + else: + queryreturn = sqlQuery('''SELECT label, address, enabled FROM whitelist''') + self.tableWidgetBlacklist.setSortingEnabled(False) + for row in queryreturn: + label, address, enabled = row + self.tableWidgetBlacklist.insertRow(0) + newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) + if not enabled: + newItem.setTextColor(QtGui.QColor(128, 128, 128)) + newItem.setIcon(avatarize(address)) + self.tableWidgetBlacklist.setItem(0, 0, newItem) + newItem = QtGui.QTableWidgetItem(address) + newItem.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + if not enabled: + newItem.setTextColor(QtGui.QColor(128, 128, 128)) + self.tableWidgetBlacklist.setItem(0, 1, newItem) + self.tableWidgetBlacklist.setSortingEnabled(True) + + # Group of functions for the Blacklist dialog box + def on_action_BlacklistNew(self): + self.click_pushButtonAddBlacklist() + + def on_action_BlacklistDelete(self): + currentRow = self.tableWidgetBlacklist.currentRow() + labelAtCurrentRow = self.tableWidgetBlacklist.item( + currentRow, 0).text().toUtf8() + addressAtCurrentRow = self.tableWidgetBlacklist.item( + currentRow, 1).text() + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': + sqlExecute( + '''DELETE FROM blacklist WHERE label=? AND address=?''', + str(labelAtCurrentRow), str(addressAtCurrentRow)) + else: + sqlExecute( + '''DELETE FROM whitelist WHERE label=? AND address=?''', + str(labelAtCurrentRow), str(addressAtCurrentRow)) + self.tableWidgetBlacklist.removeRow(currentRow) + + def on_action_BlacklistClipboard(self): + currentRow = self.tableWidgetBlacklist.currentRow() + addressAtCurrentRow = self.tableWidgetBlacklist.item( + currentRow, 1).text() + clipboard = QtGui.QApplication.clipboard() + clipboard.setText(str(addressAtCurrentRow)) + + def on_context_menuBlacklist(self, point): + self.popMenuBlacklist.exec_( + self.tableWidgetBlacklist.mapToGlobal(point)) + + def on_action_BlacklistEnable(self): + currentRow = self.tableWidgetBlacklist.currentRow() + addressAtCurrentRow = self.tableWidgetBlacklist.item( + currentRow, 1).text() + self.tableWidgetBlacklist.item( + currentRow, 0).setTextColor(QtGui.QApplication.palette().text().color()) + self.tableWidgetBlacklist.item( + currentRow, 1).setTextColor(QtGui.QApplication.palette().text().color()) + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': + sqlExecute( + '''UPDATE blacklist SET enabled=1 WHERE address=?''', + str(addressAtCurrentRow)) + else: + sqlExecute( + '''UPDATE whitelist SET enabled=1 WHERE address=?''', + str(addressAtCurrentRow)) + + def on_action_BlacklistDisable(self): + currentRow = self.tableWidgetBlacklist.currentRow() + addressAtCurrentRow = self.tableWidgetBlacklist.item( + currentRow, 1).text() + self.tableWidgetBlacklist.item( + currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128)) + self.tableWidgetBlacklist.item( + currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) + if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': + sqlExecute( + '''UPDATE blacklist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow)) + else: + sqlExecute( + '''UPDATE whitelist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow)) + + def on_action_BlacklistSetAvatar(self): + self.window().on_action_SetAvatar(self.tableWidgetBlacklist) + diff --git a/src/bitmessageqt/blacklist.ui b/src/bitmessageqt/blacklist.ui new file mode 100644 index 00000000..80993fac --- /dev/null +++ b/src/bitmessageqt/blacklist.ui @@ -0,0 +1,108 @@ + + + blacklist + + + + 0 + 0 + 819 + 295 + + + + + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + true + + + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + + + Add new entry + + + + + + + Qt::Horizontal + + + + 689 + 20 + + + + + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + true + + + 400 + + + false + + + false + + + true + + + false + + + + Name or Label + + + + + Address + + + + + + + + + STableWidget + QTableWidget +
bitmessageqt/settingsmixin.h
+
+
+ + + + +
diff --git a/src/bitmessageqt/dialogs.py b/src/bitmessageqt/dialogs.py new file mode 100644 index 00000000..d8133eb1 --- /dev/null +++ b/src/bitmessageqt/dialogs.py @@ -0,0 +1,42 @@ +from PyQt4 import QtCore, QtGui +from addaddressdialog import Ui_AddAddressDialog +from addresses import decodeAddress +from tr import _translate + + +class AddAddressDialog(QtGui.QDialog): + + def __init__(self, parent): + QtGui.QWidget.__init__(self, parent) + self.ui = Ui_AddAddressDialog() + self.ui.setupUi(self) + self.parent = parent + QtCore.QObject.connect(self.ui.lineEditAddress, QtCore.SIGNAL( + "textChanged(QString)"), self.addressChanged) + + def addressChanged(self, QString): + status, a, b, c = decodeAddress(str(QString)) + if status == 'missingbm': + self.ui.labelAddressCheck.setText(_translate( + "MainWindow", "The address should start with ''BM-''")) + elif status == 'checksumfailed': + self.ui.labelAddressCheck.setText(_translate( + "MainWindow", "The address is not typed or copied correctly (the checksum failed).")) + elif status == 'versiontoohigh': + self.ui.labelAddressCheck.setText(_translate( + "MainWindow", "The version number of this address is higher than this software can support. Please upgrade Bitmessage.")) + elif status == 'invalidcharacters': + self.ui.labelAddressCheck.setText(_translate( + "MainWindow", "The address contains invalid characters.")) + elif status == 'ripetooshort': + self.ui.labelAddressCheck.setText(_translate( + "MainWindow", "Some data encoded in the address is too short.")) + elif status == 'ripetoolong': + self.ui.labelAddressCheck.setText(_translate( + "MainWindow", "Some data encoded in the address is too long.")) + elif status == 'varintmalformed': + self.ui.labelAddressCheck.setText(_translate( + "MainWindow", "Some data encoded in the address is malformed.")) + elif status == 'success': + self.ui.labelAddressCheck.setText( + _translate("MainWindow", "Address is valid.")) diff --git a/src/bitmessageqt/emailgateway.py b/src/bitmessageqt/emailgateway.py new file mode 100644 index 00000000..54ca4529 --- /dev/null +++ b/src/bitmessageqt/emailgateway.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'emailgateway.ui' +# +# Created: Fri Apr 26 17:43:31 2013 +# by: PyQt4 UI code generator 4.9.4 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class Ui_EmailGatewayDialog(object): + def setupUi(self, EmailGatewayDialog): + EmailGatewayDialog.setObjectName(_fromUtf8("EmailGatewayDialog")) + EmailGatewayDialog.resize(386, 172) + self.gridLayout = QtGui.QGridLayout(EmailGatewayDialog) + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.radioButtonRegister = QtGui.QRadioButton(EmailGatewayDialog) + self.radioButtonRegister.setChecked(True) + self.radioButtonRegister.setObjectName(_fromUtf8("radioButtonRegister")) + self.gridLayout.addWidget(self.radioButtonRegister, 1, 0, 1, 1) + self.radioButtonStatus = QtGui.QRadioButton(EmailGatewayDialog) + self.radioButtonStatus.setObjectName(_fromUtf8("radioButtonStatus")) + self.gridLayout.addWidget(self.radioButtonStatus, 4, 0, 1, 1) + self.radioButtonSettings = QtGui.QRadioButton(EmailGatewayDialog) + self.radioButtonSettings.setObjectName(_fromUtf8("radioButtonSettings")) + self.gridLayout.addWidget(self.radioButtonSettings, 5, 0, 1, 1) + self.radioButtonUnregister = QtGui.QRadioButton(EmailGatewayDialog) + self.radioButtonUnregister.setObjectName(_fromUtf8("radioButtonUnregister")) + self.gridLayout.addWidget(self.radioButtonUnregister, 6, 0, 1, 1) + self.label = QtGui.QLabel(EmailGatewayDialog) + self.label.setWordWrap(True) + self.label.setObjectName(_fromUtf8("label")) + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + self.label_2 = QtGui.QLabel(EmailGatewayDialog) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1) + self.lineEditEmail = QtGui.QLineEdit(EmailGatewayDialog) + self.lineEditEmail.setEnabled(True) + self.lineEditEmail.setObjectName(_fromUtf8("lineEditEmail")) + self.gridLayout.addWidget(self.lineEditEmail, 3, 0, 1, 1) + self.buttonBox = QtGui.QDialogButtonBox(EmailGatewayDialog) + self.buttonBox.setMinimumSize(QtCore.QSize(368, 0)) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) + self.buttonBox.setObjectName(_fromUtf8("buttonBox")) + self.gridLayout.addWidget(self.buttonBox, 7, 0, 1, 1) + + self.retranslateUi(EmailGatewayDialog) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), EmailGatewayDialog.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), EmailGatewayDialog.reject) + QtCore.QObject.connect(self.radioButtonRegister, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.lineEditEmail.setEnabled) + QtCore.QObject.connect(self.radioButtonStatus, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.lineEditEmail.setDisabled) + QtCore.QObject.connect(self.radioButtonSettings, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.lineEditEmail.setDisabled) + QtCore.QObject.connect(self.radioButtonUnregister, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.lineEditEmail.setDisabled) + QtCore.QMetaObject.connectSlotsByName(EmailGatewayDialog) + EmailGatewayDialog.setTabOrder(self.radioButtonRegister, self.lineEditEmail) + EmailGatewayDialog.setTabOrder(self.lineEditEmail, self.radioButtonUnregister) + EmailGatewayDialog.setTabOrder(self.radioButtonUnregister, self.buttonBox) + + def retranslateUi(self, EmailGatewayDialog): + EmailGatewayDialog.setWindowTitle(QtGui.QApplication.translate("EmailGatewayDialog", "Email gateway", None, QtGui.QApplication.UnicodeUTF8)) + self.radioButtonRegister.setText(QtGui.QApplication.translate("EmailGatewayDialog", "Register on email gateway", None, QtGui.QApplication.UnicodeUTF8)) + self.radioButtonStatus.setText(QtGui.QApplication.translate("EmailGatewayDialog", "Account status at email gateway", None, QtGui.QApplication.UnicodeUTF8)) + self.radioButtonSettings.setText(QtGui.QApplication.translate("EmailGatewayDialog", "Change account settings at email gateway", None, QtGui.QApplication.UnicodeUTF8)) + self.radioButtonUnregister.setText(QtGui.QApplication.translate("EmailGatewayDialog", "Unregister from email gateway", None, QtGui.QApplication.UnicodeUTF8)) + self.label.setText(QtGui.QApplication.translate("EmailGatewayDialog", "Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available.", None, QtGui.QApplication.UnicodeUTF8)) + self.label_2.setText(QtGui.QApplication.translate("EmailGatewayDialog", "Desired email address (including @mailchuck.com):", None, QtGui.QApplication.UnicodeUTF8)) + + +class Ui_EmailGatewayRegistrationDialog(object): + def setupUi(self, EmailGatewayRegistrationDialog): + EmailGatewayRegistrationDialog.setObjectName(_fromUtf8("EmailGatewayRegistrationDialog")) + EmailGatewayRegistrationDialog.resize(386, 172) + self.gridLayout = QtGui.QGridLayout(EmailGatewayRegistrationDialog) + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.label = QtGui.QLabel(EmailGatewayRegistrationDialog) + self.label.setWordWrap(True) + self.label.setObjectName(_fromUtf8("label")) + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + self.lineEditEmail = QtGui.QLineEdit(EmailGatewayRegistrationDialog) + self.lineEditEmail.setObjectName(_fromUtf8("lineEditEmail")) + self.gridLayout.addWidget(self.lineEditEmail, 1, 0, 1, 1) + self.buttonBox = QtGui.QDialogButtonBox(EmailGatewayRegistrationDialog) + self.buttonBox.setMinimumSize(QtCore.QSize(368, 0)) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) + self.buttonBox.setObjectName(_fromUtf8("buttonBox")) + self.gridLayout.addWidget(self.buttonBox, 7, 0, 1, 1) + + self.retranslateUi(EmailGatewayRegistrationDialog) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), EmailGatewayRegistrationDialog.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), EmailGatewayRegistrationDialog.reject) + QtCore.QMetaObject.connectSlotsByName(EmailGatewayRegistrationDialog) + + def retranslateUi(self, EmailGatewayRegistrationDialog): + EmailGatewayRegistrationDialog.setWindowTitle(QtGui.QApplication.translate("EmailGatewayRegistrationDialog", "Email gateway registration", None, QtGui.QApplication.UnicodeUTF8)) + self.label.setText(QtGui.QApplication.translate("EmailGatewayRegistrationDialog", "Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available.\nPlease type the desired email address (including @mailchuck.com) below:", None, QtGui.QApplication.UnicodeUTF8)) diff --git a/src/bitmessageqt/emailgateway.ui b/src/bitmessageqt/emailgateway.ui new file mode 100644 index 00000000..927df46a --- /dev/null +++ b/src/bitmessageqt/emailgateway.ui @@ -0,0 +1,157 @@ + + + EmailGatewayDialog + + + + 0 + 0 + 386 + 172 + + + + Email gateway + + + + + + true + + + Desired email address (including @mailchuck.com) + + + + + + + Register on email gateway + + + true + + + + + + + + 368 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + true + + + @mailchuck.com + + + + + + + Email gateway alows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + true + + + + + + + Unregister from email gateway + + + false + + + + + + + radioButtonRegister + lineEditEmailAddress + buttonBox + + + + + buttonBox + accepted() + EmailGatewayDialog + accept() + + + 227 + 152 + + + 157 + 171 + + + + + buttonBox + rejected() + EmailGatewayDialog + reject() + + + 295 + 158 + + + 286 + 171 + + + + + radioButtonRegister + clicked(bool) + lineEditEmailAddress + setEnabled(bool) + + + 95 + 40 + + + 94 + 123 + + + + + radioButtonUnregister + clicked(bool) + lineEditEmailAddress + setDisabled(bool) + + + 139 + 19 + + + 187 + 123 + + + + + diff --git a/src/bitmessageqt/foldertree.py b/src/bitmessageqt/foldertree.py new file mode 100644 index 00000000..ed76eac2 --- /dev/null +++ b/src/bitmessageqt/foldertree.py @@ -0,0 +1,534 @@ +from PyQt4 import QtCore, QtGui +from string import find, rfind, rstrip, lstrip + +from helper_sql import * +from utils import * +import shared +from settingsmixin import SettingsMixin + +class AccountMixin (object): + ALL = 0 + NORMAL = 1 + CHAN = 2 + MAILINGLIST = 3 + SUBSCRIPTION = 4 + BROADCAST = 5 + + def accountColor (self): + if not self.isEnabled: + return QtGui.QColor(128, 128, 128) + elif self.type == self.CHAN: + return QtGui.QColor(216, 119, 0) + elif self.type in [self.MAILINGLIST, self.SUBSCRIPTION]: + return QtGui.QColor(137, 04, 177) + else: + return QtGui.QApplication.palette().text().color() + + def folderColor (self): + if not self.parent().isEnabled: + return QtGui.QColor(128, 128, 128) + else: + return QtGui.QApplication.palette().text().color() + + def accountBrush(self): + brush = QtGui.QBrush(self.accountColor()) + brush.setStyle(QtCore.Qt.NoBrush) + return brush + + def folderBrush(self): + brush = QtGui.QBrush(self.folderColor()) + brush.setStyle(QtCore.Qt.NoBrush) + return brush + + def setAddress(self, address): + if address is None: + self.address = None + else: + self.address = str(address) + + def setUnreadCount(self, cnt): + if hasattr(self, "unreadCount") and self.unreadCount == int(cnt): + return + self.unreadCount = int(cnt) + if isinstance(self, QtGui.QTreeWidgetItem): + self.emitDataChanged() + + def setEnabled(self, enabled): + self.isEnabled = enabled + if hasattr(self, "setExpanded"): + self.setExpanded(enabled) + if isinstance(self, Ui_AddressWidget): + for i in range(self.childCount()): + if isinstance(self.child(i), Ui_FolderWidget): + self.child(i).setEnabled(enabled) + if isinstance(self, QtGui.QTreeWidgetItem): + self.emitDataChanged() + + def setType(self): + self.setFlags(self.flags() | QtCore.Qt.ItemIsEditable) + if self.address is None: + self.type = self.ALL + self.setFlags(self.flags() & ~QtCore.Qt.ItemIsEditable) + elif shared.safeConfigGetBoolean(self.address, 'chan'): + self.type = self.CHAN + elif shared.safeConfigGetBoolean(self.address, 'mailinglist'): + self.type = self.MAILINGLIST + elif sqlQuery( + '''select label from subscriptions where address=?''', self.address): + self.type = AccountMixin.SUBSCRIPTION + else: + self.type = self.NORMAL + + def defaultLabel(self): + queryreturn = None + retval = None + if self.type in (AccountMixin.NORMAL, AccountMixin.CHAN, AccountMixin.MAILINGLIST): + try: + retval = unicode(shared.config.get(self.address, 'label'), 'utf-8') + except Exception as e: + queryreturn = sqlQuery( + '''select label from addressbook where address=?''', self.address) + elif self.type == AccountMixin.SUBSCRIPTION: + queryreturn = sqlQuery( + '''select label from subscriptions where address=?''', self.address) + if queryreturn is not None: + if queryreturn != []: + for row in queryreturn: + retval, = row + retval = unicode(retval, 'utf-8') + elif self.address is None or self.type == AccountMixin.ALL: + return unicode(str(QtGui.QApplication.translate("MainWindow", "All accounts")), 'utf-8') + if retval is None: + return unicode(self.address, 'utf-8') + else: + return retval + + +class Ui_FolderWidget(QtGui.QTreeWidgetItem, AccountMixin): + folderWeight = {"inbox": 1, "new": 2, "sent": 3, "trash": 4} + def __init__(self, parent, pos = 0, address = "", folderName = "", unreadCount = 0): + super(QtGui.QTreeWidgetItem, self).__init__() + self.setAddress(address) + self.setFolderName(folderName) + self.setUnreadCount(unreadCount) + parent.insertChild(pos, self) + + def setFolderName(self, fname): + self.folderName = str(fname) + + def data(self, column, role): + if column == 0: + if role == QtCore.Qt.DisplayRole: + return QtGui.QApplication.translate("MainWindow", self.folderName) + (" (" + str(self.unreadCount) + ")" if self.unreadCount > 0 else "") + elif role == QtCore.Qt.EditRole: + return QtGui.QApplication.translate("MainWindow", self.folderName) + elif role == QtCore.Qt.ToolTipRole: + return QtGui.QApplication.translate("MainWindow", self.folderName) + elif role == QtCore.Qt.DecorationRole: + pass + elif role == QtCore.Qt.FontRole: + font = QtGui.QFont() + font.setBold(self.unreadCount > 0) + return font + elif role == QtCore.Qt.ForegroundRole: + return self.folderBrush() + return super(Ui_FolderWidget, self).data(column, role) + + # inbox, sent, thrash first, rest alphabetically + def __lt__(self, other): + if (isinstance(other, Ui_FolderWidget)): + if self.folderName in self.folderWeight: + x = self.folderWeight[self.folderName] + else: + x = 99 + if other.folderName in self.folderWeight: + y = self.folderWeight[other.folderName] + else: + y = 99 + reverse = False + if self.treeWidget().header().sortIndicatorOrder() == QtCore.Qt.DescendingOrder: + reverse = True + if x == y: + return self.folderName < other.folderName + else: + return (x >= y if reverse else x < y) + + return super(QtGui.QTreeWidgetItem, self).__lt__(other) + + +class Ui_AddressWidget(QtGui.QTreeWidgetItem, AccountMixin, SettingsMixin): + def __init__(self, parent, pos = 0, address = None, unreadCount = 0, enabled = True): + super(QtGui.QTreeWidgetItem, self).__init__() + parent.insertTopLevelItem(pos, self) + # only set default when creating + #super(QtGui.QTreeWidgetItem, self).setExpanded(shared.config.getboolean(self.address, 'enabled')) + self.setAddress(address) + self.setEnabled(enabled) + self.setUnreadCount(unreadCount) + self.setType() + + def _getLabel(self): + if self.address is None: + return unicode(QtGui.QApplication.translate("MainWindow", "All accounts").toUtf8(), 'utf-8', 'ignore') + else: + try: + return unicode(shared.config.get(self.address, 'label'), 'utf-8', 'ignore') + except: + return unicode(self.address, 'utf-8') + + def _getAddressBracket(self, unreadCount = False): + ret = "" + if unreadCount: + ret += " (" + str(self.unreadCount) + ")" + if self.address is not None: + ret += " (" + self.address + ")" + return ret + + def data(self, column, role): + if column == 0: + if role == QtCore.Qt.DisplayRole: + if self.unreadCount > 0 and not self.isExpanded(): + return self._getLabel() + self._getAddressBracket(True) + else: + return self._getLabel() + self._getAddressBracket(False) + elif role == QtCore.Qt.EditRole: + return self._getLabel() + elif role == QtCore.Qt.ToolTipRole: + return self._getLabel() + self._getAddressBracket(False) + elif role == QtCore.Qt.DecorationRole: + if self.address is None: + return avatarize(self._getLabel().encode('utf8')) + else: + return avatarize(self.address) + elif role == QtCore.Qt.FontRole: + font = QtGui.QFont() + font.setBold(self.unreadCount > 0) + return font + elif role == QtCore.Qt.ForegroundRole: + return self.accountBrush() + return super(Ui_AddressWidget, self).data(column, role) + + def setData(self, column, role, value): + if role == QtCore.Qt.EditRole and self.type != AccountMixin.SUBSCRIPTION: + if isinstance(value, QtCore.QVariant): + shared.config.set(str(self.address), 'label', str(value.toString().toUtf8())) + else: + shared.config.set(str(self.address), 'label', str(value)) + shared.writeKeysFile() + return super(Ui_AddressWidget, self).setData(column, role, value) + + def setAddress(self, address): + super(Ui_AddressWidget, self).setAddress(address) + self.setData(0, QtCore.Qt.UserRole, self.address) + + def setExpanded(self, expand): + super(Ui_AddressWidget, self).setExpanded(expand) + + def _getSortRank(self): + ret = self.type + if not self.isEnabled: + ret += 100 + return ret + + # label (or address) alphabetically, disabled at the end + def __lt__(self, other): + if (isinstance(other, Ui_AddressWidget)): + reverse = False + if self.treeWidget().header().sortIndicatorOrder() == QtCore.Qt.DescendingOrder: + reverse = True + if self._getSortRank() == other._getSortRank(): + x = self._getLabel().lower() + y = other._getLabel().lower() + return x < y + return (not reverse if self._getSortRank() < other._getSortRank() else reverse) + + return super(QtGui.QTreeWidgetItem, self).__lt__(other) + + +class Ui_SubscriptionWidget(Ui_AddressWidget, AccountMixin): + def __init__(self, parent, pos = 0, address = "", unreadCount = 0, label = "", enabled = True): + super(QtGui.QTreeWidgetItem, self).__init__() + parent.insertTopLevelItem(pos, self) + # only set default when creating + #super(QtGui.QTreeWidgetItem, self).setExpanded(shared.config.getboolean(self.address, 'enabled')) + self.setAddress(address) + self.setEnabled(enabled) + self.setType() + self.setUnreadCount(unreadCount) + + def _getLabel(self): + queryreturn = sqlQuery( + '''select label from subscriptions where address=?''', self.address) + if queryreturn != []: + for row in queryreturn: + retval, = row + return unicode(retval, 'utf-8', 'ignore') + return unicode(self.address, 'utf-8') + + def setType(self): + super(Ui_SubscriptionWidget, self).setType() # sets it editable + self.type = AccountMixin.SUBSCRIPTION # overrides type + + def setData(self, column, role, value): + if role == QtCore.Qt.EditRole: + from debug import logger + if isinstance(value, QtCore.QVariant): + label = str(value.toString().toUtf8()).decode('utf-8', 'ignore') + else: + label = unicode(value, 'utf-8', 'ignore') + sqlExecute( + '''UPDATE subscriptions SET label=? WHERE address=?''', + label, self.address) + return super(Ui_SubscriptionWidget, self).setData(column, role, value) + + +class MessageList_AddressWidget(QtGui.QTableWidgetItem, AccountMixin, SettingsMixin): + def __init__(self, parent, address = None, label = None, unread = False): + super(QtGui.QTableWidgetItem, self).__init__() + #parent.insertTopLevelItem(pos, self) + # only set default when creating + #super(QtGui.QTreeWidgetItem, self).setExpanded(shared.config.getboolean(self.address, 'enabled')) + self.isEnabled = True + self.setAddress(address) + self.setLabel(label) + self.setUnread(unread) + self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.setType() + parent.append(self) + + def setLabel(self, label = None): + newLabel = self.address + if label is None: + queryreturn = None + if self.type in (AccountMixin.NORMAL, AccountMixin.CHAN, AccountMixin.MAILINGLIST): + try: + newLabel = unicode(shared.config.get(self.address, 'label'), 'utf-8', 'ignore') + except: + queryreturn = sqlQuery( + '''select label from addressbook where address=?''', self.address) + elif self.type == AccountMixin.SUBSCRIPTION: + queryreturn = sqlQuery( + '''select label from subscriptions where address=?''', self.address) + if queryreturn is not None: + if queryreturn != []: + for row in queryreturn: + newLabel, = row + else: + newLabel = label + if hasattr(self, 'label') and newLabel == self.label: + return + self.label = newLabel + + def setUnread(self, unread): + self.unread = unread + + def data(self, role): + if role == QtCore.Qt.DisplayRole: + return self.label + elif role == QtCore.Qt.EditRole: + return self.label + elif role == QtCore.Qt.ToolTipRole: + return self.label + " (" + self.address + ")" + elif role == QtCore.Qt.DecorationRole: + if shared.safeConfigGetBoolean('bitmessagesettings', 'useidenticons'): + if self.address is None: + return avatarize(self.label) + else: + return avatarize(self.address) + elif role == QtCore.Qt.FontRole: + font = QtGui.QFont() + font.setBold(self.unread) + return font + elif role == QtCore.Qt.ForegroundRole: + return self.accountBrush() + elif role == QtCore.Qt.UserRole: + return self.address + return super(MessageList_AddressWidget, self).data(role) + + def setData(self, role, value): + if role == QtCore.Qt.EditRole: + self.setLabel() + return super(MessageList_AddressWidget, self).setData(role, value) + + # label (or address) alphabetically, disabled at the end + def __lt__(self, other): + if (isinstance(other, MessageList_AddressWidget)): + return self.label.lower() < other.label.lower() + return super(QtGui.QTableWidgetItem, self).__lt__(other) + + +class MessageList_SubjectWidget(QtGui.QTableWidgetItem, SettingsMixin): + def __init__(self, parent, subject = None, label = None, unread = False): + super(QtGui.QTableWidgetItem, self).__init__() + #parent.insertTopLevelItem(pos, self) + # only set default when creating + #super(QtGui.QTreeWidgetItem, self).setExpanded(shared.config.getboolean(self.address, 'enabled')) + self.setSubject(subject) + self.setLabel(label) + self.setUnread(unread) + self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + parent.append(self) + + def setLabel(self, label): + self.label = label + + def setSubject(self, subject): + self.subject = subject + + def setUnread(self, unread): + self.unread = unread + + def data(self, role): + if role == QtCore.Qt.DisplayRole: + return self.label + elif role == QtCore.Qt.EditRole: + return self.label + elif role == QtCore.Qt.ToolTipRole: + return self.label + elif role == QtCore.Qt.FontRole: + font = QtGui.QFont() + font.setBold(self.unread) + return font + elif role == QtCore.Qt.UserRole: + return self.subject + return super(MessageList_SubjectWidget, self).data(role) + + def setData(self, role, value): + return super(MessageList_SubjectWidget, self).setData(role, value) + + # label (or address) alphabetically, disabled at the end + def __lt__(self, other): + if (isinstance(other, MessageList_SubjectWidget)): + return self.label.lower() < other.label.lower() + return super(QtGui.QTableWidgetItem, self).__lt__(other) + + +class Ui_AddressBookWidgetItem(QtGui.QTableWidgetItem, AccountMixin): + def __init__ (self, text, type = AccountMixin.NORMAL): + super(QtGui.QTableWidgetItem, self).__init__(text) + self.label = text + self.type = type + self.setEnabled(True) + + def data(self, role): + if role == QtCore.Qt.DisplayRole: + return self.label + elif role == QtCore.Qt.EditRole: + return self.label + elif role == QtCore.Qt.ToolTipRole: + return self.label + " (" + self.address + ")" + elif role == QtCore.Qt.DecorationRole: + if shared.safeConfigGetBoolean('bitmessagesettings', 'useidenticons'): + if self.address is None: + return avatarize(self.label) + else: + return avatarize(self.address) + elif role == QtCore.Qt.FontRole: + font = QtGui.QFont() + return font + elif role == QtCore.Qt.ForegroundRole: + return self.accountBrush() + elif role == QtCore.Qt.UserRole: + return self.type + return super(Ui_AddressBookWidgetItem, self).data(role) + + def setData(self, role, value): + if role == QtCore.Qt.EditRole: + if isinstance(value, QtCore.QVariant): + self.label = str(value.toString().toUtf8()) + else: + self.label = str(value) + if self.type in (AccountMixin.NORMAL, AccountMixin.MAILINGLIST, AccountMixin.CHAN): + try: + a = shared.config.get(self.address, 'label') + shared.config.set(self.address, 'label', self.label) + except: + sqlExecute('''UPDATE addressbook set label=? WHERE address=?''', self.label, self.address) + elif self.type == AccountMixin.SUBSCRIPTION: + from debug import logger + sqlExecute('''UPDATE subscriptions set label=? WHERE address=?''', self.label, self.address) + else: + pass + return super(Ui_AddressBookWidgetItem, self).setData(role, value) + + def __lt__ (self, other): + if (isinstance(other, Ui_AddressBookWidgetItem)): + reverse = False + if self.tableWidget().horizontalHeader().sortIndicatorOrder() == QtCore.Qt.DescendingOrder: + reverse = True + if self.type == other.type: + return self.label.lower() < other.label.lower() + else: + return (not reverse if self.type < other.type else reverse) + return super(QtGui.QTableWidgetItem, self).__lt__(other) + + +class Ui_AddressBookWidgetItemLabel(Ui_AddressBookWidgetItem): + def __init__ (self, address, label, type): + Ui_AddressBookWidgetItem.__init__(self, label, type) + self.address = address + self.label = label + + def data(self, role): + self.label = self.defaultLabel() + return super(Ui_AddressBookWidgetItemLabel, self).data(role) + + +class Ui_AddressBookWidgetItemAddress(Ui_AddressBookWidgetItem): + def __init__ (self, address, label, type): + Ui_AddressBookWidgetItem.__init__(self, address, type) + self.address = address + self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + +class AddressBookCompleter(QtGui.QCompleter): + def __init__(self): + super(QtGui.QCompleter, self).__init__() + self.cursorPos = -1 + + def onCursorPositionChanged(self, oldPos, newPos): + if oldPos != self.cursorPos: + self.cursorPos = -1 + + def splitPath(self, path): + stringList = [] + text = unicode(path.toUtf8(), encoding="UTF-8") + splitIndex = rfind(text[0:self.widget().cursorPosition()], ";") + 1 + str = text[splitIndex:self.widget().cursorPosition()] + str = rstrip(lstrip(str)) + stringList.append(str) + return stringList + + def pathFromIndex(self, index): + autoString = unicode(index.data(QtCore.Qt.EditRole).toString().toUtf8(), encoding="UTF-8") + text = unicode(self.widget().text().toUtf8(), encoding="UTF-8") + + # If cursor position was saved, restore it, else save it + if self.cursorPos != -1: + self.widget().setCursorPosition(self.cursorPos) + else: + self.cursorPos = self.widget().cursorPosition() + + # Get current prosition + curIndex = self.widget().cursorPosition() + + # prev_delimiter_index should actually point at final white space AFTER the delimiter + # Get index of last delimiter before current position + prevDelimiterIndex = rfind(text[0:curIndex], ";") + while text[prevDelimiterIndex + 1] == " ": + prevDelimiterIndex += 1 + + # Get index of first delimiter after current position (or EOL if no delimiter after cursor) + nextDelimiterIndex = find(text, ";", curIndex) + if nextDelimiterIndex == -1: + nextDelimiterIndex = len(text) + + # Get part of string that occurs before cursor + part1 = text[0:prevDelimiterIndex + 1] + + # Get string value from before auto finished string is selected + pre = text[prevDelimiterIndex + 1:curIndex - 1]; + + # Get part of string that occurs AFTER cursor + part2 = text[nextDelimiterIndex:] + + return part1 + autoString + part2; diff --git a/src/bitmessageqt/languagebox.py b/src/bitmessageqt/languagebox.py new file mode 100644 index 00000000..2a8cb865 --- /dev/null +++ b/src/bitmessageqt/languagebox.py @@ -0,0 +1,37 @@ +import glob +import os +from PyQt4 import QtCore, QtGui + +from shared import codePath, config + +class LanguageBox(QtGui.QComboBox): + languageName = {"system": "System Settings", "eo": "Esperanto", "en_pirate": "Pirate English"} + def __init__(self, parent = None): + super(QtGui.QComboBox, self).__init__(parent) + self.populate() + + def populate(self): + self.languages = [] + self.clear() + localesPath = os.path.join (codePath(), 'translations') + configuredLocale = "system" + try: + configuredLocale = config.get('bitmessagesettings', 'userlocale', "system") + except: + pass + self.addItem(QtGui.QApplication.translate("settingsDialog", "System Settings", "system"), "system") + self.setCurrentIndex(0) + self.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically) + for translationFile in sorted(glob.glob(os.path.join(localesPath, "bitmessage_*.qm"))): + localeShort = os.path.split(translationFile)[1].split("_", 1)[1][:-3] + locale = QtCore.QLocale(QtCore.QString(localeShort)) + if localeShort in LanguageBox.languageName: + self.addItem(LanguageBox.languageName[localeShort], localeShort) + elif locale.nativeLanguageName() == "": + self.addItem(localeShort, localeShort) + else: + self.addItem(locale.nativeLanguageName(), localeShort) + for i in range(self.count()): + if self.itemData(i) == configuredLocale: + self.setCurrentIndex(i) + break diff --git a/src/bitmessageqt/messagecompose.py b/src/bitmessageqt/messagecompose.py new file mode 100644 index 00000000..f7d5dac3 --- /dev/null +++ b/src/bitmessageqt/messagecompose.py @@ -0,0 +1,23 @@ +from PyQt4 import QtCore, QtGui + +class MessageCompose(QtGui.QTextEdit): + + def __init__(self, parent = 0): + super(MessageCompose, self).__init__(parent) + self.setAcceptRichText(False) # we'll deal with this later when we have a new message format + self.defaultFontPointSize = self.currentFont().pointSize() + + def wheelEvent(self, event): + if (QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ControlModifier) == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical: + if event.delta() > 0: + self.zoomIn(1) + else: + self.zoomOut(1) + zoom = self.currentFont().pointSize() * 100 / self.defaultFontPointSize + QtGui.QApplication.activeWindow().statusBar().showMessage(QtGui.QApplication.translate("MainWindow", "Zoom level %1%").arg(str(zoom))) + else: + # in QTextEdit, super does not zoom, only scroll + super(MessageCompose, self).wheelEvent(event) + + def reset(self): + self.setText('') diff --git a/src/bitmessageqt/messageview.py b/src/bitmessageqt/messageview.py new file mode 100644 index 00000000..c322e421 --- /dev/null +++ b/src/bitmessageqt/messageview.py @@ -0,0 +1,124 @@ +from PyQt4 import QtCore, QtGui + +from urlparse import urlparse +from safehtmlparser import * + +class MessageView(QtGui.QTextBrowser): + MODE_PLAIN = 0 + MODE_HTML = 1 + TEXT_PLAIN = "HTML detected, click here to display" + TEXT_HTML = "Click here to disable HTML" + CONFIRM_TITLE = "Follow external link" + CONFIRM_TEXT = "The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you or download malicious data. Are you sure?" + + def __init__(self, parent = 0): + super(MessageView, self).__init__(parent) + self.mode = MessageView.MODE_PLAIN + self.html = None + self.setOpenExternalLinks(False) + self.setOpenLinks(False) + self.anchorClicked.connect(self.confirmURL) + self.out = "" + self.outpos = 0 + self.document().setUndoRedoEnabled(False) + self.rendering = False + self.defaultFontPointSize = self.currentFont().pointSize() + self.verticalScrollBar().valueChanged.connect(self.lazyRender) + + def mousePressEvent(self, event): + #text = textCursor.block().text() + if event.button() == QtCore.Qt.LeftButton and self.html and self.html.has_html and self.cursorForPosition(event.pos()).block().blockNumber() == 0: + if self.mode == MessageView.MODE_PLAIN: + self.showHTML() + else: + self.showPlain() + else: + super(MessageView, self).mousePressEvent(event) + + def wheelEvent(self, event): + # super will actually automatically take care of zooming + super(MessageView, self).wheelEvent(event) + if (QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ControlModifier) == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical: + zoom = self.currentFont().pointSize() * 100 / self.defaultFontPointSize + QtGui.QApplication.activeWindow().statusBar().showMessage(QtGui.QApplication.translate("MainWindow", "Zoom level %1%").arg(str(zoom))) + + def confirmURL(self, link): + if link.scheme() == "mailto": + QtGui.QApplication.activeWindow().ui.lineEditTo.setText(link.path()) + if link.hasQueryItem("subject"): + QtGui.QApplication.activeWindow().ui.lineEditSubject.setText(link.queryItemValue("subject")) + if link.hasQueryItem("body"): + QtGui.QApplication.activeWindow().ui.textEditMessage.setText(link.queryItemValue("body")) + QtGui.QApplication.activeWindow().setSendFromComboBox() + QtGui.QApplication.activeWindow().ui.tabWidgetSend.setCurrentIndex(0) + QtGui.QApplication.activeWindow().ui.tabWidget.setCurrentIndex(1) + QtGui.QApplication.activeWindow().ui.textEditMessage.setFocus() + return + reply = QtGui.QMessageBox.warning(self, + QtGui.QApplication.translate(type(self).__name__, MessageView.CONFIRM_TITLE), + QtGui.QApplication.translate(type(self).__name__, MessageView.CONFIRM_TEXT).arg(str(link.toString())), + QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) + if reply == QtGui.QMessageBox.Yes: + QtGui.QDesktopServices.openUrl(link) + + def loadResource (self, restype, name): + if restype == QtGui.QTextDocument.ImageResource and name.scheme() == "bmmsg": + pass +# QImage correctImage; +# lookup the correct QImage from a cache +# return QVariant::fromValue(correctImage); +# elif restype == QtGui.QTextDocument.HtmlResource: +# elif restype == QtGui.QTextDocument.ImageResource: +# elif restype == QtGui.QTextDocument.StyleSheetResource: +# elif restype == QtGui.QTextDocument.UserResource: + else: + pass +# by default, this will interpret it as a local file +# QtGui.QTextBrowser.loadResource(restype, name) + + def lazyRender(self): + if self.rendering: + return + self.rendering = True + position = self.verticalScrollBar().value() + cursor = QtGui.QTextCursor(self.document()) + while self.outpos < len(self.out) and self.verticalScrollBar().value() >= self.document().size().height() - 2 * self.size().height(): + startpos = self.outpos + self.outpos += 10240 + # find next end of tag + if self.mode == MessageView.MODE_HTML: + pos = self.out.find(">", self.outpos) + if pos > self.outpos: + self.outpos = pos + cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.MoveAnchor) + cursor.insertHtml(QtCore.QString(self.out[startpos:self.outpos])) + self.verticalScrollBar().setValue(position) + self.rendering = False + + def showPlain(self): + self.mode = MessageView.MODE_PLAIN + out = self.html.raw + if self.html.has_html: + out = "
" + str(QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_PLAIN)) + "

" + out + self.out = out + self.outpos = 0 + self.setHtml("") + self.lazyRender() + + def showHTML(self): + self.mode = MessageView.MODE_HTML + out = self.html.sanitised + out = "
" + str(QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_HTML)) + "

" + out + self.out = out + self.outpos = 0 + self.setHtml("") + self.lazyRender() + + def setContent(self, data): + self.html = SafeHTMLParser() + self.html.reset() + self.html.reset_safe() + self.html.allow_picture = True + self.html.feed(data) + self.html.close() + self.showPlain() diff --git a/src/bitmessageqt/migrationwizard.py b/src/bitmessageqt/migrationwizard.py new file mode 100644 index 00000000..6e80f1dc --- /dev/null +++ b/src/bitmessageqt/migrationwizard.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python2.7 +from PyQt4 import QtCore, QtGui + +class MigrationWizardIntroPage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Migrating configuration") + + label = QtGui.QLabel("This wizard will help you to migrate your configuration. " + "You can still keep using PyBitMessage once you migrate, the changes are backwards compatible.") + label.setWordWrap(True) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) + self.setLayout(layout) + + def nextId(self): + return 1 + + +class MigrationWizardAddressesPage(QtGui.QWizardPage): + def __init__(self, addresses): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Addresses") + + label = QtGui.QLabel("Please select addresses that you are already using with mailchuck. ") + label.setWordWrap(True) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) + self.setLayout(layout) + + def nextId(self): + return 10 + + +class MigrationWizardGPUPage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("GPU") + + label = QtGui.QLabel("Are you using a GPU? ") + label.setWordWrap(True) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) + self.setLayout(layout) + + def nextId(self): + return 10 + + +class MigrationWizardConclusionPage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("All done!") + + label = QtGui.QLabel("You successfully migrated.") + label.setWordWrap(True) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) + self.setLayout(layout) + + +class Ui_MigrationWizard(QtGui.QWizard): + def __init__(self, addresses): + super(QtGui.QWizard, self).__init__() + + self.pages = {} + + page = MigrationWizardIntroPage() + self.setPage(0, page) + self.setStartId(0) + page = MigrationWizardAddressesPage(addresses) + self.setPage(1, page) + page = MigrationWizardGPUPage() + self.setPage(2, page) + page = MigrationWizardConclusionPage() + self.setPage(10, page) + + self.setWindowTitle("Migration from PyBitMessage wizard") + self.adjustSize() + self.show() \ No newline at end of file diff --git a/src/bitmessageqt/networkstatus.py b/src/bitmessageqt/networkstatus.py new file mode 100644 index 00000000..09d05c63 --- /dev/null +++ b/src/bitmessageqt/networkstatus.py @@ -0,0 +1,138 @@ +from PyQt4 import QtCore, QtGui +import time +import shared +from tr import _translate +import l10n +from retranslateui import RetranslateMixin +from uisignaler import UISignaler +import widgets + + +class NetworkStatus(QtGui.QWidget, RetranslateMixin): + def __init__(self, parent=None): + super(NetworkStatus, self).__init__(parent) + widgets.load('networkstatus.ui', self) + + self.startup = time.localtime() + self.labelStartupTime.setText(_translate("networkstatus", "Since startup on %1").arg( + l10n.formatTimestamp(self.startup))) + + self.UISignalThread = UISignaler.get() + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "updateNumberOfMessagesProcessed()"), self.updateNumberOfMessagesProcessed) + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "updateNumberOfPubkeysProcessed()"), self.updateNumberOfPubkeysProcessed) + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "updateNumberOfBroadcastsProcessed()"), self.updateNumberOfBroadcastsProcessed) + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "updateNetworkStatusTab()"), self.updateNetworkStatusTab) + + self.totalNumberOfBytesReceived = 0 + self.totalNumberOfBytesSent = 0 + + self.timer = QtCore.QTimer() + self.timer.start(2000) # milliseconds + QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.runEveryTwoSeconds) + + def formatBytes(self, num): + for x in [_translate("networkstatus", "byte(s)", None, QtCore.QCoreApplication.CodecForTr, num), "kB", "MB", "GB"]: + if num < 1000.0: + return "%3.0f %s" % (num, x) + num /= 1000.0 + return "%3.0f %s" % (num, 'TB') + + def formatByteRate(self, num): + num /= 1000 + return "%4.0f kB" % num + + def updateNumberOfObjectsToBeSynced(self): + self.labelSyncStatus.setText(_translate("networkstatus", "Object(s) to be synced: %n", None, QtCore.QCoreApplication.CodecForTr, sum(shared.numberOfObjectsThatWeHaveYetToGetPerPeer.itervalues()))) + + def updateNumberOfMessagesProcessed(self): + self.updateNumberOfObjectsToBeSynced() + self.labelMessageCount.setText(_translate( + "networkstatus", "Processed %n person-to-person message(s).", None, QtCore.QCoreApplication.CodecForTr, shared.numberOfMessagesProcessed)) + + def updateNumberOfBroadcastsProcessed(self): + self.updateNumberOfObjectsToBeSynced() + self.labelBroadcastCount.setText(_translate( + "networkstatus", "Processed %n broadcast message(s).", None, QtCore.QCoreApplication.CodecForTr, shared.numberOfBroadcastsProcessed)) + + def updateNumberOfPubkeysProcessed(self): + self.updateNumberOfObjectsToBeSynced() + self.labelPubkeyCount.setText(_translate( + "networkstatus", "Processed %n public key(s).", None, QtCore.QCoreApplication.CodecForTr, shared.numberOfPubkeysProcessed)) + + def updateNumberOfBytes(self): + """ + This function is run every two seconds, so we divide the rate of bytes + sent and received by 2. + """ + self.labelBytesRecvCount.setText(_translate( + "networkstatus", "Down: %1/s Total: %2").arg(self.formatByteRate(shared.numberOfBytesReceived/2), self.formatBytes(self.totalNumberOfBytesReceived))) + self.labelBytesSentCount.setText(_translate( + "networkstatus", "Up: %1/s Total: %2").arg(self.formatByteRate(shared.numberOfBytesSent/2), self.formatBytes(self.totalNumberOfBytesSent))) + self.totalNumberOfBytesReceived += shared.numberOfBytesReceived + self.totalNumberOfBytesSent += shared.numberOfBytesSent + shared.numberOfBytesReceived = 0 + shared.numberOfBytesSent = 0 + + def updateNetworkStatusTab(self): + totalNumberOfConnectionsFromAllStreams = 0 # One would think we could use len(sendDataQueues) for this but the number doesn't always match: just because we have a sendDataThread running doesn't mean that the connection has been fully established (with the exchange of version messages). + streamNumberTotals = {} + for host, streamNumber in shared.connectedHostsList.items(): + if not streamNumber in streamNumberTotals: + streamNumberTotals[streamNumber] = 1 + else: + streamNumberTotals[streamNumber] += 1 + + while self.tableWidgetConnectionCount.rowCount() > 0: + self.tableWidgetConnectionCount.removeRow(0) + for streamNumber, connectionCount in streamNumberTotals.items(): + self.tableWidgetConnectionCount.insertRow(0) + if streamNumber == 0: + newItem = QtGui.QTableWidgetItem("?") + else: + newItem = QtGui.QTableWidgetItem(str(streamNumber)) + newItem.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.tableWidgetConnectionCount.setItem(0, 0, newItem) + newItem = QtGui.QTableWidgetItem(str(connectionCount)) + newItem.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.tableWidgetConnectionCount.setItem(0, 1, newItem) + """for currentRow in range(self.tableWidgetConnectionCount.rowCount()): + rowStreamNumber = int(self.tableWidgetConnectionCount.item(currentRow,0).text()) + if streamNumber == rowStreamNumber: + foundTheRowThatNeedsUpdating = True + self.tableWidgetConnectionCount.item(currentRow,1).setText(str(connectionCount)) + #totalNumberOfConnectionsFromAllStreams += connectionCount + if foundTheRowThatNeedsUpdating == False: + #Add a line to the table for this stream number and update its count with the current connection count. + self.tableWidgetConnectionCount.insertRow(0) + newItem = QtGui.QTableWidgetItem(str(streamNumber)) + newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) + self.tableWidgetConnectionCount.setItem(0,0,newItem) + newItem = QtGui.QTableWidgetItem(str(connectionCount)) + newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) + self.tableWidgetConnectionCount.setItem(0,1,newItem) + totalNumberOfConnectionsFromAllStreams += connectionCount""" + self.labelTotalConnections.setText(_translate( + "networkstatus", "Total Connections: %1").arg(str(len(shared.connectedHostsList)))) + if len(shared.connectedHostsList) > 0 and shared.statusIconColor == 'red': # FYI: The 'singlelistener' thread sets the icon color to green when it receives an incoming connection, meaning that the user's firewall is configured correctly. + self.window().setStatusIcon('yellow') + elif len(shared.connectedHostsList) == 0: + self.window().setStatusIcon('red') + + # timer driven + def runEveryTwoSeconds(self): + self.labelLookupsPerSecond.setText(_translate( + "networkstatus", "Inventory lookups per second: %1").arg(str(shared.numberOfInventoryLookupsPerformed/2))) + shared.numberOfInventoryLookupsPerformed = 0 + self.updateNumberOfBytes() + self.updateNumberOfObjectsToBeSynced() + + def retranslateUi(self): + super(QtGui.QWidget, self).retranslateUi() + self.labelStartupTime.setText(_translate("networkstatus", "Since startup on %1").arg( + l10n.formatTimestamp(self.startup))) diff --git a/src/bitmessageqt/networkstatus.ui b/src/bitmessageqt/networkstatus.ui new file mode 100644 index 00000000..6ae988bf --- /dev/null +++ b/src/bitmessageqt/networkstatus.ui @@ -0,0 +1,264 @@ + + + networkstatus + + + + 0 + 0 + 602 + 252 + + + + + 0 + 0 + + + + + + + 20 + + + QLayout::SetDefaultConstraint + + + + + 20 + + + QLayout::SetFixedSize + + + + + Total connections: + + + + + + + + + + + + 212 + 208 + 200 + + + + + + + + + 212 + 208 + 200 + + + + + + + + + 212 + 208 + 200 + + + + + + + + QFrame::Box + + + QFrame::Plain + + + false + + + true + + + QAbstractItemView::NoSelection + + + false + + + false + + + true + + + false + + + + Stream # + + + + + Connections + + + + + + + + + + 4 + + + + + + 0 + 9 + + + + + 0 + 50 + + + + Since startup: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + 0 + 0 + + + + Processed 0 person-to-person messages. + + + 0 + + + + + + + + 0 + 0 + + + + Processed 0 broadcasts. + + + + + + + + 0 + 0 + + + + Processed 0 public keys. + + + + + + + + 0 + 0 + + + + Objects to be synced: + + + + + + + + 0 + 0 + + + + Up: 0 kB/s + + + + + + + + 0 + 0 + + + + Down: 0 kB/s + + + + + + + + 0 + 0 + + + + Inventory lookups per second: 0 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + + STableWidget + QTableWidget +
bitmessageqt/settingsmixin.h
+
+
+ + + + +
diff --git a/src/bitmessageqt/newaddresswizard.py b/src/bitmessageqt/newaddresswizard.py new file mode 100644 index 00000000..e54b18c3 --- /dev/null +++ b/src/bitmessageqt/newaddresswizard.py @@ -0,0 +1,354 @@ +#!/usr/bin/env python2.7 +from PyQt4 import QtCore, QtGui + +class NewAddressWizardIntroPage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Creating a new address") + + label = QtGui.QLabel("This wizard will help you create as many addresses as you like. Indeed, creating and abandoning addresses is encouraged.\n\n" + "What type of address would you like? Would you like to send emails or not?\n" + "You can still change your mind later, and register/unregister with an email service provider.\n\n") + label.setWordWrap(True) + + self.emailAsWell = QtGui.QRadioButton("Combined email and bitmessage address") + self.onlyBM = QtGui.QRadioButton("Bitmessage-only address (no email)") + self.emailAsWell.setChecked(True) + self.registerField("emailAsWell", self.emailAsWell) + self.registerField("onlyBM", self.onlyBM) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) + layout.addWidget(self.emailAsWell) + layout.addWidget(self.onlyBM) + self.setLayout(layout) + + def nextId(self): + if self.emailAsWell.isChecked(): + return 4 + else: + return 1 + + +class NewAddressWizardRngPassphrasePage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Random or Passphrase") + + label = QtGui.QLabel("

You may generate addresses by using either random numbers or by using a passphrase. " + "If you use a passphrase, the address is called a "deterministic" address. " + "The \'Random Number\' option is selected by default but deterministic addresses have several pros and cons:

" + "" + "" + "
Pros:Cons:
You can recreate your addresses on any computer from memory. " + "You need-not worry about backing up your keys.dat file as long as you can remember your passphrase.You must remember (or write down) your passphrase if you expect to be able " + "to recreate your keys if they are lost. " +# "You must remember the address version number and the stream number along with your passphrase. " + "If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you." + "

") + label.setWordWrap(True) + + self.randomAddress = QtGui.QRadioButton("Use a random number generator to make an address") + self.deterministicAddress = QtGui.QRadioButton("Use a passphrase to make an address") + self.randomAddress.setChecked(True) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) + layout.addWidget(self.randomAddress) + layout.addWidget(self.deterministicAddress) + self.setLayout(layout) + + def nextId(self): + if self.randomAddress.isChecked(): + return 2 + else: + return 3 + +class NewAddressWizardRandomPage(QtGui.QWizardPage): + def __init__(self, addresses): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Random") + + label = QtGui.QLabel("Random address.") + label.setWordWrap(True) + + labelLabel = QtGui.QLabel("Label (not shown to anyone except you):") + self.labelLineEdit = QtGui.QLineEdit() + + self.radioButtonMostAvailable = QtGui.QRadioButton("Use the most available stream\n" + "(best if this is the first of many addresses you will create)") + self.radioButtonExisting = QtGui.QRadioButton("Use the same stream as an existing address\n" + "(saves you some bandwidth and processing power)") + self.radioButtonMostAvailable.setChecked(True) + self.comboBoxExisting = QtGui.QComboBox() + self.comboBoxExisting.setEnabled(False) + self.comboBoxExisting.setEditable(True) + + for address in addresses: + self.comboBoxExisting.addItem(address) + +# self.comboBoxExisting.setObjectName(_fromUtf8("comboBoxExisting")) + self.checkBoxEighteenByteRipe = QtGui.QCheckBox("Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter") + + layout = QtGui.QGridLayout() + layout.addWidget(label, 0, 0) + layout.addWidget(labelLabel, 1, 0) + layout.addWidget(self.labelLineEdit, 2, 0) + layout.addWidget(self.radioButtonMostAvailable, 3, 0) + layout.addWidget(self.radioButtonExisting, 4, 0) + layout.addWidget(self.comboBoxExisting, 5, 0) + layout.addWidget(self.checkBoxEighteenByteRipe, 6, 0) + self.setLayout(layout) + + QtCore.QObject.connect(self.radioButtonExisting, QtCore.SIGNAL("toggled(bool)"), self.comboBoxExisting.setEnabled) + + self.registerField("label", self.labelLineEdit) + self.registerField("radioButtonMostAvailable", self.radioButtonMostAvailable) + self.registerField("radioButtonExisting", self.radioButtonExisting) + self.registerField("comboBoxExisting", self.comboBoxExisting) + +# self.emailAsWell = QtGui.QRadioButton("Combined email and bitmessage account") +# self.onlyBM = QtGui.QRadioButton("Bitmessage-only account (no email)") +# self.emailAsWell.setChecked(True) + + def nextId(self): + return 6 + + +class NewAddressWizardPassphrasePage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Passphrase") + + label = QtGui.QLabel("Deterministric address.") + label.setWordWrap(True) + + passphraseLabel = QtGui.QLabel("Passphrase") + self.lineEditPassphrase = QtGui.QLineEdit() + self.lineEditPassphrase.setEchoMode(QtGui.QLineEdit.Password) + self.lineEditPassphrase.setInputMethodHints(QtCore.Qt.ImhHiddenText|QtCore.Qt.ImhNoAutoUppercase|QtCore.Qt.ImhNoPredictiveText) + retypePassphraseLabel = QtGui.QLabel("Retype passphrase") + self.lineEditPassphraseAgain = QtGui.QLineEdit() + self.lineEditPassphraseAgain.setEchoMode(QtGui.QLineEdit.Password) + + numberLabel = QtGui.QLabel("Number of addresses to make based on your passphrase:") + self.spinBoxNumberOfAddressesToMake = QtGui.QSpinBox() + self.spinBoxNumberOfAddressesToMake.setMinimum(1) + self.spinBoxNumberOfAddressesToMake.setProperty("value", 8) +# self.spinBoxNumberOfAddressesToMake.setObjectName(_fromUtf8("spinBoxNumberOfAddressesToMake")) + label2 = QtGui.QLabel("In addition to your passphrase, you must remember these numbers:") + label3 = QtGui.QLabel("Address version number: 4") + label4 = QtGui.QLabel("Stream number: 1") + + layout = QtGui.QGridLayout() + layout.addWidget(label, 0, 0, 1, 4) + layout.addWidget(passphraseLabel, 1, 0, 1, 4) + layout.addWidget(self.lineEditPassphrase, 2, 0, 1, 4) + layout.addWidget(retypePassphraseLabel, 3, 0, 1, 4) + layout.addWidget(self.lineEditPassphraseAgain, 4, 0, 1, 4) + layout.addWidget(numberLabel, 5, 0, 1, 3) + layout.addWidget(self.spinBoxNumberOfAddressesToMake, 5, 3) + layout.setColumnMinimumWidth(3, 1) + layout.addWidget(label2, 6, 0, 1, 4) + layout.addWidget(label3, 7, 0, 1, 2) + layout.addWidget(label4, 7, 2, 1, 2) + self.setLayout(layout) + + def nextId(self): + return 6 + + +class NewAddressWizardEmailProviderPage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Choose email provider") + + label = QtGui.QLabel("Currently only Mailchuck email gateway is available " + "(@mailchuck.com email address). In the future, maybe other gateways will be available. " + "Press Next.") + label.setWordWrap(True) + +# self.mailchuck = QtGui.QRadioButton("Mailchuck email gateway (@mailchuck.com)") +# self.mailchuck.setChecked(True) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) +# layout.addWidget(self.mailchuck) + self.setLayout(layout) + + def nextId(self): + return 5 + + +class NewAddressWizardEmailAddressPage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Email address") + + label = QtGui.QLabel("Choosing an email address. Address must end with @mailchuck.com") + label.setWordWrap(True) + + self.specificEmail = QtGui.QRadioButton("Pick your own email address:") + self.specificEmail.setChecked(True) + self.emailLineEdit = QtGui.QLineEdit() + self.randomEmail = QtGui.QRadioButton("Generate a random email address") + + QtCore.QObject.connect(self.specificEmail, QtCore.SIGNAL("toggled(bool)"), self.emailLineEdit.setEnabled) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) + layout.addWidget(self.specificEmail) + layout.addWidget(self.emailLineEdit) + layout.addWidget(self.randomEmail) + self.setLayout(layout) + + def nextId(self): + return 6 + + +class NewAddressWizardWaitPage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("Wait") + + self.label = QtGui.QLabel("Wait!") + self.label.setWordWrap(True) + self.progressBar = QtGui.QProgressBar() + self.progressBar.setMinimum(0) + self.progressBar.setMaximum(100) + self.progressBar.setValue(0) + +# self.emailAsWell = QtGui.QRadioButton("Combined email and bitmessage account") +# self.onlyBM = QtGui.QRadioButton("Bitmessage-only account (no email)") +# self.emailAsWell.setChecked(True) + + layout = QtGui.QVBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.progressBar) +# layout.addWidget(self.emailAsWell) +# layout.addWidget(self.onlyBM) + self.setLayout(layout) + + def update(self, i): + if i == 101 and self.wizard().currentId() == 6: + self.wizard().button(QtGui.QWizard.NextButton).click() + return + elif i == 101: + print "haha" + return + self.progressBar.setValue(i) + if i == 50: + self.emit(QtCore.SIGNAL('completeChanged()')) + + def isComplete(self): +# print "val = " + str(self.progressBar.value()) + if self.progressBar.value() >= 50: + return True + else: + return False + + def initializePage(self): + if self.field("emailAsWell").toBool(): + val = "yes/" + else: + val = "no/" + if self.field("onlyBM").toBool(): + val += "yes" + else: + val += "no" + + self.label.setText("Wait! " + val) +# self.wizard().button(QtGui.QWizard.NextButton).setEnabled(False) + self.progressBar.setValue(0) + self.thread = NewAddressThread() + self.connect(self.thread, self.thread.signal, self.update) + self.thread.start() + + def nextId(self): + return 10 + + +class NewAddressWizardConclusionPage(QtGui.QWizardPage): + def __init__(self): + super(QtGui.QWizardPage, self).__init__() + self.setTitle("All done!") + + label = QtGui.QLabel("You successfully created a new address.") + label.setWordWrap(True) + + layout = QtGui.QVBoxLayout() + layout.addWidget(label) + self.setLayout(layout) + +class Ui_NewAddressWizard(QtGui.QWizard): + def __init__(self, addresses): + super(QtGui.QWizard, self).__init__() + + self.pages = {} + + page = NewAddressWizardIntroPage() + self.setPage(0, page) + self.setStartId(0) + page = NewAddressWizardRngPassphrasePage() + self.setPage(1, page) + page = NewAddressWizardRandomPage(addresses) + self.setPage(2, page) + page = NewAddressWizardPassphrasePage() + self.setPage(3, page) + page = NewAddressWizardEmailProviderPage() + self.setPage(4, page) + page = NewAddressWizardEmailAddressPage() + self.setPage(5, page) + page = NewAddressWizardWaitPage() + self.setPage(6, page) + page = NewAddressWizardConclusionPage() + self.setPage(10, page) + + self.setWindowTitle("New address wizard") + self.adjustSize() + self.show() + +class NewAddressThread(QtCore.QThread): + def __init__(self): + QtCore.QThread.__init__(self) + self.signal = QtCore.SIGNAL("signal") + + def __del__(self): + self.wait() + + def createDeterministic(): + pass + + def createPassphrase(): + pass + + def broadcastAddress(): + pass + + def registerMailchuck(): + pass + + def waitRegistration(): + pass + + def run(self): + import time + for i in range(1, 101): + time.sleep(0.1) # artificial time delay + self.emit(self.signal, i) + self.emit(self.signal, 101) +# self.terminate() + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + + wizard = Ui_NewAddressWizard(["a", "b", "c", "d"]) + if (wizard.exec_()): + print "Email: " + ("yes" if wizard.field("emailAsWell").toBool() else "no") + print "BM: " + ("yes" if wizard.field("onlyBM").toBool() else "no") + else: + print "Wizard cancelled" + sys.exit() diff --git a/src/bitmessageqt/newsubscriptiondialog.py b/src/bitmessageqt/newsubscriptiondialog.py index d71eec0c..a63cce4a 100644 --- a/src/bitmessageqt/newsubscriptiondialog.py +++ b/src/bitmessageqt/newsubscriptiondialog.py @@ -65,5 +65,5 @@ class Ui_NewSubscriptionDialog(object): NewSubscriptionDialog.setWindowTitle(_translate("NewSubscriptionDialog", "Add new entry", None)) self.label_2.setText(_translate("NewSubscriptionDialog", "Label", None)) self.label.setText(_translate("NewSubscriptionDialog", "Address", None)) - self.checkBoxDisplayMessagesAlreadyInInventory.setText(_translate("NewSubscriptionDialog", "CheckBox", None)) + self.checkBoxDisplayMessagesAlreadyInInventory.setText(_translate("NewSubscriptionDialog", "Enter an address above.", None)) diff --git a/src/bitmessageqt/retranslateui.py b/src/bitmessageqt/retranslateui.py new file mode 100644 index 00000000..e9d5bb3a --- /dev/null +++ b/src/bitmessageqt/retranslateui.py @@ -0,0 +1,18 @@ +from os import path +from PyQt4 import QtGui +from debug import logger +import widgets + +class RetranslateMixin(object): + def retranslateUi(self): + defaults = QtGui.QWidget() + widgets.load(self.__class__.__name__.lower() + '.ui', defaults) + for attr, value in defaults.__dict__.iteritems(): + setTextMethod = getattr(value, "setText", None) + if callable(setTextMethod): + getattr(self, attr).setText(getattr(defaults, attr).text()) + elif isinstance(value, QtGui.QTableWidget): + for i in range (value.columnCount()): + getattr(self, attr).horizontalHeaderItem(i).setText(getattr(defaults, attr).horizontalHeaderItem(i).text()) + for i in range (value.rowCount()): + getattr(self, attr).verticalHeaderItem(i).setText(getattr(defaults, attr).verticalHeaderItem(i).text()) diff --git a/src/bitmessageqt/safehtmlparser.py b/src/bitmessageqt/safehtmlparser.py new file mode 100644 index 00000000..77fc9d70 --- /dev/null +++ b/src/bitmessageqt/safehtmlparser.py @@ -0,0 +1,109 @@ +from HTMLParser import HTMLParser +import inspect +import re +from urllib import quote, quote_plus +from urlparse import urlparse + +class SafeHTMLParser(HTMLParser): + # from html5lib.sanitiser + acceptable_elements = ['a', 'abbr', 'acronym', 'address', 'area', + 'article', 'aside', 'audio', 'b', 'big', 'blockquote', 'br', 'button', + 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', + 'command', 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn', + 'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'event-source', 'fieldset', + 'figcaption', 'figure', 'footer', 'font', 'header', 'h1', + 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', + 'keygen', 'kbd', 'label', 'legend', 'li', 'm', 'map', 'menu', 'meter', + 'multicol', 'nav', 'nextid', 'ol', 'output', 'optgroup', 'option', + 'p', 'pre', 'progress', 'q', 's', 'samp', 'section', 'select', + 'small', 'sound', 'source', 'spacer', 'span', 'strike', 'strong', + 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'time', 'tfoot', + 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'video'] + replaces = [["&", "&"], ["\"", """], ["<", "<"], [">", ">"], ["\n", "
"], ["\t", "    "], [" ", "  "], [" ", "  "], ["
", "
 "]] + src_schemes = [ "data" ] + uriregex1 = re.compile(r'(?i)\b((?:(https?|ftp|bitcoin):(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?]))') + uriregex2 = re.compile(r' 1 and text[0] == " ": + text = " " + text[1:] + return text + + def __init__(self, *args, **kwargs): + HTMLParser.__init__(self, *args, **kwargs) + self.reset_safe() + + def reset_safe(self): + self.elements = set() + self.raw = u"" + self.sanitised = u"" + self.has_html = False + self.allow_picture = False + self.allow_external_src = False + + def add_if_acceptable(self, tag, attrs = None): + if not tag in SafeHTMLParser.acceptable_elements: + return + self.sanitised += "<" + if inspect.stack()[1][3] == "handle_endtag": + self.sanitised += "/" + self.sanitised += tag + if not attrs is None: + for attr, val in attrs: + if tag == "img" and attr == "src" and not self.allow_picture: + val = "" + elif attr == "src" and not self.allow_external_src: + url = urlparse(val) + if url.scheme not in SafeHTMLParser.src_schemes: + val == "" + self.sanitised += " " + quote_plus(attr) + if not (val is None): + self.sanitised += "=\"" + val + "\"" + if inspect.stack()[1][3] == "handle_startendtag": + self.sanitised += "/" + self.sanitised += ">" + + def handle_starttag(self, tag, attrs): + if tag in SafeHTMLParser.acceptable_elements: + self.has_html = True + self.add_if_acceptable(tag, attrs) + + def handle_endtag(self, tag): + self.add_if_acceptable(tag) + + def handle_startendtag(self, tag, attrs): + if tag in SafeHTMLParser.acceptable_elements: + self.has_html = True + self.add_if_acceptable(tag, attrs) + + def handle_data(self, data): + self.sanitised += unicode(data, 'utf-8', 'replace') + + def handle_charref(self, name): + self.sanitised += "&#" + name + ";" + + def handle_entityref(self, name): + self.sanitised += "&" + name + ";" + + def feed(self, data): + HTMLParser.feed(self, data) + tmp = SafeHTMLParser.multi_replace(data) + tmp = SafeHTMLParser.uriregex1.sub( + r'\1', + unicode(tmp, 'utf-8', 'replace')) + tmp = SafeHTMLParser.uriregex2.sub(r'\1', tmp) + self.raw += tmp + + def is_html(self, text = None, allow_picture = False): + if text: + self.reset() + self.reset_safe() + self.allow_picture = allow_picture + self.feed(text) + self.close() + return self.has_html diff --git a/src/bitmessageqt/settings.py b/src/bitmessageqt/settings.py index 6d854773..6b7dd9b3 100644 --- a/src/bitmessageqt/settings.py +++ b/src/bitmessageqt/settings.py @@ -8,6 +8,7 @@ # WARNING! All changes made in this file will be lost! from PyQt4 import QtCore, QtGui +from languagebox import LanguageBox try: _fromUtf8 = QtCore.QString.fromUtf8 @@ -44,13 +45,22 @@ class Ui_settingsDialog(object): self.checkBoxStartOnLogon = QtGui.QCheckBox(self.tabUserInterface) self.checkBoxStartOnLogon.setObjectName(_fromUtf8("checkBoxStartOnLogon")) self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.checkBoxStartOnLogon) - self.checkBoxStartInTray = QtGui.QCheckBox(self.tabUserInterface) + self.groupBoxTray = QtGui.QGroupBox(self.tabUserInterface) + self.groupBoxTray.setObjectName(_fromUtf8("groupBoxTray")) + self.formLayoutTray = QtGui.QFormLayout(self.groupBoxTray) + self.formLayoutTray.setObjectName(_fromUtf8("formLayoutTray")) + self.checkBoxStartInTray = QtGui.QCheckBox(self.groupBoxTray) self.checkBoxStartInTray.setObjectName(_fromUtf8("checkBoxStartInTray")) - self.formLayout.setWidget(1, QtGui.QFormLayout.SpanningRole, self.checkBoxStartInTray) - self.checkBoxMinimizeToTray = QtGui.QCheckBox(self.tabUserInterface) + self.formLayoutTray.setWidget(0, QtGui.QFormLayout.SpanningRole, self.checkBoxStartInTray) + self.checkBoxMinimizeToTray = QtGui.QCheckBox(self.groupBoxTray) self.checkBoxMinimizeToTray.setChecked(True) self.checkBoxMinimizeToTray.setObjectName(_fromUtf8("checkBoxMinimizeToTray")) - self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.checkBoxMinimizeToTray) + self.formLayoutTray.setWidget(1, QtGui.QFormLayout.LabelRole, self.checkBoxMinimizeToTray) + self.checkBoxTrayOnClose = QtGui.QCheckBox(self.groupBoxTray) + self.checkBoxTrayOnClose.setChecked(True) + self.checkBoxTrayOnClose.setObjectName(_fromUtf8("checkBoxTrayOnClose")) + self.formLayoutTray.setWidget(2, QtGui.QFormLayout.LabelRole, self.checkBoxTrayOnClose) + self.formLayout.setWidget(1, QtGui.QFormLayout.SpanningRole, self.groupBoxTray) self.checkBoxShowTrayNotifications = QtGui.QCheckBox(self.tabUserInterface) self.checkBoxShowTrayNotifications.setObjectName(_fromUtf8("checkBoxShowTrayNotifications")) self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.checkBoxShowTrayNotifications) @@ -79,36 +89,9 @@ class Ui_settingsDialog(object): self.groupBox.setObjectName(_fromUtf8("groupBox")) self.formLayout_2 = QtGui.QFormLayout(self.groupBox) self.formLayout_2.setObjectName(_fromUtf8("formLayout_2")) - self.languageComboBox = QtGui.QComboBox(self.groupBox) + self.languageComboBox = LanguageBox(self.groupBox) self.languageComboBox.setMinimumSize(QtCore.QSize(100, 0)) self.languageComboBox.setObjectName(_fromUtf8("languageComboBox")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(1, _fromUtf8("English")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(2, _fromUtf8("Esperanto")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(3, _fromUtf8("Français")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(4, _fromUtf8("Deutsch")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(5, _fromUtf8("Españl")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(6, _fromUtf8("русский")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(7, _fromUtf8("Norsk")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(8, _fromUtf8("العربية")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(9, _fromUtf8("简体中文")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(10, _fromUtf8("日本語")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(11, _fromUtf8("Nederlands")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.setItemText(12, _fromUtf8("Česky")) - self.languageComboBox.addItem(_fromUtf8("")) - self.languageComboBox.addItem(_fromUtf8("")) 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("")) @@ -120,15 +103,21 @@ 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) + #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, 1, 1, 1) + self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1, QtCore.Qt.AlignRight) self.lineEditTCPPort = QtGui.QLineEdit(self.groupBox1) self.lineEditTCPPort.setMaximumSize(QtCore.QSize(70, 16777215)) self.lineEditTCPPort.setObjectName(_fromUtf8("lineEditTCPPort")) - self.gridLayout_3.addWidget(self.lineEditTCPPort, 0, 2, 1, 1) + self.gridLayout_3.addWidget(self.lineEditTCPPort, 0, 1, 1, 1, QtCore.Qt.AlignLeft) + self.labelUPnP = QtGui.QLabel(self.groupBox1) + self.labelUPnP.setObjectName(_fromUtf8("labelUPnP")) + self.gridLayout_3.addWidget(self.labelUPnP, 0, 2, 1, 1, QtCore.Qt.AlignRight) + self.checkBoxUPnP = QtGui.QCheckBox(self.groupBox1) + self.checkBoxUPnP.setObjectName(_fromUtf8("checkBoxUPnP")) + self.gridLayout_3.addWidget(self.checkBoxUPnP, 0, 3, 1, 1, QtCore.Qt.AlignLeft) self.gridLayout_4.addWidget(self.groupBox1, 0, 0, 1, 1) self.groupBox_3 = QtGui.QGroupBox(self.tabNetworkSettings) self.groupBox_3.setObjectName(_fromUtf8("groupBox_3")) @@ -302,6 +291,12 @@ class Ui_settingsDialog(object): 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) + self.labelOpenCL = QtGui.QLabel(self.tabMaxAcceptableDifficulty) + self.labelOpenCL.setObjectName(_fromUtf8("labelOpenCL")) + self.gridLayout_7.addWidget(self.labelOpenCL, 4, 0, 1, 1) + self.checkBoxOpenCL = QtGui.QCheckBox(self.tabMaxAcceptableDifficulty) + self.checkBoxOpenCL.setObjectName = (_fromUtf8("checkBoxOpenCL")) + self.gridLayout_7.addWidget(self.checkBoxOpenCL, 4, 1, 1, 1) self.tabWidgetSettings.addTab(self.tabMaxAcceptableDifficulty, _fromUtf8("")) self.tabNamecoin = QtGui.QWidget() self.tabNamecoin.setObjectName(_fromUtf8("tabNamecoin")) @@ -434,8 +429,10 @@ class Ui_settingsDialog(object): def retranslateUi(self, settingsDialog): 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.checkBoxMinimizeToTray.setText(_translate("settingsDialog", "Minimize to tray", None)) + self.checkBoxTrayOnClose.setText(_translate("settingsDialog", "Close to tray", 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)) @@ -444,11 +441,10 @@ class Ui_settingsDialog(object): 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(13, _translate("settingsDialog", "Pirate English", "en_pirate")) - self.languageComboBox.setItemText(14, _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)) + self.labelUPnP.setText(_translate("settingsDialog", "UPnP:", None)) self.groupBox_3.setTitle(_translate("settingsDialog", "Bandwidth limit", None)) self.label_24.setText(_translate("settingsDialog", "Maximum download rate (kB/s): [0: unlimited]", None)) self.label_25.setText(_translate("settingsDialog", "Maximum upload rate (kB/s): [0: unlimited]", None)) @@ -474,6 +470,7 @@ class Ui_settingsDialog(object): 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.labelOpenCL.setText(_translate("settingsDialog", "Hardware GPU acceleration (OpenCL)", None)) self.label_16.setText(_translate("settingsDialog", "

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 test.

(Getting your own Bitmessage address into Namecoin is still rather difficult).

Bitmessage can use either namecoind directly or a running nmcontrol instance.

", None)) self.label_17.setText(_translate("settingsDialog", "Host:", None)) self.label_18.setText(_translate("settingsDialog", "Port:", None)) diff --git a/src/bitmessageqt/settings.ui b/src/bitmessageqt/settings.ui index a41d7e4e..475821f8 100644 --- a/src/bitmessageqt/settings.ui +++ b/src/bitmessageqt/settings.ui @@ -153,7 +153,7 @@ - Españl + Español diff --git a/src/bitmessageqt/settingsmixin.py b/src/bitmessageqt/settingsmixin.py new file mode 100644 index 00000000..c534d1b5 --- /dev/null +++ b/src/bitmessageqt/settingsmixin.py @@ -0,0 +1,79 @@ +#!/usr/bin/python2.7 + +from PyQt4 import QtCore, QtGui + +class SettingsMixin(object): + def warnIfNoObjectName(self): + if self.objectName() == "": + # TODO: logger + pass + + def writeState(self, source): + self.warnIfNoObjectName() + settings = QtCore.QSettings() + settings.beginGroup(self.objectName()) + settings.setValue("state", source.saveState()) + settings.endGroup() + + def writeGeometry(self, source): + self.warnIfNoObjectName() + settings = QtCore.QSettings() + settings.beginGroup(self.objectName()) + settings.setValue("geometry", source.saveGeometry()) + settings.endGroup() + + def readGeometry(self, target): + self.warnIfNoObjectName() + settings = QtCore.QSettings() + try: + geom = settings.value("/".join([str(self.objectName()), "geometry"])) + target.restoreGeometry(geom.toByteArray() if hasattr(geom, 'toByteArray') else geom) + except Exception as e: + pass + + def readState(self, target): + self.warnIfNoObjectName() + settings = QtCore.QSettings() + try: + state = settings.value("/".join([str(self.objectName()), "state"])) + target.restoreState(state.toByteArray() if hasattr(state, 'toByteArray') else state) + except Exception as e: + pass + + +class SMainWindow(QtGui.QMainWindow, SettingsMixin): + def loadSettings(self): + self.readGeometry(self) + self.readState(self) + + def saveSettings(self): + self.writeState(self) + self.writeGeometry(self) + + +class STableWidget(QtGui.QTableWidget, SettingsMixin): + def loadSettings(self): + self.readState(self.horizontalHeader()) + + def saveSettings(self): + self.writeState(self.horizontalHeader()) + + +class SSplitter(QtGui.QSplitter, SettingsMixin): + def loadSettings(self): + self.readState(self) + + def saveSettings(self): + self.writeState(self) + + +class STreeWidget(QtGui.QTreeWidget, SettingsMixin): + def loadSettings(self): + #recurse children + #self.readState(self) + pass + + def saveSettings(self): + #recurse children + #self.writeState(self) + pass diff --git a/src/bitmessageqt/support.py b/src/bitmessageqt/support.py new file mode 100644 index 00000000..4742e175 --- /dev/null +++ b/src/bitmessageqt/support.py @@ -0,0 +1,128 @@ +import ctypes +from PyQt4 import QtCore, QtGui +import ssl +import sys +import time + +import account +from debug import logger +from foldertree import AccountMixin +from helper_sql import * +from l10n import getTranslationLanguage +from openclpow import has_opencl +from proofofwork import bmpow +from pyelliptic.openssl import OpenSSL +import shared + +# this is BM support address going to Peter Surda +SUPPORT_ADDRESS = 'BM-2cTkCtMYkrSPwFTpgcBrMrf5d8oZwvMZWK' +SUPPORT_LABEL = 'PyBitmessage support' +SUPPORT_MY_LABEL = 'My new address' +SUPPORT_SUBJECT = 'Support request' +SUPPORT_MESSAGE = '''You can use this message to send a report to one of the PyBitmessage core developers regarding PyBitmessage or the mailchuck.com email service. If you are using PyBitmessage involuntarily, for example because your computer was infected with ransomware, this is not an appropriate venue for resolving such issues. + +Please describe what you are trying to do: + +Please describe what you expect to happen: + +Please describe what happens instead: + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Please write above this line and if possible, keep the information about your environment below intact. + +PyBitmesage version: {} +Operating system: {} +Architecture: {}bit +Python Version: {} +OpenSSL Version: {} +Frozen: {} +Portable mode: {} +C PoW: {} +OpenCL PoW: {} +Locale: {} +SOCKS: {} +UPnP: {} +Connected hosts: {} +''' + +def checkAddressBook(myapp): + queryreturn = sqlQuery('''SELECT * FROM addressbook WHERE address=?''', SUPPORT_ADDRESS) + if queryreturn == []: + sqlExecute('''INSERT INTO addressbook VALUES (?,?)''', str(QtGui.QApplication.translate("Support", SUPPORT_LABEL)), SUPPORT_ADDRESS) + myapp.rerenderAddressBook() + +def checkHasNormalAddress(): + for address in account.getSortedAccounts(): + acct = account.accountClass(address) + if acct.type == AccountMixin.NORMAL and shared.safeConfigGetBoolean(address, 'enabled'): + return address + return False + +def createAddressIfNeeded(myapp): + if not checkHasNormalAddress(): + shared.addressGeneratorQueue.put(('createRandomAddress', 4, 1, str(QtGui.QApplication.translate("Support", SUPPORT_MY_LABEL)), 1, "", False, shared.networkDefaultProofOfWorkNonceTrialsPerByte, shared.networkDefaultPayloadLengthExtraBytes)) + while shared.shutdown == 0 and not checkHasNormalAddress(): + time.sleep(.2) + myapp.rerenderComboBoxSendFrom() + return checkHasNormalAddress() + +def createSupportMessage(myapp): + checkAddressBook(myapp) + address = createAddressIfNeeded(myapp) + if shared.shutdown: + return + + myapp.ui.lineEditSubject.setText(str(QtGui.QApplication.translate("Support", SUPPORT_SUBJECT))) + addrIndex = myapp.ui.comboBoxSendFrom.findData(address, QtCore.Qt.UserRole, QtCore.Qt.MatchFixedString | QtCore.Qt.MatchCaseSensitive) + if addrIndex == -1: # something is very wrong + return + myapp.ui.comboBoxSendFrom.setCurrentIndex(addrIndex) + myapp.ui.lineEditTo.setText(SUPPORT_ADDRESS) + + version = shared.softwareVersion + os = sys.platform + if os == "win32": + windowsversion = sys.getwindowsversion() + os = "Windows " + str(windowsversion[0]) + "." + str(windowsversion[1]) + else: + try: + from os import uname + unixversion = uname() + os = unixversion[0] + " " + unixversion[2] + except: + pass + architecture = "32" if ctypes.sizeof(ctypes.c_voidp) == 4 else "64" + pythonversion = sys.version + + SSLEAY_VERSION = 0 + OpenSSL._lib.SSLeay.restype = ctypes.c_long + OpenSSL._lib.SSLeay_version.restype = ctypes.c_char_p + OpenSSL._lib.SSLeay_version.argtypes = [ctypes.c_int] + opensslversion = "%s (Python internal), %s (external for PyElliptic)" % (ssl.OPENSSL_VERSION, OpenSSL._lib.SSLeay_version(SSLEAY_VERSION)) + + frozen = "N/A" + if shared.frozen: + frozen = shared.frozen + portablemode = "True" if shared.appdata == shared.lookupExeFolder() else "False" + cpow = "True" if bmpow else "False" + #cpow = QtGui.QApplication.translate("Support", cpow) + openclpow = "True" if shared.safeConfigGetBoolean('bitmessagesettings', 'opencl') and has_opencl() else "False" + #openclpow = QtGui.QApplication.translate("Support", openclpow) + locale = getTranslationLanguage() + try: + socks = shared.config.get('bitmessagesettings', 'socksproxytype') + except: + socks = "N/A" + try: + upnp = shared.config.get('bitmessagesettings', 'upnp') + except: + upnp = "N/A" + connectedhosts = len(shared.connectedHostsList) + + myapp.ui.textEditMessage.setText(str(QtGui.QApplication.translate("Support", SUPPORT_MESSAGE)).format(version, os, architecture, pythonversion, opensslversion, frozen, portablemode, cpow, openclpow, locale, socks, upnp, connectedhosts)) + + # single msg tab + myapp.ui.tabWidgetSend.setCurrentIndex(0) + # send tab + myapp.ui.tabWidget.setCurrentIndex(1) diff --git a/src/bitmessageqt/uisignaler.py b/src/bitmessageqt/uisignaler.py new file mode 100644 index 00000000..ea18f0b0 --- /dev/null +++ b/src/bitmessageqt/uisignaler.py @@ -0,0 +1,77 @@ + +from PyQt4.QtCore import QThread, SIGNAL +import shared +import sys + + +class UISignaler(QThread): + _instance = None + + def __init__(self, parent=None): + QThread.__init__(self, parent) + + @classmethod + def get(cls): + if not cls._instance: + cls._instance = UISignaler() + return cls._instance + + def run(self): + while True: + command, data = shared.UISignalQueue.get() + if command == 'writeNewAddressToTable': + label, address, streamNumber = data + self.emit(SIGNAL( + "writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), label, address, str(streamNumber)) + elif command == 'updateStatusBar': + self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"), data) + elif command == 'updateSentItemStatusByToAddress': + toAddress, message = data + self.emit(SIGNAL( + "updateSentItemStatusByToAddress(PyQt_PyObject,PyQt_PyObject)"), toAddress, message) + elif command == 'updateSentItemStatusByAckdata': + ackData, message = data + self.emit(SIGNAL( + "updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), ackData, message) + elif command == 'displayNewInboxMessage': + inventoryHash, toAddress, fromAddress, subject, body = data + self.emit(SIGNAL( + "displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), + inventoryHash, toAddress, fromAddress, subject, body) + elif command == 'displayNewSentMessage': + toAddress, fromLabel, fromAddress, subject, message, ackdata = data + self.emit(SIGNAL( + "displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), + toAddress, fromLabel, fromAddress, subject, message, ackdata) + elif command == 'updateNetworkStatusTab': + self.emit(SIGNAL("updateNetworkStatusTab()")) + elif command == 'updateNumberOfMessagesProcessed': + self.emit(SIGNAL("updateNumberOfMessagesProcessed()")) + elif command == 'updateNumberOfPubkeysProcessed': + self.emit(SIGNAL("updateNumberOfPubkeysProcessed()")) + elif command == 'updateNumberOfBroadcastsProcessed': + self.emit(SIGNAL("updateNumberOfBroadcastsProcessed()")) + elif command == 'setStatusIcon': + self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"), data) + elif command == 'changedInboxUnread': + self.emit(SIGNAL("changedInboxUnread(PyQt_PyObject)"), data) + elif command == 'rerenderMessagelistFromLabels': + self.emit(SIGNAL("rerenderMessagelistFromLabels()")) + elif command == 'rerenderMessagelistToLabels': + self.emit(SIGNAL("rerenderMessagelistToLabels()")) + elif command == 'rerenderAddressBook': + self.emit(SIGNAL("rerenderAddressBook()")) + elif command == 'rerenderSubscriptions': + self.emit(SIGNAL("rerenderSubscriptions()")) + elif command == 'rerenderBlackWhiteList': + self.emit(SIGNAL("rerenderBlackWhiteList()")) + elif command == 'removeInboxRowByMsgid': + self.emit(SIGNAL("removeInboxRowByMsgid(PyQt_PyObject)"), data) + elif command == 'newVersionAvailable': + self.emit(SIGNAL("newVersionAvailable(PyQt_PyObject)"), data) + elif command == 'alert': + title, text, exitAfterUserClicksOk = data + self.emit(SIGNAL("displayAlert(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), title, text, exitAfterUserClicksOk) + else: + sys.stderr.write( + 'Command sent to UISignaler not recognized: %s\n' % command) diff --git a/src/bitmessageqt/utils.py b/src/bitmessageqt/utils.py new file mode 100644 index 00000000..79b0e2a9 --- /dev/null +++ b/src/bitmessageqt/utils.py @@ -0,0 +1,106 @@ +from PyQt4 import QtGui +import hashlib +import os +import shared +from addresses import addBMIfNotPresent + +str_broadcast_subscribers = '[Broadcast subscribers]' + +def identiconize(address): + size = 48 + + # If you include another identicon library, please generate an + # example identicon with the following md5 hash: + # 3fd4bf901b9d4ea1394f0fb358725b28 + + try: + identicon_lib = shared.config.get('bitmessagesettings', 'identiconlib') + except: + # default to qidenticon_two_x + identicon_lib = 'qidenticon_two_x' + + # As an 'identiconsuffix' you could put "@bitmessge.ch" or "@bm.addr" to make it compatible with other identicon generators. (Note however, that E-Mail programs might convert the BM-address to lowercase first.) + # It can be used as a pseudo-password to salt the generation of the identicons to decrease the risk + # of attacks where someone creates an address to mimic someone else's identicon. + identiconsuffix = shared.config.get('bitmessagesettings', 'identiconsuffix') + + if not shared.config.getboolean('bitmessagesettings', 'useidenticons'): + idcon = QtGui.QIcon() + return idcon + + if (identicon_lib[:len('qidenticon')] == 'qidenticon'): + # print identicon_lib + # originally by: + # :Author:Shin Adachi + # Licesensed under FreeBSD License. + # stripped from PIL and uses QT instead (by sendiulo, same license) + import qidenticon + hash = hashlib.md5(addBMIfNotPresent(address)+identiconsuffix).hexdigest() + use_two_colors = (identicon_lib[:len('qidenticon_two')] == 'qidenticon_two') + opacity = int(not((identicon_lib == 'qidenticon_x') | (identicon_lib == 'qidenticon_two_x') | (identicon_lib == 'qidenticon_b') | (identicon_lib == 'qidenticon_two_b')))*255 + penwidth = 0 + image = qidenticon.render_identicon(int(hash, 16), size, use_two_colors, opacity, penwidth) + # filename = './images/identicons/'+hash+'.png' + # image.save(filename) + idcon = QtGui.QIcon() + idcon.addPixmap(image, QtGui.QIcon.Normal, QtGui.QIcon.Off) + return idcon + elif identicon_lib == 'pydenticon': + # print identicon_lib + # Here you could load pydenticon.py (just put it in the "src" folder of your Bitmessage source) + from pydenticon import Pydenticon + # It is not included in the source, because it is licensed under GPLv3 + # GPLv3 is a copyleft license that would influence our licensing + # Find the source here: http://boottunes.googlecode.com/svn-history/r302/trunk/src/pydenticon.py + # note that it requires PIL to be installed: http://www.pythonware.com/products/pil/ + idcon_render = Pydenticon(addBMIfNotPresent(address)+identiconsuffix, size*3) + rendering = idcon_render._render() + data = rendering.convert("RGBA").tostring("raw", "RGBA") + qim = QImage(data, size, size, QImage.Format_ARGB32) + pix = QPixmap.fromImage(qim) + idcon = QtGui.QIcon() + idcon.addPixmap(pix, QtGui.QIcon.Normal, QtGui.QIcon.Off) + return idcon + +def avatarize(address): + """ + loads a supported image for the given address' hash form 'avatars' folder + falls back to default avatar if 'default.*' file exists + falls back to identiconize(address) + """ + idcon = QtGui.QIcon() + hash = hashlib.md5(addBMIfNotPresent(address)).hexdigest() + str_broadcast_subscribers = '[Broadcast subscribers]' + if address == str_broadcast_subscribers: + # don't hash [Broadcast subscribers] + hash = address + # http://pyqt.sourceforge.net/Docs/PyQt4/qimagereader.html#supportedImageFormats + # print QImageReader.supportedImageFormats () + # QImageReader.supportedImageFormats () + extensions = ['PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM', 'PGM', 'PPM', 'TIFF', 'XBM', 'XPM', 'TGA'] + # try to find a specific avatar + for ext in extensions: + lower_hash = shared.appdata + 'avatars/' + hash + '.' + ext.lower() + upper_hash = shared.appdata + 'avatars/' + hash + '.' + ext.upper() + if os.path.isfile(lower_hash): + # print 'found avatar of ', address + idcon.addFile(lower_hash) + return idcon + elif os.path.isfile(upper_hash): + # print 'found avatar of ', address + idcon.addFile(upper_hash) + return idcon + # if we haven't found any, try to find a default avatar + for ext in extensions: + lower_default = shared.appdata + 'avatars/' + 'default.' + ext.lower() + upper_default = shared.appdata + 'avatars/' + 'default.' + ext.upper() + if os.path.isfile(lower_default): + default = lower_default + idcon.addFile(lower_default) + return idcon + elif os.path.isfile(upper_default): + default = upper_default + idcon.addFile(upper_default) + return idcon + # If no avatar is found + return identiconize(address) diff --git a/src/bitmessageqt/widgets.py b/src/bitmessageqt/widgets.py new file mode 100644 index 00000000..02394296 --- /dev/null +++ b/src/bitmessageqt/widgets.py @@ -0,0 +1,13 @@ +from PyQt4 import uic +import os.path +import sys +from shared import codePath + +def resource_path(resFile): + baseDir = codePath() + for subDir in ["ui", "bitmessageqt"]: + if os.path.isdir(os.path.join(baseDir, subDir)) and os.path.isfile(os.path.join(baseDir, subDir, resFile)): + return os.path.join(baseDir, subDir, resFile) + +def load(resFile, widget): + uic.loadUi(resource_path(resFile), widget) diff --git a/src/bitmsghash/Makefile b/src/bitmsghash/Makefile new file mode 100644 index 00000000..88744524 --- /dev/null +++ b/src/bitmsghash/Makefile @@ -0,0 +1,20 @@ +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Darwin) + CCFLAGS += -I/usr/local/Cellar/openssl/1.0.2d_1/include + LDFLAGS += -L/usr/local/Cellar/openssl/1.0.2d_1/lib +endif + +all: bitmsghash.so + +powtest: + ./testpow.py + +bitmsghash.so: bitmsghash.o + g++ bitmsghash.o -shared -fPIC -lpthread -lcrypto $(LDFLAGS) -o bitmsghash.so + +bitmsghash.o: + g++ -Wall -O3 -march=native -fPIC $(CCFLAGS) -c bitmsghash.cpp + +clean: + rm -f bitmsghash.o bitmsghash.so + diff --git a/src/bitmsghash/bitmsghash.cl b/src/bitmsghash/bitmsghash.cl new file mode 100644 index 00000000..3c8c21a5 --- /dev/null +++ b/src/bitmsghash/bitmsghash.cl @@ -0,0 +1,276 @@ +/* +* This is based on the John The Ripper SHA512 code, modified for double SHA512 and for use as a miner in Bitmessage. +* This software is originally Copyright (c) 2012 Myrice +* and it is hereby released to the general public under the following terms: +* Redistribution and use in source and binary forms, with or without modification, are permitted. +*/ + +#ifdef cl_khr_byte_addressable_store +#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : disable +#endif + +#define uint8_t unsigned char +#define uint32_t unsigned int +#define uint64_t unsigned long +#define SALT_SIZE 0 + +#define BINARY_SIZE 8 +#define FULL_BINARY_SIZE 64 + + +#define PLAINTEXT_LENGTH 72 + +#define CIPHERTEXT_LENGTH 128 + + +/// Warning: This version of SWAP64(n) is slow and avoid bugs on AMD GPUs(7970) +// #define SWAP64(n) as_ulong(as_uchar8(n).s76543210) + +#define SWAP64(n) \ + (((n) << 56) \ + | (((n) & 0xff00) << 40) \ + | (((n) & 0xff0000) << 24) \ + | (((n) & 0xff000000) << 8) \ + | (((n) >> 8) & 0xff000000) \ + | (((n) >> 24) & 0xff0000) \ + | (((n) >> 40) & 0xff00) \ + | ((n) >> 56)) + + + +#define rol(x,n) ((x << n) | (x >> (64-n))) +#define ror(x,n) ((x >> n) | (x << (64-n))) +#define Ch(x,y,z) ((x & y) ^ ( (~x) & z)) +#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) +#define Sigma0(x) ((ror(x,28)) ^ (ror(x,34)) ^ (ror(x,39))) +#define Sigma1(x) ((ror(x,14)) ^ (ror(x,18)) ^ (ror(x,41))) +#define sigma0(x) ((ror(x,1)) ^ (ror(x,8)) ^(x>>7)) +#define sigma1(x) ((ror(x,19)) ^ (ror(x,61)) ^(x>>6)) + + + +typedef struct { // notice memory align problem + uint64_t H[8]; + uint32_t buffer[32]; //1024 bits + uint32_t buflen; +} sha512_ctx; + +typedef struct { + uint64_t target; + char v[PLAINTEXT_LENGTH+1]; +} sha512_key; + + +/* Macros for reading/writing chars from int32's */ +#define PUTCHAR(buf, index, val) (buf)[(index)>>2] = ((buf)[(index)>>2] & ~(0xffU << (((index) & 3) << 3))) + ((val) << (((index) & 3) << 3)) + + +__constant uint64_t k[] = { + 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, + 0xe9b5dba58189dbbcUL, + 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, + 0xab1c5ed5da6d8118UL, + 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, + 0x550c7dc3d5ffb4e2UL, + 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, + 0xc19bf174cf692694UL, + 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, + 0x240ca1cc77ac9c65UL, + 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, + 0x76f988da831153b5UL, + 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, + 0xbf597fc7beef0ee4UL, + 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, + 0x142929670a0e6e70UL, + 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, + 0x53380d139d95b3dfUL, + 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, + 0x92722c851482353bUL, + 0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, + 0xc76c51a30654be30UL, + 0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, + 0x106aa07032bbd1b8UL, + 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, + 0x34b0bcb5e19b48a8UL, + 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, + 0x682e6ff3d6b2b8a3UL, + 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, + 0x8cc702081a6439ecUL, + 0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, + 0xc67178f2e372532bUL, + 0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, + 0xf57d4f7fee6ed178UL, + 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, + 0x1b710b35131c471bUL, + 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, + 0x431d67c49c100d4cUL, + 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, + 0x6c44198c4a475817UL, +}; + + + +static void setup_ctx(sha512_ctx* ctx, const char * password, uint8_t pass_len) +{ + uint32_t* b32 = ctx->buffer; + + //set password to buffer + for (uint32_t i = 0; i < pass_len; i++) { + PUTCHAR(b32,i,password[i]); + } + ctx->buflen = pass_len; + + //append 1 to ctx buffer + uint32_t length = ctx->buflen; + PUTCHAR(b32, length, 0x80); + while((++length & 3) != 0) { + PUTCHAR(b32, length, 0); + } + + uint32_t* buffer32 = b32+(length>>2); + for(uint32_t i = length; i < 128; i+=4) {// append 0 to 128 + *buffer32++=0; + } + + //append length to buffer + uint64_t *buffer64 = (uint64_t *)ctx->buffer; + buffer64[15] = SWAP64(((uint64_t) ctx->buflen) * 8); +} + +inline uint64_t sha512(char* password) +{ + __private sha512_ctx ctx; + setup_ctx(&ctx, password, 72); + // sha512 main` + int i; + + uint64_t a = 0x6a09e667f3bcc908UL; + uint64_t b = 0xbb67ae8584caa73bUL; + uint64_t c = 0x3c6ef372fe94f82bUL; + uint64_t d = 0xa54ff53a5f1d36f1UL; + uint64_t e = 0x510e527fade682d1UL; + uint64_t f = 0x9b05688c2b3e6c1fUL; + uint64_t g = 0x1f83d9abfb41bd6bUL; + uint64_t h = 0x5be0cd19137e2179UL; + + __private uint64_t w[16]; + + uint64_t *data = (uint64_t *) ctx.buffer; + + for (i = 0; i < 16; i++) + w[i] = SWAP64(data[i]); + + uint64_t t1, t2; + for (i = 0; i < 16; i++) { + t1 = k[i] + w[i] + h + Sigma1(e) + Ch(e, f, g); + t2 = Maj(a, b, c) + Sigma0(a); + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + for (i = 16; i < 80; i++) { + + w[i & 15] =sigma1(w[(i - 2) & 15]) + sigma0(w[(i - 15) & 15]) + w[(i -16) & 15] + w[(i - 7) & 15]; + t1 = k[i] + w[i & 15] + h + Sigma1(e) + Ch(e, f, g); + t2 = Maj(a, b, c) + Sigma0(a); + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + uint64_t finalhash[8]; + + finalhash[0] = SWAP64(a + 0x6a09e667f3bcc908UL); + finalhash[1] = SWAP64(b + 0xbb67ae8584caa73bUL); + finalhash[2] = SWAP64(c + 0x3c6ef372fe94f82bUL); + finalhash[3] = SWAP64(d + 0xa54ff53a5f1d36f1UL); + finalhash[4] = SWAP64(e + 0x510e527fade682d1UL); + finalhash[5] = SWAP64(f + 0x9b05688c2b3e6c1fUL); + finalhash[6] = SWAP64(g + 0x1f83d9abfb41bd6bUL); + finalhash[7] = SWAP64(h + 0x5be0cd19137e2179UL); + + setup_ctx(&ctx, (char*) finalhash, 64); + + a = 0x6a09e667f3bcc908UL; + b = 0xbb67ae8584caa73bUL; + c = 0x3c6ef372fe94f82bUL; + d = 0xa54ff53a5f1d36f1UL; + e = 0x510e527fade682d1UL; + f = 0x9b05688c2b3e6c1fUL; + g = 0x1f83d9abfb41bd6bUL; + h = 0x5be0cd19137e2179UL; + + data = (uint64_t *) ctx.buffer; + //((uint64_t*)ctx.buffer)[8] = SWAP64((uint64_t)0x80); + + for (i = 0; i < 16; i++) + w[i] = SWAP64(data[i]); + + for (i = 0; i < 16; i++) { + t1 = k[i] + w[i] + h + Sigma1(e) + Ch(e, f, g); + t2 = Maj(a, b, c) + Sigma0(a); + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + for (i = 16; i < 80; i++) { + + w[i & 15] =sigma1(w[(i - 2) & 15]) + sigma0(w[(i - 15) & 15]) + w[(i -16) & 15] + w[(i - 7) & 15]; + t1 = k[i] + w[i & 15] + h + Sigma1(e) + Ch(e, f, g); + t2 = Maj(a, b, c) + Sigma0(a); + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + return SWAP64(a + 0x6a09e667f3bcc908UL); +} + +__kernel void kernel_sha512(__global const sha512_key *password,__global uint64_t *hash, uint64_t start) +{ + uint64_t idx = get_global_id(0); + if (idx == 0 && start == 0) { + *hash = 0; + } + uint64_t winval; + + uint64_t junk[9]; + + __global uint64_t * source = (__global uint64_t*) password->v; + for (int i = 1; i < 9; i++) { + junk[i] = source[i]; + } + + junk[0] = SWAP64(idx + (start)); + + winval = sha512((char*)junk); + if (SWAP64(winval) < password->target) { + *hash = SWAP64(junk[0]); + } +} + diff --git a/src/bitmsghash/bitmsghash.cpp b/src/bitmsghash/bitmsghash.cpp new file mode 100644 index 00000000..4862c341 --- /dev/null +++ b/src/bitmsghash/bitmsghash.cpp @@ -0,0 +1,145 @@ +// bitmessage cracker, build with g++ or MSVS to a shared library, use included python code for usage under bitmessage +#ifdef _WIN32 +#include "Winsock.h" +#include "Windows.h" +#define uint64_t unsigned __int64 +#else +#include +#include +#include +#endif +#include +#include +#include +#ifdef __APPLE__ +#include +#include +#endif + +#include "openssl/sha.h" + +#define HASH_SIZE 64 +#define BUFLEN 16384 + +#if defined(__GNUC__) + #define EXPORT __attribute__ ((__visibility__("default"))) +#elif defined(_WIN32) + #define EXPORT __declspec(dllexport) +#endif + +#ifndef __APPLE__ +#define ntohll(x) ( ( (uint64_t)(ntohl( (unsigned int)((x << 32) >> 32) )) << 32) | ntohl( ((unsigned int)(x >> 32)) ) ) +#endif + +unsigned long long max_val; +unsigned char *initialHash; +unsigned long long successval = 0; +unsigned int numthreads = 0; + +#ifdef _WIN32 +DWORD WINAPI threadfunc(LPVOID param) { +#else +void * threadfunc(void* param) { +#endif + unsigned int incamt = *((unsigned int*)param); + SHA512_CTX sha; + unsigned char buf[HASH_SIZE + sizeof(uint64_t)] = { 0 }; + unsigned char output[HASH_SIZE] = { 0 }; + + memcpy(buf + sizeof(uint64_t), initialHash, HASH_SIZE); + + unsigned long long tmpnonce = incamt; + unsigned long long * nonce = (unsigned long long *)buf; + unsigned long long * hash = (unsigned long long *)output; + while (successval == 0) { + tmpnonce += numthreads; + + (*nonce) = ntohll(tmpnonce); /* increment nonce */ + SHA512_Init(&sha); + SHA512_Update(&sha, buf, HASH_SIZE + sizeof(uint64_t)); + SHA512_Final(output, &sha); + SHA512_Init(&sha); + SHA512_Update(&sha, output, HASH_SIZE); + SHA512_Final(output, &sha); + + if (ntohll(*hash) < max_val) { + successval = tmpnonce; + } + } + return NULL; +} + +void getnumthreads() +{ +#ifdef _WIN32 + DWORD_PTR dwProcessAffinity, dwSystemAffinity; +#elif __linux__ + cpu_set_t dwProcessAffinity; +#else + int dwProcessAffinity = 0; + int32_t core_count = 0; +#endif + size_t len = sizeof(dwProcessAffinity); + if (numthreads > 0) + return; +#ifdef _WIN32 + GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinity, &dwSystemAffinity); +#elif __linux__ + sched_getaffinity(0, len, &dwProcessAffinity); +#else + if (sysctlbyname("hw.logicalcpu", &core_count, &len, 0, 0) == 0) + numthreads = core_count; +#endif + for (unsigned int i = 0; i < len * 8; i++) +#if defined(_WIN32) + if (dwProcessAffinity & (1i64 << i)) { +#elif defined __linux__ + if (CPU_ISSET(i, &dwProcessAffinity)) { +#else + if (dwProcessAffinity & (1 << i)) { +#endif + numthreads++; + printf("Detected core on: %u\n", i); + } + printf("Number of threads: %i\n", (int)numthreads); +} + +extern "C" EXPORT unsigned long long BitmessagePOW(unsigned char * starthash, unsigned long long target) +{ + successval = 0; + max_val = target; + getnumthreads(); + initialHash = (unsigned char *)starthash; +# ifdef _WIN32 + HANDLE* threads = (HANDLE*)calloc(sizeof(HANDLE), numthreads); +# else + pthread_t* threads = (pthread_t*)calloc(sizeof(pthread_t), numthreads); + struct sched_param schparam; + schparam.sched_priority = 0; +# endif + unsigned int *threaddata = (unsigned int *)calloc(sizeof(unsigned int), numthreads); + for (unsigned int i = 0; i < numthreads; i++) { + threaddata[i] = i; +# ifdef _WIN32 + threads[i] = CreateThread(NULL, 0, threadfunc, (LPVOID)&threaddata[i], 0, NULL); + SetThreadPriority(threads[i], THREAD_PRIORITY_IDLE); +# else + pthread_create(&threads[i], NULL, threadfunc, (void*)&threaddata[i]); +# ifdef __linux__ + pthread_setschedparam(threads[i], SCHED_IDLE, &schparam); +# else + pthread_setschedparam(threads[i], SCHED_RR, &schparam); +# endif +# endif + } +# ifdef _WIN32 + WaitForMultipleObjects(numthreads, threads, TRUE, INFINITE); +# else + for (unsigned int i = 0; i < numthreads; i++) { + pthread_join(threads[i], NULL); + } +# endif + free(threads); + free(threaddata); + return successval; +} diff --git a/src/build_osx.py b/src/build_osx.py index ce70cd54..1d8f470e 100644 --- a/src/build_osx.py +++ b/src/build_osx.py @@ -1,17 +1,29 @@ +from glob import glob +import os +from PyQt4 import QtCore from setuptools import setup name = "Bitmessage" -version = "0.4.4" +version = os.getenv("PYBITMESSAGEVERSION", "custom") mainscript = ["bitmessagemain.py"] +DATA_FILES = [ + ('', ['sslkeys', 'images']), + ('bitmsghash', ['bitmsghash/bitmsghash.cl', 'bitmsghash/bitmsghash.so']), + ('translations', glob('translations/*.qm')), + ('ui', glob('bitmessageqt/*.ui')), + ('translations', glob(str(QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)) + '/qt_??.qm')), + ('translations', glob(str(QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)) + '/qt_??_??.qm')), +] + setup( name = name, version = version, app = mainscript, + data_files = DATA_FILES, setup_requires = ["py2app"], options = dict( py2app = dict( - resources = ["images", "translations"], includes = ['sip', 'PyQt4._qt'], iconfile = "images/bitmessage.icns" ) diff --git a/src/class_addressGenerator.py b/src/class_addressGenerator.py index af25b210..bca9697d 100644 --- a/src/class_addressGenerator.py +++ b/src/class_addressGenerator.py @@ -8,17 +8,27 @@ import hashlib import highlevelcrypto from addresses import * from debug import logger +from helper_threading import * from pyelliptic import arithmetic import tr +from binascii import hexlify -class addressGenerator(threading.Thread): +class addressGenerator(threading.Thread, StoppableThread): def __init__(self): # QThread.__init__(self, parent) - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="addressGenerator") + self.initStop() + + def stopThread(self): + try: + shared.addressGeneratorQueue.put(("stopThread", "data")) + except: + pass + super(addressGenerator, self).stopThread() def run(self): - while True: + while shared.shutdown == 0: queueValue = shared.addressGeneratorQueue.get() nonceTrialsPerByte = 0 payloadLengthExtraBytes = 0 @@ -54,6 +64,8 @@ class addressGenerator(threading.Thread): numberOfNullBytesDemandedOnFrontOfRipeHash = 2 else: numberOfNullBytesDemandedOnFrontOfRipeHash = 1 # the default + elif queueValue[0] == 'stopThread': + break else: sys.stderr.write( 'Programming error: A structure with the wrong number of values was passed into the addressGeneratorQueue. Here is the queueValue: %s\n' % repr(queueValue)) @@ -72,7 +84,7 @@ class addressGenerator(threading.Thread): payloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes if command == 'createRandomAddress': shared.UISignalQueue.put(( - 'updateStatusBar', tr.translateText("MainWindow", "Generating one new address"))) + 'updateStatusBar', tr._translate("MainWindow", "Generating one new address"))) # This next section is a little bit strange. We're going to generate keys over and over until we # find one that starts with either \x00 or \x00\x00. Then when we pack them into a Bitmessage address, # we won't store the \x00 or \x00\x00 bytes thus making the @@ -93,7 +105,7 @@ class addressGenerator(threading.Thread): ripe.update(sha.digest()) if ripe.digest()[:numberOfNullBytesDemandedOnFrontOfRipeHash] == '\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash: break - logger.info('Generated address with ripe digest: %s' % ripe.digest().encode('hex')) + logger.info('Generated address with ripe digest: %s' % hexlify(ripe.digest())) try: logger.info('Address generator calculated %s addresses at %s addresses per second before finding one with the correct ripe-prefix.' % (numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix / (time.time() - startTime))) except ZeroDivisionError: @@ -134,7 +146,7 @@ class addressGenerator(threading.Thread): shared.apiAddressGeneratorReturnQueue.put(address) shared.UISignalQueue.put(( - 'updateStatusBar', tr.translateText("MainWindow", "Done generating address. Doing work necessary to broadcast it..."))) + 'updateStatusBar', tr._translate("MainWindow", "Done generating address. Doing work necessary to broadcast it..."))) shared.UISignalQueue.put(('writeNewAddressToTable', ( label, address, streamNumber))) shared.reloadMyAddressHashes() @@ -150,10 +162,8 @@ class addressGenerator(threading.Thread): sys.stderr.write( 'WARNING: You are creating deterministic address(es) using a blank passphrase. Bitmessage will do it but it is rather stupid.') if command == 'createDeterministicAddresses': - statusbar = 'Generating ' + str( - numberOfAddressesToMake) + ' new addresses.' shared.UISignalQueue.put(( - 'updateStatusBar', statusbar)) + 'updateStatusBar', tr._translate("MainWindow","Generating %1 new addresses.").arg(str(numberOfAddressesToMake)))) signingKeyNonce = 0 encryptionKeyNonce = 1 listOfNewAddressesToSendOutThroughTheAPI = [ @@ -187,7 +197,7 @@ class addressGenerator(threading.Thread): break - logger.info('Generated address with ripe digest: %s' % ripe.digest().encode('hex')) + logger.info('Generated address with ripe digest: %s' % hexlify(ripe.digest())) try: logger.info('Address generator calculated %s addresses at %s addresses per second before finding one with the correct ripe-prefix.' % (numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix / (time.time() - startTime))) except ZeroDivisionError: @@ -230,7 +240,7 @@ class addressGenerator(threading.Thread): if addressAlreadyExists: logger.info('%s already exists. Not adding it again.' % address) shared.UISignalQueue.put(( - 'updateStatusBar', tr.translateText("MainWindow","%1 is already in 'Your Identities'. Not adding it again.").arg(address))) + 'updateStatusBar', tr._translate("MainWindow","%1 is already in 'Your Identities'. Not adding it again.").arg(address))) else: logger.debug('label: %s' % label) shared.config.set(address, 'label', label) @@ -253,7 +263,7 @@ class addressGenerator(threading.Thread): listOfNewAddressesToSendOutThroughTheAPI.append( address) shared.myECCryptorObjects[ripe.digest()] = highlevelcrypto.makeCryptor( - potentialPrivEncryptionKey.encode('hex')) + hexlify(potentialPrivEncryptionKey)) shared.myAddressesByHash[ripe.digest()] = address tag = hashlib.sha512(hashlib.sha512(encodeVarint( addressVersionNumber) + encodeVarint(streamNumber) + ripe.digest()).digest()).digest()[32:] @@ -266,7 +276,7 @@ class addressGenerator(threading.Thread): shared.workerQueue.put(( 'sendOutOrStoreMyV4Pubkey', address)) shared.UISignalQueue.put(( - 'updateStatusBar', tr.translateText("MainWindow", "Done generating address"))) + 'updateStatusBar', tr._translate("MainWindow", "Done generating address"))) # Done generating addresses. @@ -278,4 +288,4 @@ class addressGenerator(threading.Thread): else: raise Exception( "Error in the addressGenerator thread. Thread was given a command it could not understand: " + command) - + shared.addressGeneratorQueue.task_done() diff --git a/src/class_objectHashHolder.py b/src/class_objectHashHolder.py index c91b1c23..e4e2c6d8 100644 --- a/src/class_objectHashHolder.py +++ b/src/class_objectHashHolder.py @@ -12,13 +12,14 @@ import time import threading class objectHashHolder(threading.Thread): + size = 10 def __init__(self, sendDataThreadMailbox): threading.Thread.__init__(self) self.shutdown = False self.sendDataThreadMailbox = sendDataThreadMailbox # This queue is used to submit data back to our associated sendDataThread. self.collectionOfHashLists = {} self.collectionOfPeerLists = {} - for i in range(10): + for i in range(self.size): self.collectionOfHashLists[i] = [] self.collectionOfPeerLists[i] = [] @@ -32,14 +33,23 @@ class objectHashHolder(threading.Thread): self.sendDataThreadMailbox.put((0, 'sendaddr', self.collectionOfPeerLists[iterator])) self.collectionOfPeerLists[iterator] = [] iterator += 1 - iterator %= 10 + iterator %= self.size time.sleep(1) def holdHash(self,hash): - self.collectionOfHashLists[random.randrange(0, 10)].append(hash) + self.collectionOfHashLists[random.randrange(0, self.size)].append(hash) + + def hasHash(self, hash): + if hash in (hashlist for hashlist in self.collectionOfHashLists): + logger.debug("Hash in hashHolder") + return True + return False def holdPeer(self,peerDetails): - self.collectionOfPeerLists[random.randrange(0, 10)].append(peerDetails) + self.collectionOfPeerLists[random.randrange(0, self.size)].append(peerDetails) + + def hashCount(self): + return sum([len(x) for x in self.collectionOfHashLists]) def close(self): - self.shutdown = True \ No newline at end of file + self.shutdown = True diff --git a/src/class_objectProcessor.py b/src/class_objectProcessor.py index f9972fe6..d5fe3a31 100644 --- a/src/class_objectProcessor.py +++ b/src/class_objectProcessor.py @@ -8,6 +8,7 @@ import sys import string from subprocess import call # used when the API must execute an outside program import traceback +from binascii import hexlify from pyelliptic.openssl import OpenSSL import highlevelcrypto @@ -26,10 +27,10 @@ import l10n class objectProcessor(threading.Thread): """ The objectProcessor thread, of which there is only one, receives network - objecs (msg, broadcast, pubkey, getpubkey) from the receiveDataThreads. + objects (msg, broadcast, pubkey, getpubkey) from the receiveDataThreads. """ def __init__(self): - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="objectProcessor") """ It may be the case that the last time Bitmessage was running, the user closed it before it finished processing everything in the @@ -39,11 +40,9 @@ class objectProcessor(threading.Thread): """ queryreturn = sqlQuery( '''SELECT objecttype, data FROM objectprocessorqueue''') - with shared.objectProcessorQueueSizeLock: - for row in queryreturn: - objectType, data = row - shared.objectProcessorQueueSize += len(data) - shared.objectProcessorQueue.put((objectType,data)) + for row in queryreturn: + objectType, data = row + shared.objectProcessorQueue.put((objectType,data)) sqlExecute('''DELETE FROM objectprocessorqueue''') logger.debug('Loaded %s objects from disk into the objectProcessorQueue.' % str(len(queryreturn))) @@ -70,19 +69,14 @@ class objectProcessor(threading.Thread): except Exception as e: logger.critical("Critical error within objectProcessorThread: \n%s" % traceback.format_exc()) - with shared.objectProcessorQueueSizeLock: - shared.objectProcessorQueueSize -= len(data) # We maintain objectProcessorQueueSize so that we will slow down requesting objects if too much data accumulates in the queue. - if shared.shutdown: time.sleep(.5) # Wait just a moment for most of the connections to close numberOfObjectsThatWereInTheObjectProcessorQueue = 0 with SqlBulkExecute() as sql: - while shared.objectProcessorQueueSize > 1: + while shared.objectProcessorQueue.curSize > 0: objectType, data = shared.objectProcessorQueue.get() sql.execute('''INSERT INTO objectprocessorqueue VALUES (?,?)''', objectType,data) - with shared.objectProcessorQueueSizeLock: - shared.objectProcessorQueueSize -= len(data) # We maintain objectProcessorQueueSize so that we will slow down requesting objects if too much data accumulates in the queue. numberOfObjectsThatWereInTheObjectProcessorQueue += 1 logger.debug('Saved %s objects from the objectProcessorQueue to disk. objectProcessorThread exiting.' % str(numberOfObjectsThatWereInTheObjectProcessorQueue)) shared.shutdown = 2 @@ -113,7 +107,7 @@ class objectProcessor(threading.Thread): if len(requestedHash) != 20: logger.debug('The length of the requested hash is not 20 bytes. Something is wrong. Ignoring.') return - logger.info('the hash requested in this getpubkey request is: %s' % requestedHash.encode('hex')) + logger.info('the hash requested in this getpubkey request is: %s' % hexlify(requestedHash)) if requestedHash in shared.myAddressesByHash: # if this address hash is one of mine myAddress = shared.myAddressesByHash[requestedHash] elif requestedAddressVersionNumber >= 4: @@ -121,7 +115,7 @@ class objectProcessor(threading.Thread): if len(requestedTag) != 32: logger.debug('The length of the requested tag is not 32 bytes. Something is wrong. Ignoring.') return - logger.debug('the tag requested in this getpubkey request is: %s' % requestedTag.encode('hex')) + logger.debug('the tag requested in this getpubkey request is: %s' % hexlify(requestedTag)) if requestedTag in shared.myAddressesByTag: myAddress = shared.myAddressesByTag[requestedTag] @@ -206,9 +200,9 @@ class objectProcessor(threading.Thread): publicSigningKey in hex: %s\n\ publicEncryptionKey in hex: %s' % (addressVersion, streamNumber, - ripe.encode('hex'), - publicSigningKey.encode('hex'), - publicEncryptionKey.encode('hex') + hexlify(ripe), + hexlify(publicSigningKey), + hexlify(publicEncryptionKey) ) ) @@ -247,7 +241,7 @@ class objectProcessor(threading.Thread): data[readPosition:readPosition + 10]) readPosition += signatureLengthLength signature = data[readPosition:readPosition + signatureLength] - if highlevelcrypto.verify(data[8:endOfSignedDataPosition], signature, publicSigningKey.encode('hex')): + if highlevelcrypto.verify(data[8:endOfSignedDataPosition], signature, hexlify(publicSigningKey)): logger.debug('ECDSA verify passed (within processpubkey)') else: logger.warning('ECDSA verify failed (within processpubkey)') @@ -265,9 +259,9 @@ class objectProcessor(threading.Thread): publicSigningKey in hex: %s\n\ publicEncryptionKey in hex: %s' % (addressVersion, streamNumber, - ripe.encode('hex'), - publicSigningKey.encode('hex'), - publicEncryptionKey.encode('hex') + hexlify(ripe), + hexlify(publicSigningKey), + hexlify(publicEncryptionKey) ) ) @@ -331,7 +325,7 @@ class objectProcessor(threading.Thread): 'ackreceived', int(time.time()), data[-32:]) - shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (data[-32:], tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(l10n.formatTimestamp())))) + shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (data[-32:], tr._translate("MainWindow",'Acknowledgement of the message received %1').arg(l10n.formatTimestamp())))) return else: logger.info('This was NOT an acknowledgement bound for me.') @@ -342,11 +336,13 @@ class objectProcessor(threading.Thread): for key, cryptorObject in shared.myECCryptorObjects.items(): try: - decryptedData = cryptorObject.decrypt(data[readPosition:]) - toRipe = key # This is the RIPE hash of my pubkeys. We need this below to compare to the destination_ripe included in the encrypted data. - initialDecryptionSuccessful = True - logger.info('EC decryption successful using key associated with ripe hash: %s.' % key.encode('hex')) - break + if initialDecryptionSuccessful: # continue decryption attempts to avoid timing attacks + cryptorObject.decrypt(data[readPosition:]) + else: + decryptedData = cryptorObject.decrypt(data[readPosition:]) + toRipe = key # This is the RIPE hash of my pubkeys. We need this below to compare to the destination_ripe included in the encrypted data. + initialDecryptionSuccessful = True + logger.info('EC decryption successful using key associated with ripe hash: %s.' % hexlify(key)) except Exception as err: pass if not initialDecryptionSuccessful: @@ -398,7 +394,7 @@ class objectProcessor(threading.Thread): logger.info('The original sender of this message did not send it to you. Someone is attempting a Surreptitious Forwarding Attack.\n\ See: http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html \n\ your toRipe: %s\n\ - embedded destination toRipe: %s' % (toRipe.encode('hex'), decryptedData[readPosition:readPosition + 20].encode('hex')) + embedded destination toRipe: %s' % (hexlify(toRipe), hexlify(decryptedData[readPosition:readPosition + 20])) ) return readPosition += 20 @@ -424,7 +420,7 @@ class objectProcessor(threading.Thread): readPosition:readPosition + signatureLength] signedData = data[8:20] + encodeVarint(1) + encodeVarint(streamNumberAsClaimedByMsg) + decryptedData[:positionOfBottomOfAckData] - if not highlevelcrypto.verify(signedData, signature, pubSigningKey.encode('hex')): + if not highlevelcrypto.verify(signedData, signature, hexlify(pubSigningKey)): logger.debug('ECDSA verify failed') return logger.debug('ECDSA verify passed') @@ -531,7 +527,7 @@ class objectProcessor(threading.Thread): # Let us now check and see whether our receiving address is # behaving as a mailing list - if shared.safeConfigGetBoolean(toAddress, 'mailinglist'): + if shared.safeConfigGetBoolean(toAddress, 'mailinglist') and messageEncodingType != 0: try: mailingListName = shared.config.get( toAddress, 'mailinglistname') @@ -574,7 +570,12 @@ class objectProcessor(threading.Thread): toAddress, '[Broadcast subscribers]', fromAddress, subject, message, ackdataForBroadcast))) shared.workerQueue.put(('sendbroadcast', '')) - if self.ackDataHasAVaildHeader(ackData): + # Don't send ACK if invalid, blacklisted senders, invisible messages, disabled or chan + if self.ackDataHasAValidHeader(ackData) and \ + not blockMessage and \ + messageEncodingType != 0 and \ + not shared.safeConfigGetBoolean(toAddress, 'dontsendack') and \ + not shared.safeConfigGetBoolean(toAddress, 'chan'): shared.checkAndShareObjectWithPeers(ackData[24:]) # Display timing data @@ -617,11 +618,13 @@ class objectProcessor(threading.Thread): initialDecryptionSuccessful = False for key, cryptorObject in shared.MyECSubscriptionCryptorObjects.items(): try: - decryptedData = cryptorObject.decrypt(data[readPosition:]) - toRipe = key # This is the RIPE hash of the sender's pubkey. We need this below to compare to the RIPE hash of the sender's address to verify that it was encrypted by with their key rather than some other key. - initialDecryptionSuccessful = True - logger.info('EC decryption successful using key associated with ripe hash: %s' % key.encode('hex')) - break + if initialDecryptionSuccessful: # continue decryption attempts to avoid timing attacks + cryptorObject.decrypt(data[readPosition:]) + else: + decryptedData = cryptorObject.decrypt(data[readPosition:]) + toRipe = key # This is the RIPE hash of the sender's pubkey. We need this below to compare to the RIPE hash of the sender's address to verify that it was encrypted by with their key rather than some other key. + initialDecryptionSuccessful = True + logger.info('EC decryption successful using key associated with ripe hash: %s' % hexlify(key)) except Exception as err: pass # print 'cryptorObject.decrypt Exception:', err @@ -716,7 +719,7 @@ class objectProcessor(threading.Thread): signature = decryptedData[ readPosition:readPosition + signatureLength] signedData += decryptedData[:readPositionAtBottomOfMessage] - if not highlevelcrypto.verify(signedData, signature, sendersPubSigningKey.encode('hex')): + if not highlevelcrypto.verify(signedData, signature, hexlify(sendersPubSigningKey)): logger.debug('ECDSA verify failed') return logger.debug('ECDSA verify passed') @@ -741,8 +744,7 @@ class objectProcessor(threading.Thread): fromAddress = encodeAddress( sendersAddressVersion, sendersStream, calculatedRipe) - with shared.printLock: - print 'fromAddress:', fromAddress + logger.debug('fromAddress: ' + fromAddress) if messageEncodingType == 2: subject, body = self.decodeType2Message(message) @@ -822,7 +824,7 @@ class objectProcessor(threading.Thread): address) shared.workerQueue.put(('sendmessage', '')) - def ackDataHasAVaildHeader(self, ackData): + def ackDataHasAValidHeader(self, ackData): if len(ackData) < shared.Header.size: logger.info('The length of ackData is unreasonably short. Not sending ackData.') return False diff --git a/src/class_objectProcessorQueue.py b/src/class_objectProcessorQueue.py new file mode 100644 index 00000000..9bf3f82a --- /dev/null +++ b/src/class_objectProcessorQueue.py @@ -0,0 +1,29 @@ +import shared + +import Queue +import threading +import time + +class ObjectProcessorQueue(Queue.Queue): + maxSize = 32000000 + + def __init__(self): + Queue.Queue.__init__(self) + self.sizeLock = threading.Lock() + self.curSize = 0 # in Bytes. We maintain this to prevent nodes from flooing us with objects which take up too much memory. If this gets too big we'll sleep before asking for further objects. + + def put(self, item, block = True, timeout = None): + while self.curSize >= self.maxSize: + time.sleep(1) + with self.sizeLock: + self.curSize += len(item[1]) + Queue.Queue.put(self, item, block, timeout) + + def get(self, block = True, timeout = None): + try: + item = Queue.Queue.get(self, block, timeout) + except Queue.Empty as e: + raise Queue.Empty() + with self.sizeLock: + self.curSize -= len(item[1]) + return item diff --git a/src/class_outgoingSynSender.py b/src/class_outgoingSynSender.py index 453acfe1..71d650ed 100644 --- a/src/class_outgoingSynSender.py +++ b/src/class_outgoingSynSender.py @@ -2,6 +2,7 @@ import threading import time import random import shared +import select import socks import socket import sys @@ -9,14 +10,16 @@ import tr from class_sendDataThread import * from class_receiveDataThread import * +from helper_threading import * # For each stream to which we connect, several outgoingSynSender threads # will exist and will collectively create 8 connections with peers. -class outgoingSynSender(threading.Thread): +class outgoingSynSender(threading.Thread, StoppableThread): def __init__(self): - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="outgoingSynSender") + self.initStop() def setup(self, streamNumber, selfInitiatedConnections): self.streamNumber = streamNumber @@ -26,23 +29,36 @@ class outgoingSynSender(threading.Thread): # 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: + shared.knownNodesLock.acquire() peer = shared.trustedPeer shared.knownNodes[self.streamNumber][peer] = time.time() + shared.knownNodesLock.release() else: - peer, = random.sample(shared.knownNodes[self.streamNumber], 1) - shared.knownNodesLock.release() - + while True: + shared.knownNodesLock.acquire() + peer, = random.sample(shared.knownNodes[self.streamNumber], 1) + shared.knownNodesLock.release() + if shared.config.get('bitmessagesettings', 'socksproxytype') != 'none' or peer.host.find(".onion") == -1: + break + time.sleep(1) return peer + + def stopThread(self): + super(outgoingSynSender, self).stopThread() + try: + self.sock.shutdown(socket.SHUT_RDWR) + except: + pass def run(self): - while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'): - time.sleep(2) - while shared.safeConfigGetBoolean('bitmessagesettings', 'sendoutgoingconnections'): + while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect') and not self._stopped: + self.stop.wait(2) + while shared.safeConfigGetBoolean('bitmessagesettings', 'sendoutgoingconnections') and not self._stopped: + self.name = "outgoingSynSender" maximumConnections = 1 if shared.trustedPeer else 8 # maximum number of outgoing connections = 8 while len(self.selfInitiatedConnections[self.streamNumber]) >= maximumConnections: - time.sleep(10) + self.stop.wait(10) if shared.shutdown: break random.seed() @@ -53,7 +69,9 @@ class outgoingSynSender(threading.Thread): # print 'choosing new sample' random.seed() peer = self._getPeer() - time.sleep(1) + self.stop.wait(1) + if shared.shutdown: + break # Clear out the shared.alreadyAttemptedConnectionsList every half # hour so that this program will again attempt a connection # to any nodes, even ones it has already tried. @@ -63,13 +81,17 @@ class outgoingSynSender(threading.Thread): time.time()) shared.alreadyAttemptedConnectionsListLock.acquire() shared.alreadyAttemptedConnectionsList[peer] = 0 - shared.alreadyAttemptedConnectionsListLock.release() + try: + shared.alreadyAttemptedConnectionsListLock.release() + except threading.ThreadError as e: + pass + self.name = "outgoingSynSender-" + peer.host.replace(":", ".") # log parser field separator if peer.host.find(':') == -1: address_family = socket.AF_INET else: address_family = socket.AF_INET6 try: - sock = socks.socksocket(address_family, socket.SOCK_STREAM) + self.sock = socks.socksocket(address_family, socket.SOCK_STREAM) except: """ The line can fail on Windows systems which aren't @@ -86,22 +108,19 @@ class outgoingSynSender(threading.Thread): except: pass shared.knownNodesLock.release() - with shared.printLock: - print 'deleting ', peer, 'from shared.knownNodes because it caused a socks.socksocket exception. We must not be 64-bit compatible.' + logger.debug('deleting ' + str(peer) + ' from shared.knownNodes because it caused a socks.socksocket exception. We must not be 64-bit compatible.') continue # This option apparently avoids the TIME_WAIT state so that we # can rebind faster - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - sock.settimeout(20) + self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.sock.settimeout(20) if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none' and shared.verbose >= 2: - with shared.printLock: - print 'Trying an outgoing connection to', peer + logger.debug('Trying an outgoing connection to ' + str(peer)) # sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) elif shared.config.get('bitmessagesettings', 'socksproxytype') == 'SOCKS4a': if shared.verbose >= 2: - with shared.printLock: - print '(Using SOCKS4a) Trying an outgoing connection to', peer + logger.debug ('(Using SOCKS4a) Trying an outgoing connection to ' + str(peer)) proxytype = socks.PROXY_TYPE_SOCKS4 sockshostname = shared.config.get( @@ -114,15 +133,14 @@ class outgoingSynSender(threading.Thread): 'bitmessagesettings', 'socksusername') sockspassword = shared.config.get( 'bitmessagesettings', 'sockspassword') - sock.setproxy( + self.sock.setproxy( proxytype, sockshostname, socksport, rdns, socksusername, sockspassword) else: - sock.setproxy( + self.sock.setproxy( proxytype, sockshostname, socksport, rdns) elif shared.config.get('bitmessagesettings', 'socksproxytype') == 'SOCKS5': if shared.verbose >= 2: - with shared.printLock: - print '(Using SOCKS5) Trying an outgoing connection to', peer + logger.debug ('(Using SOCKS5) Trying an outgoing connection to ' + str(peer)) proxytype = socks.PROXY_TYPE_SOCKS5 sockshostname = shared.config.get( @@ -135,40 +153,40 @@ class outgoingSynSender(threading.Thread): 'bitmessagesettings', 'socksusername') sockspassword = shared.config.get( 'bitmessagesettings', 'sockspassword') - sock.setproxy( + self.sock.setproxy( proxytype, sockshostname, socksport, rdns, socksusername, sockspassword) else: - sock.setproxy( + self.sock.setproxy( proxytype, sockshostname, socksport, rdns) try: - sock.connect((peer.host, peer.port)) - rd = receiveDataThread() - rd.daemon = True # close the main program even if there are threads left + self.sock.connect((peer.host, peer.port)) someObjectsOfWhichThisRemoteNodeIsAlreadyAware = {} # This is not necessairly a complete list; we clear it from time to time to save memory. sendDataThreadQueue = Queue.Queue() # Used to submit information to the send data thread for this connection. - rd.setup(sock, + + sd = sendDataThread(sendDataThreadQueue) + sd.setup(self.sock, peer.host, peer.port, self.streamNumber, + someObjectsOfWhichThisRemoteNodeIsAlreadyAware) + sd.start() + + rd = receiveDataThread() + rd.daemon = True # close the main program even if there are threads left + rd.setup(self.sock, peer.host, peer.port, self.streamNumber, someObjectsOfWhichThisRemoteNodeIsAlreadyAware, self.selfInitiatedConnections, - sendDataThreadQueue) + sendDataThreadQueue, + sd.objectHashHolderInstance) rd.start() - with shared.printLock: - print self, 'connected to', peer, 'during an outgoing attempt.' - - sd = sendDataThread(sendDataThreadQueue) - sd.setup(sock, peer.host, peer.port, self.streamNumber, - someObjectsOfWhichThisRemoteNodeIsAlreadyAware) - sd.start() sd.sendVersionMessage() + logger.debug(str(self) + ' connected to ' + str(peer) + ' during an outgoing attempt.') except socks.GeneralProxyError as err: if shared.verbose >= 2: - with shared.printLock: - print 'Could NOT connect to', peer, 'during outgoing attempt.', err + logger.debug('Could NOT connect to ' + str(peer) + ' during outgoing attempt. ' + str(err)) deletedPeer = None with shared.knownNodesLock: @@ -186,25 +204,23 @@ class outgoingSynSender(threading.Thread): del shared.knownNodes[self.streamNumber][peer] deletedPeer = peer if deletedPeer: - with shared.printLock: - print 'deleting', peer, 'from shared.knownNodes because it is more than 48 hours old and we could not connect to it.' + str ('deleting ' + str(peer) + ' from shared.knownNodes because it is more than 48 hours old and we could not connect to it.') except socks.Socks5AuthError as err: shared.UISignalQueue.put(( - 'updateStatusBar', tr.translateText( + 'updateStatusBar', tr._translate( "MainWindow", "SOCKS5 Authentication problem: %1").arg(str(err)))) except socks.Socks5Error as err: pass - print 'SOCKS5 error. (It is possible that the server wants authentication).)', str(err) + logger.error('SOCKS5 error. (It is possible that the server wants authentication).) ' + str(err)) except socks.Socks4Error as err: - print 'Socks4Error:', err + logger.error('Socks4Error: ' + str(err)) except socket.error as err: if shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS': - print 'Bitmessage MIGHT be having trouble connecting to the SOCKS server. ' + str(err) + logger.error('Bitmessage MIGHT be having trouble connecting to the SOCKS server. ' + str(err)) else: if shared.verbose >= 1: - with shared.printLock: - print 'Could NOT connect to', peer, 'during outgoing attempt.', err + logger.debug('Could NOT connect to ' + str(peer) + 'during outgoing attempt. ' + str(err)) deletedPeer = None with shared.knownNodesLock: @@ -222,12 +238,9 @@ class outgoingSynSender(threading.Thread): del shared.knownNodes[self.streamNumber][peer] deletedPeer = peer if deletedPeer: - with shared.printLock: - print 'deleting', peer, 'from shared.knownNodes because it is more than 48 hours old and we could not connect to it.' + logger.debug('deleting ' + str(peer) + ' from shared.knownNodes because it is more than 48 hours old and we could not connect to it.') except Exception as err: - sys.stderr.write( - 'An exception has occurred in the outgoingSynSender thread that was not caught by other exception types: ') import traceback - traceback.print_exc() - time.sleep(0.1) + logger.exception('An exception has occurred in the outgoingSynSender thread that was not caught by other exception types:') + self.stop.wait(0.1) diff --git a/src/class_receiveDataThread.py b/src/class_receiveDataThread.py index ff5371ad..5883ab42 100644 --- a/src/class_receiveDataThread.py +++ b/src/class_receiveDataThread.py @@ -1,20 +1,28 @@ -doTimingAttackMitigation = True +doTimingAttackMitigation = False +import base64 +import errno +import math import time import threading import shared import hashlib +import os +import select import socket import random +import ssl from struct import unpack, pack import sys import traceback +from binascii import hexlify #import string #from subprocess import call # used when the API must execute an outside program #from pyelliptic.openssl import OpenSSL #import highlevelcrypto from addresses import * +from class_objectHashHolder import objectHashHolder from helper_generic import addDataPadding, isHostInPrivateIPRange from helper_sql import sqlQuery from debug import logger @@ -25,7 +33,7 @@ from debug import logger class receiveDataThread(threading.Thread): def __init__(self): - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="receiveData") self.data = '' self.verackSent = False self.verackReceived = False @@ -38,10 +46,12 @@ class receiveDataThread(threading.Thread): streamNumber, someObjectsOfWhichThisRemoteNodeIsAlreadyAware, selfInitiatedConnections, - sendDataThreadQueue): + sendDataThreadQueue, + objectHashHolderInstance): self.sock = sock self.peer = shared.Peer(HOST, port) + self.name = "receiveData-" + self.peer.host.replace(":", ".") # ":" log parser field separator self.streamNumber = streamNumber self.objectsThatWeHaveYetToGetFromThisPeer = {} self.selfInitiatedConnections = selfInitiatedConnections @@ -49,16 +59,18 @@ class receiveDataThread(threading.Thread): shared.connectedHostsList[ self.peer.host] = 0 # The very fact that this receiveData thread exists shows that we are connected to the remote host. Let's add it to this list so that an outgoingSynSender thread doesn't try to connect to it. self.connectionIsOrWasFullyEstablished = False # set to true after the remote node and I accept each other's version messages. This is needed to allow the user interface to accurately reflect the current number of connections. + self.services = 0 if self.streamNumber == -1: # This was an incoming connection. Send out a version message if we accept the other node's version message. self.initiatedConnection = False else: self.initiatedConnection = True self.selfInitiatedConnections[streamNumber][self] = 0 self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware = someObjectsOfWhichThisRemoteNodeIsAlreadyAware + self.objectHashHolderInstance = objectHashHolderInstance + self.startTime = time.time() def run(self): - with shared.printLock: - print 'receiveDataThread starting. ID', str(id(self)) + '. The size of the shared.connectedHostsList is now', len(shared.connectedHostsList) + logger.debug('receiveDataThread starting. ID ' + str(id(self)) + '. The size of the shared.connectedHostsList is now ' + str(len(shared.connectedHostsList))) while True: if shared.config.getint('bitmessagesettings', 'maxdownloadrate') == 0: @@ -76,38 +88,41 @@ class receiveDataThread(threading.Thread): shared.numberOfBytesReceivedLastSecond = 0 dataLen = len(self.data) try: - dataRecv = self.sock.recv(1024) + if ((self.services & shared.NODE_SSL == shared.NODE_SSL) and + self.connectionIsOrWasFullyEstablished and + shared.haveSSL(not self.initiatedConnection)): + dataRecv = self.sslSock.recv(1024) + else: + dataRecv = self.sock.recv(1024) self.data += dataRecv shared.numberOfBytesReceived += len(dataRecv) # for the 'network status' UI tab. The UI clears this value whenever it updates. shared.numberOfBytesReceivedLastSecond += len(dataRecv) # for the download rate limit except socket.timeout: - with shared.printLock: - print 'Timeout occurred waiting for data from', self.peer, '. Closing receiveData thread. (ID:', str(id(self)) + ')' + logger.error ('Timeout occurred waiting for data from ' + str(self.peer) + '. Closing receiveData thread. (ID: ' + str(id(self)) + ')') break except Exception as err: - with shared.printLock: - print 'sock.recv error. Closing receiveData thread (' + str(self.peer) + ', Thread ID:', str(id(self)) + ').', err + if (sys.platform == 'win32' and err.errno in ([2, 10035])) or (sys.platform != 'win32' and err.errno == errno.EWOULDBLOCK): + select.select([self.sslSock], [], []) + continue + logger.error('sock.recv error. Closing receiveData thread (' + str(self.peer) + ', Thread ID: ' + str(id(self)) + ').' + str(err.errno) + "/" + str(err)) break # print 'Received', repr(self.data) if len(self.data) == dataLen: # If self.sock.recv returned no data: - with shared.printLock: - print 'Connection to', self.peer, 'closed. Closing receiveData thread. (ID:', str(id(self)) + ')' + logger.debug('Connection to ' + str(self.peer) + ' closed. Closing receiveData thread. (ID: ' + str(id(self)) + ')') break else: self.processData() try: del self.selfInitiatedConnections[self.streamNumber][self] - with shared.printLock: - print 'removed self (a receiveDataThread) from selfInitiatedConnections' + logger.debug('removed self (a receiveDataThread) from selfInitiatedConnections') except: pass self.sendDataThreadQueue.put((0, 'shutdown','no data')) # commands the corresponding sendDataThread to shut itself down. try: del shared.connectedHostsList[self.peer.host] except Exception as err: - with shared.printLock: - print 'Could not delete', self.peer.host, 'from shared.connectedHostsList.', err + logger.error('Could not delete ' + str(self.peer.host) + ' from shared.connectedHostsList.' + str(err)) try: del shared.numberOfObjectsThatWeHaveYetToGetPerPeer[ @@ -115,9 +130,21 @@ class receiveDataThread(threading.Thread): except: pass shared.UISignalQueue.put(('updateNetworkStatusTab', 'no data')) - with shared.printLock: - print 'receiveDataThread ending. ID', str(id(self)) + '. The size of the shared.connectedHostsList is now', len(shared.connectedHostsList) + logger.debug('receiveDataThread ending. ID ' + str(id(self)) + '. The size of the shared.connectedHostsList is now ' + str(len(shared.connectedHostsList))) + def antiIntersectionDelay(self, initial = False): + # estimated time for a small object to propagate across the whole network + delay = math.ceil(math.log(len(shared.knownNodes[self.streamNumber]) + 2, 20)) * (0.2 + objectHashHolder.size/2) + # +2 is to avoid problems with log(0) and log(1) + # 20 is avg connected nodes count + # 0.2 is avg message transmission time + now = time.time() + if initial and now - delay < self.startTime: + logger.debug("Initial sleeping for %.2fs", delay - (now - self.startTime)) + time.sleep(delay - (now - self.startTime)) + elif not initial: + logger.debug("Sleeping due to missing object for %.2fs", delay) + time.sleep(delay) def processData(self): if len(self.data) < shared.Header.size: # if so little of the data has arrived that we can't even read the checksum then wait for more data. @@ -137,7 +164,7 @@ class receiveDataThread(threading.Thread): return payload = self.data[shared.Header.size:payloadLength + shared.Header.size] if checksum != hashlib.sha512(payload).digest()[0:4]: # test the checksum in the message. - print 'Checksum incorrect. Clearing this message.' + logger.error('Checksum incorrect. Clearing this message.') self.data = self.data[payloadLength + shared.Header.size:] del magic,command,payloadLength,checksum,payload # better to clean up before the recursive call self.processData() @@ -152,8 +179,7 @@ class receiveDataThread(threading.Thread): #Strip the nulls command = command.rstrip('\x00') - with shared.printLock: - print 'remoteCommand', repr(command), ' from', self.peer + logger.debug('remoteCommand ' + repr(command) + ' from ' + str(self.peer)) try: #TODO: Use a dispatcher here @@ -191,24 +217,15 @@ class receiveDataThread(threading.Thread): objectHash, = random.sample( self.objectsThatWeHaveYetToGetFromThisPeer, 1) if objectHash in shared.inventory: - with shared.printLock: - print 'Inventory (in memory) already has object listed in inv message.' - del self.objectsThatWeHaveYetToGetFromThisPeer[ - objectHash] - elif shared.isInSqlInventory(objectHash): - if shared.verbose >= 3: - with shared.printLock: - print 'Inventory (SQL on disk) already has object listed in inv message.' - del self.objectsThatWeHaveYetToGetFromThisPeer[ - objectHash] + logger.debug('Inventory already has object listed in inv message.') + del self.objectsThatWeHaveYetToGetFromThisPeer[objectHash] else: # We don't have the object in our inventory. Let's request it. self.sendgetdata(objectHash) del self.objectsThatWeHaveYetToGetFromThisPeer[ objectHash] # It is possible that the remote node might not respond with the object. In that case, we'll very likely get it from someone else anyway. if len(self.objectsThatWeHaveYetToGetFromThisPeer) == 0: - with shared.printLock: - print '(concerning', str(self.peer) + ')', 'number of objectsThatWeHaveYetToGetFromThisPeer is now 0' + logger.debug('(concerning' + str(self.peer) + ') number of objectsThatWeHaveYetToGetFromThisPeer is now 0') try: del shared.numberOfObjectsThatWeHaveYetToGetPerPeer[ self.peer] # this data structure is maintained so that we can keep track of how many total objects, across all connections, are currently outstanding. If it goes too high it can indicate that we are under attack by multiple nodes working together. @@ -217,16 +234,14 @@ class receiveDataThread(threading.Thread): break if len(self.objectsThatWeHaveYetToGetFromThisPeer) == 0: # We had objectsThatWeHaveYetToGetFromThisPeer but the loop ran, they were all in our inventory, and now we don't have any to get anymore. - with shared.printLock: - print '(concerning', str(self.peer) + ')', 'number of objectsThatWeHaveYetToGetFromThisPeer is now 0' + logger.debug('(concerning' + str(self.peer) + ') number of objectsThatWeHaveYetToGetFromThisPeer is now 0') try: del shared.numberOfObjectsThatWeHaveYetToGetPerPeer[ self.peer] # this data structure is maintained so that we can keep track of how many total objects, across all connections, are currently outstanding. If it goes too high it can indicate that we are under attack by multiple nodes working together. except: pass if len(self.objectsThatWeHaveYetToGetFromThisPeer) > 0: - with shared.printLock: - print '(concerning', str(self.peer) + ')', 'number of objectsThatWeHaveYetToGetFromThisPeer is now', len(self.objectsThatWeHaveYetToGetFromThisPeer) + logger.debug('(concerning' + str(self.peer) + ') number of objectsThatWeHaveYetToGetFromThisPeer is now ' + str(len(self.objectsThatWeHaveYetToGetFromThisPeer))) shared.numberOfObjectsThatWeHaveYetToGetPerPeer[self.peer] = len( self.objectsThatWeHaveYetToGetFromThisPeer) # this data structure is maintained so that we can keep track of how many total objects, across all connections, are currently outstanding. If it goes too high it can indicate that we are under attack by multiple nodes working together. @@ -234,14 +249,12 @@ class receiveDataThread(threading.Thread): def sendpong(self): - with shared.printLock: - print 'Sending pong' + logger.debug('Sending pong') self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('pong'))) def recverack(self): - with shared.printLock: - print 'verack received' + logger.debug('verack received') self.verackReceived = True if self.verackSent: # We have thus both sent and received a verack. @@ -252,19 +265,38 @@ class receiveDataThread(threading.Thread): # there is no reason to run this function a second time return self.connectionIsOrWasFullyEstablished = True + + self.sslSock = self.sock + if ((self.services & shared.NODE_SSL == shared.NODE_SSL) and + shared.haveSSL(not self.initiatedConnection)): + logger.debug("Initialising TLS") + self.sslSock = ssl.wrap_socket(self.sock, keyfile = os.path.join(shared.codePath(), 'sslkeys', 'key.pem'), certfile = os.path.join(shared.codePath(), 'sslkeys', 'cert.pem'), server_side = not self.initiatedConnection, ssl_version=ssl.PROTOCOL_TLSv1, do_handshake_on_connect=False, ciphers='AECDH-AES256-SHA') + if hasattr(self.sslSock, "context"): + self.sslSock.context.set_ecdh_curve("secp256k1") + while True: + try: + self.sslSock.do_handshake() + break + except ssl.SSLError as e: + if e.errno == 2: + select.select([self.sslSock], [self.sslSock], []) + else: + break + except: + break # Command the corresponding sendDataThread to set its own connectionIsOrWasFullyEstablished variable to True also - self.sendDataThreadQueue.put((0, 'connectionIsOrWasFullyEstablished', 'no data')) + self.sendDataThreadQueue.put((0, 'connectionIsOrWasFullyEstablished', (self.services, self.sslSock))) + if not self.initiatedConnection: shared.clientHasReceivedIncomingConnections = True shared.UISignalQueue.put(('setStatusIcon', 'green')) self.sock.settimeout( 600) # We'll send out a pong every 5 minutes to make sure the connection stays alive if there has been no other traffic to send lately. shared.UISignalQueue.put(('updateNetworkStatusTab', 'no data')) - with shared.printLock: - print 'Connection fully established with', self.peer - print 'The size of the connectedHostsList is now', len(shared.connectedHostsList) - print 'The length of sendDataQueues is now:', len(shared.sendDataQueues) - print 'broadcasting addr from within connectionFullyEstablished function.' + logger.debug('Connection fully established with ' + str(self.peer) + "\n" + \ + 'The size of the connectedHostsList is now ' + str(len(shared.connectedHostsList)) + "\n" + \ + 'The length of sendDataQueues is now: ' + str(len(shared.sendDataQueues)) + "\n" + \ + 'broadcasting addr from within connectionFullyEstablished function.') # Let all of our peers know about this new node. dataToSend = (int(time.time()), self.streamNumber, 1, self.peer.host, self.remoteNodeIncomingPort) @@ -273,8 +305,7 @@ class receiveDataThread(threading.Thread): self.sendaddr() # This is one large addr message to this one peer. if not self.initiatedConnection and len(shared.connectedHostsList) > 200: - with shared.printLock: - print 'We are connected to too many people. Closing connection.' + logger.info ('We are connected to too many people. Closing connection.') self.sendDataThreadQueue.put((0, 'shutdown','no data')) return @@ -282,23 +313,10 @@ class receiveDataThread(threading.Thread): def sendBigInv(self): # Select all hashes for objects in this stream. - queryreturn = sqlQuery( - '''SELECT hash FROM inventory WHERE expirestime>? and streamnumber=?''', - int(time.time()), - self.streamNumber) bigInvList = {} - for row in queryreturn: - hash, = row - if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware: + for hash in shared.inventory.unexpired_hashes_by_stream(self.streamNumber): + if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware and not self.objectHashHolderInstance.hasHash(hash): bigInvList[hash] = 0 - # We also have messages in our inventory in memory (which is a python - # dictionary). Let's fetch those too. - with shared.inventoryLock: - for hash, storedValue in shared.inventory.items(): - if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware: - objectType, streamNumber, payload, expiresTime, tag = storedValue - if streamNumber == self.streamNumber and expiresTime > int(time.time()): - bigInvList[hash] = 0 numberOfObjectsInInvMessage = 0 payload = '' # Now let us start appending all of these hashes together. They will be @@ -320,8 +338,7 @@ class receiveDataThread(threading.Thread): # function for broadcasting invs to everyone in our stream. def sendinvMessageToJustThisOnePeer(self, numberOfObjects, payload): payload = encodeVarint(numberOfObjects) + payload - with shared.printLock: - print 'Sending huge inv message with', numberOfObjects, 'objects to just this one peer' + logger.debug('Sending huge inv message with ' + str(numberOfObjects) + ' objects to just this one peer') self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('inv', payload))) def _sleepForTimingAttackMitigation(self, sleepTime): @@ -329,8 +346,7 @@ class receiveDataThread(threading.Thread): # 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.' + logger.debug('Timing attack mitigation: Sleeping for ' + str(sleepTime) + ' seconds.') time.sleep(sleepTime) def recerror(self, data): @@ -359,7 +375,7 @@ class receiveDataThread(threading.Thread): fatalHumanFriendly = 'Fatal' message = '%s message received from %s: %s.' % (fatalHumanFriendly, self.peer, errorText) if inventoryVector: - message += " This concerns object %s" % inventoryVector.encode('hex') + message += " This concerns object %s" % hexlify(inventoryVector) if banTime > 0: message += " Remote node says that the ban time is %s" % banTime logger.error(message) @@ -388,30 +404,25 @@ class receiveDataThread(threading.Thread): if len(shared.numberOfObjectsThatWeHaveYetToGetPerPeer) > 0: for key, value in shared.numberOfObjectsThatWeHaveYetToGetPerPeer.items(): totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers += value - with shared.printLock: - print 'number of keys(hosts) in shared.numberOfObjectsThatWeHaveYetToGetPerPeer:', len(shared.numberOfObjectsThatWeHaveYetToGetPerPeer) - print 'totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers = ', totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers + logger.debug('number of keys(hosts) in shared.numberOfObjectsThatWeHaveYetToGetPerPeer: ' + str(len(shared.numberOfObjectsThatWeHaveYetToGetPerPeer)) + "\n" + \ + 'totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers = ' + str(totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers)) numberOfItemsInInv, lengthOfVarint = decodeVarint(data[:10]) if numberOfItemsInInv > 50000: sys.stderr.write('Too many items in inv message!') return if len(data) < lengthOfVarint + (numberOfItemsInInv * 32): - print 'inv message doesn\'t contain enough data. Ignoring.' + logger.info('inv message doesn\'t contain enough data. Ignoring.') return if numberOfItemsInInv == 1: # we'll just request this data from the person who advertised the object. - if totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers > 200000 and len(self.objectsThatWeHaveYetToGetFromThisPeer) > 1000: # inv flooding attack mitigation - with shared.printLock: - print 'We already have', totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers, 'items yet to retrieve from peers and over 1000 from this node in particular. Ignoring this inv message.' + if totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers > 200000 and len(self.objectsThatWeHaveYetToGetFromThisPeer) > 1000 and shared.trustedPeer == None: # inv flooding attack mitigation + logger.debug('We already have ' + str(totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers) + ' items yet to retrieve from peers and over 1000 from this node in particular. Ignoring this inv message.') return self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware[ data[lengthOfVarint:32 + lengthOfVarint]] = 0 shared.numberOfInventoryLookupsPerformed += 1 if data[lengthOfVarint:32 + lengthOfVarint] in shared.inventory: - with shared.printLock: - print 'Inventory (in memory) has inventory item already.' - elif shared.isInSqlInventory(data[lengthOfVarint:32 + lengthOfVarint]): - print 'Inventory (SQL on disk) has inventory item already.' + logger.debug('Inventory has inventory item already.') else: self.sendgetdata(data[lengthOfVarint:32 + lengthOfVarint]) else: @@ -422,12 +433,11 @@ class receiveDataThread(threading.Thread): advertisedSet = set() for i in range(numberOfItemsInInv): advertisedSet.add(data[lengthOfVarint + (32 * i):32 + lengthOfVarint + (32 * i)]) - objectsNewToMe = advertisedSet - shared.inventorySets[self.streamNumber] + objectsNewToMe = advertisedSet - shared.inventory.hashes_by_stream(self.streamNumber) logger.info('inv message lists %s objects. Of those %s are new to me. It took %s seconds to figure that out.', numberOfItemsInInv, len(objectsNewToMe), time.time()-startTime) for item in objectsNewToMe: - if totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers > 200000 and len(self.objectsThatWeHaveYetToGetFromThisPeer) > 1000: # inv flooding attack mitigation - with shared.printLock: - print 'We already have', totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers, 'items yet to retrieve from peers and over', len(self.objectsThatWeHaveYetToGetFromThisPeer), 'from this node in particular. Ignoring the rest of this inv message.' + if totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers > 200000 and len(self.objectsThatWeHaveYetToGetFromThisPeer) > 1000 and shared.trustedPeer == None: # inv flooding attack mitigation + logger.debug('We already have ' + str(totalNumberOfobjectsThatWeHaveYetToGetFromAllPeers) + ' items yet to retrieve from peers and over ' + str(len(self.objectsThatWeHaveYetToGetFromThisPeer)), ' from this node in particular. Ignoring the rest of this inv message.') break self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware[item] = 0 # helps us keep from sending inv messages to peers that already know about the objects listed therein self.objectsThatWeHaveYetToGetFromThisPeer[item] = 0 # upon finishing dealing with an incoming message, the receiveDataThread will request a random object of from peer out of this data structure. This way if we get multiple inv messages from multiple peers which list mostly the same objects, we will make getdata requests for different random objects from the various peers. @@ -438,8 +448,7 @@ class receiveDataThread(threading.Thread): # Send a getdata message to our peer to request the object with the given # hash def sendgetdata(self, hash): - with shared.printLock: - print 'sending getdata to retrieve object with hash:', hash.encode('hex') + logger.debug('sending getdata to retrieve object with hash: ' + hexlify(hash)) payload = '\x01' + hash self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('getdata', payload))) @@ -449,64 +458,74 @@ class receiveDataThread(threading.Thread): numberOfRequestedInventoryItems, lengthOfVarint = decodeVarint( data[:10]) if len(data) < lengthOfVarint + (32 * numberOfRequestedInventoryItems): - print 'getdata message does not contain enough data. Ignoring.' + logger.debug('getdata message does not contain enough data. Ignoring.') return + self.antiIntersectionDelay(True) # only handle getdata requests if we have been connected long enough for i in xrange(numberOfRequestedInventoryItems): hash = data[lengthOfVarint + ( i * 32):32 + lengthOfVarint + (i * 32)] - with shared.printLock: - print 'received getdata request for item:', hash.encode('hex') + logger.debug('received getdata request for item:' + hexlify(hash)) shared.numberOfInventoryLookupsPerformed += 1 shared.inventoryLock.acquire() - if hash in shared.inventory: - objectType, streamNumber, payload, expiresTime, tag = shared.inventory[hash] + if self.objectHashHolderInstance.hasHash(hash): shared.inventoryLock.release() - self.sendObject(payload) + self.antiIntersectionDelay() else: shared.inventoryLock.release() - queryreturn = sqlQuery( - '''select payload from inventory where hash=? and expirestime>=?''', - hash, - int(time.time())) - if queryreturn != []: - for row in queryreturn: - payload, = row - self.sendObject(payload) + if hash in shared.inventory: + self.sendObject(shared.inventory[hash].payload) else: + self.antiIntersectionDelay() logger.warning('%s asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. We probably cleaned it out after advertising it but before they got around to asking for it.' % (self.peer,)) # Our peer has requested (in a getdata message) that we send an object. def sendObject(self, payload): - with shared.printLock: - print 'sending an object.' + logger.debug('sending an object.') self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('object',payload))) + def _checkIPAddress(self, host): + if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': + hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) + return self._checkIPv4Address(host[12:], hostStandardFormat) + elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43': + # Onion, based on BMD/bitcoind + hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion" + return hostStandardFormat + else: + hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host) + if hostStandardFormat == "": + # This can happen on Windows systems which are not 64-bit compatible + # so let us drop the IPv6 address. + return False + return self._checkIPv6Address(host, hostStandardFormat) def _checkIPv4Address(self, host, hostStandardFormat): - # print 'hostStandardFormat', hostStandardFormat - if host[0] == '\x7F': - print 'Ignoring IP address in loopback range:', hostStandardFormat + if host[0] == '\x7F': # 127/8 + logger.debug('Ignoring IP address in loopback range: ' + hostStandardFormat) return False - if host[0] == '\x0A': - print 'Ignoring IP address in private range:', hostStandardFormat + if host[0] == '\x0A': # 10/8 + logger.debug('Ignoring IP address in private range: ' + hostStandardFormat) return False - if host[0:2] == '\xC0\xA8': - print 'Ignoring IP address in private range:', hostStandardFormat + if host[0:2] == '\xC0\xA8': # 192.168/16 + logger.debug('Ignoring IP address in private range: ' + hostStandardFormat) return False - return True + if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12 + logger.debug('Ignoring IP address in private range:' + hostStandardFormat) + return False + return hostStandardFormat def _checkIPv6Address(self, host, hostStandardFormat): if host == ('\x00' * 15) + '\x01': - print 'Ignoring loopback address:', hostStandardFormat + logger.debug('Ignoring loopback address: ' + hostStandardFormat) return False if host[0] == '\xFE' and (ord(host[1]) & 0xc0) == 0x80: - print 'Ignoring local address:', hostStandardFormat + logger.debug ('Ignoring local address: ' + hostStandardFormat) return False if (ord(host[0]) & 0xfe) == 0xfc: - print 'Ignoring unique local address:', hostStandardFormat + logger.debug ('Ignoring unique local address: ' + hostStandardFormat) return False - return True + return hostStandardFormat # We have received an addr message. def recaddr(self, data): @@ -514,13 +533,12 @@ class receiveDataThread(threading.Thread): data[:10]) if shared.verbose >= 1: - with shared.printLock: - print 'addr message contains', numberOfAddressesIncluded, 'IP addresses.' + logger.debug('addr message contains ' + str(numberOfAddressesIncluded) + ' IP addresses.') if numberOfAddressesIncluded > 1000 or numberOfAddressesIncluded == 0: return if len(data) != lengthOfNumberOfAddresses + (38 * numberOfAddressesIncluded): - print 'addr message does not contain the correct amount of data. Ignoring.' + logger.debug('addr message does not contain the correct amount of data. Ignoring.') return for i in range(0, numberOfAddressesIncluded): @@ -535,19 +553,11 @@ class receiveDataThread(threading.Thread): 38 * i):20 + lengthOfNumberOfAddresses + (38 * i)]) recaddrPort, = unpack('>H', data[36 + lengthOfNumberOfAddresses + ( 38 * i):38 + lengthOfNumberOfAddresses + (38 * i)]) - if fullHost[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': - ipv4Host = fullHost[12:] - hostStandardFormat = socket.inet_ntop(socket.AF_INET, ipv4Host) - if not self._checkIPv4Address(ipv4Host, hostStandardFormat): - continue - else: - hostStandardFormat = socket.inet_ntop(socket.AF_INET6, fullHost) - if hostStandardFormat == "": - # This can happen on Windows systems which are not 64-bit compatible - # so let us drop the IPv6 address. - continue - if not self._checkIPv6Address(fullHost, hostStandardFormat): - continue + hostStandardFormat = self._checkIPAddress(fullHost) + if hostStandardFormat is False: + continue + if recaddrPort == 0: + continue timeSomeoneElseReceivedMessageFromThisNode, = unpack('>Q', data[lengthOfNumberOfAddresses + ( 38 * i):8 + lengthOfNumberOfAddresses + (38 * i)]) # This is the 'time' value in the received addr message. 64-bit. if recaddrStream not in shared.knownNodes: # knownNodes is a dictionary of dictionaries with one outer dictionary for each stream. If the outer stream dictionary doesn't exist yet then we must make it. @@ -558,8 +568,7 @@ class receiveDataThread(threading.Thread): if len(shared.knownNodes[recaddrStream]) < 20000 and timeSomeoneElseReceivedMessageFromThisNode > (int(time.time()) - 10800) and timeSomeoneElseReceivedMessageFromThisNode < (int(time.time()) + 10800): # If we have more than 20000 nodes in our list already then just forget about adding more. Also, make sure that the time that someone else received a message from this node is within three hours from now. with shared.knownNodesLock: shared.knownNodes[recaddrStream][peerFromAddrMessage] = timeSomeoneElseReceivedMessageFromThisNode - with shared.printLock: - print 'added new node', peerFromAddrMessage, 'to knownNodes in stream', recaddrStream + logger.debug('added new node ' + str(peerFromAddrMessage) + ' to knownNodes in stream ' + str(recaddrStream)) shared.needToWriteKnownNodesToDisk = True hostDetails = ( @@ -574,8 +583,7 @@ class receiveDataThread(threading.Thread): with shared.knownNodesLock: shared.knownNodes[recaddrStream][peerFromAddrMessage] = timeSomeoneElseReceivedMessageFromThisNode - with shared.printLock: - print 'knownNodes currently has', len(shared.knownNodes[self.streamNumber]), 'nodes for this stream.' + logger.debug('knownNodes currently has ' + str(len(shared.knownNodes[self.streamNumber])) + ' nodes for this stream.') # Send a huge addr message to our peer. This is only used @@ -671,10 +679,10 @@ class receiveDataThread(threading.Thread): """ return self.remoteProtocolVersion, = unpack('>L', data[:4]) + self.services, = unpack('>q', data[4:12]) if self.remoteProtocolVersion < 3: self.sendDataThreadQueue.put((0, 'shutdown','no data')) - with shared.printLock: - print 'Closing connection to old protocol version', self.remoteProtocolVersion, 'node: ', self.peer + logger.debug ('Closing connection to old protocol version ' + str(self.remoteProtocolVersion) + ' node: ' + str(self.peer)) return timestamp, = unpack('>Q', data[12:20]) timeOffset = timestamp - int(time.time()) @@ -698,19 +706,38 @@ class receiveDataThread(threading.Thread): data[80:84]) readPosition = 80 + lengthOfUseragentVarint useragent = data[readPosition:readPosition + useragentLength] + + # version check + try: + userAgentName, userAgentVersion = useragent[1:-1].split(":", 2) + except: + userAgentName = useragent + userAgentVersion = "0.0.0" + if userAgentName == "PyBitmessage": + myVersion = [int(n) for n in shared.softwareVersion.split(".")] + try: + remoteVersion = [int(n) for n in userAgentVersion.split(".")] + except: + remoteVersion = 0 + # remote is newer, but do not cross between stable and unstable + try: + if cmp(remoteVersion, myVersion) > 0 and \ + (myVersion[1] % 2 == remoteVersion[1] % 2): + shared.UISignalQueue.put(('newVersionAvailable', remoteVersion)) + except: + pass + 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, ' time offset:', timeOffset, 'seconds.' + logger.debug('Remote node useragent: ' + useragent + ' stream number:' + str(self.streamNumber) + ' time offset: ' + str(timeOffset) + ' seconds.') if self.streamNumber != 1: self.sendDataThreadQueue.put((0, 'shutdown','no data')) - with shared.printLock: - print 'Closed connection to', self.peer, 'because they are interested in stream', self.streamNumber, '.' + logger.debug ('Closed connection to ' + str(self.peer) + ' because they are interested in stream ' + str(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. @@ -720,17 +747,17 @@ class receiveDataThread(threading.Thread): self.sendDataThreadQueue.put((0, 'setStreamNumber', self.streamNumber)) if data[72:80] == shared.eightBytesOfRandomDataUsedToDetectConnectionsToSelf: self.sendDataThreadQueue.put((0, 'shutdown','no data')) - with shared.printLock: - print 'Closing connection to myself: ', self.peer + logger.debug('Closing connection to myself: ' + str(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)) - with shared.knownNodesLock: - shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time()) - shared.needToWriteKnownNodesToDisk = True + if not isHostInPrivateIPRange(self.peer.host): + with shared.knownNodesLock: + shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time()) + shared.needToWriteKnownNodesToDisk = True self.sendverack() if self.initiatedConnection == False: @@ -738,16 +765,14 @@ class receiveDataThread(threading.Thread): # Sends a version message def sendversion(self): - with shared.printLock: - print 'Sending version message' + logger.debug('Sending version message') self.sendDataThreadQueue.put((0, 'sendRawData', shared.assembleVersionMessage( - self.peer.host, self.peer.port, self.streamNumber))) + self.peer.host, self.peer.port, self.streamNumber, not self.initiatedConnection))) # Sends a verack message def sendverack(self): - with shared.printLock: - print 'Sending verack' + logger.debug('Sending verack') self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('verack'))) self.verackSent = True if self.verackReceived: diff --git a/src/class_sendDataThread.py b/src/class_sendDataThread.py index bb19c9f6..9c048d32 100644 --- a/src/class_sendDataThread.py +++ b/src/class_sendDataThread.py @@ -11,13 +11,14 @@ import socket from helper_generic import addDataPadding from class_objectHashHolder import * from addresses import * +from debug import logger # Every connection to a peer has a sendDataThread (and also a # receiveDataThread). class sendDataThread(threading.Thread): def __init__(self, sendDataThreadQueue): - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="sendData") self.sendDataThreadQueue = sendDataThreadQueue shared.sendDataQueues.append(self.sendDataThreadQueue) self.data = '' @@ -35,29 +36,33 @@ class sendDataThread(threading.Thread): someObjectsOfWhichThisRemoteNodeIsAlreadyAware): self.sock = sock self.peer = shared.Peer(HOST, PORT) + self.name = "sendData-" + self.peer.host.replace(":", ".") # log parser field separator self.streamNumber = streamNumber + self.services = 0 + self.initiatedConnection = False self.remoteProtocolVersion = - \ 1 # This must be set using setRemoteProtocolVersion command which is sent through the self.sendDataThreadQueue queue. self.lastTimeISentData = int( time.time()) # If this value increases beyond five minutes ago, we'll send a pong message to keep the connection alive. self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware = someObjectsOfWhichThisRemoteNodeIsAlreadyAware - with shared.printLock: - print 'The streamNumber of this sendDataThread (ID:', str(id(self)) + ') at setup() is', self.streamNumber + if self.streamNumber == -1: # This was an incoming connection. + self.initiatedConnection = False + else: + self.initiatedConnection = True + logger.debug('The streamNumber of this sendDataThread (ID: ' + str(id(self)) + ') at setup() is' + str(self.streamNumber)) def sendVersionMessage(self): datatosend = shared.assembleVersionMessage( - self.peer.host, self.peer.port, self.streamNumber) # the IP and port of the remote host, and my streamNumber. + self.peer.host, self.peer.port, self.streamNumber, not self.initiatedConnection) # the IP and port of the remote host, and my streamNumber. - with shared.printLock: - print 'Sending version packet: ', repr(datatosend) + logger.debug('Sending version packet: ' + repr(datatosend)) try: self.sendBytes(datatosend) except Exception as err: # if not 'Bad file descriptor' in err: - with shared.printLock: - sys.stderr.write('sock.sendall error: %s\n' % err) + logger.error('sock.sendall error: %s\n' % err) self.versionSent = 1 @@ -82,7 +87,12 @@ class sendDataThread(threading.Thread): uploadRateLimitBytes = 999999999 # float("inf") doesn't work else: uploadRateLimitBytes = shared.config.getint('bitmessagesettings', 'maxuploadrate') * 1000 - amountSent = self.sock.send(data[:1000]) + if ((self.services & shared.NODE_SSL == shared.NODE_SSL) and + self.connectionIsOrWasFullyEstablished and + shared.haveSSL(not self.initiatedConnection)): + amountSent = self.sslSock.send(data[:1000]) + else: + amountSent = self.sock.send(data[:1000]) shared.numberOfBytesSent += amountSent # used for the 'network status' tab in the UI shared.numberOfBytesSentLastSecond += amountSent self.lastTimeISentData = int(time.time()) @@ -90,15 +100,13 @@ class sendDataThread(threading.Thread): def run(self): - with shared.printLock: - print 'sendDataThread starting. ID:', str(id(self))+'. Number of queues in sendDataQueues:', len(shared.sendDataQueues) + logger.debug('sendDataThread starting. ID: ' + str(id(self)) + '. Number of queues in sendDataQueues: ' + str(len(shared.sendDataQueues))) while True: deststream, command, data = self.sendDataThreadQueue.get() if deststream == self.streamNumber or deststream == 0: if command == 'shutdown': - with shared.printLock: - print 'sendDataThread (associated with', self.peer, ') ID:', id(self), 'shutting down now.' + logger.debug('sendDataThread (associated with ' + str(self.peer) + ') ID: ' + str(id(self)) + ' shutting down now.') break # When you receive an incoming connection, a sendDataThread is # created even though you don't yet know what stream number the @@ -108,12 +116,10 @@ class sendDataThread(threading.Thread): # streamNumber of this send data thread here: elif command == 'setStreamNumber': self.streamNumber = data - with shared.printLock: - print 'setting the stream number in the sendData thread (ID:', id(self), ') to', self.streamNumber + logger.debug('setting the stream number in the sendData thread (ID: ' + str(id(self)) + ') to ' + str(self.streamNumber)) elif command == 'setRemoteProtocolVersion': specifiedRemoteProtocolVersion = data - with shared.printLock: - print 'setting the remote node\'s protocol version in the sendDataThread (ID:', id(self), ') to', specifiedRemoteProtocolVersion + logger.debug('setting the remote node\'s protocol version in the sendDataThread (ID: ' + str(id(self)) + ') to ' + str(specifiedRemoteProtocolVersion)) self.remoteProtocolVersion = specifiedRemoteProtocolVersion elif command == 'advertisepeer': self.objectHashHolderInstance.holdPeer(data) @@ -136,8 +142,7 @@ class sendDataThread(threading.Thread): try: self.sendBytes(packet) except: - with shared.printLock: - print 'sendaddr: self.sock.sendall failed' + logger.error('sendaddr: self.sock.sendall failed') break elif command == 'advertiseobject': self.objectHashHolderInstance.holdHash(data) @@ -153,34 +158,30 @@ class sendDataThread(threading.Thread): try: self.sendBytes(packet) except: - with shared.printLock: - print 'sendinv: self.sock.sendall failed' + logger.error('sendinv: self.sock.sendall failed') 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. if self.lastTimeISentData < (int(time.time()) - 298): # Send out a pong message to keep the connection alive. - with shared.printLock: - print 'Sending pong to', self.peer, 'to keep connection alive.' + logger.debug('Sending pong to ' + str(self.peer) + ' to keep connection alive.') packet = shared.CreatePacket('pong') try: self.sendBytes(packet) except: - with shared.printLock: - print 'send pong failed' + logger.error('send pong failed') break elif command == 'sendRawData': try: self.sendBytes(data) except: - with shared.printLock: - print 'Sending of data to', self.peer, 'failed. sendDataThread thread', self, 'ending now.' + logger.error('Sending of data to ' + str(self.peer) + ' failed. sendDataThread thread ' + str(self) + ' ending now.') break elif command == 'connectionIsOrWasFullyEstablished': self.connectionIsOrWasFullyEstablished = True + self.services, self.sslSock = data else: - with shared.printLock: - print 'sendDataThread ID:', id(self), 'ignoring command', command, 'because the thread is not in stream', deststream + logger.error('sendDataThread ID: ' + str(id(self)) + ' ignoring command ' + command + ' because the thread is not in stream' + str(deststream)) try: self.sock.shutdown(socket.SHUT_RDWR) @@ -188,6 +189,5 @@ class sendDataThread(threading.Thread): except: pass shared.sendDataQueues.remove(self.sendDataThreadQueue) - with shared.printLock: - print 'sendDataThread ending. ID:', str(id(self))+'. Number of queues in sendDataQueues:', len(shared.sendDataQueues) + logger.info('sendDataThread ending. ID: ' + str(id(self)) + '. Number of queues in sendDataQueues: ' + str(len(shared.sendDataQueues))) self.objectHashHolderInstance.close() diff --git a/src/class_singleCleaner.py b/src/class_singleCleaner.py index b441d11c..8fa8e6d1 100644 --- a/src/class_singleCleaner.py +++ b/src/class_singleCleaner.py @@ -7,6 +7,7 @@ import pickle import tr#anslate from helper_sql import * +from helper_threading import * from debug import logger """ @@ -28,10 +29,11 @@ resends msg messages in 5 days (then 10 days, then 20 days, etc...) """ -class singleCleaner(threading.Thread): +class singleCleaner(threading.Thread, StoppableThread): def __init__(self): - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="singleCleaner") + self.initStop() def run(self): timeWeLastClearedInventoryAndPubkeysTables = 0 @@ -41,22 +43,10 @@ class singleCleaner(threading.Thread): # Either the user hasn't set stopresendingafterxdays and stopresendingafterxmonths yet or the options are missing from the config file. shared.maximumLengthOfTimeToBotherResendingMessages = float('inf') - while True: + while shared.shutdown == 0: shared.UISignalQueue.put(( 'updateStatusBar', 'Doing housekeeping (Flushing inventory in memory to disk...)')) - with shared.inventoryLock: # If you use both the inventoryLock and the sqlLock, always use the inventoryLock OUTSIDE of the sqlLock. - with SqlBulkExecute() as sql: - for hash, storedValue in shared.inventory.items(): - objectType, streamNumber, payload, expiresTime, tag = storedValue - sql.execute( - '''INSERT INTO inventory VALUES (?,?,?,?,?,?)''', - hash, - objectType, - streamNumber, - payload, - expiresTime, - tag) - del shared.inventory[hash] + shared.inventory.flush() shared.UISignalQueue.put(('updateStatusBar', '')) shared.broadcastToSendDataQueues(( @@ -68,9 +58,7 @@ class singleCleaner(threading.Thread): shared.UISignalQueue.queue.clear() if timeWeLastClearedInventoryAndPubkeysTables < int(time.time()) - 7380: timeWeLastClearedInventoryAndPubkeysTables = int(time.time()) - sqlExecute( - '''DELETE FROM inventory WHERE expirestime 220: - with shared.printLock: - print 'We are connected to too many people. Not accepting further incoming connections for ten seconds.' + while shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS' and not shared.config.getboolean('bitmessagesettings', 'sockslisten') and shared.shutdown == 0: + self.stop.wait(10) + while len(shared.connectedHostsList) > 220 and shared.shutdown == 0: + logger.info('We are connected to too many people. Not accepting further incoming connections for ten seconds.') - time.sleep(10) + self.stop.wait(10) - while True: + while shared.shutdown == 0: socketObject, sockaddr = sock.accept() (HOST, PORT) = sockaddr[0:2] @@ -104,8 +114,7 @@ class singleListener(threading.Thread): # connection flooding. if HOST in shared.connectedHostsList: socketObject.close() - with shared.printLock: - print 'We are already connected to', HOST + '. Ignoring connection.' + logger.info('We are already connected to ' + str(HOST) + '. Ignoring connection.') else: break @@ -121,9 +130,8 @@ class singleListener(threading.Thread): rd = receiveDataThread() rd.daemon = True # close the main program even if there are threads left rd.setup( - socketObject, HOST, PORT, -1, someObjectsOfWhichThisRemoteNodeIsAlreadyAware, self.selfInitiatedConnections, sendDataThreadQueue) + socketObject, HOST, PORT, -1, someObjectsOfWhichThisRemoteNodeIsAlreadyAware, self.selfInitiatedConnections, sendDataThreadQueue, sd.objectHashHolderInstance) rd.start() - with shared.printLock: - print self, 'connected to', HOST, 'during INCOMING request.' + logger.info('connected to ' + HOST + ' during INCOMING request.') diff --git a/src/class_singleWorker.py b/src/class_singleWorker.py index 327f526a..f5ac16aa 100644 --- a/src/class_singleWorker.py +++ b/src/class_singleWorker.py @@ -15,17 +15,34 @@ from debug import logger from helper_sql import * import helper_inbox from helper_generic import addDataPadding +from helper_threading import * import l10n +from protocol import * +from binascii import hexlify, unhexlify # This thread, of which there is only one, does the heavy lifting: # calculating POWs. +def sizeof_fmt(num, suffix='h/s'): + for unit in ['','k','M','G','T','P','E','Z']: + if abs(num) < 1000.0: + return "%3.1f%s%s" % (num, unit, suffix) + num /= 1024.0 + return "%.1f%s%s" % (num, 'Yi', suffix) -class singleWorker(threading.Thread): +class singleWorker(threading.Thread, StoppableThread): def __init__(self): # QThread.__init__(self, parent) - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="singleWorker") + self.initStop() + + def stopThread(self): + try: + shared.workerQueue.put(("stopThread", "data")) + except: + pass + super(singleWorker, self).stopThread() def run(self): @@ -42,48 +59,67 @@ class singleWorker(threading.Thread): toAddressVersionNumber) + encodeVarint(toStreamNumber) + toRipe).digest()).digest() privEncryptionKey = doubleHashOfAddressData[:32] # Note that this is the first half of the sha512 hash. tag = doubleHashOfAddressData[32:] - shared.neededPubkeys[tag] = (toAddress, highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex'))) # We'll need this for when we receive a pubkey reply: it will be encrypted and we'll need to decrypt it. + shared.neededPubkeys[tag] = (toAddress, highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))) # We'll need this for when we receive a pubkey reply: it will be encrypted and we'll need to decrypt it. # Initialize the shared.ackdataForWhichImWatching data structure queryreturn = sqlQuery( '''SELECT ackdata FROM sent where (status='msgsent' OR status='doingmsgpow')''') for row in queryreturn: ackdata, = row - print 'Watching for ackdata', ackdata.encode('hex') + logger.info('Watching for ackdata ' + hexlify(ackdata)) shared.ackdataForWhichImWatching[ackdata] = 0 - time.sleep( + self.stop.wait( 10) # give some time for the GUI to start before we start on existing POW tasks. - queryreturn = sqlQuery( - '''SELECT DISTINCT toaddress FROM sent WHERE (status='doingpubkeypow' AND folder='sent')''') - for row in queryreturn: - toaddress, = row - self.requestPubKey(toaddress) + if shared.shutdown == 0: + queryreturn = sqlQuery( + '''SELECT DISTINCT toaddress FROM sent WHERE (status='doingpubkeypow' AND folder='sent')''') + for row in queryreturn: + toaddress, = row + logger.debug("c: %s", shared.shutdown) + self.requestPubKey(toaddress) + # just in case there are any pending tasks for msg + # messages that have yet to be sent. + self.sendMsg() + # just in case there are any tasks for Broadcasts + # that have yet to be sent. + self.sendBroadcast() - self.sendMsg() - # just in case there are any pending tasks for msg - # messages that have yet to be sent. - self.sendBroadcast() - # just in case there are any tasks for Broadcasts - # that have yet to be sent. - - while True: + while shared.shutdown == 0: + self.busy = 0 command, data = shared.workerQueue.get() + self.busy = 1 if command == 'sendmessage': - self.sendMsg() + try: + self.sendMsg() + except: + pass elif command == 'sendbroadcast': - self.sendBroadcast() + try: + self.sendBroadcast() + except: + pass elif command == 'doPOWForMyV2Pubkey': - self.doPOWForMyV2Pubkey(data) + try: + self.doPOWForMyV2Pubkey(data) + except: + pass elif command == 'sendOutOrStoreMyV3Pubkey': - self.sendOutOrStoreMyV3Pubkey(data) + try: + self.sendOutOrStoreMyV3Pubkey(data) + except: + pass elif command == 'sendOutOrStoreMyV4Pubkey': - self.sendOutOrStoreMyV4Pubkey(data) + try: + self.sendOutOrStoreMyV4Pubkey(data) + except: + pass + elif command == 'stopThread': + self.busy = 0 + return else: - with shared.printLock: - sys.stderr.write( - 'Probable programming error: The command sent to the workerThread is weird. It is: %s\n' % command) + logger.error('Probable programming error: The command sent to the workerThread is weird. It is: %s\n' % command) shared.workerQueue.task_done() @@ -106,7 +142,7 @@ class singleWorker(threading.Thread): payload += '\x00\x00\x00\x01' # object type: pubkey payload += encodeVarint(addressVersionNumber) # Address version number payload += encodeVarint(streamNumber) - payload += '\x00\x00\x00\x01' # bitfield of features supported by me (see the wiki). + payload += getBitfield(myAddress) # bitfield of features supported by me (see the wiki). try: privSigningKeyBase58 = shared.config.get( @@ -114,39 +150,35 @@ class singleWorker(threading.Thread): privEncryptionKeyBase58 = shared.config.get( myAddress, 'privencryptionkey') except Exception as err: - with shared.printLock: - sys.stderr.write( - 'Error within doPOWForMyV2Pubkey. Could not read the keys from the keys.dat file for a requested address. %s\n' % err) + logger.error('Error within doPOWForMyV2Pubkey. Could not read the keys from the keys.dat file for a requested address. %s\n' % err) return - privSigningKeyHex = shared.decodeWalletImportFormat( - privSigningKeyBase58).encode('hex') - privEncryptionKeyHex = shared.decodeWalletImportFormat( - privEncryptionKeyBase58).encode('hex') - pubSigningKey = highlevelcrypto.privToPub( - privSigningKeyHex).decode('hex') - pubEncryptionKey = highlevelcrypto.privToPub( - privEncryptionKeyHex).decode('hex') + privSigningKeyHex = hexlify(shared.decodeWalletImportFormat( + privSigningKeyBase58)) + privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat( + privEncryptionKeyBase58)) + pubSigningKey = unhexlify(highlevelcrypto.privToPub( + privSigningKeyHex)) + pubEncryptionKey = unhexlify(highlevelcrypto.privToPub( + privEncryptionKeyHex)) payload += pubSigningKey[1:] payload += pubEncryptionKey[1:] # Do the POW for this pubkey message target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16)))) - print '(For pubkey message) Doing proof of work...' + logger.info('(For pubkey message) Doing proof of work...') initialHash = hashlib.sha512(payload).digest() trialValue, nonce = proofofwork.run(target, initialHash) - print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce + logger.info('(For pubkey message) Found proof of work ' + str(trialValue), ' Nonce: ', str(nonce)) payload = pack('>Q', nonce) + payload inventoryHash = calculateInventoryHash(payload) objectType = 1 shared.inventory[inventoryHash] = ( objectType, streamNumber, payload, embeddedTime,'') - shared.inventorySets[streamNumber].add(inventoryHash) - with shared.printLock: - print 'broadcasting inv with hash:', inventoryHash.encode('hex') + logger.info('broadcasting inv with hash: ' + hexlify(inventoryHash)) shared.broadcastToSendDataQueues(( streamNumber, 'advertiseobject', inventoryHash)) @@ -171,8 +203,7 @@ class singleWorker(threading.Thread): #The address has been deleted. return if shared.safeConfigGetBoolean(myAddress, 'chan'): - with shared.printLock: - print 'This is a chan address. Not sending pubkey.' + logger.info('This is a chan address. Not sending pubkey.') return status, addressVersionNumber, streamNumber, hash = decodeAddress( myAddress) @@ -191,7 +222,7 @@ class singleWorker(threading.Thread): payload += '\x00\x00\x00\x01' # object type: pubkey payload += encodeVarint(addressVersionNumber) # Address version number payload += encodeVarint(streamNumber) - payload += '\x00\x00\x00\x01' # bitfield of features supported by me (see the wiki). + payload += getBitfield(myAddress) # bitfield of features supported by me (see the wiki). try: privSigningKeyBase58 = shared.config.get( @@ -199,20 +230,18 @@ class singleWorker(threading.Thread): privEncryptionKeyBase58 = shared.config.get( myAddress, 'privencryptionkey') except Exception as err: - with shared.printLock: - sys.stderr.write( - 'Error within sendOutOrStoreMyV3Pubkey. Could not read the keys from the keys.dat file for a requested address. %s\n' % err) + logger.error('Error within sendOutOrStoreMyV3Pubkey. Could not read the keys from the keys.dat file for a requested address. %s\n' % err) return - privSigningKeyHex = shared.decodeWalletImportFormat( - privSigningKeyBase58).encode('hex') - privEncryptionKeyHex = shared.decodeWalletImportFormat( - privEncryptionKeyBase58).encode('hex') - pubSigningKey = highlevelcrypto.privToPub( - privSigningKeyHex).decode('hex') - pubEncryptionKey = highlevelcrypto.privToPub( - privEncryptionKeyHex).decode('hex') + privSigningKeyHex = hexlify(shared.decodeWalletImportFormat( + privSigningKeyBase58)) + privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat( + privEncryptionKeyBase58)) + pubSigningKey = unhexlify(highlevelcrypto.privToPub( + privSigningKeyHex)) + pubEncryptionKey = unhexlify(highlevelcrypto.privToPub( + privEncryptionKeyHex)) payload += pubSigningKey[1:] payload += pubEncryptionKey[1:] @@ -228,22 +257,18 @@ class singleWorker(threading.Thread): # Do the POW for this pubkey message target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16)))) - with shared.printLock: - print '(For pubkey message) Doing proof of work...' + logger.info('(For pubkey message) Doing proof of work...') initialHash = hashlib.sha512(payload).digest() trialValue, nonce = proofofwork.run(target, initialHash) - with shared.printLock: - print '(For pubkey message) Found proof of work. Nonce:', nonce + logger.info('(For pubkey message) Found proof of work. Nonce: ' + str(nonce)) payload = pack('>Q', nonce) + payload inventoryHash = calculateInventoryHash(payload) objectType = 1 shared.inventory[inventoryHash] = ( objectType, streamNumber, payload, embeddedTime,'') - shared.inventorySets[streamNumber].add(inventoryHash) - with shared.printLock: - print 'broadcasting inv with hash:', inventoryHash.encode('hex') + logger.info('broadcasting inv with hash: ' + hexlify(inventoryHash)) shared.broadcastToSendDataQueues(( streamNumber, 'advertiseobject', inventoryHash)) @@ -264,8 +289,7 @@ class singleWorker(threading.Thread): #The address has been deleted. return if shared.safeConfigGetBoolean(myAddress, 'chan'): - with shared.printLock: - print 'This is a chan address. Not sending pubkey.' + logger.info('This is a chan address. Not sending pubkey.') return status, addressVersionNumber, streamNumber, hash = decodeAddress( myAddress) @@ -276,8 +300,7 @@ class singleWorker(threading.Thread): payload += '\x00\x00\x00\x01' # object type: pubkey payload += encodeVarint(addressVersionNumber) # Address version number payload += encodeVarint(streamNumber) - - dataToEncrypt = '\x00\x00\x00\x01' # bitfield of features supported by me (see the wiki). + dataToEncrypt = getBitfield(myAddress) try: privSigningKeyBase58 = shared.config.get( @@ -285,19 +308,17 @@ class singleWorker(threading.Thread): privEncryptionKeyBase58 = shared.config.get( myAddress, 'privencryptionkey') except Exception as err: - with shared.printLock: - sys.stderr.write( - 'Error within sendOutOrStoreMyV4Pubkey. Could not read the keys from the keys.dat file for a requested address. %s\n' % err) + logger.error('Error within sendOutOrStoreMyV4Pubkey. Could not read the keys from the keys.dat file for a requested address. %s\n' % err) return - privSigningKeyHex = shared.decodeWalletImportFormat( - privSigningKeyBase58).encode('hex') - privEncryptionKeyHex = shared.decodeWalletImportFormat( - privEncryptionKeyBase58).encode('hex') - pubSigningKey = highlevelcrypto.privToPub( - privSigningKeyHex).decode('hex') - pubEncryptionKey = highlevelcrypto.privToPub( - privEncryptionKeyHex).decode('hex') + privSigningKeyHex = hexlify(shared.decodeWalletImportFormat( + privSigningKeyBase58)) + privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat( + privEncryptionKeyBase58)) + pubSigningKey = unhexlify(highlevelcrypto.privToPub( + privSigningKeyHex)) + pubEncryptionKey = unhexlify(highlevelcrypto.privToPub( + privEncryptionKeyHex)) dataToEncrypt += pubSigningKey[1:] dataToEncrypt += pubEncryptionKey[1:] @@ -322,24 +343,22 @@ class singleWorker(threading.Thread): privEncryptionKey = doubleHashOfAddressData[:32] pubEncryptionKey = highlevelcrypto.pointMult(privEncryptionKey) payload += highlevelcrypto.encrypt( - dataToEncrypt, pubEncryptionKey.encode('hex')) + dataToEncrypt, hexlify(pubEncryptionKey)) # Do the POW for this pubkey message target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16)))) - print '(For pubkey message) Doing proof of work...' + logger.info('(For pubkey message) Doing proof of work...') initialHash = hashlib.sha512(payload).digest() trialValue, nonce = proofofwork.run(target, initialHash) - print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce + logger.info('(For pubkey message) Found proof of work ' + str(trialValue) + 'Nonce: ' + str(nonce)) payload = pack('>Q', nonce) + payload inventoryHash = calculateInventoryHash(payload) objectType = 1 shared.inventory[inventoryHash] = ( objectType, streamNumber, payload, embeddedTime, doubleHashOfAddressData[32:]) - shared.inventorySets[streamNumber].add(inventoryHash) - with shared.printLock: - print 'broadcasting inv with hash:', inventoryHash.encode('hex') + logger.info('broadcasting inv with hash: ' + hexlify(inventoryHash)) shared.broadcastToSendDataQueues(( streamNumber, 'advertiseobject', inventoryHash)) @@ -359,9 +378,7 @@ class singleWorker(threading.Thread): status, addressVersionNumber, streamNumber, ripe = decodeAddress( fromaddress) if addressVersionNumber <= 1: - with shared.printLock: - sys.stderr.write( - 'Error: In the singleWorker thread, the sendBroadcast function doesn\'t understand the address version.\n') + logger.error('Error: In the singleWorker thread, the sendBroadcast function doesn\'t understand the address version.\n') return # We need to convert our private keys to public keys in order # to include them. @@ -372,18 +389,18 @@ class singleWorker(threading.Thread): fromaddress, 'privencryptionkey') except: shared.UISignalQueue.put(('updateSentItemStatusByAckdata', ( - ackdata, tr.translateText("MainWindow", "Error! Could not find sender address (your address) in the keys.dat file.")))) + ackdata, tr._translate("MainWindow", "Error! Could not find sender address (your address) in the keys.dat file.")))) continue - privSigningKeyHex = shared.decodeWalletImportFormat( - privSigningKeyBase58).encode('hex') - privEncryptionKeyHex = shared.decodeWalletImportFormat( - privEncryptionKeyBase58).encode('hex') + privSigningKeyHex = hexlify(shared.decodeWalletImportFormat( + privSigningKeyBase58)) + privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat( + privEncryptionKeyBase58)) pubSigningKey = highlevelcrypto.privToPub(privSigningKeyHex).decode( 'hex') # At this time these pubkeys are 65 bytes long because they include the encoding byte which we won't be sending in the broadcast message. - pubEncryptionKey = highlevelcrypto.privToPub( - privEncryptionKeyHex).decode('hex') + pubEncryptionKey = unhexlify(highlevelcrypto.privToPub( + privEncryptionKeyHex)) if TTL > 28 * 24 * 60 * 60: TTL = 28 * 24 * 60 * 60 @@ -410,7 +427,7 @@ class singleWorker(threading.Thread): dataToEncrypt = encodeVarint(addressVersionNumber) dataToEncrypt += encodeVarint(streamNumber) - dataToEncrypt += '\x00\x00\x00\x01' # behavior bitfield + dataToEncrypt += getBitfield(fromaddress) # behavior bitfield dataToEncrypt += pubSigningKey[1:] dataToEncrypt += pubEncryptionKey[1:] if addressVersionNumber >= 3: @@ -439,15 +456,15 @@ class singleWorker(threading.Thread): pubEncryptionKey = highlevelcrypto.pointMult(privEncryptionKey) payload += highlevelcrypto.encrypt( - dataToEncrypt, pubEncryptionKey.encode('hex')) + dataToEncrypt, hexlify(pubEncryptionKey)) target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16)))) - print '(For broadcast message) Doing proof of work...' + logger.info('(For broadcast message) Doing proof of work...') shared.UISignalQueue.put(('updateSentItemStatusByAckdata', ( - ackdata, tr.translateText("MainWindow", "Doing work necessary to send broadcast...")))) + ackdata, tr._translate("MainWindow", "Doing work necessary to send broadcast...")))) initialHash = hashlib.sha512(payload).digest() trialValue, nonce = proofofwork.run(target, initialHash) - print '(For broadcast message) Found proof of work', trialValue, 'Nonce:', nonce + logger.info('(For broadcast message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce)) payload = pack('>Q', nonce) + payload @@ -462,13 +479,11 @@ class singleWorker(threading.Thread): objectType = 3 shared.inventory[inventoryHash] = ( objectType, streamNumber, payload, embeddedTime, tag) - shared.inventorySets[streamNumber].add(inventoryHash) - with shared.printLock: - print 'sending inv (within sendBroadcast function) for object:', inventoryHash.encode('hex') + logger.info('sending inv (within sendBroadcast function) for object: ' + hexlify(inventoryHash)) shared.broadcastToSendDataQueues(( streamNumber, 'advertiseobject', inventoryHash)) - shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Broadcast sent on %1").arg(l10n.formatTimestamp())))) + shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr._translate("MainWindow", "Broadcast sent on %1").arg(l10n.formatTimestamp())))) # Update the status of the message in the 'sent' table to have # a 'broadcastsent' status @@ -540,7 +555,7 @@ class singleWorker(threading.Thread): int(time.time()) + 2.5*24*60*60, toaddress) shared.UISignalQueue.put(('updateSentItemStatusByToAddress', ( - toaddress, tr.translateText("MainWindow",'Encryption key was requested earlier.')))) + toaddress, tr._translate("MainWindow",'Encryption key was requested earlier.')))) continue #on with the next msg on which we can do some work else: # We have not yet sent a request for the pubkey @@ -557,44 +572,27 @@ class singleWorker(threading.Thread): toAddressVersionNumber) + encodeVarint(toStreamNumber) + toRipe).digest()).digest() privEncryptionKey = doubleHashOfToAddressData[:32] # The first half of the sha512 hash. tag = doubleHashOfToAddressData[32:] # The second half of the sha512 hash. - shared.neededPubkeys[tag] = (toaddress, highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex'))) - - queryreturn = sqlQuery( - '''SELECT payload FROM inventory WHERE objecttype=1 and tag=? ''', toTag) - if queryreturn != []: # if there are any pubkeys in our inventory with the correct tag.. - for row in queryreturn: - payload, = row - if shared.decryptAndCheckPubkeyPayload(payload, toaddress) == 'successful': - needToRequestPubkey = False - sqlExecute( - '''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''', - toaddress) - del shared.neededPubkeys[tag] - break - #else: # There was something wrong with this pubkey object even - # though it had the correct tag- almost certainly because - # of malicious behavior or a badly programmed client. If - # there are any other pubkeys in our inventory with the correct - # tag then we'll try to decrypt those. + shared.neededPubkeys[tag] = (toaddress, highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))) - if needToRequestPubkey: # Obviously we had no success looking in the sql inventory. Let's look through the memory inventory. - with shared.inventoryLock: - for hash, storedValue in shared.inventory.items(): - objectType, streamNumber, payload, expiresTime, tag = storedValue - if objectType == 1 and tag == toTag: - if shared.decryptAndCheckPubkeyPayload(payload, toaddress) == 'successful': #if valid, this function also puts it in the pubkeys table. - needToRequestPubkey = False - sqlExecute( - '''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''', - toaddress) - del shared.neededPubkeys[tag] - break + for value in shared.inventory.by_type_and_tag(1, toTag): + if shared.decryptAndCheckPubkeyPayload(value.payload, toaddress) == 'successful': #if valid, this function also puts it in the pubkeys table. + needToRequestPubkey = False + sqlExecute( + '''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''', + toaddress) + del shared.neededPubkeys[tag] + break + #else: # There was something wrong with this pubkey object even + # though it had the correct tag- almost certainly because + # of malicious behavior or a badly programmed client. If + # there are any other pubkeys in our inventory with the correct + # tag then we'll try to decrypt those. if needToRequestPubkey: sqlExecute( '''UPDATE sent SET status='doingpubkeypow' WHERE toaddress=? AND status='msgqueued' ''', toaddress) shared.UISignalQueue.put(('updateSentItemStatusByToAddress', ( - toaddress, tr.translateText("MainWindow",'Sending a request for the recipient\'s encryption key.')))) + toaddress, tr._translate("MainWindow",'Sending a request for the recipient\'s encryption key.')))) self.requestPubKey(toaddress) continue #on with the next msg on which we can do some work @@ -611,9 +609,9 @@ class singleWorker(threading.Thread): if not shared.config.has_section(toaddress): # if we aren't sending this to ourselves or a chan shared.ackdataForWhichImWatching[ackdata] = 0 shared.UISignalQueue.put(('updateSentItemStatusByAckdata', ( - ackdata, tr.translateText("MainWindow", "Looking up the receiver\'s public key")))) - with shared.printLock: - print 'Sending a message. First 150 characters of message:', repr(message[:150]) + ackdata, tr._translate("MainWindow", "Looking up the receiver\'s public key")))) + logger.info('Sending a message.') + logger.debug('First 150 characters of message: ' + repr(message[:150])) # Let us fetch the recipient's public key out of our database. If # the required proof of work difficulty is too hard then we'll @@ -644,7 +642,7 @@ class singleWorker(threading.Thread): if shared.isBitSetWithinBitfield(behaviorBitfield,30): # if receiver is a mobile device who expects that their address RIPE is included unencrypted on the front of the message.. if not shared.safeConfigGetBoolean('bitmessagesettings','willinglysendtomobile'): # if we are Not willing to include the receiver's RIPE hash on the message.. logger.info('The receiver is a mobile user but the sender (you) has not selected that you are willing to send to mobiles. Aborting send.') - shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1').arg(l10n.formatTimestamp())))) + shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr._translate("MainWindow",'Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1').arg(l10n.formatTimestamp())))) # if the human changes their setting and then sends another message or restarts their client, this one will send at that time. continue readPosition += 4 # to bypass the bitfield of behaviors @@ -659,7 +657,7 @@ class singleWorker(threading.Thread): requiredAverageProofOfWorkNonceTrialsPerByte = shared.networkDefaultProofOfWorkNonceTrialsPerByte requiredPayloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes shared.UISignalQueue.put(('updateSentItemStatusByAckdata', ( - ackdata, tr.translateText("MainWindow", "Doing work necessary to send message.\nThere is no required difficulty for version 2 addresses like this.")))) + ackdata, tr._translate("MainWindow", "Doing work necessary to send message.\nThere is no required difficulty for version 2 addresses like this.")))) elif toAddressVersionNumber >= 3: requiredAverageProofOfWorkNonceTrialsPerByte, varintLength = decodeVarint( pubkeyPayload[readPosition:readPosition + 10]) @@ -672,7 +670,7 @@ class singleWorker(threading.Thread): if requiredPayloadLengthExtraBytes < shared.networkDefaultPayloadLengthExtraBytes: requiredPayloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes logger.debug('Using averageProofOfWorkNonceTrialsPerByte: %s and payloadLengthExtraBytes: %s.' % (requiredAverageProofOfWorkNonceTrialsPerByte, requiredPayloadLengthExtraBytes)) - shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Doing work necessary to send message.\nReceiver\'s required difficulty: %1 and %2").arg(str(float( + shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr._translate("MainWindow", "Doing work necessary to send message.\nReceiver\'s required difficulty: %1 and %2").arg(str(float( requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte)).arg(str(float(requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes))))) if status != 'forcepow': if (requiredAverageProofOfWorkNonceTrialsPerByte > shared.config.getint('bitmessagesettings', 'maxacceptablenoncetrialsperbyte') and shared.config.getint('bitmessagesettings', 'maxacceptablenoncetrialsperbyte') != 0) or (requiredPayloadLengthExtraBytes > shared.config.getint('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes') and shared.config.getint('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes') != 0): @@ -681,36 +679,34 @@ class singleWorker(threading.Thread): sqlExecute( '''UPDATE sent SET status='toodifficult' WHERE ackdata=? ''', ackdata) - shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3").arg(str(float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte)).arg(str(float( + shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr._translate("MainWindow", "Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3").arg(str(float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte)).arg(str(float( requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes)).arg(l10n.formatTimestamp())))) continue else: # if we are sending a message to ourselves or a chan.. - with shared.printLock: - print 'Sending a message. First 150 characters of message:', repr(message[:150]) - behaviorBitfield = '\x00\x00\x00\x01' + logger.info('Sending a message.') + logger.debug('First 150 characters of message: ' + repr(message[:150])) + behaviorBitfield = getBitfield(fromaddress) try: privEncryptionKeyBase58 = shared.config.get( toaddress, 'privencryptionkey') except Exception as err: - shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1').arg(l10n.formatTimestamp())))) - with shared.printLock: - sys.stderr.write( - 'Error within sendMsg. Could not read the keys from the keys.dat file for our own address. %s\n' % err) + shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr._translate("MainWindow",'Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1').arg(l10n.formatTimestamp())))) + logger.error('Error within sendMsg. Could not read the keys from the keys.dat file for our own address. %s\n' % err) continue - privEncryptionKeyHex = shared.decodeWalletImportFormat( - privEncryptionKeyBase58).encode('hex') - pubEncryptionKeyBase256 = highlevelcrypto.privToPub( - privEncryptionKeyHex).decode('hex')[1:] + privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat( + privEncryptionKeyBase58)) + pubEncryptionKeyBase256 = unhexlify(highlevelcrypto.privToPub( + privEncryptionKeyHex))[1:] requiredAverageProofOfWorkNonceTrialsPerByte = shared.networkDefaultProofOfWorkNonceTrialsPerByte requiredPayloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes shared.UISignalQueue.put(('updateSentItemStatusByAckdata', ( - ackdata, tr.translateText("MainWindow", "Doing work necessary to send message.")))) + ackdata, tr._translate("MainWindow", "Doing work necessary to send message.")))) # Now we can start to assemble our message. payload = encodeVarint(fromAddressVersionNumber) payload += encodeVarint(fromStreamNumber) - payload += '\x00\x00\x00\x01' # Bitfield of features and behaviors that can be expected from me. (See https://bitmessage.org/wiki/Protocol_specification#Pubkey_bitfield_features ) + payload += getBitfield(fromaddress) # Bitfield of features and behaviors that can be expected from me. (See https://bitmessage.org/wiki/Protocol_specification#Pubkey_bitfield_features ) # We need to convert our private keys to public keys in order # to include them. @@ -721,18 +717,18 @@ class singleWorker(threading.Thread): fromaddress, 'privencryptionkey') except: shared.UISignalQueue.put(('updateSentItemStatusByAckdata', ( - ackdata, tr.translateText("MainWindow", "Error! Could not find sender address (your address) in the keys.dat file.")))) + ackdata, tr._translate("MainWindow", "Error! Could not find sender address (your address) in the keys.dat file.")))) continue - privSigningKeyHex = shared.decodeWalletImportFormat( - privSigningKeyBase58).encode('hex') - privEncryptionKeyHex = shared.decodeWalletImportFormat( - privEncryptionKeyBase58).encode('hex') + privSigningKeyHex = hexlify(shared.decodeWalletImportFormat( + privSigningKeyBase58)) + privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat( + privEncryptionKeyBase58)) - pubSigningKey = highlevelcrypto.privToPub( - privSigningKeyHex).decode('hex') - pubEncryptionKey = highlevelcrypto.privToPub( - privEncryptionKeyHex).decode('hex') + pubSigningKey = unhexlify(highlevelcrypto.privToPub( + privSigningKeyHex)) + pubEncryptionKey = unhexlify(highlevelcrypto.privToPub( + privEncryptionKeyHex)) payload += pubSigningKey[ 1:] # The \x04 on the beginning of the public keys are not sent. This way there is only one acceptable way to encode and send a public key. @@ -761,12 +757,10 @@ class singleWorker(threading.Thread): payload += encodeVarint(len(messageToTransmit)) payload += messageToTransmit if shared.config.has_section(toaddress): - with shared.printLock: - print 'Not bothering to include ackdata because we are sending to ourselves or a chan.' + logger.info('Not bothering to include ackdata because we are sending to ourselves or a chan.') fullAckPayload = '' - elif not shared.isBitSetWithinBitfield(behaviorBitfield,31): - with shared.printLock: - print 'Not bothering to include ackdata because the receiver said that they won\'t relay it anyway.' + elif not checkBitfield(behaviorBitfield, shared.BITFIELD_DOESACK): + logger.info('Not bothering to include ackdata because the receiver said that they won\'t relay it anyway.') fullAckPayload = '' else: fullAckPayload = self.generateFullAckMessage( @@ -780,10 +774,10 @@ class singleWorker(threading.Thread): # We have assembled the data that will be encrypted. try: - encrypted = highlevelcrypto.encrypt(payload,"04"+pubEncryptionKeyBase256.encode('hex')) + encrypted = highlevelcrypto.encrypt(payload,"04"+hexlify(pubEncryptionKeyBase256)) except: sqlExecute('''UPDATE sent SET status='badkey' WHERE ackdata=?''', ackdata) - shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1').arg(l10n.formatTimestamp())))) + shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr._translate("MainWindow",'Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1').arg(l10n.formatTimestamp())))) continue encryptedPayload = pack('>Q', embeddedTime) @@ -791,18 +785,16 @@ class singleWorker(threading.Thread): encryptedPayload += encodeVarint(1) # msg version encryptedPayload += encodeVarint(toStreamNumber) + encrypted target = 2 ** 64 / (requiredAverageProofOfWorkNonceTrialsPerByte*(len(encryptedPayload) + 8 + requiredPayloadLengthExtraBytes + ((TTL*(len(encryptedPayload)+8+requiredPayloadLengthExtraBytes))/(2 ** 16)))) - with shared.printLock: - print '(For msg message) Doing proof of work. Total required difficulty:', float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte, 'Required small message difficulty:', float(requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes + logger.info('(For msg message) Doing proof of work. Total required difficulty: %f. Required small message difficulty: %f.', float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte, float(requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes) powStartTime = time.time() initialHash = hashlib.sha512(encryptedPayload).digest() trialValue, nonce = proofofwork.run(target, initialHash) - with shared.printLock: - print '(For msg message) Found proof of work', trialValue, 'Nonce:', nonce - try: - print 'POW took', int(time.time() - powStartTime), 'seconds.', nonce / (time.time() - powStartTime), 'nonce trials per second.' - except: - pass + logger.info('(For msg message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce)) + try: + logger.info('PoW took %.1f seconds, speed %s.', time.time() - powStartTime, sizeof_fmt(nonce / (time.time() - powStartTime))) + except: + pass encryptedPayload = pack('>Q', nonce) + encryptedPayload @@ -817,18 +809,17 @@ class singleWorker(threading.Thread): objectType = 2 shared.inventory[inventoryHash] = ( objectType, toStreamNumber, encryptedPayload, embeddedTime, '') - shared.inventorySets[toStreamNumber].add(inventoryHash) - if shared.config.has_section(toaddress): - shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Sent on %1").arg(l10n.formatTimestamp())))) + if shared.config.has_section(toaddress) or not checkBitfield(behaviorBitfield, shared.BITFIELD_DOESACK): + shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr._translate("MainWindow", "Message sent. Sent at %1").arg(l10n.formatTimestamp())))) else: # not sending to a chan or one of my addresses - shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Waiting for acknowledgement. Sent on %1").arg(l10n.formatTimestamp())))) - print 'Broadcasting inv for my msg(within sendmsg function):', inventoryHash.encode('hex') + shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr._translate("MainWindow", "Message sent. Waiting for acknowledgement. Sent on %1").arg(l10n.formatTimestamp())))) + logger.info('Broadcasting inv for my msg(within sendmsg function):' + hexlify(inventoryHash)) shared.broadcastToSendDataQueues(( toStreamNumber, 'advertiseobject', inventoryHash)) # Update the sent message in the sent table with the necessary information. - if shared.config.has_section(toaddress): + if shared.config.has_section(toaddress) or not checkBitfield(behaviorBitfield, shared.BITFIELD_DOESACK): newStatus = 'msgsentnoackexpected' else: newStatus = 'msgsent' @@ -871,8 +862,7 @@ class singleWorker(threading.Thread): toStatus, addressVersionNumber, streamNumber, ripe = decodeAddress( toAddress) if toStatus != 'success': - with shared.printLock: - sys.stderr.write('Very abnormal error occurred in requestPubKey. toAddress is: ' + repr( + logger.error('Very abnormal error occurred in requestPubKey. toAddress is: ' + repr( toAddress) + '. Please report this error to Atheros.') return @@ -893,7 +883,7 @@ class singleWorker(threading.Thread): privEncryptionKey = hashlib.sha512(hashlib.sha512(encodeVarint(addressVersionNumber)+encodeVarint(streamNumber)+ripe).digest()).digest()[:32] # Note that this is the first half of the sha512 hash. tag = hashlib.sha512(hashlib.sha512(encodeVarint(addressVersionNumber)+encodeVarint(streamNumber)+ripe).digest()).digest()[32:] # Note that this is the second half of the sha512 hash. if tag not in shared.neededPubkeys: - shared.neededPubkeys[tag] = (toAddress, highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex'))) # We'll need this for when we receive a pubkey reply: it will be encrypted and we'll need to decrypt it. + shared.neededPubkeys[tag] = (toAddress, highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))) # We'll need this for when we receive a pubkey reply: it will be encrypted and we'll need to decrypt it. if retryNumber == 0: TTL = 2.5*24*60*60 # 2.5 days. This was chosen fairly arbitrarily. @@ -907,32 +897,28 @@ class singleWorker(threading.Thread): payload += encodeVarint(streamNumber) if addressVersionNumber <= 3: payload += ripe - with shared.printLock: - print 'making request for pubkey with ripe:', ripe.encode('hex') + logger.info('making request for pubkey with ripe: %s', hexlify(ripe)) else: payload += tag - with shared.printLock: - print 'making request for v4 pubkey with tag:', tag.encode('hex') + logger.info('making request for v4 pubkey with tag: %s', hexlify(tag)) # print 'trial value', trialValue statusbar = 'Doing the computations necessary to request the recipient\'s public key.' shared.UISignalQueue.put(('updateStatusBar', statusbar)) shared.UISignalQueue.put(('updateSentItemStatusByToAddress', ( - toAddress, tr.translateText("MainWindow",'Doing work necessary to request encryption key.')))) + toAddress, tr._translate("MainWindow",'Doing work necessary to request encryption key.')))) target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16)))) initialHash = hashlib.sha512(payload).digest() trialValue, nonce = proofofwork.run(target, initialHash) - with shared.printLock: - print 'Found proof of work', trialValue, 'Nonce:', nonce + logger.info('Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce)) payload = pack('>Q', nonce) + payload inventoryHash = calculateInventoryHash(payload) objectType = 1 shared.inventory[inventoryHash] = ( objectType, streamNumber, payload, embeddedTime, '') - shared.inventorySets[streamNumber].add(inventoryHash) - print 'sending inv (for the getpubkey message)' + logger.info('sending inv (for the getpubkey message)') shared.broadcastToSendDataQueues(( streamNumber, 'advertiseobject', inventoryHash)) @@ -948,8 +934,8 @@ class singleWorker(threading.Thread): toAddress) shared.UISignalQueue.put(( - 'updateStatusBar', tr.translateText("MainWindow",'Broacasting the public key request. This program will auto-retry if they are offline.'))) - shared.UISignalQueue.put(('updateSentItemStatusByToAddress', (toAddress, tr.translateText("MainWindow",'Sending public key request. Waiting for reply. Requested at %1').arg(l10n.formatTimestamp())))) + 'updateStatusBar', tr._translate("MainWindow",'Broadcasting the public key request. This program will auto-retry if they are offline.'))) + shared.UISignalQueue.put(('updateSentItemStatusByToAddress', (toAddress, tr._translate("MainWindow",'Sending public key request. Waiting for reply. Requested at %1').arg(l10n.formatTimestamp())))) def generateFullAckMessage(self, ackdata, toStreamNumber, TTL): @@ -976,18 +962,16 @@ class singleWorker(threading.Thread): payload += encodeVarint(toStreamNumber) + ackdata target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16)))) - with shared.printLock: - print '(For ack message) Doing proof of work. TTL set to', TTL + logger.info('(For ack message) Doing proof of work. TTL set to ' + str(TTL)) powStartTime = time.time() initialHash = hashlib.sha512(payload).digest() trialValue, nonce = proofofwork.run(target, initialHash) - with shared.printLock: - print '(For ack message) Found proof of work', trialValue, 'Nonce:', nonce - try: - print 'POW took', int(time.time() - powStartTime), 'seconds.', nonce / (time.time() - powStartTime), 'nonce trials per second.' - except: - pass + logger.info('(For ack message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce)) + try: + logger.info('PoW took %.1f seconds, speed %s.', time.time() - powStartTime, sizeof_fmt(nonce / (time.time() - powStartTime))) + except: + pass payload = pack('>Q', nonce) + payload return shared.CreatePacket('object', payload) diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index 514f772e..4147c0d2 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -19,12 +19,14 @@ import tr#anslate class sqlThread(threading.Thread): def __init__(self): - threading.Thread.__init__(self) + threading.Thread.__init__(self, name="SQL") def run(self): self.conn = sqlite3.connect(shared.appdata + 'messages.dat') self.conn.text_factory = str self.cur = self.conn.cursor() + + self.cur.execute('PRAGMA secure_delete = true') try: self.cur.execute( @@ -324,7 +326,13 @@ class sqlThread(threading.Thread): shared.config.set('bitmessagesettings', 'maxdownloadrate', '0') shared.config.set('bitmessagesettings', 'maxuploadrate', '0') shared.config.set('bitmessagesettings', 'settingsversion', '10') - shared.writeKeysFile() + shared.writeKeysFile() + + # sanity check + if shared.config.getint('bitmessagesettings', 'maxacceptablenoncetrialsperbyte') == 0: + shared.config.set('bitmessagesettings','maxacceptablenoncetrialsperbyte', str(shared.ridiculousDifficulty * shared.networkDefaultProofOfWorkNonceTrialsPerByte)) + if shared.config.getint('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes') == 0: + shared.config.set('bitmessagesettings','maxacceptablepayloadlengthextrabytes', str(shared.ridiculousDifficulty * shared.networkDefaultPayloadLengthExtraBytes)) # The format of data stored in the pubkeys table has changed. Let's # clear it, and the pubkeys from inventory, so that they'll be re-downloaded. @@ -434,7 +442,7 @@ class sqlThread(threading.Thread): except Exception as err: if str(err) == 'database or disk is full': logger.fatal('(While null value test) Alert: Your disk or data storage volume is full. sqlThread will now exit.') - shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + shared.UISignalQueue.put(('alert', (tr._translate("MainWindow", "Disk full"), tr._translate("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) if shared.daemon: os._exit(0) else: @@ -450,14 +458,14 @@ class sqlThread(threading.Thread): queryreturn = self.cur.fetchall() for row in queryreturn: value, = row - if int(value) < int(time.time()) - 2592000: + if int(value) < int(time.time()) - 86400: logger.info('It has been a long time since the messages.dat file has been vacuumed. Vacuuming now...') try: self.cur.execute( ''' VACUUM ''') except Exception as err: if str(err) == 'database or disk is full': logger.fatal('(While VACUUM) Alert: Your disk or data storage volume is full. sqlThread will now exit.') - shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + shared.UISignalQueue.put(('alert', (tr._translate("MainWindow", "Disk full"), tr._translate("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) if shared.daemon: os._exit(0) else: @@ -474,7 +482,7 @@ class sqlThread(threading.Thread): except Exception as err: if str(err) == 'database or disk is full': logger.fatal('(While committing) Alert: Your disk or data storage volume is full. sqlThread will now exit.') - shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + shared.UISignalQueue.put(('alert', (tr._translate("MainWindow", "Disk full"), tr._translate("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) if shared.daemon: os._exit(0) else: @@ -492,15 +500,15 @@ class sqlThread(threading.Thread): except Exception as err: if str(err) == 'database or disk is full': logger.fatal('(while movemessagstoprog) Alert: Your disk or data storage volume is full. sqlThread will now exit.') - shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + shared.UISignalQueue.put(('alert', (tr._translate("MainWindow", "Disk full"), tr._translate("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) if shared.daemon: os._exit(0) else: return self.conn.close() shutil.move( - shared.lookupAppdataFolder() + 'messages.dat', 'messages.dat') - self.conn = sqlite3.connect('messages.dat') + shared.lookupAppdataFolder() + 'messages.dat', shared.lookupExeFolder() + 'messages.dat') + self.conn = sqlite3.connect(shared.lookupExeFolder() + 'messages.dat') self.conn.text_factory = str self.cur = self.conn.cursor() elif item == 'movemessagstoappdata': @@ -511,15 +519,15 @@ class sqlThread(threading.Thread): except Exception as err: if str(err) == 'database or disk is full': logger.fatal('(while movemessagstoappdata) Alert: Your disk or data storage volume is full. sqlThread will now exit.') - shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + shared.UISignalQueue.put(('alert', (tr._translate("MainWindow", "Disk full"), tr._translate("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) if shared.daemon: os._exit(0) else: return self.conn.close() shutil.move( - 'messages.dat', shared.lookupAppdataFolder() + 'messages.dat') - self.conn = sqlite3.connect(shared.appdata + 'messages.dat') + shared.lookupExeFolder() + 'messages.dat', shared.lookupAppdataFolder() + 'messages.dat') + self.conn = sqlite3.connect(shared.lookupAppdataFolder() + 'messages.dat') self.conn.text_factory = str self.cur = self.conn.cursor() elif item == 'deleteandvacuume': @@ -531,21 +539,23 @@ class sqlThread(threading.Thread): except Exception as err: if str(err) == 'database or disk is full': logger.fatal('(while deleteandvacuume) Alert: Your disk or data storage volume is full. sqlThread will now exit.') - shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + shared.UISignalQueue.put(('alert', (tr._translate("MainWindow", "Disk full"), tr._translate("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) if shared.daemon: os._exit(0) else: return else: parameters = shared.sqlSubmitQueue.get() + rowcount = 0 # print 'item', item # print 'parameters', parameters try: self.cur.execute(item, parameters) + rowcount = self.cur.rowcount except Exception as err: if str(err) == 'database or disk is full': logger.fatal('(while cur.execute) Alert: Your disk or data storage volume is full. sqlThread will now exit.') - shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + shared.UISignalQueue.put(('alert', (tr._translate("MainWindow", "Disk full"), tr._translate("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) if shared.daemon: os._exit(0) else: @@ -556,5 +566,5 @@ class sqlThread(threading.Thread): os._exit(0) - shared.sqlReturnQueue.put(self.cur.fetchall()) + shared.sqlReturnQueue.put((self.cur.fetchall(), rowcount)) # shared.sqlSubmitQueue.task_done() diff --git a/src/debug.py b/src/debug.py index 30c64ea4..707d7062 100644 --- a/src/debug.py +++ b/src/debug.py @@ -18,15 +18,36 @@ Use: `from debug import logger` to import this facility into whatever module you ''' import logging import logging.config +import os import shared import sys +import traceback import helper_startup helper_startup.loadConfig() -# TODO(xj9): Get from a config file. -log_level = 'DEBUG' +# Now can be overriden from a config file, which uses standard python logging.config.fileConfig interface +# examples are here: https://bitmessage.org/forum/index.php/topic,4820.msg11163.html#msg11163 +log_level = 'WARNING' + +def log_uncaught_exceptions(ex_cls, ex, tb): + logging.critical(''.join(traceback.format_tb(tb))) + logging.critical('{0}: {1}'.format(ex_cls, ex)) def configureLogging(): + have_logging = False + try: + logging.config.fileConfig(os.path.join (shared.appdata, 'logging.dat')) + have_logging = True + print "Loaded debug config from %s" % (os.path.join(shared.appdata, 'logging.dat')) + except: + print "Failed to load debug config from %s, using default logging config" % (os.path.join(shared.appdata, 'logging.dat')) + print sys.exc_info() + + sys.excepthook = log_uncaught_exceptions + + if have_logging: + return False + logging.config.dictConfig({ 'version': 1, 'formatters': { @@ -69,13 +90,17 @@ def configureLogging(): 'handlers': ['console'], }, }) + return True + # TODO (xj9): Get from a config file. #logger = logging.getLogger('console_only') -configureLogging() -if '-c' in sys.argv: - logger = logging.getLogger('file_only') +if configureLogging(): + if '-c' in sys.argv: + logger = logging.getLogger('file_only') + else: + logger = logging.getLogger('both') else: - logger = logging.getLogger('both') + logger = logging.getLogger('default') def restartLoggingInUpdatedAppdataLocation(): global logger @@ -83,9 +108,11 @@ def restartLoggingInUpdatedAppdataLocation(): logger.removeHandler(i) i.flush() i.close() - configureLogging() - if '-c' in sys.argv: - logger = logging.getLogger('file_only') + if configureLogging(): + if '-c' in sys.argv: + logger = logging.getLogger('file_only') + else: + logger = logging.getLogger('both') else: - logger = logging.getLogger('both') + logger = logging.getLogger('default') diff --git a/src/depends.py b/src/depends.py index 553a5031..294c6a22 100755 --- a/src/depends.py +++ b/src/depends.py @@ -87,7 +87,7 @@ def check_openssl(): paths = ['libeay32.dll'] if getattr(sys, 'frozen', False): import os.path - paths.append(os.path.join(sys._MEIPASS, 'libeay32.dll')) + paths.insert(0, os.path.join(sys._MEIPASS, 'libeay32.dll')) else: paths = ['libcrypto.so'] if sys.platform == 'darwin': diff --git a/src/helper_bootstrap.py b/src/helper_bootstrap.py index edeeb984..fbb1a81b 100644 --- a/src/helper_bootstrap.py +++ b/src/helper_bootstrap.py @@ -4,6 +4,9 @@ import defaultKnownNodes import pickle import time +from debug import logger +import socks + def knownNodes(): try: # We shouldn't have to use the shared.knownNodesLock because this had @@ -26,7 +29,7 @@ def knownNodes(): except: shared.knownNodes = defaultKnownNodes.createDefaultKnownNodes(shared.appdata) if shared.config.getint('bitmessagesettings', 'settingsversion') > 10: - print 'Bitmessage cannot read future versions of the keys file (keys.dat). Run the newer version of Bitmessage.' + logger.error('Bitmessage cannot read future versions of the keys file (keys.dat). Run the newer version of Bitmessage.') raise SystemExit def dns(): @@ -35,20 +38,53 @@ def dns(): # defaultKnownNodes.py. Hopefully either they are up to date or the user # has run Bitmessage recently without SOCKS turned on and received good # bootstrap nodes using that method. - with shared.printLock: - if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none': + if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none': + try: + for item in socket.getaddrinfo('bootstrap8080.bitmessage.org', 80): + logger.info('Adding ' + item[4][0] + ' to knownNodes based on DNS bootstrap method') + shared.knownNodes[1][shared.Peer(item[4][0], 8080)] = int(time.time()) + except: + logger.error('bootstrap8080.bitmessage.org DNS bootstrapping failed.') + try: + for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80): + logger.info ('Adding ' + item[4][0] + ' to knownNodes based on DNS bootstrap method') + shared.knownNodes[1][shared.Peer(item[4][0], 8444)] = int(time.time()) + except: + logger.error('bootstrap8444.bitmessage.org DNS bootstrapping failed.') + elif shared.config.get('bitmessagesettings', 'socksproxytype') == 'SOCKS5': + shared.knownNodes[1][shared.Peer('quzwelsuziwqgpt2.onion', 8444)] = int(time.time()) + logger.debug("Adding quzwelsuziwqgpt2.onion:8444 to knownNodes.") + for port in [8080, 8444]: + logger.debug("Resolving %i through SOCKS...", port) + address_family = socket.AF_INET + sock = socks.socksocket(address_family, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.settimeout(20) + proxytype = socks.PROXY_TYPE_SOCKS5 + sockshostname = shared.config.get( + 'bitmessagesettings', 'sockshostname') + socksport = shared.config.getint( + 'bitmessagesettings', 'socksport') + rdns = True # Do domain name lookups through the proxy; though this setting doesn't really matter since we won't be doing any domain name lookups anyway. + if shared.config.getboolean('bitmessagesettings', 'socksauthentication'): + socksusername = shared.config.get( + 'bitmessagesettings', 'socksusername') + sockspassword = shared.config.get( + 'bitmessagesettings', 'sockspassword') + sock.setproxy( + proxytype, sockshostname, socksport, rdns, socksusername, sockspassword) + else: + sock.setproxy( + proxytype, sockshostname, socksport, rdns) try: - for item in socket.getaddrinfo('bootstrap8080.bitmessage.org', 80): - print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method' - shared.knownNodes[1][shared.Peer(item[4][0], 8080)] = int(time.time()) + ip = sock.resolve("bootstrap" + str(port) + ".bitmessage.org") + sock.shutdown(socket.SHUT_RDWR) + sock.close() except: - print 'bootstrap8080.bitmessage.org DNS bootstrapping failed.' - try: - for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80): - print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method' - shared.knownNodes[1][shared.Peer(item[4][0], 8444)] = int(time.time()) - except: - print 'bootstrap8444.bitmessage.org DNS bootstrapping failed.' - else: - print 'DNS bootstrap skipped because SOCKS is used.' + logger.error("SOCKS DNS resolving failed", exc_info=True) + if ip is not None: + logger.info ('Adding ' + ip + ' to knownNodes based on SOCKS DNS bootstrap method') + shared.knownNodes[1][shared.Peer(ip, port)] = time.time() + else: + logger.info('DNS bootstrap skipped because the proxy type does not support DNS resolution.') diff --git a/src/helper_generic.py b/src/helper_generic.py index f3380b26..b8a38863 100644 --- a/src/helper_generic.py +++ b/src/helper_generic.py @@ -1,18 +1,21 @@ -import shared +import socket import sys +from binascii import hexlify, unhexlify + +import shared def convertIntToString(n): a = __builtins__.hex(n) if a[-1:] == 'L': a = a[:-1] if (len(a) % 2) == 0: - return a[2:].decode('hex') + return unhexlify(a[2:]) else: - return ('0' + a[2:]).decode('hex') + return unhexlify('0' + a[2:]) def convertStringToInt(s): - return int(s.encode('hex'), 16) + return int(hexlify(s), 16) def signal_handler(signal, frame): @@ -23,14 +26,24 @@ def signal_handler(signal, frame): print 'Unfortunately you cannot use Ctrl+C when running the UI because the UI captures the signal.' def isHostInPrivateIPRange(host): - if host[:3] == '10.': - return True - if host[:4] == '172.': - if host[6] == '.': - if int(host[4:6]) >= 16 and int(host[4:6]) <= 31: - return True - if host[:8] == '192.168.': - return True + if ":" in host: #IPv6 + hostAddr = socket.inet_pton(socket.AF_INET6, host) + if hostAddr == ('\x00' * 15) + '\x01': + return False + if hostAddr[0] == '\xFE' and (ord(hostAddr[1]) & 0xc0) == 0x80: + return False + if (ord(hostAddr[0]) & 0xfe) == 0xfc: + return False + pass + else: + if host[:3] == '10.': + return True + if host[:4] == '172.': + if host[6] == '.': + if int(host[4:6]) >= 16 and int(host[4:6]) <= 31: + return True + if host[:8] == '192.168.': + return True return False def addDataPadding(data, desiredMsgLength = 12, paddingChar = '\x00'): diff --git a/src/helper_inbox.py b/src/helper_inbox.py index 09c7edbc..a3ad9755 100644 --- a/src/helper_inbox.py +++ b/src/helper_inbox.py @@ -3,7 +3,8 @@ import shared def insert(t): sqlExecute('''INSERT INTO inbox VALUES (?,?,?,?,?,?,?,?,?,?)''', *t) - shared.UISignalQueue.put(('changedInboxUnread', None)) + #shouldn't emit changedInboxUnread and displayNewInboxMessage at the same time + #shared.UISignalQueue.put(('changedInboxUnread', None)) def trash(msgid): sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', msgid) diff --git a/src/helper_search.py b/src/helper_search.py new file mode 100644 index 00000000..2217974f --- /dev/null +++ b/src/helper_search.py @@ -0,0 +1,85 @@ +#!/usr/bin/python2.7 + +from helper_sql import * + +try: + from PyQt4 import QtCore, QtGui + haveQt = True +except: + haveQt = False + +def search_translate (context, text): + if haveQt: + return QtGui.QApplication.translate(context, text) + else: + return text.lower() + +def search_sql(xAddress = "toaddress", account = None, folder = "inbox", where = None, what = None, unreadOnly = False): + if what is not None and what != "": + what = "%" + what + "%" + if where == search_translate("MainWindow", "To"): + where = "toaddress" + elif where == search_translate("MainWindow", "From"): + where = "fromaddress" + elif where == search_translate("MainWindow", "Subject"): + where = "subject" + elif where == search_translate("MainWindow", "Message"): + where = "message" + else: + where = "toaddress || fromaddress || subject || message" + else: + what = None + + if folder == "sent": + sqlStatementBase = ''' + SELECT toaddress, fromaddress, subject, status, ackdata, lastactiontime + FROM sent ''' + else: + sqlStatementBase = '''SELECT folder, msgid, toaddress, fromaddress, subject, received, read + FROM inbox ''' + + sqlStatementParts = [] + sqlArguments = [] + if account is not None: + if xAddress == 'both': + sqlStatementParts.append("(fromaddress = ? OR toaddress = ?)") + sqlArguments.append(account) + sqlArguments.append(account) + else: + sqlStatementParts.append(xAddress + " = ? ") + sqlArguments.append(account) + if folder is not None: + if folder == "new": + folder = "inbox" + unreadOnly = True + sqlStatementParts.append("folder = ? ") + sqlArguments.append(folder) + else: + sqlStatementParts.append("folder != ?") + sqlArguments.append("trash") + if what is not None: + sqlStatementParts.append("%s LIKE ?" % (where)) + sqlArguments.append(what) + if unreadOnly: + sqlStatementParts.append("read = 0") + if len(sqlStatementParts) > 0: + sqlStatementBase += "WHERE " + " AND ".join(sqlStatementParts) + if folder == "sent": + sqlStatementBase += " ORDER BY lastactiontime" + return sqlQuery(sqlStatementBase, sqlArguments) + +def check_match(toAddress, fromAddress, subject, message, where = None, what = None): + if what is not None and what != "": + if where in (search_translate("MainWindow", "To"), search_translate("MainWindow", "All")): + if what.lower() not in toAddress.lower(): + return False + elif where in (search_translate("MainWindow", "From"), search_translate("MainWindow", "All")): + if what.lower() not in fromAddress.lower(): + return False + elif where in (search_translate("MainWindow", "Subject"), search_translate("MainWindow", "All")): + if what.lower() not in subject.lower(): + return False + elif where in (search_translate("MainWindow", "Message"), search_translate("MainWindow", "All")): + if what.lower() not in message.lower(): + return False + return True diff --git a/src/helper_sql.py b/src/helper_sql.py index 0353f9ae..d27401cf 100644 --- a/src/helper_sql.py +++ b/src/helper_sql.py @@ -11,10 +11,12 @@ def sqlQuery(sqlStatement, *args): if args == (): sqlSubmitQueue.put('') + elif type(args[0]) in [list, tuple]: + sqlSubmitQueue.put(args[0]) else: sqlSubmitQueue.put(args) - queryreturn = sqlReturnQueue.get() + queryreturn, rowcount = sqlReturnQueue.get() sqlLock.release() return queryreturn @@ -28,9 +30,10 @@ def sqlExecute(sqlStatement, *args): else: sqlSubmitQueue.put(args) - sqlReturnQueue.get() + queryreturn, rowcount = sqlReturnQueue.get() sqlSubmitQueue.put('commit') sqlLock.release() + return rowcount def sqlStoredProcedure(procName): sqlLock.acquire() diff --git a/src/helper_startup.py b/src/helper_startup.py index 778fe70a..a194a574 100644 --- a/src/helper_startup.py +++ b/src/helper_startup.py @@ -35,12 +35,12 @@ def loadConfig(): needToCreateKeysFile = True else: - shared.config.read('keys.dat') + shared.config.read(shared.lookupExeFolder() + 'keys.dat') try: shared.config.get('bitmessagesettings', 'settingsversion') print 'Loading config files from same directory as program.' needToCreateKeysFile = False - shared.appdata = '' + shared.appdata = shared.lookupExeFolder() except: # Could not load the keys.dat file in the program directory. Perhaps it # is in the appdata directory. @@ -145,5 +145,5 @@ def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections(): return StrictVersion("5.1.2600")<=VER_THIS and StrictVersion("6.0.6000")>=VER_THIS return False except Exception as err: - print "Info: we could not tell whether your OS is limited to having very view half open connections because we couldn't interpret the platform version. Don't worry; we'll assume that it is not limited. This tends to occur on Raspberry Pis. :", err + print "Info: we could not tell whether your OS is limited to having very few half open connections because we couldn't interpret the platform version. Don't worry; we'll assume that it is not limited. This tends to occur on Raspberry Pis. :", err return False diff --git a/src/helper_threading.py b/src/helper_threading.py new file mode 100644 index 00000000..599d297d --- /dev/null +++ b/src/helper_threading.py @@ -0,0 +1,10 @@ +import threading + +class StoppableThread(object): + def initStop(self): + self.stop = threading.Event() + self._stopped = False + + def stopThread(self): + self._stopped = True + self.stop.set() \ No newline at end of file diff --git a/src/highlevelcrypto.py b/src/highlevelcrypto.py index 5a2ae920..c8b67e77 100644 --- a/src/highlevelcrypto.py +++ b/src/highlevelcrypto.py @@ -1,3 +1,4 @@ +from binascii import hexlify import pyelliptic from pyelliptic import arithmetic as a, OpenSSL def makeCryptor(privkey): @@ -18,7 +19,7 @@ def makePubCryptor(pubkey): def privToPub(privkey): private_key = a.changebase(privkey, 16, 256, minlen=32) public_key = pointMult(private_key) - return public_key.encode('hex') + return hexlify(public_key) # Encrypts message with hex public key def encrypt(msg,hexPubkey): return pyelliptic.ECC(curve='secp256k1').encrypt(msg,hexToPubkey(hexPubkey)) diff --git a/src/l10n.py b/src/l10n.py index f9c9b456..a32abb84 100644 --- a/src/l10n.py +++ b/src/l10n.py @@ -16,6 +16,29 @@ DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S' encoding = DEFAULT_ENCODING language = DEFAULT_LANGUAGE +windowsLanguageMap = { + "ar": "arabic", + "cs": "czech", + "da": "danish", + "de": "german", + "en": "english", + "eo": "esperanto", + "fr": "french", + "it": "italian", + "ja": "japanese", + "nl": "dutch", + "no": "norwegian", + "pl": "polish", + "pt": "portuguese", + "ru": "russian", + "sk": "slovak", + "zh": "chinese", + "zh_CN": "chinese-simplified", + "zh_HK": "chinese-traditional", + "zh_SG": "chinese-simplified", + "zh_TW": "chinese-traditional" +} + try: import locale encoding = locale.getpreferredencoding(True) or DEFAULT_ENCODING @@ -91,3 +114,17 @@ def getTranslationLanguage(): return userlocale +def getWindowsLocale(posixLocale): + if posixLocale in windowsLanguageMap: + return windowsLanguageMap[posixLocale] + if "." in posixLocale: + loc = posixLocale.split(".", 1) + if loc[0] in windowsLanguageMap: + return windowsLanguageMap[loc[0]] + if "_" in posixLocale: + loc = posixLocale.split("_", 1) + if loc[0] in windowsLanguageMap: + return windowsLanguageMap[loc[0]] + if posixLocale != DEFAULT_LANGUAGE: + return getWindowsLocale(DEFAULT_LANGUAGE) + return None diff --git a/src/message_data_reader.py b/src/message_data_reader.py index 250e06a9..a99be336 100644 --- a/src/message_data_reader.py +++ b/src/message_data_reader.py @@ -7,6 +7,7 @@ from time import strftime, localtime import sys import shared import string +from binascii import hexlify appdata = shared.lookupAppdataFolder() @@ -31,7 +32,7 @@ def readSent(): output = cur.fetchall() for row in output: msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, sleeptill, status, retrynumber, folder, encodingtype, ttl = row - print msgid.encode('hex'), toaddress, 'toripe:', toripe.encode('hex'), 'fromaddress:', fromaddress, 'ENCODING TYPE:', encodingtype, 'SUBJECT:', repr(subject), 'MESSAGE:', repr(message), 'ACKDATA:', ackdata.encode('hex'), lastactiontime, status, retrynumber, folder + print hexlify(msgid), toaddress, 'toripe:', hexlify(toripe), 'fromaddress:', fromaddress, 'ENCODING TYPE:', encodingtype, 'SUBJECT:', repr(subject), 'MESSAGE:', repr(message), 'ACKDATA:', hexlify(ackdata), lastactiontime, status, retrynumber, folder def readSubscriptions(): print 'Printing everything in subscriptions table:' @@ -50,7 +51,7 @@ def readPubkeys(): output = cur.fetchall() for row in output: address, transmitdata, time, usedpersonally = row - print 'Address:', address, '\tTime first broadcast:', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(time)),'utf-8'), '\tUsed by me personally:', usedpersonally, '\tFull pubkey message:', transmitdata.encode('hex') + print 'Address:', address, '\tTime first broadcast:', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(time)),'utf-8'), '\tUsed by me personally:', usedpersonally, '\tFull pubkey message:', hexlify(transmitdata) def readInventory(): print 'Printing everything in inventory table:' @@ -60,7 +61,7 @@ def readInventory(): output = cur.fetchall() for row in output: hash, objecttype, streamnumber, payload, expirestime = row - print 'Hash:', hash.encode('hex'), objecttype, streamnumber, '\t', payload.encode('hex'), '\t', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(expirestime)),'utf-8') + print 'Hash:', hexlify(hash), objecttype, streamnumber, '\t', hexlify(payload), '\t', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(expirestime)),'utf-8') def takeInboxMessagesOutOfTrash(): diff --git a/src/namecoin.py b/src/namecoin.py index 03cd3080..8e1a0b13 100644 --- a/src/namecoin.py +++ b/src/namecoin.py @@ -90,21 +90,21 @@ class namecoinConnection (object): assert False except RPCError as exc: if exc.error["code"] == -4: - return (tr.translateText("MainWindow",'The name %1 was not found.').arg(unicode(string)), None) + return (tr._translate("MainWindow",'The name %1 was not found.').arg(unicode(string)), None) else: - return (tr.translateText("MainWindow",'The namecoin query failed (%1)').arg(unicode(exc.error["message"])), None) + return (tr._translate("MainWindow",'The namecoin query failed (%1)').arg(unicode(exc.error["message"])), None) except Exception as exc: print "Namecoin query exception: %s" % str (exc) - return (tr.translateText("MainWindow",'The namecoin query failed.'), None) + return (tr._translate("MainWindow",'The namecoin query failed.'), None) try: val = json.loads (res) except: - return (tr.translateText("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: return (None, val["bitmessage"]) - return (tr.translateText("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 @@ -124,16 +124,16 @@ class namecoinConnection (object): versStr = "0.%d.%d" % (v1, v2) else: versStr = "0.%d.%d.%d" % (v1, v2, v3) - return ('success', tr.translateText("MainWindow",'Success! Namecoind version %1 running.').arg(unicode(versStr)) ) + return ('success', tr._translate("MainWindow",'Success! Namecoind version %1 running.').arg(unicode(versStr)) ) elif self.nmctype == "nmcontrol": res = self.callRPC ("data", ["status"]) prefix = "Plugin data running" if ("reply" in res) and res["reply"][:len(prefix)] == prefix: - return ('success', tr.translateText("MainWindow",'Success! NMControll is up and running.')) + return ('success', tr._translate("MainWindow",'Success! NMControll is up and running.')) print "Unexpected nmcontrol reply: %s" % res - return ('failed', tr.translateText("MainWindow",'Couldn\'t understand NMControl.')) + return ('failed', tr._translate("MainWindow",'Couldn\'t understand NMControl.')) else: assert False diff --git a/src/openclpow.py b/src/openclpow.py new file mode 100644 index 00000000..b643ca57 --- /dev/null +++ b/src/openclpow.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python2.7 +from struct import pack, unpack +import time +import hashlib +import random +import os + +from shared import codePath, safeConfigGetBoolean, shutdown +from debug import logger + +libAvailable = True +ctx = False +queue = False +program = False +gpus = [] +hash_dt = None + +try: + import numpy + import pyopencl as cl +except: + libAvailable = False + +def initCL(): + global ctx, queue, program, gpus, hash_dt + try: + hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)]) + for platform in cl.get_platforms(): + gpus.extend(platform.get_devices(device_type=cl.device_type.GPU)) + if (len(gpus) > 0): + ctx = cl.Context(devices=gpus) + queue = cl.CommandQueue(ctx) + f = open(os.path.join(codePath(), "bitmsghash", 'bitmsghash.cl'), 'r') + fstr = ''.join(f.readlines()) + program = cl.Program(ctx, fstr).build(options="") + logger.info("Loaded OpenCL kernel") + else: + logger.info("No OpenCL GPUs found") + ctx = False + except Exception as e: + logger.error("OpenCL fail: ", exc_info=True) + ctx = False + +def has_opencl(): + global ctx + return (ctx != False) + +def do_opencl_pow(hash, target): + global ctx, queue, program, gpus, hash_dt + + output = numpy.zeros(1, dtype=[('v', numpy.uint64, 1)]) + if (ctx == False): + return output[0][0] + + data = numpy.zeros(1, dtype=hash_dt, order='C') + data[0]['v'] = ("0000000000000000" + hash).decode("hex") + data[0]['target'] = target + + hash_buf = cl.Buffer(ctx, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=data) + dest_buf = cl.Buffer(ctx, cl.mem_flags.WRITE_ONLY, output.nbytes) + + kernel = program.kernel_sha512 + worksize = kernel.get_work_group_info(cl.kernel_work_group_info.WORK_GROUP_SIZE, gpus[0]) + + kernel.set_arg(0, hash_buf) + kernel.set_arg(1, dest_buf) + + start = time.time() + progress = 0 + globamt = worksize*2000 + + while output[0][0] == 0 and shutdown == 0: + kernel.set_arg(2, pack("Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + print "{} - value {} < {}".format(nonce, trialValue, target) + diff --git a/src/proofofwork.py b/src/proofofwork.py index 4392bc7e..9d53b39e 100644 --- a/src/proofofwork.py +++ b/src/proofofwork.py @@ -4,9 +4,12 @@ import hashlib from struct import unpack, pack import sys -from shared import config, frozen -import shared -#import os +from debug import logger +from shared import config, frozen, codePath, shutdown, safeConfigGetBoolean, UISignalQueue +import openclpow +import tr +import os +import ctypes def _set_idle(): if 'linux' in sys.platform: @@ -26,20 +29,25 @@ def _set_idle(): def _pool_worker(nonce, initialHash, target, pool_size): _set_idle() trialValue = float('inf') - while trialValue > target: + while trialValue > target and shutdown == 0: nonce += pool_size trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) return [trialValue, nonce] def _doSafePoW(target, initialHash): + logger.debug("Safe PoW start") nonce = 0 trialValue = float('inf') - while trialValue > target: + while trialValue > target and shutdown == 0: nonce += 1 trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + if shutdown != 0: + raise Exception("Interrupted") + logger.debug("Safe PoW done") return [trialValue, nonce] def _doFastPoW(target, initialHash): + logger.debug("Fast PoW start") import time from multiprocessing import Pool, cpu_count try: @@ -57,22 +65,151 @@ def _doFastPoW(target, initialHash): for i in range(pool_size): result.append(pool.apply_async(_pool_worker, args = (i, initialHash, target, pool_size))) while True: - if shared.shutdown >= 1: + if shutdown >= 1: pool.terminate() - while True: - time.sleep(10) # Don't let this thread return here; it will return nothing and cause an exception in bitmessagemain.py - return + raise Exception("Interrupted") for i in range(pool_size): if result[i].ready(): result = result[i].get() pool.terminate() pool.join() #Wait for the workers to exit... + logger.debug("Fast PoW done") return result[0], result[1] time.sleep(0.2) + +def _doCPoW(target, initialHash): + h = initialHash + m = target + out_h = ctypes.pointer(ctypes.create_string_buffer(h, 64)) + out_m = ctypes.c_ulonglong(m) + logger.debug("C PoW start") + nonce = bmpow(out_h, out_m) + trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + if shutdown != 0: + raise Exception("Interrupted") + logger.debug("C PoW done") + return [trialValue, nonce] + +def _doGPUPoW(target, initialHash): + logger.debug("GPU PoW start") + nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target) + trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) + #print "{} - value {} < {}".format(nonce, trialValue, target) + if trialValue > target: + deviceNames = ", ".join(gpu.name for gpu in openclpow.gpus) + UISignalQueue.put(('updateStatusBar', tr._translate("MainWindow",'Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers.'))) + logger.error("Your GPUs (%s) did not calculate correctly, disabling OpenCL. Please report to the developers.", deviceNames) + openclpow.ctx = False + raise Exception("GPU did not calculate correctly.") + if shutdown != 0: + raise Exception("Interrupted") + logger.debug("GPU PoW done") + return [trialValue, nonce] + +def estimate(difficulty, format = False): + ret = difficulty / 10 + if ret < 1: + ret = 1 + if format: + out = str(int(ret)) + " seconds" + if ret > 60: + ret /= 60 + out = str(int(ret)) + " minutes" + if ret > 60: + ret /= 60 + out = str(int(ret)) + " hours" + if ret > 24: + ret /= 24 + out = str(int(ret)) + " days" + if ret > 7: + out = str(int(ret)) + " weeks" + if ret > 31: + out = str(int(ret)) + " months" + if ret > 366: + ret /= 366 + out = str(int(ret)) + " years" + else: + return ret def run(target, initialHash): target = int(target) + if safeConfigGetBoolean('bitmessagesettings', 'opencl') and openclpow.has_opencl(): +# trialvalue1, nonce1 = _doGPUPoW(target, initialHash) +# trialvalue, nonce = _doFastPoW(target, initialHash) +# print "GPU: %s, %s" % (trialvalue1, nonce1) +# print "Fast: %s, %s" % (trialvalue, nonce) +# return [trialvalue, nonce] + try: + return _doGPUPoW(target, initialHash) + except: + if shutdown != 0: + raise + pass # fallback + if bmpow: + try: + return _doCPoW(target, initialHash) + except: + if shutdown != 0: + raise + pass # fallback if frozen == "macosx_app" or not frozen: - return _doFastPoW(target, initialHash) - else: + # on my (Peter Surda) Windows 10, Windows Defender + # does not like this and fights with PyBitmessage + # over CPU, resulting in very slow PoW + # added on 2015-11-29: multiprocesing.freeze_support() doesn't help + try: + return _doFastPoW(target, initialHash) + except: + if shutdown != 0: + raise + pass #fallback + try: return _doSafePoW(target, initialHash) + except: + if shutdown != 0: + raise + pass #fallback + +# init +bitmsglib = 'bitmsghash.so' +if "win32" == sys.platform: + if ctypes.sizeof(ctypes.c_voidp) == 4: + bitmsglib = 'bitmsghash32.dll' + else: + bitmsglib = 'bitmsghash64.dll' + try: + # MSVS + bso = ctypes.WinDLL(os.path.join(codePath(), "bitmsghash", bitmsglib)) + logger.info("Loaded C PoW DLL (stdcall) %s", bitmsglib) + bmpow = bso.BitmessagePOW + bmpow.restype = ctypes.c_ulonglong + _doCPoW(2**63, "") + logger.info("Successfully tested C PoW DLL (stdcall) %s", bitmsglib) + except: + logger.error("C PoW test fail.", exc_info=True) + try: + # MinGW + bso = ctypes.CDLL(os.path.join(codePath(), "bitmsghash", bitmsglib)) + logger.info("Loaded C PoW DLL (cdecl) %s", bitmsglib) + bmpow = bso.BitmessagePOW + bmpow.restype = ctypes.c_ulonglong + _doCPoW(2**63, "") + logger.info("Successfully tested C PoW DLL (cdecl) %s", bitmsglib) + except: + logger.error("C PoW test fail.", exc_info=True) + bso = None +else: + try: + bso = ctypes.CDLL(os.path.join(codePath(), "bitmsghash", bitmsglib)) + logger.info("Loaded C PoW DLL %s", bitmsglib) + except: + bso = None +if bso: + try: + bmpow = bso.BitmessagePOW + bmpow.restype = ctypes.c_ulonglong + except: + bmpow = None +else: + bmpow = None + diff --git a/src/protocol.py b/src/protocol.py new file mode 100644 index 00000000..40feaaf4 --- /dev/null +++ b/src/protocol.py @@ -0,0 +1,14 @@ +import struct +import shared + +def getBitfield(address): + # bitfield of features supported by me (see the wiki). + bitfield = 0 + # send ack + if not shared.safeConfigGetBoolean(address, 'dontsendack'): + bitfield |= shared.BITFIELD_DOESACK + return struct.pack('>I', bitfield) + +def checkBitfield(bitfieldBinary, flags): + bitfield, = struct.unpack('>I', bitfieldBinary) + return (bitfield & flags) == flags \ No newline at end of file diff --git a/src/pyelliptic/openssl.py b/src/pyelliptic/openssl.py index c6b72b65..be2f2afc 100644 --- a/src/pyelliptic/openssl.py +++ b/src/pyelliptic/openssl.py @@ -427,35 +427,44 @@ class _OpenSSL: buffer = self.create_string_buffer(size) return buffer -try: - OpenSSL = _OpenSSL('libcrypto.so') -except: - try: - OpenSSL = _OpenSSL('libeay32.dll') - except: +def loadOpenSSL(): + global OpenSSL + from os import path, environ + from ctypes.util import find_library + + libdir = [] + if getattr(sys,'frozen', None): + if 'darwin' in sys.platform: + libdir.extend([ + path.join(environ['RESOURCEPATH'], '..', 'Frameworks','libcrypto.dylib'), + path.join(environ['RESOURCEPATH'], '..', 'Frameworks','libcrypto.1.0.0.dylib') + ]) + elif 'win32' in sys.platform or 'win64' in sys.platform: + libdir.append(path.join(sys._MEIPASS, 'libeay32.dll')) + else: + libdir.extend([ + path.join(sys._MEIPASS, 'libcrypto.so'), + path.join(sys._MEIPASS, 'libssl.so'), + path.join(sys._MEIPASS, 'libcrypto.so.1.0.0'), + path.join(sys._MEIPASS, 'libssl.so.1.0.0'), + ]) + if 'darwin' in sys.platform: + libdir.extend(['libcrypto.dylib', '/usr/local/opt/openssl/lib/libcrypto.dylib']) + elif 'win32' in sys.platform or 'win64' in sys.platform: + libdir.append('libeay32.dll') + else: + libdir.append('libcrypto.so') + libdir.append('libssl.so') + if 'linux' in sys.platform or 'darwin' in sys.platform or 'freebsd' in sys.platform: + libdir.append(find_library('ssl')) + elif 'win32' in sys.platform or 'win64' in sys.platform: + libdir.append(find_library('libeay32')) + for library in libdir: try: - OpenSSL = _OpenSSL('libcrypto.dylib') + OpenSSL = _OpenSSL(library) + return except: - try: - # try homebrew installation - OpenSSL = _OpenSSL('/usr/local/opt/openssl/lib/libcrypto.dylib') - except: - try: - # Load it from an Bitmessage.app on OSX - OpenSSL = _OpenSSL('./../Frameworks/libcrypto.dylib') - except: - try: - from os import path - lib_path = path.join(sys._MEIPASS, "libeay32.dll") - OpenSSL = _OpenSSL(lib_path) - except: - if 'linux' in sys.platform or 'darwin' in sys.platform or 'freebsd' in sys.platform: - try: - from ctypes.util import find_library - OpenSSL = _OpenSSL(find_library('ssl')) - except Exception, err: - sys.stderr.write('(On Linux) Couldn\'t find and load the OpenSSL library. You must install it. If you believe that you already have it installed, this exception information might be of use:\n') - from ctypes.util import find_library - OpenSSL = _OpenSSL(find_library('ssl')) - else: - raise Exception("Couldn't find and load the OpenSSL library. You must install it.") + pass + raise Exception("Couldn't find and load the OpenSSL library. You must install it.") + +loadOpenSSL() \ No newline at end of file diff --git a/src/shared.py b/src/shared.py index d82f00a5..9388ebdd 100644 --- a/src/shared.py +++ b/src/shared.py @@ -1,6 +1,6 @@ -from __future__ import division +from __future__ import division -softwareVersion = '0.4.4' +softwareVersion = '0.6.0' verbose = 1 maximumAgeOfAnObjectThatIAmWillingToAccept = 216000 # This is obsolete with the change to protocol v3 but the singleCleaner thread still hasn't been updated so we need this a little longer. lengthOfTimeToHoldOnToAllPubkeys = 2419200 # Equals 4 weeks. You could make this longer if you want but making it shorter would not be advisable because there is a very small possibility that it could keep you from obtaining a needed pubkey for a period of time. @@ -9,6 +9,7 @@ useVeryEasyProofOfWorkForTesting = False # If you set this to True while on the # Libraries. +import base64 import collections import ConfigParser import os @@ -25,13 +26,16 @@ import datetime from os import path, environ from struct import Struct import traceback +from binascii import hexlify # Project imports. from addresses import * +from class_objectProcessorQueue import ObjectProcessorQueue import highlevelcrypto import shared #import helper_startup from helper_sql import * +from helper_threading import * config = ConfigParser.SafeConfigParser() @@ -46,15 +50,13 @@ addressGeneratorQueue = Queue.Queue() knownNodesLock = threading.Lock() knownNodes = {} sendDataQueues = [] #each sendData thread puts its queue in this list. -inventory = {} #of objects (like msg payloads and pubkey payloads) Does not include protocol headers (the first 24 bytes of each packet). -inventoryLock = threading.Lock() #Guarantees that two receiveDataThreads don't receive and process the same message concurrently (probably sent by a malicious individual) +inventoryLock = threading.RLock() #Guarantees that two receiveDataThreads don't receive and process the same message concurrently (probably sent by a malicious individual) printLock = threading.Lock() -objectProcessorQueueSizeLock = threading.Lock() -objectProcessorQueueSize = 0 # in Bytes. We maintain this to prevent nodes from flooing us with objects which take up too much memory. If this gets too big we'll sleep before asking for further objects. appdata = '' #holds the location of the application data storage directory statusIconColor = 'red' connectedHostsList = {} #List of hosts to which we are connected. Used to guarantee that the outgoingSynSender threads won't connect to the same remote node twice. shutdown = 0 #Set to 1 by the doCleanShutdown function. Used to tell the proof of work worker threads to exit. +thisapp = None # singleton lock instance alreadyAttemptedConnectionsList = { } # This is a list of nodes to which we have already attempted a connection alreadyAttemptedConnectionsListLock = threading.Lock() @@ -83,13 +85,15 @@ lastTimeWeResetBytesSent = 0 # used for the bandwidth rate limit sendDataLock = threading.Lock() # used for the bandwidth rate limit receiveDataLock = threading.Lock() # used for the bandwidth rate limit daemon = False -inventorySets = {} # key = streamNumer, value = a set which holds the inventory object hashes that we are aware of. This is used whenever we receive an inv message from a peer to check to see what items are new to us. We don't delete things out of it; instead, the singleCleaner thread clears and refills it every couple hours. needToWriteKnownNodesToDisk = False # If True, the singleCleaner will write it to disk eventually. maximumLengthOfTimeToBotherResendingMessages = 0 -objectProcessorQueue = Queue.Queue( - ) # receiveDataThreads dump objects they hear on the network into this queue to be processed. +objectProcessorQueue = ObjectProcessorQueue() # receiveDataThreads dump objects they hear on the network into this queue to be processed. streamsInWhichIAmParticipating = {} +# sanity check, prevent doing ridiculous PoW +# 20 million PoWs equals approximately 2 days on dev's dual R9 290 +ridiculousDifficulty = 20000000 + #If changed, these values will cause particularly unexpected behavior: You won't be able to either send or receive messages because the proof of work you do (or demand) won't match that done or demanded by others. Don't change them! networkDefaultProofOfWorkNonceTrialsPerByte = 1000 #The amount of work that should be performed (and demanded) per byte of the payload. networkDefaultPayloadLengthExtraBytes = 1000 #To make sending short messages a little more difficult, this value is added to the payload length for use in calculating the proof of work target. @@ -116,10 +120,102 @@ frozen = getattr(sys,'frozen', None) # security. trustedPeer = None +# For UPnP +extPort = None + #Compiled struct for packing/unpacking headers #New code should use CreatePacket instead of Header.pack Header = Struct('!L12sL4s') +#Service flags +NODE_NETWORK = 1 +NODE_SSL = 2 + +#Bitfield flags +BITFIELD_DOESACK = 1 + +import collections + +InventoryItem = collections.namedtuple('InventoryItem', 'type stream payload expires tag') + + +class Inventory(collections.MutableMapping): + def __init__(self): + super(Inventory, self).__init__() + self._inventory = {} #of objects (like msg payloads and pubkey payloads) Does not include protocol headers (the first 24 bytes of each packet). + self._streams = collections.defaultdict(set) # key = streamNumer, value = a set which holds the inventory object hashes that we are aware of. This is used whenever we receive an inv message from a peer to check to see what items are new to us. We don't delete things out of it; instead, the singleCleaner thread clears and refills it every couple hours. + + def __contains__(self, hash): + global numberOfInventoryLookupsPerformed + with inventoryLock: + numberOfInventoryLookupsPerformed += 1 + if hash in self._inventory: + return True + return bool(sqlQuery('SELECT 1 FROM inventory WHERE hash=?', hash)) + + def __getitem__(self, hash): + with inventoryLock: + if hash in self._inventory: + return self._inventory[hash] + rows = sqlQuery('SELECT objecttype, streamnumber, payload, expirestime, tag FROM inventory WHERE hash=?', hash) + if not rows: + raise KeyError(hash) + return InventoryItem(*rows[0]) + + def __setitem__(self, hash, value): + with inventoryLock: + value = InventoryItem(*value) + self._inventory[hash] = value + self._streams[value.stream].add(hash) + + def __delitem__(self, hash): + raise NotImplementedError + + def __iter__(self): + with inventoryLock: + hashes = self._inventory.keys()[:] + hashes += (hash for hash, in sqlQuery('SELECT hash FROM inventory')) + return hashes.__iter__() + + def __len__(self): + with inventoryLock: + return len(self._inventory) + sqlQuery('SELECT count(*) FROM inventory')[0][0] + + def by_type_and_tag(self, type, tag): + with inventoryLock: + values = [value for value in self._inventory.values() if value.type == type and value.tag == tag] + values += (InventoryItem(*value) for value in sqlQuery('SELECT objecttype, streamnumber, payload, expirestime, tag FROM inventory WHERE objecttype=? AND tag=?', type, tag)) + return values + + def hashes_by_stream(self, stream): + with inventoryLock: + return self._streams[stream] + + def unexpired_hashes_by_stream(self, stream): + with inventoryLock: + t = int(time.time()) + hashes = [hash for hash, value in self._inventory.items() if value.stream == stream and value.expires > t] + hashes += (payload for payload, in sqlQuery('SELECT hash FROM inventory WHERE streamnumber=? AND expirestime>?', stream, t)) + return hashes + + def flush(self): + with inventoryLock: # If you use both the inventoryLock and the sqlLock, always use the inventoryLock OUTSIDE of the sqlLock. + with SqlBulkExecute() as sql: + for hash, value in self._inventory.items(): + sql.execute('INSERT INTO inventory VALUES (?, ?, ?, ?, ?, ?)', hash, *value) + self._inventory.clear() + + def clean(self): + with inventoryLock: + sqlExecute('DELETE FROM inventory WHERE expirestime -1: + return '\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode(host.split(".")[0], True) + elif host.find(':') == -1: return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ socket.inet_aton(host) else: return socket.inet_pton(socket.AF_INET6, host) -def assembleVersionMessage(remoteHost, remotePort, myStreamNumber): +def haveSSL(server = False): + # python < 2.7.9's ssl library does not support ECDSA server due to missing initialisation of available curves, but client works ok + if server == False: + return True + elif sys.version_info >= (2,7,9): + return True + return False + +def assembleVersionMessage(remoteHost, remotePort, myStreamNumber, server = False): payload = '' payload += pack('>L', 3) # protocol version. - payload += pack('>q', 1) # bitflags of the services I offer. + payload += pack('>q', NODE_NETWORK|(NODE_SSL if haveSSL(server) else 0)) # bitflags of the services I offer. payload += pack('>q', int(time.time())) payload += pack( @@ -155,8 +258,10 @@ def assembleVersionMessage(remoteHost, remotePort, myStreamNumber): payload += pack('>q', 1) # bitflags of the services I offer. payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + pack( '>L', 2130706433) # = 127.0.0.1. This will be ignored by the remote host. The actual remote connected IP will be used. - payload += pack('>H', shared.config.getint( - 'bitmessagesettings', 'port')) + if safeConfigGetBoolean('bitmessagesettings', 'upnp') and extPort: + payload += pack('>H', extPort) + else: + payload += pack('>H', shared.config.getint('bitmessagesettings', 'port')) random.seed() payload += eightBytesOfRandomDataUsedToDetectConnectionsToSelf @@ -178,6 +283,19 @@ def assembleErrorMessage(fatal=0, banTime=0, inventoryVector='', errorText=''): payload += errorText return CreatePacket('error', payload) +def lookupExeFolder(): + if frozen: + if frozen == "macosx_app": + # targetdir/Bitmessage.app/Contents/MacOS/Bitmessage + exeFolder = path.dirname(path.dirname(path.dirname(path.dirname(sys.executable)))) + path.sep + else: + exeFolder = path.dirname(sys.executable) + path.sep + elif __file__: + exeFolder = path.dirname(__file__) + path.sep + else: + exeFolder = '' + return exeFolder + def lookupAppdataFolder(): APPNAME = "PyBitmessage" if "BITMESSAGE_HOME" in environ: @@ -217,6 +335,15 @@ def lookupAppdataFolder(): pass dataFolder = dataFolder + '/' return dataFolder + +def codePath(): + if frozen == "macosx_app": + codePath = os.environ.get("RESOURCEPATH") + elif frozen: # windows + codePath = sys._MEIPASS + else: + codePath = os.path.dirname(__file__) + return codePath def isAddressInMyAddressBook(address): queryreturn = sqlQuery( @@ -291,8 +418,8 @@ def reloadMyAddressHashes(): if addressVersionNumber == 2 or addressVersionNumber == 3 or addressVersionNumber == 4: # Returns a simple 32 bytes of information encoded in 64 Hex characters, # or null if there was an error. - privEncryptionKey = decodeWalletImportFormat( - config.get(addressInKeysFile, 'privencryptionkey')).encode('hex') + privEncryptionKey = hexlify(decodeWalletImportFormat( + config.get(addressInKeysFile, 'privencryptionkey'))) if len(privEncryptionKey) == 64:#It is 32 bytes encoded as 64 hex characters myECCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey) @@ -321,13 +448,13 @@ def reloadBroadcastSendersForWhichImWatching(): if addressVersionNumber <= 3: privEncryptionKey = hashlib.sha512(encodeVarint(addressVersionNumber)+encodeVarint(streamNumber)+hash).digest()[:32] - MyECSubscriptionCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex')) + MyECSubscriptionCryptorObjects[hash] = highlevelcrypto.makeCryptor(hexlify(privEncryptionKey)) else: doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(encodeVarint( addressVersionNumber) + encodeVarint(streamNumber) + hash).digest()).digest() tag = doubleHashOfAddressData[32:] privEncryptionKey = doubleHashOfAddressData[:32] - MyECSubscriptionCryptorObjects[tag] = highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex')) + MyECSubscriptionCryptorObjects[tag] = highlevelcrypto.makeCryptor(hexlify(privEncryptionKey)) def isProofOfWorkSufficient(data, nonceTrialsPerByte=0, @@ -345,13 +472,13 @@ def isProofOfWorkSufficient(data, return POW <= 2 ** 64 / (nonceTrialsPerByte*(len(data) + payloadLengthExtraBytes + ((TTL*(len(data)+payloadLengthExtraBytes))/(2 ** 16)))) def doCleanShutdown(): - global shutdown + global shutdown, thisapp shutdown = 1 #Used to tell proof of work worker threads and the objectProcessorThread to exit. broadcastToSendDataQueues((0, 'shutdown', 'no data')) - with shared.objectProcessorQueueSizeLock: - data = 'no data' - shared.objectProcessorQueueSize += len(data) - objectProcessorQueue.put(('checkShutdownVariable',data)) + objectProcessorQueue.put(('checkShutdownVariable', 'no data')) + for thread in threading.enumerate(): + if thread.isAlive() and isinstance(thread, StoppableThread): + thread.stopThread() knownNodesLock.acquire() UISignalQueue.put(('updateStatusBar','Saving the knownNodes list of peers to disk...')) @@ -368,8 +495,8 @@ def doCleanShutdown(): UISignalQueue.put(( 'updateStatusBar', 'Flushing inventory in memory out to disk. This should normally only take a second...')) - flushInventory() - + inventory.flush() + # Verify that the objectProcessor has finished exiting. It should have incremented the # shutdown variable from 1 to 2. This must finish before we command the sqlThread to exit. while shutdown == 1: @@ -383,11 +510,20 @@ def doCleanShutdown(): # Wait long enough to guarantee that any running proof of work worker threads will check the # shutdown variable and exit. If the main thread closes before they do then they won't stop. - time.sleep(.25) + time.sleep(.25) + + from class_outgoingSynSender import outgoingSynSender + for thread in threading.enumerate(): + if thread is not threading.currentThread() and isinstance(thread, StoppableThread) and not isinstance(thread, outgoingSynSender): + logger.debug("Waiting for thread %s", thread.name) + thread.join() if safeConfigGetBoolean('bitmessagesettings','daemon'): logger.info('Clean shutdown complete.') + thisapp.cleanup() os._exit(0) + else: + logger.info('Core shutdown complete.') # If you want to command all of the sendDataThreads to do something, like shutdown or send some data, this # function puts your data into the queues for each of the sendDataThreads. The sendDataThreads are @@ -396,15 +532,6 @@ def broadcastToSendDataQueues(data): # logger.debug('running broadcastToSendDataQueues') for q in sendDataQueues: q.put(data) - -def flushInventory(): - #Note that the singleCleanerThread clears out the inventory dictionary from time to time, although it only clears things that have been in the dictionary for a long time. This clears the inventory dictionary Now. - with SqlBulkExecute() as sql: - for hash, storedValue in inventory.items(): - objectType, streamNumber, payload, expiresTime, tag = storedValue - sql.execute('''INSERT INTO inventory VALUES (?,?,?,?,?,?)''', - hash,objectType,streamNumber,payload,expiresTime,tag) - del inventory[hash] def fixPotentiallyInvalidUTF8Data(text): try: @@ -538,7 +665,7 @@ def decryptAndCheckPubkeyPayload(data, address): readPosition += signatureLengthLength signature = decryptedData[readPosition:readPosition + signatureLength] - if highlevelcrypto.verify(signedData, signature, publicSigningKey.encode('hex')): + if highlevelcrypto.verify(signedData, signature, hexlify(publicSigningKey)): logger.info('ECDSA verify passed (within decryptAndCheckPubkeyPayload)') else: logger.info('ECDSA verify failed (within decryptAndCheckPubkeyPayload)') @@ -564,9 +691,9 @@ def decryptAndCheckPubkeyPayload(data, address): publicSigningKey in hex: %s\n\ publicEncryptionKey in hex: %s' % (addressVersion, streamNumber, - ripe.encode('hex'), - publicSigningKey.encode('hex'), - publicEncryptionKey.encode('hex') + hexlify(ripe), + hexlify(publicSigningKey), + hexlify(publicEncryptionKey) ) ) @@ -647,16 +774,11 @@ def _checkAndShareUndefinedObjectWithPeers(data): logger.debug('We have already received this undefined object. Ignoring.') inventoryLock.release() return - elif isInSqlInventory(inventoryHash): - logger.debug('We have already received this undefined object (it is stored on disk in the SQL inventory). Ignoring it.') - inventoryLock.release() - return objectType, = unpack('>I', data[16:20]) inventory[inventoryHash] = ( objectType, streamNumber, data, embeddedTime,'') - inventorySets[streamNumber].add(inventoryHash) inventoryLock.release() - logger.debug('advertising inv with hash: %s' % inventoryHash.encode('hex')) + logger.debug('advertising inv with hash: %s' % hexlify(inventoryHash)) broadcastToSendDataQueues((streamNumber, 'advertiseobject', inventoryHash)) @@ -679,26 +801,16 @@ def _checkAndShareMsgWithPeers(data): logger.debug('We have already received this msg message. Ignoring.') inventoryLock.release() return - elif isInSqlInventory(inventoryHash): - logger.debug('We have already received this msg message (it is stored on disk in the SQL inventory). Ignoring it.') - inventoryLock.release() - return # This msg message is valid. Let's let our peers know about it. objectType = 2 inventory[inventoryHash] = ( objectType, streamNumber, data, embeddedTime,'') - inventorySets[streamNumber].add(inventoryHash) inventoryLock.release() - logger.debug('advertising inv with hash: %s' % inventoryHash.encode('hex')) + logger.debug('advertising inv with hash: %s' % hexlify(inventoryHash)) broadcastToSendDataQueues((streamNumber, 'advertiseobject', inventoryHash)) # Now let's enqueue it to be processed ourselves. - # If we already have too much data in the queue to be processed, just sleep for now. - while shared.objectProcessorQueueSize > 120000000: - time.sleep(2) - with shared.objectProcessorQueueSizeLock: - shared.objectProcessorQueueSize += len(data) - objectProcessorQueue.put((objectType,data)) + objectProcessorQueue.put((objectType,data)) def _checkAndShareGetpubkeyWithPeers(data): if len(data) < 42: @@ -725,27 +837,17 @@ def _checkAndShareGetpubkeyWithPeers(data): logger.debug('We have already received this getpubkey request. Ignoring it.') inventoryLock.release() return - elif isInSqlInventory(inventoryHash): - logger.debug('We have already received this getpubkey request (it is stored on disk in the SQL inventory). Ignoring it.') - inventoryLock.release() - return objectType = 0 inventory[inventoryHash] = ( objectType, streamNumber, data, embeddedTime,'') - inventorySets[streamNumber].add(inventoryHash) inventoryLock.release() # This getpubkey request is valid. Forward to peers. - logger.debug('advertising inv with hash: %s' % inventoryHash.encode('hex')) + logger.debug('advertising inv with hash: %s' % hexlify(inventoryHash)) broadcastToSendDataQueues((streamNumber, 'advertiseobject', inventoryHash)) # Now let's queue it to be processed ourselves. - # If we already have too much data in the queue to be processed, just sleep for now. - while shared.objectProcessorQueueSize > 120000000: - time.sleep(2) - with shared.objectProcessorQueueSizeLock: - shared.objectProcessorQueueSize += len(data) - objectProcessorQueue.put((objectType,data)) + objectProcessorQueue.put((objectType,data)) def _checkAndSharePubkeyWithPeers(data): if len(data) < 146 or len(data) > 440: # sanity check @@ -763,7 +865,7 @@ def _checkAndSharePubkeyWithPeers(data): return if addressVersion >= 4: tag = data[readPosition:readPosition + 32] - logger.debug('tag in received pubkey is: %s' % tag.encode('hex')) + logger.debug('tag in received pubkey is: %s' % hexlify(tag)) else: tag = '' @@ -774,27 +876,17 @@ def _checkAndSharePubkeyWithPeers(data): logger.debug('We have already received this pubkey. Ignoring it.') inventoryLock.release() return - elif isInSqlInventory(inventoryHash): - logger.debug('We have already received this pubkey (it is stored on disk in the SQL inventory). Ignoring it.') - inventoryLock.release() - return objectType = 1 inventory[inventoryHash] = ( objectType, streamNumber, data, embeddedTime, tag) - inventorySets[streamNumber].add(inventoryHash) inventoryLock.release() # This object is valid. Forward it to peers. - logger.debug('advertising inv with hash: %s' % inventoryHash.encode('hex')) + logger.debug('advertising inv with hash: %s' % hexlify(inventoryHash)) broadcastToSendDataQueues((streamNumber, 'advertiseobject', inventoryHash)) # Now let's queue it to be processed ourselves. - # If we already have too much data in the queue to be processed, just sleep for now. - while shared.objectProcessorQueueSize > 120000000: - time.sleep(2) - with shared.objectProcessorQueueSizeLock: - shared.objectProcessorQueueSize += len(data) - objectProcessorQueue.put((objectType,data)) + objectProcessorQueue.put((objectType,data)) def _checkAndShareBroadcastWithPeers(data): @@ -823,27 +915,17 @@ def _checkAndShareBroadcastWithPeers(data): logger.debug('We have already received this broadcast object. Ignoring.') inventoryLock.release() return - elif isInSqlInventory(inventoryHash): - logger.debug('We have already received this broadcast object (it is stored on disk in the SQL inventory). Ignoring it.') - inventoryLock.release() - return # It is valid. Let's let our peers know about it. objectType = 3 inventory[inventoryHash] = ( objectType, streamNumber, data, embeddedTime, tag) - inventorySets[streamNumber].add(inventoryHash) inventoryLock.release() # This object is valid. Forward it to peers. - logger.debug('advertising inv with hash: %s' % inventoryHash.encode('hex')) + logger.debug('advertising inv with hash: %s' % hexlify(inventoryHash)) broadcastToSendDataQueues((streamNumber, 'advertiseobject', inventoryHash)) # Now let's queue it to be processed ourselves. - # If we already have too much data in the queue to be processed, just sleep for now. - while shared.objectProcessorQueueSize > 120000000: - time.sleep(2) - with shared.objectProcessorQueueSizeLock: - shared.objectProcessorQueueSize += len(data) - objectProcessorQueue.put((objectType,data)) + objectProcessorQueue.put((objectType,data)) def openKeysFile(): if 'linux' in sys.platform: diff --git a/src/singleton.py b/src/singleton.py index ee5c3077..a4b6c678 100644 --- a/src/singleton.py +++ b/src/singleton.py @@ -1,24 +1,33 @@ #! /usr/bin/env python -import sys -import os +import atexit import errno -import tempfile from multiprocessing import Process +import os +import sys +import shared +try: + import fcntl # @UnresolvedImport +except: + pass class singleinstance: """ - Implements a single instance application by creating a lock file based on the full path to the script file. + Implements a single instance application by creating a lock file at appdata. This is based upon the singleton class from tendo https://github.com/pycontribs/tendo which is under the Python Software Foundation License version 2 """ - def __init__(self, flavor_id=""): - import sys + def __init__(self, flavor_id="", daemon=False): self.initialized = False - basename = os.path.splitext(os.path.abspath(sys.argv[0]))[0].replace("/", "-").replace(":", "").replace("\\", "-") + '-%s' % flavor_id + '.lock' - self.lockfile = os.path.normpath(tempfile.gettempdir() + '/' + basename) + self.daemon = daemon + self.lockfile = os.path.normpath(os.path.join(shared.appdata, 'singleton%s.lock' % flavor_id)) + + if not self.daemon: + # Tells the already running (if any) application to get focus. + import bitmessageqt + bitmessageqt.init() if sys.platform == 'win32': try: @@ -34,7 +43,6 @@ class singleinstance: print(e.errno) raise else: # non Windows - import fcntl # @UnresolvedImport self.fp = open(self.lockfile, 'w') try: fcntl.lockf(self.fp, fcntl.LOCK_EX | fcntl.LOCK_NB) @@ -42,20 +50,20 @@ class singleinstance: print 'Another instance of this application is already running' sys.exit(-1) self.initialized = True + atexit.register(self.cleanup) - def __del__(self): - import sys + def cleanup(self): if not self.initialized: return + print "Cleaning up lockfile" try: if sys.platform == 'win32': if hasattr(self, 'fd'): os.close(self.fd) os.unlink(self.lockfile) else: - import fcntl # @UnresolvedImport fcntl.lockf(self.fp, fcntl.LOCK_UN) if os.path.isfile(self.lockfile): os.unlink(self.lockfile) except Exception, e: - sys.exit(-1) + pass diff --git a/src/socks/__init__.py b/src/socks/__init__.py index ebb68f45..d5d59687 100644 --- a/src/socks/__init__.py +++ b/src/socks/__init__.py @@ -155,7 +155,7 @@ class socksocket(socket.socket): """ self.__proxy = (proxytype, addr, port, rdns, username, password) - def __negotiatesocks5(self, destaddr, destport): + def __negotiatesocks5(self): """__negotiatesocks5(self,destaddr,destport) Negotiates a connection through a SOCKS5 server. """ @@ -200,6 +200,8 @@ class socksocket(socket.socket): raise Socks5AuthError((2, _socks5autherrors[2])) else: raise GeneralProxyError((1, _generalerrors[1])) + + def __connectsocks5(self, destaddr, destport): # Now we can request the actual connection req = struct.pack('BBB', 0x05, 0x01, 0x00) # If the given destination address is an IP address, we'll @@ -247,6 +249,37 @@ class socksocket(socket.socket): else: self.__proxypeername = (destaddr, destport) + def __resolvesocks5(self, host): + # Now we can request the actual connection + req = struct.pack('BBB', 0x05, 0xF0, 0x00) + req += chr(0x03).encode() + chr(len(host)).encode() + host + req = req + struct.pack(">H", 8444) + self.sendall(req) + # Get the response + ip = "" + resp = self.__recvall(4) + if resp[0:1] != chr(0x05).encode(): + self.close() + raise GeneralProxyError((1, _generalerrors[1])) + elif resp[1:2] != chr(0x00).encode(): + # Connection failed + self.close() + if ord(resp[1:2])<=8: + raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])])) + else: + raise Socks5Error((9, _socks5errors[9])) + # Get the bound address/port + elif resp[3:4] == chr(0x01).encode(): + ip = socket.inet_ntoa(self.__recvall(4)) + elif resp[3:4] == chr(0x03).encode(): + resp = resp + self.recv(1) + ip = self.__recvall(ord(resp[4:5])) + else: + self.close() + raise GeneralProxyError((1,_generalerrors[1])) + boundport = struct.unpack(">H", self.__recvall(2))[0] + return ip + def getproxysockname(self): """getsockname() -> address info Returns the bound IP address and port number at the proxy. @@ -361,7 +394,8 @@ class socksocket(socket.socket): else: portnum = 1080 _orgsocket.connect(self, (self.__proxy[1], portnum)) - self.__negotiatesocks5(destpair[0], destpair[1]) + self.__negotiatesocks5() + self.__connectsocks5(destpair[0], destpair[1]) elif self.__proxy[0] == PROXY_TYPE_SOCKS4: if self.__proxy[2] != None: portnum = self.__proxy[2] @@ -380,3 +414,15 @@ class socksocket(socket.socket): _orgsocket.connect(self, (destpair[0], destpair[1])) else: raise GeneralProxyError((4, _generalerrors[4])) + + def resolve(self, host): + if self.__proxy[0] == PROXY_TYPE_SOCKS5: + if self.__proxy[2] != None: + portnum = self.__proxy[2] + else: + portnum = 1080 + _orgsocket.connect(self, (self.__proxy[1], portnum)) + self.__negotiatesocks5() + return self.__resolvesocks5(host) + else: + return None \ No newline at end of file diff --git a/src/sslkeys/cert.pem b/src/sslkeys/cert.pem new file mode 100644 index 00000000..a976db75 --- /dev/null +++ b/src/sslkeys/cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWDCCAcGgAwIBAgIJAJs5yni/cDh5MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTEzMDk1NTU3WhcNMTUxMTE0MDk1NTU3WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQCg8XkFpIAYsTSBealTubvu4dzpMnnAOwANG5K9TJeclG9O65cmKWpH8k3hNDif +xagIAI8UanBsQo6SQrK1Iby2kz6DCKmySO1OwoNOOF0Ok31N+5aWsQvYF1wLbk2m +Ti/CSLWBgL25ywCCiP3Mgr+krapT4TrfvF4gCchUdcxMQQIDAQABo1AwTjAdBgNV +HQ4EFgQUWuFUJQC6zu6OTDgHZzhfZxsgJOMwHwYDVR0jBBgwFoAUWuFUJQC6zu6O +TDgHZzhfZxsgJOMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAT1I/x +GbsYAE4pM4sVQrcuz7jLwr3k5Zve0z4WKR41W17Nc44G3DyLbkTWYESLfAYsivkx +tRRtYTtJm1qmTPtedXQJK+wJGNHCWRfwSB2CYwmO7+C2rYYzkFndN68kB6RJmyOr +eCX+9vkbQqgh7KfiNquJxCfMSDfhA2RszU43jg== +-----END CERTIFICATE----- diff --git a/src/sslkeys/key.pem b/src/sslkeys/key.pem new file mode 100644 index 00000000..a47bcc3c --- /dev/null +++ b/src/sslkeys/key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKDxeQWkgBixNIF5 +qVO5u+7h3OkyecA7AA0bkr1Ml5yUb07rlyYpakfyTeE0OJ/FqAgAjxRqcGxCjpJC +srUhvLaTPoMIqbJI7U7Cg044XQ6TfU37lpaxC9gXXAtuTaZOL8JItYGAvbnLAIKI +/cyCv6StqlPhOt+8XiAJyFR1zExBAgMBAAECgYEAmd2hpQpayMCJgQsOHhRgnoXi +jDOMgIInj2CADmguPi0OqTXEoGBR0ozNdfNV+zGdbmESaSNFbcrHwP7xGQgzABlv +5ANLgBYrHnW/oFCCuw4Lj/CAAHRA4its+2wzf13BYoVitDiYBt3JMRqwLV03aHyy +Oqhvt2nVicz85+HERj0CQQDMJAPUIyOQLO+BPC5MsuxyQFJgie0aB5swumxanOv4 +J8GIvulNEJMG/dq+h/x4paV2LGDlUAOsBUmjXfTPMQAHAkEAydQtYorqYqhFZWWD +3lUMAoa8pGb6BfNXUqxdH0H8fk6B7OxYPpvwm7ce1lD1Oje3/+rMnn8i6A1p9HUy +l9wvdwJAdhxIUs7Z3qsBD8bgCuRixV/NyalDk5HfCnxyAKNWK8fkw9ehaEM0rhDm +JOLNAojkiND4ZvS6iyasCmdsIwx4tQJAAV+eR3NmkPFQN5ZvRU4S3NmJ4xyISw4S +5A8kOxg53aovHCunlhV9l7GxVggLAzBp4iX46oM2+5lLxUwe4gWvlQJBAK0IR8bB +85bKZ+M/O8rbs9kQHjx6GCbbDxH+qbIKkNcvLUvMgwwIFKiwqX+Tedtu2xET0mQM +9tEE5eMBOJ8GrxQ= +-----END PRIVATE KEY----- diff --git a/src/tr.py b/src/tr.py index c11d1f57..d61d6c34 100644 --- a/src/tr.py +++ b/src/tr.py @@ -12,10 +12,10 @@ class translateClass: else: return self.text -def _translate(context, text): - return translateText(context, text) +def _translate(context, text, disambiguation = None, encoding = None, n = None): + return translateText(context, text, n) -def translateText(context, text): +def translateText(context, text, n = None): if not shared.safeConfigGetBoolean('bitmessagesettings', 'daemon'): try: from PyQt4 import QtCore, QtGui @@ -23,9 +23,12 @@ def translateText(context, text): print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon' print 'Error message:', err os._exit(0) - return QtGui.QApplication.translate(context, text) + if n is None: + return QtGui.QApplication.translate(context, text) + else: + return QtGui.QApplication.translate(context, text, None, QtCore.QCoreApplication.CodecForTr, n) else: if '%' in text: return translateClass(context, text.replace('%','',1)) else: - return text \ No newline at end of file + return text diff --git a/src/translations/bitmessage_eo.pro b/src/translations/bitmessage.pro similarity index 55% rename from src/translations/bitmessage_eo.pro rename to src/translations/bitmessage.pro index 1e9492cd..78858dfc 100644 --- a/src/translations/bitmessage_eo.pro +++ b/src/translations/bitmessage.pro @@ -1,8 +1,8 @@ SOURCES = ../addresses.py\ ../bitmessagemain.py\ ../class_addressGenerator.py\ - ../class_objectProcessor.py\ ../class_outgoingSynSender.py\ + ../class_objectProcessor.py\ ../class_receiveDataThread.py\ ../class_sendDataThread.py\ ../class_singleCleaner.py\ @@ -16,20 +16,49 @@ SOURCES = ../addresses.py\ ../helper_sent.py\ ../helper_startup.py\ ../shared.py\ + ../upnp.py\ ../bitmessageqt/__init__.py\ ../bitmessageqt/about.py\ + ../bitmessageqt/account.py\ ../bitmessageqt/addaddressdialog.py\ ../bitmessageqt/bitmessageui.py\ + ../bitmessageqt/blacklist.py\ ../bitmessageqt/connect.py\ + ../bitmessageqt/emailgateway.py\ + ../bitmessageqt/foldertree.py\ ../bitmessageqt/help.py\ ../bitmessageqt/iconglossary.py\ + ../bitmessageqt/languagebox.py\ + ../bitmessageqt/messagecompose.py\ + ../bitmessageqt/messageview.py\ + ../bitmessageqt/networkstatus.py\ ../bitmessageqt/newaddressdialog.py\ ../bitmessageqt/newchandialog.py\ ../bitmessageqt/newsubscriptiondialog.py\ ../bitmessageqt/regenerateaddresses.py\ + ../bitmessageqt/safehtmlparser.py\ ../bitmessageqt/settings.py\ ../bitmessageqt/specialaddressbehavior.py - -TRANSLATIONS = bitmessage_eo.ts +FORMS = \ + ../bitmessageqt/blacklist.ui\ + ../bitmessageqt/networkstatus.ui + +TRANSLATIONS = \ + bitmessage_ar.ts \ + bitmessage_cs.ts \ + bitmessage_da.ts \ + bitmessage_de.ts \ + bitmessage_en.ts \ + bitmessage_en_pirate.ts \ + bitmessage_eo.ts \ + bitmessage_fr.ts \ + bitmessage_it.ts \ + bitmessage_ja.ts \ + bitmessage_nl.ts \ + bitmessage_no.ts \ + bitmessage_sk.ts \ + bitmessage_ru.ts \ + bitmessage_zh_cn.ts + CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_ar.pro b/src/translations/bitmessage_ar.pro deleted file mode 100644 index 1cd8dd64..00000000 --- a/src/translations/bitmessage_ar.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_outgoingSynSender.py\ - ../class_objectProcessor.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_ar.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_ar.qm b/src/translations/bitmessage_ar.qm index 477a7586..63e30f09 100644 Binary files a/src/translations/bitmessage_ar.qm and b/src/translations/bitmessage_ar.qm differ diff --git a/src/translations/bitmessage_ar.ts b/src/translations/bitmessage_ar.ts index b37dcc0b..3742d190 100644 --- a/src/translations/bitmessage_ar.ts +++ b/src/translations/bitmessage_ar.ts @@ -1,389 +1,350 @@ - - - + - MainWindow + AddAddressDialog - - Bitmessage - Bitmessage + + Add new entry + إضافة مدخل جديد - - To - إلى - - - - From - من - - - - Subject - الموضوع - - - - Received - تاريخ الإستلام - - - - Inbox - البريد الوارد - - - - Load from Address book - تحميل من دفتر العناوين - - - - Message: - الرسالة: - - - - Subject: - الموضوع: - - - - Send to one or more specific people - إرسال لشخص أو عدة أشخاص - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - - To: - إلى: - - - - From: - من: - - - - Broadcast to everyone who is subscribed to your address - إرسال لجميع المتابعين - - - - Send - إرسال - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - إنتبه أن البث مشفر فقط بعنوانك، و يمكن لأي شخص يعرف عنوانك قراءة البث - - - - Status - الحالة - - - - Sent - البريد المرسل - - - - New - جديد - - - - Label (not shown to anyone) - إسم مستعار خاص - غير مرئي للآخرين - - - - Address - العنوان - - - - Group - المجموعة - - - - Stream - مجرى - - - - Your Identities - هوياتك - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - هنا يمكن التسجيل لمتابعة مشاركات الآخرين، الرسائل ستظهر في البريد الوارد، و العناوين هنا تبطل العناوين في القائمة السوداء. - - - - Add new Subscription - إدخال إشتراك جديدة - - - + Label إسم مستعار - - Subscriptions - الإشتراكات + + Address + عنوان + + + + EmailGatewayDialog + + + Email gateway + - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - دفتر العناوين مفيد لإضافة أسماء أو طوابع بريدية للأشخاص الآخرين مع عناوينهم لكي يسهل تمييزهم بسهولة في البريد الوارد، يمكنك إضافة جهات اتصال جديدة باستخدام زر إضافة أو من البريد الوارد بالضغط الأيمن على الرسالة الواردة. + + Register on email gateway + - - Add new entry - إضافة جهة اتصال جديدة + + Account status at email gateway + - - Name or Label - إسم مستعار + + Change account settings at email gateway + - - Address Book - دفتر العناوين + + Unregister from email gateway + - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - إستخدام القائمة السوداء - تسمح وصول كل الرسائل الواردة عدا العناوين المسجلة في القائمة السوداء + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - إستخدام القائمة البيضاء - تمنع وصول كل الرسائل الواردة عدا العناوين المسجلة في القائمة البيضاء + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + - - Blacklist - القائمة السوداء + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + - - Stream Number - Numéro de flux + + Email gateway registration + - - Number of Connections - Nombre de connexions + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + + + MainWindow + + + Reply to sender + - - Total connections: 0 - إجمالي الروابط + + Reply to channel + - - Since startup at asdf: - منذ بداية التشغيل: + + Add sender to your Address Book + إضافة جهة اتصال لدفتر العناوين - - Processed 0 person-to-person message. - تم معالجة 0 رسالة -شخص إلى شخص-. + + Add sender to your Blacklist + - - Processed 0 public key. - تم معالجة 0 مفتاح علني. + + Move to Trash + حذف إلى سلة المهملات - - Processed 0 broadcast. - تم معالجة 0 بث. + + Undelete + - - Inventory lookups per second: 0 - معدل البحث ضمن المخزن لكل ثانية: 0 + + View HTML code as formatted text + إظهار نظام تشفير HTML كنص منسق - - Network Status - حالة الشبكة + + Save message as... + حفظ الرسالة ك - - File - ملف + + Mark Unread + وضع علامة غير مقروء - - Settings - الضبط + + New + جديد - - View - إظهار + + Enable + تفعيل - - Hashtags - هاشتاق + + Disable + تعطيل - - Help - مساعدة + + Set avatar... + تغيير الصورة الرمزية - - Import keys - إدراج المفاتيح + + Copy address to clipboard + نسخ العنوان إلى الحافظة - - Manage keys - إدارة المفاتيح + + Special address behavior... + سلوك عنوان خاص - - Quit - الخروج + + Email gateway + - - About - عن + + Delete + حذف - - Regenerate deterministic addresses - إعادة إنتاج عناوين حتمية - غير عشوائية + + Send message to this address + أرسل رسالة لهذا العنوان - - Delete all trashed messages - حذف سلة المهملات + + Subscribe to this address + متابعة هذا العنوان - - Total Connections: %1 - إجمالي الروابط %1 + + Add New Address + إضافة جهة إتصال - - Not Connected - غير متصل + + Copy destination address to clipboard + نسخ عنوان المرسل إليه إلى الحافظة - - Connected - متصل + + Force send + إرسال قصري - - Show Bitmessage - إظهار Bitmessage + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + واحد من العناوين، %1، حاصل على رقم إصدار 1، العناوين ذات رقم الإصدار 1 غير مدعومه حالياً، هل باستطاعتنا حذفه الآن؟ - - Subscribe - إشتراك + + Waiting for their encryption key. Will request it again soon. + - - Processed %1 person-to-person messages. - تم معالجة %1 من رسالة - شخص إلى شخص - - - - Processed %1 broadcast messages. - تم معالجة %1 من رسائل البث - - - - Processed %1 public keys. - تم معالجة %1 من المفاتيح العامة - - - - Since startup on %1 - منذ بداية التشغيل في %1 - - - - Waiting on their encryption key. Will request it again soon. - بانتظار مفتاح التشفير، سيتم طلبه مرة أخرى قريباً - - - + Encryption key request queued. تم إدراح طلب مفتاح التشفير بقائمة الإنتظار. - + Queued. تم الإدراج بقائمة الانتظار - + + Message sent. Waiting for acknowledgement. Sent at %1 + + + + + Message sent. Sent at %1 + تم إرسال الرسالة في %1 + + + Need to do work to send message. Work is queued. تحتاج لبعض العمل لإرسال الرسالة، تم إدراج العمل بقائمة الانتظار - + Acknowledgement of the message received %1 تم استلام إشعار الاستلام للرسالة %1 - + Broadcast queued. تم إدراج البث في قائمة الانتظار - + Broadcast on %1 البث في %1 - + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 مشكلة: العمل المطلوب من قبل المستلم أصعب من ما كنت مستعد للقيام به %1 - + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + مشكلة: مفتاح تشفير المرسل إليه غير جيد، لا يمكن تشفير الرسالة. %1 + + + Forced difficulty override. Send should start soon. تم تجازو الصعوبة قصراً، ستبدأ الإرسال قريباً - - Message sent. Waiting on acknowledgement. Sent at %1 - تم إرسال الرسالة، بانتظار إشعار الإستلام، تم الإرسال في %1 + + Unknown status: %1 %2 + حالة غير معروفه: %1 %2 - + + Not Connected + غير متصل + + + + Show Bitmessage + إظهار Bitmessage + + + + Send + إرسال + + + + Subscribe + إشتراك + + + + Channel + + + + + Quit + الخروج + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. يمكنك إدارة مفاتيحك بتعديل ملف keys.dat المحفوظ بنفس المجلد الخاص بالبرنامج، مهم جداً أن تحتفظ بنسخة إضافية للملف المذكور سلفاً. - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. @@ -392,12 +353,17 @@ It is important that you back up this file. مهم جداً أن تحتفظ بنسخة إضافية من هذا الملف. - + + Open keys.dat? + فتح ملف keys.dat؟ + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) يمكنك إدارة مفاتيحك بتعديل ملف keys.dat المحفوظ بنفس المجلد الخاص بالبرنامج، مهم جداً أن تحتفظ بنسخة إضافية للملف المذكور سلفاً. هل ترغب بفتح الملف الآن؟ تأكد من إغلاق البرنامج Bitmessage قبل تعديل الملف. - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) @@ -406,617 +372,898 @@ It is important that you back up this file. Would you like to open the file now? مهم جداً أن تحتفظ بنسخة إضافية من هذا الملف. هل ترغب بفتح الملف الآن؟ تأكد من إغلاق البرنامج Bitmessage قبل تعديل الملف. - - Add sender to your Address Book - إضافة جهة اتصال لدفتر العناوين - - - - Move to Trash - حذف إلى سلة المهملات - - - - View HTML code as formatted text - إظهار نظام تشفير HTML كنص منسق - - - - Enable - تفعيل - - - - Disable - تعطيل - - - - Copy address to clipboard - نسخ العنوان إلى الحافظة - - - - Special address behavior... - سلوك عنوان خاص - - - - Send message to this address - أرسل رسالة لهذا العنوان - - - - Send message to this group - أرسل رسالة لهذه المجموعة - - - - Set avatar... - تغيير الصورة الرمزية - - - - Add New Address - إضافة جهة إتصال - - - - Delete - حذف - - - - Copy destination address to clipboard - نسخ عنوان المرسل إليه إلى الحافظة - - - - Force send - إرسال قصري - - - - Are you sure you want to delete all trashed messages? - هل أنت متأكد من رغبتك في حذف كل الرسائل من سلة المهملات؟ - - - - You must type your passphrase. If you don't have one then this is not the form for you. - يجب إدخال عبارة المرور، إن لم تكن لديك عبارة مرور، إذاً هذه ليست الطريقة المناسبة لك - - - + Delete trash? حذف سلة المهملات؟ - - Open keys.dat? - فتح ملف keys.dat؟ + + Are you sure you want to delete all trashed messages? + هل أنت متأكد من رغبتك في حذف كل الرسائل من سلة المهملات؟ - + bad passphrase عبارة المرور غير جيدة - - Restart - إعادة تشغيل + + You must type your passphrase. If you don't have one then this is not the form for you. + يجب إدخال عبارة المرور، إن لم تكن لديك عبارة مرور، إذاً هذه ليست الطريقة المناسبة لك - - You must restart Bitmessage for the port number change to take effect. - لتفعيل تغيير رقم نقطة العبور (port) يجب عليك إعادة تشغيل برنامج Bitmessage. + + Bad address version number + - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections. - Bitmessage utilisera votre proxy à partir de maintenant mais il vous faudra redémarrer Bitmessage pour fermer les connexions existantes. + + Your address version number must be a number: either 3 or 4. + - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - خطأ: لا يمكنك إضافة نفس العنوان مرتين إلى القائمة، يمكنك إعادة تسمية العنوان. + + Your address version number must be either 3 or 4. + - - The address you entered was invalid. Ignoring it. - العنوان الذي أدخلته غير صالح، سيتم تجاهله. - - - - Passphrase mismatch - عبارة المرور غير متطابقه - - - - The passphrase you entered twice doesn't match. Try again. - عبارة المرور التي أدخلتها مرتين غير متطابقه، أعد المحاولة. - - - - Choose a passphrase - اختر عبارة المرور - - - - You really do need a passphrase. - أنت بحاجة لعبارة مرور. - - - - All done. Closing user interface... - تم عمل اللازم، سيتم إغلاق واجهة المستخدم - - - - Address is gone - تم إنتاج العنوان - - - - Bitmessage cannot find your address %1. Perhaps you removed it? - لم يستطع Bitmessage العثور على عنوانك %1, ربما قمت بحذف العنوان؟ - - - - Address disabled - تم تعطيل العنوان - - - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - خطأ: العنوان المستخدم للإرسال منه معطل، يجب عليك تفعيله في تبويب "هوياتك" قبل استخدامه. - - - - Entry added to the Address Book. Edit the label to your liking. - تم إضافة جهة الاتصال لدفتر العناوين، يمكنك تعديل الإسم المستعار إذا أحببت. - - - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - خطأ: لا يمكنك إضافة نفس العنوان إلى دفتر العناوين مرتين، يمكنك إعادة تسمية العنوان. - - - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - تم نقل المادة لسلة المهملات، لا يتوفر واجهة مستخدم لإظهار سلة المهملات حالياً، و لكن يمكنك إيجاد الرسالة المحذوفة على القرص الصلب إذا أردت استرجاعها. - - - - No addresses selected. - لم يتم اختيار عناوين - - - - Options have been disabled because they either aren't applicable or because they haven't yet been implimented for your operating system. - Certaines options ont été désactivées car elles n'étaient pas applicables ou car elles n'ont pas encore été implémentées pour votre système d'exploitation. - - - - The address should start with ''BM-'' - العنوان يجب أن يبدأ ب "BM-". - - - - The address is not typed or copied correctly (the checksum failed). - لم يتم إدخال أو نسخ العنوان بالطريقة الصحيحة - اختبار checksum فشل. - - - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - رقم إصدار هذا العنوان أعلى من إمكانية هذا البرنامج، قم بتحديث البرنامج. - - - - The address contains invalid characters. - العنوان يحتوي على حروف غير صحيحة - - - - Some data encoded in the address is too short. - بعض البيانات المشفرة ضمن العنوان قصيرة جداً - - - - Some data encoded in the address is too long. - بعض البيانات المشفرة ضمن العنوان طويلة جداً. - - - - Address is valid. - العنوان صحيح - - - - You are using TCP port %1. (This can be changed in the settings). - أنت تستخدم نقطة عبور TCP %1 - يمكنك تغييره في قائمة الضبط. - - - - Error: Bitmessage addresses start with BM- Please check %1 - خطأ: عناوين ال Bitmessage تبدأ ب BM-، يرجى فحص %1 - - - - Error: The address %1 contains invalid characters. Please check it. - خطأ: العنوان %1 يحتوي على حروف غير صالحة، يرجى فحصه. - - - - Error: The address %1 is not typed or copied correctly. Please check it. - خطأ: لم يتم إدخال أو نسخ العنوان %1 بطريقة صحيحة، يرجى فحصه. - - - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - خطأ: رقم إصدار العنوان %1 عالي جداً، إما أن تقوم بتحديث برنامج Bitmessage أو أن شريكك ذكي جدأ. - - - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - بعض البيانات المشفرة ضمن العنوان %1 قصيرة جداً. يمكن أن يكون هناك خطأ في برنامج شريكك. - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - بعض البيانات المشفرة ضمن العنوان %1 طويلة جداً. يمكن أن يكون هناك خطأ في برنامج شريكك. - - - - Error: Something is wrong with the address %1. - خطأ: هناك خطأ في هذا العنوان %1. - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - خطأ: يجب اختيار عنوان للإرسال منه، إن لم يكن لديك واحد إذهب إلى تبويب "هوياتك". - - - - Sending to your address - يتم الإرسال إلى عنوانك - - - - Error: One of the addresses to which you are sending a message, %1, is yours. Unfortunately the Bitmessage client cannot process its own messages. Please try running a second client on a different computer or within a VM. - خطأ: عنوان من العناوين المرسل إليها، %1, يكون لك، لسوئ الحظ عميل Bitmessage لا يمكنه معالجة رسالئه، يرجى تشغيل عميل ثاني في حاسوب آخر أو ضمن حاسوب إفتراضي. - - - - Address version number - رقم إصدار العنوان - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - بالنظر إلى العنوان %1, Bitmessage لم يستطع فهم رقم إصدار العنوان %2، ربما يجب عليك تحديث برنامج Bitmessage لإصداره الأخير. - - - - Stream number - رقم المجرى - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - بالنظر إلى العنوان %1, Bitmessage لم يستطع فهم رقم إصدار العنوان %2، ربما يجب عليك تحديث برنامج Bitmessage لإصداره الأخير. - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - تحذير: أنت غير متصل حالياً، Bitmessage سيقوم بالعمل اللازم لإرسال الرسالة و لكن لن يقوم بالإرسال حتى تصبح متصلاً. - - - - Your 'To' field is empty. - حقل "إلى" فارغ. - - - - Right click one or more entries in your address book and select 'Send message to this address'. - أنقر يميناً على واحد أو أكثر من جهات الاتصال في دفتر العناوين و اختر "إرسال رسالة لهذا العنوان". - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - خطأ: لا يمكنك إضافة نفس العنوان إلى الإشتراكات مرتين، يمكنك إعادة تسمية العنوان. - - - - Message trashed - تم حذف الرسالة - - - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - واحد من العناوين، %1، حاصل على رقم إصدار 1، العناوين ذات رقم الإصدار 1 غير مدعومه حالياً، هل باستطاعتنا حذفه الآن؟ - - - - Unknown status: %1 %2 - حالة غير معروفه: %1 %2 - - - - Connection lost - تم فقد الاتصال - - - - SOCKS5 Authentication problem: %1 - Problème d'authentification SOCKS5 : %1 - - - - Reply - . - رد - - - - Generating one new address - Génération d'une nouvelle adresse - - - - Done generating address. Doing work necessary to broadcast it... - Génération de l'adresse terminée. Travail pour la diffuser en cours... - - - - Done generating address - Génération de l'adresse terminée - - - - Message sent. Waiting on acknowledgement. Sent on %1 - Message envoyé. En attente de l'accusé de réception. Envoyé le %1 - - - - Error! Could not find sender address (your address) in the keys.dat file. - Erreur ! L'adresse de l'expéditeur (vous) n'a pas pu être trouvée dans le fichier keys.dat. - - - - Doing work necessary to send broadcast... - Travail pour envoyer la diffusion en cours... - - - - Broadcast sent on %1 - Message de diffusion envoyé le %1 - - - - Looking up the receiver's public key - Recherche de la clé publique du destinataire - - - - Doing work necessary to send message. (There is no required difficulty for version 2 addresses like this.) - Travail nécessaire pour envoyer le message en cours. (Il n'y a pas de difficulté requise pour ces adresses de version 2.) - - - - Doing work necessary to send message. -Receiver's required difficulty: %1 and %2 - Travail nécessaire pour envoyer le message. -Difficulté requise par le destinataire : %1 et %2 - - - - Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. - Problème : Le travail demandé par le destinataire (%1 et %2) est plus difficile que ce que vous souhaitez faire. - - - - Work is queued. - تم إدراج العمل ضمن قائمة الإنتظار. - - - - Work is queued. %1 - تم إدراج العمل ضمن قائمة الإنتظار. %1 - - - - Doing work necessary to send message. -There is no required difficulty for version 2 addresses like this. - Travail nécessaire pour envoyer le message en cours. -Il n'y a pas de difficulté requise pour ces adresses de version 2. - - - - Problem: The recipient's encryption key is no good. Could not encrypt message. %1 - مشكلة: مفتاح تشفير المرسل إليه غير جيد، لا يمكن تشفير الرسالة. %1 - - - - Save message as... - حفظ الرسالة ك - - - - Mark Unread - وضع علامة غير مقروء - - - - Subscribe to this address - متابعة هذا العنوان - - - - Message sent. Sent at %1 - تم إرسال الرسالة في %1 - - - + Chan name needed مطلوب إسم زمرة - + You didn't enter a chan name. لم تدخل إسم الزمرة - + Address already present العنوان موجود سلفاً - + Could not add chan because it appears to already be one of your identities. لا يمكن إضافة هذه الزمرة لأنها تعتبر أحد هوياتك. - + Success نجاح - + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. تم تكوين زمرة بنجاح، لإتاحة الفرصة للأخرين بالإنضمام لمجموعتك أعطهم إسم الزمرة و هذا العنوان %1، هذا العنوان سيظهر ضمن هوياتك. - + Address too new العنوان جديد جداً - + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. بالرغم أن العنوان صحيح و لكن رقم إصداره جديد جدًا بحيث لا يمكن التعامل معه، ربما عليك تحديث البرنامج. - + Address invalid العنوان غير صحيح - + That Bitmessage address is not valid. عنوان Bitmessage غير صحيح. - + Address does not match chan name العنوان لا يتوافق مع إسم الزمرة - + Although the Bitmessage address you entered was valid, it doesn't match the chan name. بالرغم أن العنوان صحيح، و لكن لا يتوافق مع إسم الزمرة. - + Successfully joined chan. تم الإنضمام للزمرة بنجاح. - + + Connection lost + تم فقد الاتصال + + + + Connected + متصل + + + + Message trashed + تم حذف الرسالة + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + خطأ: عناوين ال Bitmessage تبدأ ب BM-، يرجى فحص %1 + + + + Error: The address %1 is not typed or copied correctly. Please check it. + خطأ: لم يتم إدخال أو نسخ العنوان %1 بطريقة صحيحة، يرجى فحصه. + + + + Error: The address %1 contains invalid characters. Please check it. + خطأ: العنوان %1 يحتوي على حروف غير صالحة، يرجى فحصه. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + خطأ: رقم إصدار العنوان %1 عالي جداً، إما أن تقوم بتحديث برنامج Bitmessage أو أن شريكك ذكي جدأ. + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + بعض البيانات المشفرة ضمن العنوان %1 قصيرة جداً. يمكن أن يكون هناك خطأ في برنامج شريكك. + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + بعض البيانات المشفرة ضمن العنوان %1 طويلة جداً. يمكن أن يكون هناك خطأ في برنامج شريكك. + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + خطأ: هناك خطأ في هذا العنوان %1. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + خطأ: يجب اختيار عنوان للإرسال منه، إن لم يكن لديك واحد إذهب إلى تبويب "هوياتك". + + + + Address version number + رقم إصدار العنوان + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + بالنظر إلى العنوان %1, Bitmessage لم يستطع فهم رقم إصدار العنوان %2، ربما يجب عليك تحديث برنامج Bitmessage لإصداره الأخير. + + + + Stream number + رقم المجرى + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + بالنظر إلى العنوان %1, Bitmessage لم يستطع فهم رقم إصدار العنوان %2، ربما يجب عليك تحديث برنامج Bitmessage لإصداره الأخير. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + تحذير: أنت غير متصل حالياً، Bitmessage سيقوم بالعمل اللازم لإرسال الرسالة و لكن لن يقوم بالإرسال حتى تصبح متصلاً. + + + + Message queued. + + + + + Your 'To' field is empty. + حقل "إلى" فارغ. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + أنقر يميناً على واحد أو أكثر من جهات الاتصال في دفتر العناوين و اختر "إرسال رسالة لهذا العنوان". + + + Fetched address from namecoin identity. تم تحصيل العنوان من هوية namecoin. - + New Message رسالة جديدة - + From من - + + Sending email gateway registration request + + + + + Address is valid. + العنوان صحيح + + + + The address you entered was invalid. Ignoring it. + العنوان الذي أدخلته غير صالح، سيتم تجاهله. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + خطأ: لا يمكنك إضافة نفس العنوان إلى دفتر العناوين مرتين، يمكنك إعادة تسمية العنوان. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + إعادة تشغيل + + + + You must restart Bitmessage for the port number change to take effect. + لتفعيل تغيير رقم نقطة العبور (port) يجب عليك إعادة تشغيل برنامج Bitmessage. + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). سيقوم Bitmessage باستخدام البروكسي الخاص بك من الآن فصاعداً و لكن يمكنك إعادة تشغيل Bitmessage يدوياً لإغلاق الروابط الحالية -إن وجدت. - + + Number needed + + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + + Will not resend ever + + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + عبارة المرور غير متطابقه + + + + The passphrase you entered twice doesn't match. Try again. + عبارة المرور التي أدخلتها مرتين غير متطابقه، أعد المحاولة. + + + + Choose a passphrase + اختر عبارة المرور + + + + You really do need a passphrase. + أنت بحاجة لعبارة مرور. + + + + Address is gone + تم إنتاج العنوان + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + لم يستطع Bitmessage العثور على عنوانك %1, ربما قمت بحذف العنوان؟ + + + + Address disabled + تم تعطيل العنوان + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + خطأ: العنوان المستخدم للإرسال منه معطل، يجب عليك تفعيله في تبويب "هوياتك" قبل استخدامه. + + + + Entry added to the Address Book. Edit the label to your liking. + تم إضافة جهة الاتصال لدفتر العناوين، يمكنك تعديل الإسم المستعار إذا أحببت. + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + تم نقل المادة لسلة المهملات. + + + + Undeleted item. + + + + Save As... حفظ بإسم - + Write error. خطأ كتابة. - - Options have been disabled because they either aren't applicable or because they haven't yet been implemented for your operating system. - تم تعطيل الخيارات لأنه إما أنها غير قابلة للتطبيق أو لم يتم برمجتها لنظام التشغيل الخاص بك. + + No addresses selected. + لم يتم اختيار عناوين - + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + + + + + You have already set an avatar for this address. Do you really want to overwrite it? + + + + + Start-on-login not yet supported on your OS. + + + + + Minimize-to-tray not yet supported on your OS. + + + + + Tray notifications not yet supported on your OS. + + + + Testing... اختبار... - + This is a chan address. You cannot use it as a pseudo-mailing list. هذا عنوان الزمرة، لا يمكنك إستخدامه كقائمة بريدية مستعاره. - + + The address should start with ''BM-'' + العنوان يجب أن يبدأ ب "BM-". + + + + The address is not typed or copied correctly (the checksum failed). + لم يتم إدخال أو نسخ العنوان بالطريقة الصحيحة - اختبار checksum فشل. + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + رقم إصدار هذا العنوان أعلى من إمكانية هذا البرنامج، قم بتحديث البرنامج. + + + + The address contains invalid characters. + العنوان يحتوي على حروف غير صحيحة + + + + Some data encoded in the address is too short. + بعض البيانات المشفرة ضمن العنوان قصيرة جداً + + + + Some data encoded in the address is too long. + بعض البيانات المشفرة ضمن العنوان طويلة جداً. + + + + Some data encoded in the address is malformed. + + + + + Enter an address above. + + + + + Address is an old type. We cannot display its past broadcasts. + + + + + There are no recent broadcasts from this address to display. + + + + + You are using TCP port %1. (This can be changed in the settings). + أنت تستخدم نقطة عبور TCP %1 - يمكنك تغييره في قائمة الضبط. + + + + Bitmessage + Bitmessage + + + + Identities + + + + + New Identity + + + + Search بحث - + All الكل - + + To + إلى + + + + From + من + + + + Subject + الموضوع + + + Message الرسالة - + + Received + تاريخ الإستلام + + + + Messages + + + + + Address book + + + + + Address + العنوان + + + + Add Contact + + + + Fetch Namecoin ID إحضار هوية namecoin - - Stream # - المجرى # + + Subject: + الموضوع: - - Connections - الروابط + + From: + من: - + + To: + إلى: + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + Subscriptions + الإشتراكات + + + + Add new Subscription + إدخال إشتراك جديدة + + + + Chans + + + + + Add Chan + + + + + File + ملف + + + + Settings + الضبط + + + + Help + مساعدة + + + + Import keys + إدراج المفاتيح + + + + Manage keys + إدارة المفاتيح + + + Ctrl+Q Ctrl+Q - + F1 F1 - + + Contact support + + + + + About + عن + + + + Regenerate deterministic addresses + إعادة إنتاج عناوين حتمية - غير عشوائية + + + + Delete all trashed messages + حذف سلة المهملات + + + Join / Create chan إنضمام / تكوين زمرة - - - MainWindows - - Address is valid. - L'adresse est valide. + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + @@ -1036,7 +1283,7 @@ The 'Random Number' option is selected by default but deterministic ad <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> - + @@ -1060,8 +1307,8 @@ The 'Random Number' option is selected by default but deterministic ad - Address version number: 3 - رقم إصدار العنوان: 3 + Address version number: 4 + @@ -1122,20 +1369,25 @@ The 'Random Number' option is selected by default but deterministic ad NewSubscriptionDialog - + Add new entry إضافة مدخل جديد - + Label إسم مستعار - + Address عنوان + + + Enter an address above. + + SpecialAddressBehaviorDialog @@ -1168,35 +1420,73 @@ The 'Random Number' option is selected by default but deterministic ad aboutDialog - + + About + عن البرنامج + + + PyBitmessage PyBitmessage - + version ? الإصدار ؟ - - About - عن البرنامج - - - - Copyright © 2013 Jonathan Warren - حقوق الحفظ © 2013 Warren Jonathan - - - + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> - + - + This is Beta software. هذه نسخة تجريبة للبرنامج + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + + connectDialog @@ -1230,8 +1520,8 @@ The 'Random Number' option is selected by default but deterministic ad - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + @@ -1267,6 +1557,119 @@ The 'Random Number' option is selected by default but deterministic ad أن على اتصال بباقي الأقران (المشاركين) و تم تضبيط الجدار الناري بطريقة صحيحة. + + networkstatus + + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + + + newChanDialog @@ -1292,7 +1695,7 @@ The 'Random Number' option is selected by default but deterministic ad <html><head/><body><p>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.</p></body></html> - + @@ -1366,315 +1769,295 @@ The 'Random Number' option is selected by default but deterministic ad settingsDialog - + Settings الضبط - + Start Bitmessage on user login إبدأ برنامج Bitmessage عند نقطة ولوج المستخدم - + + Tray + + + + Start Bitmessage in the tray (don't show main window) تشغيل البرنامج في شريط المهام - + Minimize to tray تصغير إلى شريط المهام - + + Close to tray + + + + Show notification when message received أظهر التنبيهات عن وصول رسالة - + Run in Portable Mode شغّل بالنظام المتنقل - + 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. في النظام المتنقل تكون الرسائل و ملفات الضبط محفوظة في مجلد البرنامج نفسه على خلاف بيانات البرنامج العادي، و بذلك يسهل تشغيل البرنامج من USB. - - User Interface - واجهة المستخدم - - - - Use Identicons - استخدم Identicons - - - - Interface Language - لغة العرض - - - - Listening port - نقطة عبور للإستماع - - - - Listen for connections on port: - استماع للروابط في نقطة عبور: - - - - Proxy server / Tor - خادم البروكسي / تور - - - - Type: - نوع: - - - - none - لا يوجد - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - - Server hostname: - إسم الخادم: - - - - Port: - نقطة عبور: - - - - Authentication - إثبات الهوية - - - - Username: - إسم المستخدم: - - - - Pass: - العبور: - - - - Network Settings - ضبط الشبكة - - - - 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. - عندما يقوم أحد المشاركين بإرسال رسالة لك يقوم حاسوبه بأداء بعض العمل، صعوبة هذا العمل هو 1، يمكنك زيادة هذا الرقم الإفتراضي للعناوين الجديدة بتغيير القيم هنا، لكل عنوان جديد على المرسل أن يصل على صعوبة أعلى، باستثناء المشاركين الذين قمت بإضافتهم إلى دفتر عناوينك، البرنامج سيقوم تلقائياً بتنبيه هؤلاء المشاركين عند قيامك بإرسال رسالة بأن عليهم إكمال أقل كمية من العمل: الصعوبة 1. - - - - Total difficulty: - الصعوبة الإجمالية: - - - - Small message difficulty: - صعوبة الرسالة الصغيرة: - - - - 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. - تقريبا كل صعوبات الرسائل الصغيرة تؤثر فقط على صعوبة إرسال الرسائل الصغيرة، بتضاعف هذه القيمة يجعلها تقريباً مرتين أصعب لإرسال رسالة ضغيرة و لكن لا تؤثر على الرسائل كبيرة الحجم. - - - - The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - الصعوبة الكلية تؤثر على الكمية المطلقة للعمل اللازم إكماله من قبل المرسل. تضاعف هذه القيمة يضاعف كمية العمل. - - - - Demanded difficulty - الصعوبة المطلوبة - - - - 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. - هنا يمكنك تحديد الكمية القصوى من العمل الذي ترغب بأدائه عندما ترسل رسالة لشخص آخر، تصفير هذه القيم يدل على قبولك بأي قيمة. - - - - Maximum acceptable total difficulty: - الصعوبة الكلية القصوى المقبولة: - - - - Maximum acceptable small message difficulty: - صعوبة الرسائل الصغيرة القصوى المقبولة: - - - - Max acceptable difficulty - الصعوبة القصوى المقبولة - - - + Willingly include unencrypted destination address when sending to a mobile device فضلاً أضف عنوان غير مشفر للمرسل إليه عندما ترسل إلى جهاز نقال - - Override automatic language localization (use countycode or language code, e.g. 'en_US' or 'en'): - تجاهل تحديد اللغة الآلي - استخدم رمز البلد أو رمز اللغة مثل 'en_US' أو 'en'-: + + Use Identicons + استخدم Identicons - + + Reply below Quote + + + + + Interface Language + لغة العرض + + + + System Settings + system + + + + + User Interface + واجهة المستخدم + + + + Listening port + نقطة عبور للإستماع + + + + Listen for connections on port: + استماع للروابط في نقطة عبور: + + + + UPnP: + + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + + Proxy server / Tor + خادم البروكسي / تور + + + + Type: + نوع: + + + + Server hostname: + إسم الخادم: + + + + Port: + نقطة عبور: + + + + Authentication + إثبات الهوية + + + + Username: + إسم المستخدم: + + + + Pass: + العبور: + + + Listen for incoming connections when using proxy أنصت للروابط الوارده عن استخدام البروكسي - - 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 test. (Getting your own Bitmessage address into Namecoin is still rather difficult). Bitmessage can use either namecoind directly or a running nmcontrol instance. - يستطيع برنامج Bitmessage استخدام برنامج مختلف يعتمد على Bitcoin و يسمى Namecoin لإنتاج عناوين سهله التداول بين البشر، على سيبل المثال بدلاً من أن تقوم بإخبار صديقك عن عنوانك Bitmessage الطويل، بإمكانك أن تطلب منه إرسال رسالة للإختبار، إدخال عنوانك الخاص إلى Namecoin يبقى صعب بالمقارنة. برنامج Bitmessage إما أن يستخدم namecoind مباشره أو يقوم بتشغيل طلب nmcontrol. + + none + لا يوجد - + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + ضبط الشبكة + + + + Total difficulty: + الصعوبة الإجمالية: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + الصعوبة الكلية تؤثر على الكمية المطلقة للعمل اللازم إكماله من قبل المرسل. تضاعف هذه القيمة يضاعف كمية العمل. + + + + Small message difficulty: + صعوبة الرسالة الصغيرة: + + + + 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. + عندما يقوم أحد المشاركين بإرسال رسالة لك يقوم حاسوبه بأداء بعض العمل، صعوبة هذا العمل هو 1، يمكنك زيادة هذا الرقم الإفتراضي للعناوين الجديدة بتغيير القيم هنا، لكل عنوان جديد على المرسل أن يصل على صعوبة أعلى، باستثناء المشاركين الذين قمت بإضافتهم إلى دفتر عناوينك، البرنامج سيقوم تلقائياً بتنبيه هؤلاء المشاركين عند قيامك بإرسال رسالة بأن عليهم إكمال أقل كمية من العمل: الصعوبة 1. + + + + 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. + تقريبا كل صعوبات الرسائل الصغيرة تؤثر فقط على صعوبة إرسال الرسائل الصغيرة، بتضاعف هذه القيمة يجعلها تقريباً مرتين أصعب لإرسال رسالة ضغيرة و لكن لا تؤثر على الرسائل كبيرة الحجم. + + + + Demanded difficulty + الصعوبة المطلوبة + + + + 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. + هنا يمكنك تحديد الكمية القصوى من العمل الذي ترغب بأدائه عندما ترسل رسالة لشخص آخر، تصفير هذه القيم يدل على قبولك بأي قيمة. + + + + Maximum acceptable total difficulty: + الصعوبة الكلية القصوى المقبولة: + + + + Maximum acceptable small message difficulty: + صعوبة الرسائل الصغيرة القصوى المقبولة: + + + + Max acceptable difficulty + الصعوبة القصوى المقبولة + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + + + + Host: المضيف: - + Password: كلمة العبور: - + Test اختبار - + Connect to: متصل ب: - + Namecoind Namecoind - + NMControl NMControl - + Namecoin integration دمج Namecoin - - 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. Leave these input fields blank for the default behavior. - إفتراضياً إذا أرسلت رسالة لشخص و هو غير متصل لأكثر من يومين سيقوم البرنامج بإرسال الرسالة مرة أخرى بعد يومين إضافيين، ستستمر عملية إعادة الإرسال بصور متباعده زمنياً، و عليه سيتم إعادة إرسال الرسائل بعد 5، 10، 20 يوم إلخ حتى يقوم المستلم بإرسال إشعار استلام الرسائل، هنا يمكنك تغيير أسلوب إعادة الإرسال و التوقف بعد عدة أيام أو شهور، أترك هذه الخانات فارغة لتفعيل الأسلوب الإفتراضي. + + <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> + - + Give up after توقف بعد - + and و - + days أيام - + months. شهور. - + Resends Expire إنتهاء صلاحية إعادة الإرسال - - hashtagDialog - - - Hashtag - هاشتاق - - - - Trending Hashtags - الهاشتاقات النشطة - - - - Day - يوم - - - - Week - أسبوع - - - - Month - شهر - - - - All Time - كل الأوقات - - - - Popularity - الشعبية - - - - NewGroupDialog - - - Add new entry - إضافة مدخل جديد - - - - Label - الإسم المستعار - - - - Address - العنوان - - - - Group Name - إسم المجموعة - - - + \ No newline at end of file diff --git a/src/translations/bitmessage_cs.pro b/src/translations/bitmessage_cs.pro deleted file mode 100755 index db58da97..00000000 --- a/src/translations/bitmessage_cs.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_objectProcessor.py\ - ../class_outgoingSynSender.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_cs.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_cs.qm b/src/translations/bitmessage_cs.qm index 6aadf62b..72db6210 100644 Binary files a/src/translations/bitmessage_cs.qm and b/src/translations/bitmessage_cs.qm differ diff --git a/src/translations/bitmessage_cs.ts b/src/translations/bitmessage_cs.ts old mode 100755 new mode 100644 index c16012c9..ac959a64 --- a/src/translations/bitmessage_cs.ts +++ b/src/translations/bitmessage_cs.ts @@ -1,6 +1,4 @@ - - - + AddAddressDialog @@ -19,210 +17,334 @@ Adresa + + EmailGatewayDialog + + + Email gateway + Email brána + + + + Register on email gateway + + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + MainWindow - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - Jedna z Vašich adres, %1, je stará adresa verze 1. Adresy verze 1 již nejsou podporovány. Můžeme ji nyní smazat? + + Reply to sender + - - Reply - Odpovědět + + Reply to channel + - + Add sender to your Address Book Přidat odesilatele do Vašeho adresáře - + + Add sender to your Blacklist + + + + Move to Trash Přesunout do koše - + + Undelete + + + + View HTML code as formatted text Zobrazit HTML kód jako formátovaný text - + Save message as... Uložit zprávu jako... - + Mark Unread Označit jako nepřečtené - + New Nové - + Enable Zapnout - + Disable Vypnout - + + Set avatar... + Nastavit avatar... + + + Copy address to clipboard Zkopírovat adresu do clipboardu - + Special address behavior... Speciální chování adresy... - - Send message to this address - Poslat zprávu na tuto adresu + + Email gateway + Email brána - - Subscribe to this address - Přihlásit se k odběru této adresy - - - - Add New Address - Přidat novou adresu - - - + Delete Odstranit - + + Send message to this address + Poslat zprávu na tuto adresu + + + + Subscribe to this address + Přihlásit se k odběru této adresy + + + + Add New Address + Přidat novou adresu + + + Copy destination address to clipboard Zkopírovat cílovou adresu do clipboardu - + Force send Přesto odeslat - - Add new entry - Přidat novou položku + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + Jedna z Vašich adres, %1, je stará adresa verze 1. Adresy verze 1 již nejsou podporovány. Můžeme ji nyní smazat? - - Since startup on %1 - Od spuštění v %1 - - - + Waiting for their encryption key. Will request it again soon. Čekám na šifrovací klíč. Požadavek bude brzy vyslán znovu. - + Encryption key request queued. Požadavek na šifrovací klíč zařazen do fronty. - + Queued. Zařazeno do fronty. - + Message sent. Waiting for acknowledgement. Sent at %1 Zpráva odeslána. Čekám na potvrzení. Odesláno v %1 - + Message sent. Sent at %1 Zpráva odeslána. Odesláno v %1 - + Need to do work to send message. Work is queued. Pro poslání zprávy musím provést práci. Práce byla zařazena do fronty. - + Acknowledgement of the message received %1 Potvrzení o přijetí zprávy %1 - + Broadcast queued. Rozeslání zařazeno do fronty. - + Broadcast on %1 Rozesláno v %1 - + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 Problém: Obtížnost práce požadovaná adresátem je vyšší než Vámi povolené maximum. %1 - + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 Problém: Šifrovací klíč adresáta je nepoužitelný. Zprávu nelze zašifrovat. %1 - + Forced difficulty override. Send should start soon. Vyžádáno odeslání navzdory obtížnosti. Zpráva bude brzy odeslána. - + Unknown status: %1 %2 Neznámý stav: %1 %2 - + Not Connected Nepřipojeno - + Show Bitmessage Ukázat Bitmessage - + Send Poslat - + Subscribe Přihlásit se k odběru - - Address Book - Adresář + + Channel + - + Quit Ukončit - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Své klíče můžete spravovat editováním souboru keys.dat, který najdete ve stejném adresáři jako tento program. Je důležité si tento soubor zazálohovat. - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. @@ -231,17 +353,17 @@ It is important that you back up this file. Je důležité si tento soubor zazálohovat. - + Open keys.dat? Otevřít soubor keys.dat? - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) Své klíče můžete spravovat editováním souboru keys.dat, který najdete ve stejném adresáři jako tento program. Je důležité si tento soubor zazálohovat. Přejete si tento soubor nyní otevřít? (Nezapomeňte zavřít Bitmessage předtím, než provedete jakékoli změny.) - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) @@ -250,787 +372,898 @@ It is important that you back up this file. Would you like to open the file now? Je důležité si tento soubor zazálohovat. Přejete si tento soubor nyní otevřít? (Nezapomeňte zavřít Bitmessage předtím, než provedete jakékoli změny.) - + Delete trash? Smazat obsah koše? - + Are you sure you want to delete all trashed messages? Opravdu chcete smazat všechny zprávy v koši? - + bad passphrase špatné heslo - + You must type your passphrase. If you don't have one then this is not the form for you. Musíte napsat své heslo. Pokud žádné nemáte, pak tento formulář není pro Vás. - - Chan name needed - Je třeba zadat jméno kanálu - - - - You didn't enter a chan name. - Nezadal(a) jste jméno kanálu. - - - - Address already present - Adresa je již přítomna - - - - Could not add chan because it appears to already be one of your identities. - Nelze přidat kanál. Zdá se, že ho již máte mezi svými identitami. - - - - Success - Úspěch - - - - Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. - Kanál byl úspěšně vytvořen. Když chcete jiným lidem povolit připojit se k Vašemu kanálu, řekněte jim jméno kanálu a tuto adresu Bitmessage: %1. Tuto adresu také najdete v sekci "Vaše identity". - - - - Address too new - Adresa je příliš nová - - - - Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. - Tato adresa Bitmessage může být platná, je to však adresa vyšší verze, se kterou neumíme pracovat. Možná byste měl(a) aktualizovat Bitmessage. - - - - Address invalid - Adresa je neplatná - - - - That Bitmessage address is not valid. - Toto není platná adresa Bitmessage. - - - - Address does not match chan name - Adresa nepatří ke jménu kanálu - - - - Although the Bitmessage address you entered was valid, it doesn't match the chan name. - Adresa Bitmessage, kterou jste zadal(a), je sice platná, nepatří však ke kanálu s tímto jménem. - - - - Successfully joined chan. - Úspěšně jste se připojil(a) ke kanálu. - - - - Processed %1 person-to-person messages. - Zpracováno %1 osobních zpráv. - - - - Processed %1 broadcast messages. - Zpracováno %1 hromadných zpráv. - - - - Processed %1 public keys. - Zpracováno %1 veřejných klíčů. - - - - Total Connections: %1 - Celkový počet připojení: %1 - - - - Connection lost - Připojení ztraceno - - - - Connected - Připojeno - - - - Message trashed - Zpráva byla vyhozena do koše - - - - Error: Bitmessage addresses start with BM- Please check %1 - Chyba: Adresy Bitmessage začínají na BM- Zkontroluje prosím %1 - - - - Error: The address %1 is not typed or copied correctly. Please check it. - Chyba: Adresa %1 nebyla správně opsána nebo zkopírována. Zkontrolujte ji prosím. - - - - Error: The address %1 contains invalid characters. Please check it. - Chyba: Adresa %1 obsahuje neplatné znaky. Zkontrolujte ji prosím. - - - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - Chyba: Verze adresy %1 je příliš vysoká. Buď používáte starou verzi Bitmessage a je čas na aktualizaci, nebo si Váš známý dělá legraci. - - - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - Chyba: Některá data zakódovaná v adrese %1 jsou příliš krátká. Možná je to chyba softwaru, který Váš známý používá. - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - Chyba: Některá data zakódovaná v adrese %1 jsou příliš dlouhá. Možná je to chyba softwaru, který Váš známý používá. - - - - Error: Something is wrong with the address %1. - Chyba: Nastal problém s adresou %1. - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - Chyba: V poli "Od" musíte uvést adresu. Pokud žádnou nemáte, klikněte na kartu "Vaše identity". - - - - Address version number - Číslo verze adresy - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - Co se týče adresy %1, Bitmessage nerozumí jejímu číslu verze "%2". Možná byste měl(a) aktualizovat Bitmessage na nejnovější verzi. - - - - Stream number - Číslo proudu - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - Co se týče adresy %1, Bitmessage neumí zpracovat její číslo proudu "%2". Možná byste měl(a) aktualizovat Bitmessage na nejnovější verzi. - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - Varování: Nyní nejste připojen(a). Bitmessage provede práci potřebnou k pro odeslání zprávy, ale neodešle ji, dokud se nepřipojíte. - - - - Your 'To' field is empty. - Pole "Komu" je prázdné. - - - - Right click one or more entries in your address book and select 'Send message to this address'. - Klikněte pravým tlačítkem na jeden nebo více záznamů v adresáři, a vyberte "Poslat zprávu na tuto adresu". - - - - Fetched address from namecoin identity. - Adresa načtena z namecoinové identity. - - - - Work is queued. %1 - Práce je zařazena ve frontě. %1 - - - - New Message - Nová zpráva - - - - From - Od - - - - Address is valid. - Adresa je platná. - - - - The address you entered was invalid. Ignoring it. - Zadaná adresa je neplatná, ignoruji jí. - - - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - Chyba: Nemůžete do adresáře přidat adresu, která tam již je. Můžete ale tu existující přejmenovat. - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - Chyba: Nemůžete do odběrů přidat adresu, která tam již je. Můžete ale tu existující přejmenovat. - - - - Restart - Restart - - - - You must restart Bitmessage for the port number change to take effect. - Je třeba restartovat Bitmessage, aby se změna portu projevila. - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). - Bitmessage bude od teď používat Váš proxy server. Bude ale jistější, když nyní Bitmessage restartujete, abyste zavřel(a) všechna aktivní připojení (pokud nějaká jsou). - - - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - Chyba: Nemůžete na listinu přidat adresu, která tam již je. Můžete ale tu existující přejmenovat. - - - - Passphrase mismatch - Hesla nejsou stejná - - - - The passphrase you entered twice doesn't match. Try again. - Zadaná hesla nejsou stejná. Zkuste to znovu. - - - - Choose a passphrase - Zvolte heslo - - - - You really do need a passphrase. - Opravdu je nutné zvolit heslo. - - - - All done. Closing user interface... - Vše hotovo. Zavírám uživatelské rozhraní... - - - - Address is gone - Adresa je pryč - - - - Bitmessage cannot find your address %1. Perhaps you removed it? - Bitmessage nemůže najít Vaši adresu %1. Možná jste ji odstranil(a)? - - - - Address disabled - Adresa je vypnutá - - - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - Chyba: Adresa, ze které se snažíte poslat zprávu, je vypnutá. Před použitím ji musíte zapnout na kartě "Vaše identity". - - - - Entry added to the Address Book. Edit the label to your liking. - Položka byla přidána do adresáře. Popisku můžete upravit dle svého přání. - - - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - Položky byly přesunuty do koše. Koš nemá uživatelské rozhraní, ale jeho obsah je stále na disku, pro případ že ho nutně potřebujete obnovit. - - - - Save As... - Uložit jako... - - - - Write error. - Chyba zápisu. - - - - No addresses selected. - Není vybrána žádná adresa. - - - - Testing... - Zkouším... - - - - This is a chan address. You cannot use it as a pseudo-mailing list. - Toto je adresa kanálu. Není možné ji použít jako pseudo-mailing list. - - - - The address should start with ''BM-'' - Adresa by měla začínat "BM-" - - - - The address is not typed or copied correctly (the checksum failed). - Adresa nebyla správně opsána nebo zkopírována (kontrolní součet nesouhlasí). - - - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - Verze této adresy je vyšší než s jakou tento software umí pracovat. Prosím aktualizujte Bitmessage. - - - - The address contains invalid characters. - Adresa obsahuje neplatné znaky. - - - - Some data encoded in the address is too short. - Některá data zakódovaná v této adrese jsou příliš krátká. - - - - Some data encoded in the address is too long. - Některá data zakódovaná v této adrese jsou příliš dlouhá. - - - - You are using TCP port %1. (This can be changed in the settings). - Používáte TCP port %1. (To lze změnit v nastavení). - - - - Bitmessage - Bitmessage - - - - Search - Hledej - - - - All - Vše - - - - To - Komu - - - - From - Od - - - - Subject - Předmět - - - - Message - Zpráva - - - - Received - Doručeno - - - - Inbox - Doručené - - - - Load from Address book - Vybrat z adresáře - - - - Fetch Namecoin ID - Načíst Namecoin ID - - - - Message: - Zpráva: - - - - Subject: - Předmět: - - - - Send to one or more specific people - Poslat jednomu nebo více konkrétním lidem - - - - To: - Komu: - - - - From: - Od: - - - - Broadcast to everyone who is subscribed to your address - Rozeslat všem, kteří odebírají Vaši adresu - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - Mějte na paměti, že rozesílané zprávy jsou šifrovány jen Vaší adresou. Kdokoli, kdo zná Vaši adresu, je může číst. - - - - Status - Stav - - - - Sent - Odeslané - - - - Label (not shown to anyone) - Popiska (nikomu se neukazuje) - - - - Address - Adresa - - - - Stream - Proud - - - - Your Identities - Vaše identity - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - Zde se můžete přihlásit k odběru veřejných zpráv, rozesílaných jinými uživateli. Zprávy uvidíte ve své doručené poště. Na adresy uvedené zde nemá vliv nastavení černé listiny. - - - - Add new Subscription - Přidat nový odběr - - - - Label - Popiska - - - - Subscriptions - Odběry - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - Adresář umožňuje přidat jména nebo popisky k Bitmessage adresám jiných lidí, takže je ve své doručené poště lépe rozpoznáte. Položky můžete přidávat buď kliknutím na tlačítko přidat, nebo ze své doručené pošty, když kliknete na nějakou zprávu pravým tlačítkem. - - - - Name or Label - Jméno nebo popiska - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - Použít černou listinu (povolit všechny příchozí zprávy kromě těch od adres na černé listině) - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - Použít bílou listinu (blokovat všechny příchozí zprávy kromě těch od adres na bílé listině) - - - - Blacklist - Černá listina - - - - Stream # - Číslo proudu - - - - Connections - Připojení - - - - Total connections: 0 - Celkový počet připojení: 0 - - - - Since startup at asdf: - Od spuštění v asdf: - - - - Processed 0 person-to-person message. - Zpracováno 0 osobních zpráv. - - - - Processed 0 public key. - Zpracováno 0 veřejných klíčů. - - - - Processed 0 broadcast. - Zpracováno 0 hromadných zpráv. - - - - Network Status - Stav sítě - - - - File - Soubor - - - - Settings - Nastavení - - - - Help - Nápověda - - - - Import keys - Importovat klíče - - - - Manage keys - Správa klíčů - - - - Ctrl+Q - Ctrl+Q - - - - F1 - F1 - - - - About - O aplikaci - - - - Regenerate deterministic addresses - Obnovit deterministické adresy - - - - Delete all trashed messages - Smazat všechny zprávy v koši - - - - Join / Create chan - Připojit ke kanálu / Vytvořit kanál - - - - Set avatar... - Nastavit avatar... - - - + Bad address version number Špatné číslo verze adresy - + Your address version number must be a number: either 3 or 4. Verze Vaší adresy musí být číslo: buď 3 nebo 4. - + Your address version number must be either 3 or 4. Verze Vaší adresy musí být buď 3 nebo 4. - - Inventory lookups per second: %1 - Počet kontrol inventáře za sekundu: %1 + + Chan name needed + Je třeba zadat jméno kanálu - - Will not resend ever - Nikdy nebude nic posláno znovu + + You didn't enter a chan name. + Nezadal(a) jste jméno kanálu. - - Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. - Všimněte si, že časový limit, který jste zadal(a), je menší, než čas po kterém Bitmessage poprvé zkusí opětovné odeslání, proto Vaše zprávy nebudou nikdy poslány znovu. + + Address already present + Adresa je již přítomna - - Do you really want to remove this avatar? - Opravdu chcete odstranit tento avatar? + + Could not add chan because it appears to already be one of your identities. + Nelze přidat kanál. Zdá se, že ho již máte mezi svými identitami. - - You have already set an avatar for this address. Do you really want to overwrite it? - Pro tuto adresu již avatar máte. Opravdu ho chcete přepsat? + + Success + Úspěch - - Start-on-login not yet supported on your OS. - Spuštění po přihlášení není zatím na Vašem operačním systému podporováno. + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + Kanál byl úspěšně vytvořen. Když chcete jiným lidem povolit připojit se k Vašemu kanálu, řekněte jim jméno kanálu a tuto adresu Bitmessage: %1. Tuto adresu také najdete v sekci "Vaše identity". - - Minimize-to-tray not yet supported on your OS. - Minimalizace na lištu není zatím na Vašem operačním systému podporována. + + Address too new + Adresa je příliš nová - - Tray notifications not yet supported on your OS. - Upozornění v liště nejsou zatím na Vašem operačním systému podporována. + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + Tato adresa Bitmessage může být platná, je to však adresa vyšší verze, se kterou neumíme pracovat. Možná byste měl(a) aktualizovat Bitmessage. - - Enter an address above. - Zadejte adresu výše. + + Address invalid + Adresa je neplatná - - Address is an old type. We cannot display its past broadcasts. - Toto je starý typ adresy. Neumíme zobrazit její rozesílané zprávy. + + That Bitmessage address is not valid. + Toto není platná adresa Bitmessage. - - There are no recent broadcasts from this address to display. - Z této adresy nebyly v poslední době rozesílány žádné zprávy. + + Address does not match chan name + Adresa nepatří ke jménu kanálu - - Display the %1 recent broadcast from this address. - Zobrazit %1 zprávu nedávno rozeslanou z této adresy. + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + Adresa Bitmessage, kterou jste zadal(a), je sice platná, nepatří však ke kanálu s tímto jménem. - - Display the %1 recent broadcasts from this address. - Zobrazit %1 zpráv nedávno rozeslaných z této adresy. + + Successfully joined chan. + Úspěšně jste se připojil(a) ke kanálu. - - Inventory lookups per second: 0 - Počet kontrol inventáře za sekundu: 0 + + Connection lost + Připojení ztraceno - - Down: %1/s Total: %2 - Stahování: %1/s Celkem: %2 + + Connected + Připojeno - - Up: %1/s Total: %2 - Odesílání: %1/s Celkem: %2 + + Message trashed + Zpráva byla vyhozena do koše - + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + Message too long Zpráva je příliš dlouhá - + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. Zpráva, kterou se snažíte poslat, je o %1 bajtů delší, než je dovoleno. (Maximum je 261644 bajtů). Zkuste ji prosím před odesláním zkrátit. - + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + Chyba: Adresy Bitmessage začínají na BM- Zkontroluje prosím %1 + + + + Error: The address %1 is not typed or copied correctly. Please check it. + Chyba: Adresa %1 nebyla správně opsána nebo zkopírována. Zkontrolujte ji prosím. + + + + Error: The address %1 contains invalid characters. Please check it. + Chyba: Adresa %1 obsahuje neplatné znaky. Zkontrolujte ji prosím. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + Chyba: Verze adresy %1 je příliš vysoká. Buď používáte starou verzi Bitmessage a je čas na aktualizaci, nebo si Váš známý dělá legraci. + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + Chyba: Některá data zakódovaná v adrese %1 jsou příliš krátká. Možná je to chyba softwaru, který Váš známý používá. + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + Chyba: Některá data zakódovaná v adrese %1 jsou příliš dlouhá. Možná je to chyba softwaru, který Váš známý používá. + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. Chyba: Některá data zakódovaná v adrese %1 mají neplatný formát. Možná je to chyba softwaru, který Váš známý používá. - + + Error: Something is wrong with the address %1. + Chyba: Nastal problém s adresou %1. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Chyba: V poli "Od" musíte uvést adresu. Pokud žádnou nemáte, klikněte na kartu "Vaše identity". + + + + Address version number + Číslo verze adresy + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Co se týče adresy %1, Bitmessage nerozumí jejímu číslu verze "%2". Možná byste měl(a) aktualizovat Bitmessage na nejnovější verzi. + + + + Stream number + Číslo proudu + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Co se týče adresy %1, Bitmessage neumí zpracovat její číslo proudu "%2". Možná byste měl(a) aktualizovat Bitmessage na nejnovější verzi. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Varování: Nyní nejste připojen(a). Bitmessage provede práci potřebnou k pro odeslání zprávy, ale neodešle ji, dokud se nepřipojíte. + + + + Message queued. + + + + + Your 'To' field is empty. + Pole "Komu" je prázdné. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Klikněte pravým tlačítkem na jeden nebo více záznamů v adresáři, a vyberte "Poslat zprávu na tuto adresu". + + + + Fetched address from namecoin identity. + Adresa načtena z namecoinové identity. + + + + New Message + Nová zpráva + + + + From + Od + + + + Sending email gateway registration request + + + + + Address is valid. + Adresa je platná. + + + + The address you entered was invalid. Ignoring it. + Zadaná adresa je neplatná, ignoruji jí. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Chyba: Nemůžete do adresáře přidat adresu, která tam již je. Můžete ale tu existující přejmenovat. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + Restart + + + + You must restart Bitmessage for the port number change to take effect. + Je třeba restartovat Bitmessage, aby se změna portu projevila. + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + Bitmessage bude od teď používat Váš proxy server. Bude ale jistější, když nyní Bitmessage restartujete, abyste zavřel(a) všechna aktivní připojení (pokud nějaká jsou). + + + Number needed Je třeba zadat číslo - + Your maximum download and upload rate must be numbers. Ignoring what you typed. Limity pro rychlost stahování a odesílání musejí být čísla. Vámi zadané hodnoty nelze použít. - + + Will not resend ever + Nikdy nebude nic posláno znovu + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + Všimněte si, že časový limit, který jste zadal(a), je menší, než čas po kterém Bitmessage poprvé zkusí opětovné odeslání, proto Vaše zprávy nebudou nikdy poslány znovu. + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + Hesla nejsou stejná + + + + The passphrase you entered twice doesn't match. Try again. + Zadaná hesla nejsou stejná. Zkuste to znovu. + + + + Choose a passphrase + Zvolte heslo + + + + You really do need a passphrase. + Opravdu je nutné zvolit heslo. + + + + Address is gone + Adresa je pryč + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmessage nemůže najít Vaši adresu %1. Možná jste ji odstranil(a)? + + + + Address disabled + Adresa je vypnutá + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Chyba: Adresa, ze které se snažíte poslat zprávu, je vypnutá. Před použitím ji musíte zapnout na kartě "Vaše identity". + + + + Entry added to the Address Book. Edit the label to your liking. + Položka byla přidána do adresáře. Popisku můžete upravit dle svého přání. + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + Položky byly přesunuty do koše. + + + + Undeleted item. + + + + + Save As... + Uložit jako... + + + + Write error. + Chyba zápisu. + + + + No addresses selected. + Není vybrána žádná adresa. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + Opravdu chcete odstranit tento avatar? + + + + You have already set an avatar for this address. Do you really want to overwrite it? + Pro tuto adresu již avatar máte. Opravdu ho chcete přepsat? + + + + Start-on-login not yet supported on your OS. + Spuštění po přihlášení není zatím na Vašem operačním systému podporováno. + + + + Minimize-to-tray not yet supported on your OS. + Minimalizace na lištu není zatím na Vašem operačním systému podporována. + + + + Tray notifications not yet supported on your OS. + Upozornění v liště nejsou zatím na Vašem operačním systému podporována. + + + + Testing... + Zkouším... + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + Toto je adresa kanálu. Není možné ji použít jako pseudo-mailing list. + + + + The address should start with ''BM-'' + Adresa by měla začínat "BM-" + + + + The address is not typed or copied correctly (the checksum failed). + Adresa nebyla správně opsána nebo zkopírována (kontrolní součet nesouhlasí). + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + Verze této adresy je vyšší než s jakou tento software umí pracovat. Prosím aktualizujte Bitmessage. + + + + The address contains invalid characters. + Adresa obsahuje neplatné znaky. + + + + Some data encoded in the address is too short. + Některá data zakódovaná v této adrese jsou příliš krátká. + + + + Some data encoded in the address is too long. + Některá data zakódovaná v této adrese jsou příliš dlouhá. + + + Some data encoded in the address is malformed. Některá data zakódovaná v této adrese mají neplatný formát. - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + Enter an address above. + Zadejte adresu výše. - - Down: 0 KB/s - Stahování: 0 KB/s + + Address is an old type. We cannot display its past broadcasts. + Toto je starý typ adresy. Neumíme zobrazit její rozesílané zprávy. - - Up: 0 KB/s - Odesílání: 0 KB/s + + There are no recent broadcasts from this address to display. + Z této adresy nebyly v poslední době rozesílány žádné zprávy. + + + + You are using TCP port %1. (This can be changed in the settings). + Používáte TCP port %1. (To lze změnit v nastavení). + + + + Bitmessage + Bitmessage + + + + Identities + + + + + New Identity + + + + + Search + Hledej + + + + All + Vše + + + + To + Komu + + + + From + Od + + + + Subject + Předmět + + + + Message + Zpráva + + + + Received + Doručeno + + + + Messages + + + + + Address book + + + + + Address + Adresa + + + + Add Contact + + + + + Fetch Namecoin ID + Načíst Namecoin ID + + + + Subject: + Předmět: + + + + From: + Od: + + + + To: + Komu: + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + Subscriptions + Odběry + + + + Add new Subscription + Přidat nový odběr + + + + Chans + + + + + Add Chan + + + + + File + Soubor + + + + Settings + Nastavení + + + + Help + Nápověda + + + + Import keys + Importovat klíče + + + + Manage keys + Správa klíčů + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + + + + + About + O aplikaci + + + + Regenerate deterministic addresses + Obnovit deterministické adresy + + + + Delete all trashed messages + Smazat všechny zprávy v koši + + + + Join / Create chan + Připojit ke kanálu / Vytvořit kanál + + + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + @@ -1057,6 +1290,11 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi Use a random number generator to make an address Použít generátor náhodných čísel k vytvoření adresy + + + Use a passphrase to make addresses + Použít k vytvoření adres heslo + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter @@ -1067,6 +1305,11 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi Make deterministic addresses Vytvořit deterministické adresy + + + Address version number: 4 + Číslo verze adresy: 4 + In addition to your passphrase, you must remember these numbers: @@ -1122,16 +1365,6 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi (saves you some bandwidth and processing power) (šetří přenesená data a práci procesoru) - - - Use a passphrase to make addresses - Použít k vytvoření adres heslo - - - - Address version number: 4 - Číslo verze adresy: 4 - NewSubscriptionDialog @@ -1152,8 +1385,8 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi - CheckBox - CheckBox + Enter an address above. + @@ -1186,6 +1419,11 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi aboutDialog + + + About + O aplikaci + PyBitmessage @@ -1196,11 +1434,6 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi version ? verze ? - - - About - O aplikaci - <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> @@ -1213,13 +1446,46 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 The Bitmessage Developers</p></body></html> - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 Vývojáři Bitmessage</p></body></html> + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + - - <html><head/><body><p>Copyright © 2012-2014 Jonathan Warren<br/>Copyright © 2013-2014 The Bitmessage Developers</p></body></html> - <html><head/><body><p>Copyright © 2012-2014 Jonathan Warren<br/>Copyright © 2013-2014 Vývojáři Bitmessage</p></body></html> + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + @@ -1254,8 +1520,8 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + @@ -1275,6 +1541,11 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi You have no connections with other peers. Nemáte žádná připojení k jiným uzlům. + + + 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'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. + Úspěšně jste se připojil(a) k jednomu či více uzlům pomocí odchozího spojení, ale nepřijal(a) jste žádná příchozí spojení. Váš firewall nebo domácí router pravděpodobně nemá nakonfigurováno přeposílání příchozích TCP připojení na Váš počítač. Bitmessage bude fungovat i bez toho, síti Bitmessage ale můžete pomoci, pokud povolíte příchozí připojení a stanete tak se lépe propojeným uzlem. + You are using TCP port ?. (This can be changed in the settings). @@ -1285,10 +1556,118 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi You do have connections with other peers and your firewall is correctly configured. Máte připojení k jiným uzlům a Váš firewall je správně nastaven. + + + networkstatus - - 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'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. - Úspěšně jste se připojil(a) k jednomu či více uzlům pomocí odchozího spojení, ale nepřijal(a) jste žádná příchozí spojení. Váš firewall nebo domácí router pravděpodobně nemá nakonfigurováno přeposílání příchozích TCP připojení na Váš počítač. Bitmessage bude fungovat i bez toho, síti Bitmessage ale můžete pomoci, pokud povolíte příchozí připojení a stanete tak se lépe propojeným uzlem. + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + @@ -1356,6 +1735,11 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi Number of addresses to make based on your passphrase: Počet adres, které mají být odvozeny od Vašeho hesla: + + + Address version number: + Číslo verze adresy: + Stream number: @@ -1381,338 +1765,299 @@ Možnost "Náhodné číslo" je nastavena jako výchozí, deterministi 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. Pokud jste dříve vytvořil(a) deterministické adresy, a ztratil(a) jste je při nějaké nehodě (jako třeba selhání harddisku), můžete je zde obnovit. Pokud jste k vytvoření adres použil(a) generátor náhodných čísel, pak Vám tento formulář nijak nepomůže. - - - Address version number: - Číslo verze adresy: - settingsDialog - + Settings Nastavení - + Start Bitmessage on user login Spustit Bitmessage po přihlášení uživatele - + + Tray + + + + Start Bitmessage in the tray (don't show main window) Spustit Bitmessage v liště (neukazovat hlavní okno) - + Minimize to tray Minimalizovat na lištu - + + Close to tray + + + + Show notification when message received Zobrazit upozornění na příchozí zprávu - + Run in Portable Mode Spustit v přenosném režimu - + 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. V přenosném režimu jsou zprávy a konfigurační soubory ukládány ve stejném adresáři jako program, namísto normálního adresáře pro data aplikací. To se hodí, když chcete Bitmessage spouštět z USB flashdisku. - - User Interface - Uživatelské rozhraní - - - - Listening port - Port pro naslouchání - - - - Listen for connections on port: - Naslouchat příchozím připojením na portu: - - - - Proxy server / Tor - Proxy server / Tor - - - - Type: - Typ: - - - - none - žádný - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - - Server hostname: - Jméno serveru: - - - - Port: - Port: - - - - Authentication - Přihlášení - - - - Username: - Uživatelské jméno: - - - - Pass: - Heslo: - - - - Network Settings - Nastavení sítě - - - - 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. - Když Vám někdo pošle zprávu, jeho počítač musí nejprve provést určitou práci. Výchozí obtížnost práce je 1. Tuto hodnotu můžete zvýšit tím, že zvýšíte zde uvedené hodnoty. Všechny nové adresy, které vytvoříte, budou po odesilatelích vyžadovat tuto vyšší obtížnost. Existuje jedna výjimka: když si kamaráda nebo známého přidáte do adresáře, při příští zprávě, kterou mu pošlete, ho Bitmessage upozorní, že mu od teď stačí provést minimální množství práce (obtížnost 1) když Vám chce poslat zprávu. - - - - Total difficulty: - Celková obtížnost: - - - - Small message difficulty: - Obtížnost pro malou zprávu: - - - - 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. - "Obtížnost pro malou zprávu" ovlivňuje pouze obtížnost posílání malých zpráv. Pokud ji zdvojnásobíte, bude dvakrát obtížnější poslat malou zprávu, ale velké zprávy to nijak neovlivní. - - - - The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - "Celková obtížnost" ovlivňuje množství práce, kterou musí odesilatel provést. Zdvojnásobením této hodnoty zdvojnásobíte množství práce. - - - - Demanded difficulty - Požadovaná obtížnost - - - + Willingly include unencrypted destination address when sending to a mobile device Přiložit nezašifrovanou cílovou adresu při posílání zprávy na mobilní zařízení - - Listen for incoming connections when using proxy - Naslouchat příchozím připojením při použití proxy - - - - 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. - Zde můžete nastavit maximální množství práce, které je pro Vás přijatelné, když posíláte zprávu jiné osobě. Nastavení 0 znamená, že množství není omezeno. - - - - Maximum acceptable total difficulty: - Maximální přijatelná celková obtížnost: - - - - Maximum acceptable small message difficulty: - Maximální přijatelná obtížnost pro malou zprávu: - - - - Max acceptable difficulty - Maximální přijatelná obtížnost - - - - <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> - <html><head/><body><p>Bitmessage může použít jiný program založený na technologii Bitcoin, který se jmenuje Namecoin, a nahradit tak adresy lépe čitelnými jmény. Příklad: místo toho, abyste musel(a) kamarádovi diktovat svou dlouhou adresu Bitmessage, můžete mu jednoduše říct, ať pošle zprávu na jméno <span style=" font-style:italic;">test. </span></p><p>(Vložit svou adresu Bitmessage do Namecoin je zatím stále celkem složité).</p><p>Bitmessage může použít buď přímo namecoind, nebo běžící instanci nmcontrol.</p></body></html> - - - - Host: - Server: - - - - Password: - Heslo: - - - - Test - Zkouška - - - - Connect to: - Připojit k: - - - - Namecoind - Namecoind - - - - NMControl - NMControl - - - - Namecoin integration - Integrace s Namecoin - - - + Use Identicons Používat identikony - + + Reply below Quote + Odpověď pod citací + + + Interface Language Jazyk pro rozhraní - + System Settings system Dle nastavení systému - - English - en - English - - - - Esperanto - eo - Esperanto - - - - Français - fr - Français - - - - Deutsch - de - Deutsch - - - - Españl - es - Españl - - - - русский язык - ru - русский язык - - - - Norsk - no - Norsk + + User Interface + Uživatelské rozhraní - Pirate English - en_pirate - Pirate English + Listening port + Port pro naslouchání - Other (set in keys.dat) - other - Jiný (nastavený v keys.dat) + Listen for connections on port: + Naslouchat příchozím připojením na portu: - - <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> - <html><head/><body><p>Výchozí nastavení funguje tak, že když pošlete zprávu někomu, kdo je odpojen více než dva dny, Bitmessage tuto zprávu za další dva dny pošle znovu. To bude pokračovat, ale intervaly se budou exponenciálně prodlužovat; zprávy budou znovu poslány za 5, 10, 20 dní atd. dokud adresát nepotvrdí jejich přijetí. Zde můžete toto chování změnit, a nastavit, aby to Bitmessage vzdal, pokud zpráva nebude doručena do určitého počtu dní či měsíců.</p><p>Ponechte tato pole prázdná, pokud chcete použít výchozí chování. </p></body></html> + + UPnP: + - - Give up after - Vzdát to po - - - - and - a - - - - days - dnech - - - - months. - měsících. - - - - Resends Expire - Lhůta pro opětovné poslání - - - - Reply below Quote - Odpověď pod citací - - - + Bandwidth limit Omezení rychlosti - + Maximum download rate (kB/s): [0: unlimited] Maximální rychlost stahování (kB/s): [0: bez omezení] - + Maximum upload rate (kB/s): [0: unlimited] Maximální rychlost odesílání (kB/s): [0: bez omezení] + + + Proxy server / Tor + Proxy server / Tor + + + + Type: + Typ: + + + + Server hostname: + Jméno serveru: + + + + Port: + Port: + + + + Authentication + Přihlášení + + + + Username: + Uživatelské jméno: + + + + Pass: + Heslo: + + + + Listen for incoming connections when using proxy + Naslouchat příchozím připojením při použití proxy + + + + none + žádný + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Nastavení sítě + + + + Total difficulty: + Celková obtížnost: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + "Celková obtížnost" ovlivňuje množství práce, kterou musí odesilatel provést. Zdvojnásobením této hodnoty zdvojnásobíte množství práce. + + + + Small message difficulty: + Obtížnost pro malou zprávu: + + + + 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. + Když Vám někdo pošle zprávu, jeho počítač musí nejprve provést určitou práci. Výchozí obtížnost práce je 1. Tuto hodnotu můžete zvýšit tím, že zvýšíte zde uvedené hodnoty. Všechny nové adresy, které vytvoříte, budou po odesilatelích vyžadovat tuto vyšší obtížnost. Existuje jedna výjimka: když si kamaráda nebo známého přidáte do adresáře, při příští zprávě, kterou mu pošlete, ho Bitmessage upozorní, že mu od teď stačí provést minimální množství práce (obtížnost 1) když Vám chce poslat zprávu. + + + + 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. + "Obtížnost pro malou zprávu" ovlivňuje pouze obtížnost posílání malých zpráv. Pokud ji zdvojnásobíte, bude dvakrát obtížnější poslat malou zprávu, ale velké zprávy to nijak neovlivní. + + + + Demanded difficulty + Požadovaná obtížnost + + + + 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. + Zde můžete nastavit maximální množství práce, které je pro Vás přijatelné, když posíláte zprávu jiné osobě. Nastavení 0 znamená, že množství není omezeno. + + + + Maximum acceptable total difficulty: + Maximální přijatelná celková obtížnost: + + + + Maximum acceptable small message difficulty: + Maximální přijatelná obtížnost pro malou zprávu: + + + + Max acceptable difficulty + Maximální přijatelná obtížnost + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + <html><head/><body><p>Bitmessage může použít jiný program založený na technologii Bitcoin, který se jmenuje Namecoin, a nahradit tak adresy lépe čitelnými jmény. Příklad: místo toho, abyste musel(a) kamarádovi diktovat svou dlouhou adresu Bitmessage, můžete mu jednoduše říct, ať pošle zprávu na jméno <span style=" font-style:italic;">test. </span></p><p>(Vložit svou adresu Bitmessage do Namecoin je zatím stále celkem složité).</p><p>Bitmessage může použít buď přímo namecoind, nebo běžící instanci nmcontrol.</p></body></html> + + + + Host: + Server: + + + + Password: + Heslo: + + + + Test + Zkouška + + + + Connect to: + Připojit k: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Integrace s Namecoin + + + + <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> + <html><head/><body><p>Výchozí nastavení funguje tak, že když pošlete zprávu někomu, kdo je odpojen více než dva dny, Bitmessage tuto zprávu za další dva dny pošle znovu. To bude pokračovat, ale intervaly se budou exponenciálně prodlužovat; zprávy budou znovu poslány za 5, 10, 20 dní atd. dokud adresát nepotvrdí jejich přijetí. Zde můžete toto chování změnit, a nastavit, aby to Bitmessage vzdal, pokud zpráva nebude doručena do určitého počtu dní či měsíců.</p><p>Ponechte tato pole prázdná, pokud chcete použít výchozí chování. </p></body></html> + + + + Give up after + Vzdát to po + + + + and + a + + + + days + dnech + + + + months. + měsících. + + + + Resends Expire + Lhůta pro opětovné poslání + - + \ No newline at end of file diff --git a/src/translations/bitmessage_da.qm b/src/translations/bitmessage_da.qm new file mode 100644 index 00000000..5bb11a57 Binary files /dev/null and b/src/translations/bitmessage_da.qm differ diff --git a/src/translations/bitmessage_da.ts b/src/translations/bitmessage_da.ts new file mode 100644 index 00000000..9bfd1787 --- /dev/null +++ b/src/translations/bitmessage_da.ts @@ -0,0 +1,2067 @@ + + + AddAddressDialog + + + Add new entry + Tilføj ny addresse + + + + Label + Navn + + + + Address + Adresse + + + + EmailGatewayDialog + + + Email gateway + Email gateway + + + + Register on email gateway + Registrér hos en email gateway + + + + Account status at email gateway + Status for konto hos email gateway + + + + Change account settings at email gateway + Ændr kontoindstillinger for email gateway + + + + Unregister from email gateway + Annullér registrering hos email gateway + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + Ønskede mailadresse (inklusiv @mailchuck.com) + + + + EmailGatewayRegistrationDialog + + + Registration failed: + Registrering mislykkedes: + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + Registrering hos email gateway + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + + + MainWindow + + + Reply to sender + Svar til afsender + + + + Reply to channel + Svar til kanal + + + + Add sender to your Address Book + Tilføj afsender til dn adressebog + + + + Add sender to your Blacklist + Tilføj afsender til din blacklist + + + + Move to Trash + Flyt til papirkurv + + + + Undelete + Gendan + + + + View HTML code as formatted text + Vis HTML-kode som formatteret tekst + + + + Save message as... + Gem besked som... + + + + Mark Unread + Marker som ulæst + + + + New + Ny + + + + Enable + Aktiver + + + + Disable + Deaktiver + + + + Set avatar... + Sæt ikon... + + + + Copy address to clipboard + Kopiér adresse til udklipsholder + + + + Special address behavior... + Speciel addressefunktion... + + + + Email gateway + Email gateway + + + + Delete + Slet + + + + Send message to this address + Send besked til denne adresse + + + + Subscribe to this address + Abonner på denne adresse + + + + Add New Address + Tilføj ny adresse + + + + Copy destination address to clipboard + Kopier modtageraddresse til udklipsholder + + + + Force send + Gennemtving afsendelse + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + En af dine adresser, %1 er en gammel version 1-addresse. Version 1-addresser understøttes ikke længere. Må vi slette den? + + + + Waiting for their encryption key. Will request it again soon. + Venter på krypteringsnøgle. Vil snart efterspørge den igen. + + + + Encryption key request queued. + Efterspørgsel på krypteringsnøgle er sat i kø. + + + + Queued. + Sat i kø. + + + + Message sent. Waiting for acknowledgement. Sent at %1 + Besked afsendt. Afventer bekræftelse på modtagelse. Sendt %1 + + + + Message sent. Sent at %1 + Besked sendt. Sendt %1 + + + + Need to do work to send message. Work is queued. + Skal foretage beregning for at sende besked. Beregningen er sat i kø. + + + + Acknowledgement of the message received %1 + Bekræftelse på modtagelse er modtaget %1 + + + + Broadcast queued. + Afsendelse sat i kø. + + + + Broadcast on %1 + Afsendt %1 + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + Problem: Beregningen som kræves af modtageren er mere besværlig end du accepterer. %1 + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + Problem: Modtagerens krypteringsnøgle virker ikke. Beskeden kunne ikke krypteres. %1 + + + + Forced difficulty override. Send should start soon. + Ændring af sværhedsgrad gennemtvunget. Afsendelse bør starte snart. + + + + Unknown status: %1 %2 + Ukendt status: %1 %2 + + + + Not Connected + Ikke forbundet + + + + Show Bitmessage + Vis Bitmessage + + + + Send + Send + + + + Subscribe + Abonnér + + + + Channel + Kanal + + + + Quit + Afslut + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + Du kan administrere dine nøgler ved at redigere keys.dat-filen i samme mappe som dette program. Det er vigtigt at tage backup af denne fil. + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + Du kan administrere dine nøgler ved at redigere keys.dat-filen i +%1 +Det er vigtigt at tage backup af denne fil. + + + + Open keys.dat? + Åbn keys.dat? + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Du kan administrere dine nøgler ved at redigere keys.dat-filen i samme mappe som dette program. Det er vigtigt at tage backup af denne fil. Vil du åbne denne fil nu? (Sørg for at lukke Bitmessage før du foretager ændringer.) + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Du kan administrere dine nøgler ved at redigere keys.dat-filen i +%1 +Det er vigtigt at tage backup af denne fil. (Sørg for at lukke Bitmessage før du foretager ændringer.) + + + + Delete trash? + Slet papirkurv? + + + + Are you sure you want to delete all trashed messages? + Er du sikker på at du vil slette alle beskeder i papirkurven? + + + + bad passphrase + ugyldigt kodeord + + + + You must type your passphrase. If you don't have one then this is not the form for you. + Du skal indtaste dit kodeord. Hvis du ikke har et så er dette ikke den rette dialogboks. + + + + Bad address version number + Ugyldig addresse-version + + + + Your address version number must be a number: either 3 or 4. + Din addresse-version skal være enten 3 eller 4. + + + + Your address version number must be either 3 or 4. + Din addresse-version skal være enten 3 eller 4. + + + + Chan name needed + Kanalnavnet er påkrævet + + + + You didn't enter a chan name. + Du indtastede ikke et kanalnavn. + + + + Address already present + Adressen eksisterer allerede + + + + Could not add chan because it appears to already be one of your identities. + Adressen kunne ikke tilføjes da det ser ud tilat den allerede er en af dine identiteter. + + + + Success + Succes + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + Ny kanal oprettet. For at andre kan blive medlem skal du oplyse dem kanalnavnet og denne Bitmessage-adresse: %1. Denne adresse vises også i 'Dine identiteter'. + + + + Address too new + Adressen er for ny + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + Selvom denne Bitmessage-adresse måske er gyldig, er dens versionsnummer for nyt. Måske bør du opgradere Bitmessage. + + + + Address invalid + Adressen er ugyldig + + + + That Bitmessage address is not valid. + Denne Bitmessage-adresse er ikke gyldig. + + + + Address does not match chan name + Adressen stemmer ikke overens med kanalnavnet + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + Selvom denne Bitmessage-adresse er gyldig stemmer den ikke overens med kanalnavnet. + + + + Successfully joined chan. + Du er nu medlem af kanalen + + + + Connection lost + Forbindelse afbrudt + + + + Connected + Forbundet + + + + Message trashed + Beskeden er flyttet til papirkurven + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + Beskeden er for lang + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + Beskeden som du prøver at sende er %1 byte for lang. (Den maksimale størrelse er 261644 byte). Prøv at gøre den kortere før afsendelsen. + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + Fejl: Bitmessage-adresser starter med BM- Check %1 + + + + Error: The address %1 is not typed or copied correctly. Please check it. + Fejl: Adressen %1 er skrever eller kopieret forkert. Tjek den venligst. + + + + Error: The address %1 contains invalid characters. Please check it. + Fejl: Adressen %1 indeholder ugyldige tegn. Tjek den venligst. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + Fejl: Der er noget galt med adressen %1. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Fejl: Du skal angive en afsenderadresse. Hvis du ikke har nogen skal du gå til fanen 'Dine Identiteter'. + + + + Address version number + Adresseversion + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Vedrørende adressen %1, Bitmessage forstår ikke addreseversion %2. Måske bør du opgradere Bitmessage til den nyeste version. + + + + Stream number + Flodversion + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Vedrørende adressen %1, Bitmessage kan ikke håndtere flod nummer %2. Måske bør du opgradere Bitmessage til den nyeste version. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Advarsel: Du har ingen forbindelse. Bitmessage vil foretage nødvendige beregninger for at afsende beskeder, men de vil først blive afsendt når du opretter forbindelse. + + + + Message queued. + Besked sat i kø. + + + + Your 'To' field is empty. + Du har ikke angivet en modtager. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Højreklik på en eller flere adresser i din adressebog og vælg 'Send besked til denne adresse'. + + + + Fetched address from namecoin identity. + Adresse blev hentet fra namecoin-identitet. + + + + New Message + Ny Besked + + + + From + Fra + + + + Sending email gateway registration request + Sender tilmeldelses-forespørgsel til email gateway + + + + Address is valid. + Adressen er gyldig. + + + + The address you entered was invalid. Ignoring it. + Adressen som du har indtastet er ugyldig og vil derfor blive ignoreret. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Fejl: Du kan ikke tilføje den samme adresse til din adressebog flere gange. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + Genstart + + + + You must restart Bitmessage for the port number change to take effect. + Bitmessage skal genstartes før ændringen af portnummeret træder i kraft. + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + Bitmessage vil benytte en proxy fra nu af, men hvis du ønsker at afbryde eventuelle eksisterende forbindelser skal du genstarte Bitmessage manuelt. + + + + Number needed + Et tal er nødvendigt + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + De maksimale download- og upload-hastigheder skal være tal. Det du har indtastet vil blive ignoreret. + + + + Will not resend ever + Vil aldrig gensende + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + Bemærk at den tidsgrænse du har indtastet er kortere end den tid som Bitmessage venter inden første genafsendelsesforsøg, og dine beskeder vil derfor aldrig blive genafsendt. + + + + Sending email gateway unregistration request + Sender afmeldelses-forespørgsel til email gateway + + + + Sending email gateway status request + Sender status-forespørgsel til email gateway + + + + Passphrase mismatch + Kodeordene stemmer ikke overens + + + + The passphrase you entered twice doesn't match. Try again. + De to kodeord er ikke ens. Prøv igen. + + + + Choose a passphrase + Vælg et kodeord + + + + You really do need a passphrase. + Du kan ikke undlade at indtaste et kodeord. + + + + Address is gone + Adressen er forsvundet + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmessage kan ikke finde din adresse %1. Måske har du fjernet den? + + + + Address disabled + Addresse slået fra + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Fejl: Adressen som du prøver at sende fra er deaktiveret. Du skal aktivere den fra fanen 'Dine Identiteter'. + + + + Entry added to the Address Book. Edit the label to your liking. + Adresse tilføjet til adressebogen. Rediger navnet som du ønsker. + + + + Entry added to the blacklist. Edit the label to your liking. + Adresse tilføjet til din blacklist. Rediger navnet som du ønsker. + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + Fejl: Den samme adresse kan ikke tilføjes til din sortliste flere gange. Prøv eventuelt at omdøbe den eksisterende. + + + + Moved items to trash. + Beskeder blev flyttet til papirkurven. + + + + Undeleted item. + Besked gendannet. + + + + Save As... + Gem Som... + + + + Write error. + Skrivefejl. + + + + No addresses selected. + Ingen adresser valgt. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + Hvis du sletter dette abonnement, vil beskeder som du allerede har modtaget blive utilgængelige. Måske bør du hellere slå adressen fra. Abonnementer der er slået fra modtager ikke nye beskeder, men du kan stadigvæk se de beskeder du allerede har modtaget. + +Er du sikker på at du vil slette dette abonnement? + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + Hvis du sletter denne kanal, vil beskeder som du allerede har modtaget blive utilgængelige. Måske bør du hellere slå adressen fra. Kanaler der er slået fra modtager ikke nye beskeder, men du kan stadigvæk se de beskeder du allerede har modtaget. + +Er du sikker på at du vil slette denne kanal? + + + + Do you really want to remove this avatar? + Vil du virkelig fjerne dette ikon? + + + + You have already set an avatar for this address. Do you really want to overwrite it? + Du har allerede valgt et ikon for denne adresse. Er du sikker på at du vil erstatte det? + + + + Start-on-login not yet supported on your OS. + Automatisk start er endnu ikke understøttet på din platform. + + + + Minimize-to-tray not yet supported on your OS. + Minimering til systembakken er endnu ikke understøttet på din platform. + + + + Tray notifications not yet supported on your OS. + Systembakkenotifikationer er endnu ikke understøttet på din platform. + + + + Testing... + Tester... + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + Dette er en kanaladresse. Den kan ikke benyttes som en pseudo-mailing-liste. + + + + The address should start with ''BM-'' + Adressen bør starte med "BM-" + + + + The address is not typed or copied correctly (the checksum failed). + DU har indtastet eller kopieret adressen forkert (checksummen passer ikke) + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + Versionsnummeret for denne adresse er højere end hvad der understøttes af denne softwareversion. Opgrader venligst Bitmessage. + + + + The address contains invalid characters. + Adressen indeholder ugyldige tegn. + + + + Some data encoded in the address is too short. + Nogle af dataene som er indkodet i adressen, er for korte. + + + + Some data encoded in the address is too long. + Nogle af dataene som er indkodet i adressen, er for lange. + + + + Some data encoded in the address is malformed. + Nogle af dataene som er indkodet i adressen er ugyldige. + + + + Enter an address above. + Vælg en adresse ovenfor. + + + + Address is an old type. We cannot display its past broadcasts. + Adressen er af en gammel type. Dens broadcast-beskeder kan ikke vises. + + + + There are no recent broadcasts from this address to display. + Der blev ikke fundet nogen broadcast-beskeder fra denne adresse + + + + You are using TCP port %1. (This can be changed in the settings). + Du bruger TCP-port %1. (Dette kan ændres i indstillingerne). + + + + Bitmessage + Bitmessage + + + + Identities + Identiteter + + + + New Identity + Ny identitet + + + + Search + Søg + + + + All + Alle + + + + To + Til + + + + From + Fra + + + + Subject + Emne + + + + Message + Besked + + + + Received + Modtaget + + + + Messages + Beskeder + + + + Address book + Adressebog + + + + Address + Adresse + + + + Add Contact + Tilføj Kontakt + + + + Fetch Namecoin ID + Hent Namecoin ID + + + + Subject: + Emne: + + + + From: + Fra: + + + + To: + Til: + + + + Send ordinary Message + Send almindelig besked + + + + Send Message to your Subscribers + Send besked til dine abonnenter + + + + TTL: + TTL: + + + + Subscriptions + Abonnementer + + + + Add new Subscription + Tilføj nyt abonnement + + + + Chans + Kanaler + + + + Add Chan + TIlføj kanal + + + + File + Filer + + + + Settings + Indstillinger + + + + Help + Hjælp + + + + Import keys + Importer nøgler + + + + Manage keys + Administrér nøgler + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + Kontakt support + + + + About + Om + + + + Regenerate deterministic addresses + Regenerér deterministiske addresser + + + + Delete all trashed messages + Tøm papirkurv + + + + Join / Create chan + Opret/bliv medlem af en kanal + + + + All accounts + Alle konti + + + + Zoom level %1% + Zoom %1% + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + + + + + NewAddressDialog + + + Create new Address + Opret ny adresse + + + + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + Her kan du generere så mange adresser som du vil. Det er helt fint at oprette adresser som kun bruges kortvarigt. Du kan generere adresser enten ud fra tilfældige tal eller ud fra et kodeord. Hvis du bruger et kodeord, kaldes det en "deterministisk" adresse. +Som standard er tilfældige tal valgt, men der er både fordele og ulemper ved at benytte deterministiske adresser i stedet. + + + + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + + + + + Use a random number generator to make an address + Brug en tilfældighedsgenerator til at generere adresser + + + + Use a passphrase to make addresses + Brug et kodeord til at generere adresser + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + Brug flere minutters ekstra beregningstid på at gøre adresserne 1-2 tegn kortere + + + + Make deterministic addresses + Opret deterministiske adresser + + + + Address version number: 4 + Adresse-version: 4 + + + + In addition to your passphrase, you must remember these numbers: + Udover dit kodeord skal du også huske disse tal. + + + + Passphrase + Kodeord + + + + Number of addresses to make based on your passphrase: + Antal adresser der skal genereres ud fra kodeordet: + + + + Stream number: 1 + Flod-nummer: 1 + + + + Retype passphrase + Gentag kodeord + + + + Randomly generate address + Generer adresse tilfældigt + + + + Label (not shown to anyone except you) + Navn (ikke vist til andre end dig selv) + + + + Use the most available stream + Brug den mest tilgængelige flod + + + + (best if this is the first of many addresses you will create) + (anbefales hvis dette er den første ud af mange adresser som du ønsker at oprette) + + + + Use the same stream as an existing address + Brug den samme flod som en eksisterende addresse + + + + (saves you some bandwidth and processing power) + (sparer noget båndbredde og nogle beregninger) + + + + NewSubscriptionDialog + + + Add new entry + Tilføj ny addresse + + + + Label + Navn + + + + Address + Adresse + + + + Enter an address above. + + + + + SpecialAddressBehaviorDialog + + + Special Address Behavior + Speciel adressefunktionalitet + + + + Behave as a normal address + Fungér som en almindelig adresse + + + + Behave as a pseudo-mailing-list address + Fungér som en pseudo-mailing-liste + + + + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + Beskeder som modtages af en pseudo-mailing-liste vil automatisk blive videresendt til alle abonnenter (og vil derved være offentlige). + + + + Name of the pseudo-mailing-list: + Navn på pseudo-mailing-listen: + + + + aboutDialog + + + About + Om + + + + PyBitmessage + PyBitmessage + + + + version ? + version ? + + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + <html><head/><body><p>Distribueret under MIT/X11-licensen; se <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + + + + This is Beta software. + Dette er en betaversion. + + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + + + + + connectDialog + + + Bitmessage + Bitmessage + + + + Bitmessage won't connect to anyone until you let it. + Bitmessage opretter ikke forbindelse til nogen før du beder om det. + + + + Connect now + Opret forbindelse nu + + + + Let me configure special network settings first + Lad mig først konfigurere specielle netværksindstillinger + + + + helpDialog + + + Help + Hjælp + + + + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + + + + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + Da Bitmessage er et samarbejdsprojekt, kan du finde hjælp online på Bitmessage-wikien: + + + + iconGlossaryDialog + + + Icon Glossary + + + + + You have no connections with other peers. + Du har ingen forbindelser til andre computere. + + + + 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'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. + + + + + You are using TCP port ?. (This can be changed in the settings). + Du bruger TCP-port ?. (Dette kan ændres i indstillingerne). + + + + You do have connections with other peers and your firewall is correctly configured. + Du har forbindelser til andre computere og din firewall er konfigureret korrekt. + + + + networkstatus + + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + + + + + newChanDialog + + + Dialog + Dialogboks + + + + Create a new chan + Opret en ny kanal + + + + Join a chan + Bliv medlem af en kanal + + + + Create a chan + Opret en kanal + + + + <html><head/><body><p>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.</p></body></html> + + + + + Chan name: + Kanalnavn: + + + + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + + + + + Chan bitmessage address: + Bitmessage adresse for kanalen: + + + + regenerateAddressesDialog + + + Regenerate Existing Addresses + Regenerér Eksisterende Adresser + + + + Regenerate existing addresses + Regenerér eksisterende adresser + + + + Passphrase + Kodeord + + + + Number of addresses to make based on your passphrase: + Antal adresser som skal genereres ud fra dit kodeord: + + + + Address version number: + Adresseversion: + + + + Stream number: + Flodversion: + + + + 1 + 1 + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + Brug flere minutters ekstra beregningstid på at gøre adresserne 1-2 tegn kortere + + + + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + Det er vigtigt at du vælger (eller ikke vælger) dette, ligesom du gjorde (eller ikke gjorde) første gang. + + + + 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. + Hvis du tidligere har genereret deterministiske adresser, men du har mistet dem på grund af et uheld (f.eks. harddiskfejl), kan du genskabe dem her. Hvis du brugte tilfældighedsgeneratoren til at lave adresser kan denne dialogboks ikke hjælpe dig. + + + + settingsDialog + + + Settings + Indstillinger + + + + Start Bitmessage on user login + Start Bitmessage når der logges ind + + + + Tray + Systembakke + + + + Start Bitmessage in the tray (don't show main window) + + + + + Minimize to tray + Minimér til systembakken + + + + Close to tray + Minimér til systembakken når hovedvinduet lukkes + + + + Show notification when message received + Vis notifikationer når en besked modtages + + + + Run in Portable Mode + Kør i Portable Mode + + + + 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. + I Portable Mode gemmes beskeder og konfigurationsfiler i samme mappe som programmet, i stedet for i den almindelige mappe til applikationsdata. Dette gør det nemt at køre Bitmessage fra et USB-stick. + + + + Willingly include unencrypted destination address when sending to a mobile device + Inkludér en ukrypteret destinationsaddresse når der sendes til mobile enheder + + + + Use Identicons + Brud identicons + + + + Reply below Quote + Besvar under citat + + + + Interface Language + Grænsefladesprog + + + + System Settings + system + Systemindstillinger + + + + User Interface + Brugergrænseflade + + + + Listening port + Indgående portnummer + + + + Listen for connections on port: + Tillad indgående forbindelser på port: + + + + UPnP: + UPnP: + + + + Bandwidth limit + Maksimal overførselshastighed + + + + Maximum download rate (kB/s): [0: unlimited] + Maksimal downloadhastighed (kB/s): [0: ubegrænset] + + + + Maximum upload rate (kB/s): [0: unlimited] + Maksimal uploadhastighed (kB/s): [0: ubegrænset] + + + + Proxy server / Tor + Proxyserver / Tor + + + + Type: + Type: + + + + Server hostname: + Servernavn: + + + + Port: + Port: + + + + Authentication + Autentifikation + + + + Username: + Brugernavn: + + + + Pass: + Kodeord: + + + + Listen for incoming connections when using proxy + Accepter indgående forbindelser når der benyttes en proxyserver + + + + none + ingen + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Netværksindstillinger + + + + Total difficulty: + Total sværhedsgrad: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + + + + + Small message difficulty: + Små-beskeds-sværhedsgrad: + + + + 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. + Når nogen sender dig en besked skal deres computer først foretage nogen tunge beregninger. Sværhedsgraden er som standard 1. Du kan hæve sværhedsgraden for nye adresser ved at ændre værdierne her. Alle nye adresser vil kræve at afsenderen foretager beregninger med den nye sværhedsgrad. Der er dog en undtagelse: hvis du tilføjer en ven eller bekendt til din adressebog vil Bitmessage automatisk gøre dem opmærksom på at de kun skal foretage beregninger med en sværhedsgrad på 1, så snart du sender dem en besked. + + + + 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. + + + + + Demanded difficulty + Krævet sværhedsgrad + + + + 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. + + + + + Maximum acceptable total difficulty: + Maksimal acceptabel total sværhedsgrad + + + + Maximum acceptable small message difficulty: + Maksimal acceptabel småbeskeds-sværhedsgrad + + + + Max acceptable difficulty + Maks. acceptabel sværhedsgrad + + + + Hardware GPU acceleration (OpenCL) + GPU-acceleration (OpenCL) + + + + <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> + <html><head/><body><p>Bitmessage kan benytte et andet Bitcoin-baseret program som hedder Namecoin til at gøre adresserne brugervenlige. For eksempel kan du bede din ven om at sende en besked til <span style=" font-style:italic;">test</span> i stedet for din lange Bitmessage-adresse.</p><p>(At få sin Bitmessage-adresse ind i namecoin er stadig rimelig kompliceret).</p><p>Bitmessage kan enten bruge namecoind direkte, eller bruge nmcontrol.</p></body></html> + + + + Host: + Vært: + + + + Password: + Kodeord: + + + + Test + Test + + + + Connect to: + Forbind til: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Namcoin integration + + + + <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> + + + + + Give up after + Giv op efter + + + + and + og + + + + days + dage + + + + months. + måneder. + + + + Resends Expire + Forsøg på genafsendelse stopper efter + + + \ No newline at end of file diff --git a/src/translations/bitmessage_de.pro b/src/translations/bitmessage_de.pro deleted file mode 100644 index 56e2b4f1..00000000 --- a/src/translations/bitmessage_de.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_outgoingSynSender.py\ - ../class_objectProcessor.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_de.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_de.qm b/src/translations/bitmessage_de.qm index 400ac465..9a016760 100644 Binary files a/src/translations/bitmessage_de.qm and b/src/translations/bitmessage_de.qm differ diff --git a/src/translations/bitmessage_de.ts b/src/translations/bitmessage_de.ts index 5d937bf9..e7c8fdfe 100644 --- a/src/translations/bitmessage_de.ts +++ b/src/translations/bitmessage_de.ts @@ -1,5 +1,4 @@ - - + AddAddressDialog @@ -18,1029 +17,1304 @@ Adresse + + EmailGatewayDialog + + + Email gateway + E-Mail Schnittstelle + + + + Register on email gateway + An E-Mailschnittstelle registrieren + + + + Account status at email gateway + Statusanfrage der E-Mail Schnittstelle + + + + Change account settings at email gateway + Einstellungen der E-Mail Schnittstelle ändern + + + + Unregister from email gateway + Von der E-Mail Schnittstelle abmelden + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + Die E-Mail Schnittstelle ermöglicht es, mit anderen E-Mail Nutzern zu kommunizieren. Zur Zeit ist nur die Mailchuck-E-Mail Schnittstelle (@mailchuck.com) verfügbar. + + + + Desired email address (including @mailchuck.com): + Gewünschte E-Mailaddresse (inkl. @mailchuck.com): + + + + EmailGatewayRegistrationDialog + + + Registration failed: + Registrierung fehlgeschlagen: + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + Die gewünschte E-Mailaddresse ist nicht verfügbar, bitte probieren Sie eine neue. Die gewünschte E-Mailaddresse (inkl. @mailchuck.com) unten ausfüllen: + + + + Email gateway registration + E-Mail Schnittstellen Registrierung + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + Die E-Mail Schnittstelle ermöglicht es, mit anderen E-Mail-Nutzern zu kommunizieren. Zur Zeit ist nur die Mailchuck-E-Mail-Schnittstelle verfügbar (@mailchuck.com). +Bitte geben Sie die gewünschte E-Mail-Adresse (inkl. @mailchuck.com) unten ein: + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + # Diese Nachricht können Sie für die Änderung Ihrer Einstellungen an der +# E-Mail Schnittstelle verwenden. Unkommentieren Sie die Einstellung, die Sie +# ändern möchten. Dies sind die verfügbaren Einstellungen: +# +# pgp: server +# Die E-Mail-Schnittstelle wird für Sie PGP-Schlüssel erzeugen, und die +# Nachrichten für Sie unterschreiben, Unterschriften überprüfen, ver- und +# entschlüsseln. Verwenden Sie diese Option, wenn Sie PGP verwenden möchten +# aber es manuell zu umständig finden. Erfordert Abonnement. +# +# pgp: local +# Die E-Mail-Schnittstelle wird keine PGP-verarbeitung für Sie machen. +# Sie können auf die Verwendung von PGP entweder ganz verzichten, oder es lokal machen. +# +# attachments: yes +# Eingehende Dateianhänge von E-Mails werden zu MEGA.nz hochgeladen, und Sie +# können diese über einen Link in der Nachricht herunterladen. Erfordert +# Abonnement. +# +# attachments: no +# Anhänge werden ignoriert. +# +# archive: yes +# Ihre eingehende E-Mails werden auf dem Server archiviert. Nutzen Sie dies, +# wenn Sie Hilfe bei Debugging benötigen, oder eine Bestätigung von dritter +# Partei über die E-Mails benötigen. Diese Einstellung bedeutet jedoch, dass +# der Betreiber der Dienstleistung Ihre E-Mails auch lesen kann nachdem sie +# diese erhalten haben. +# +# archive: no +# Eingehende E-Mails werden gleich nach dem Übertragen zu Ihnen bei dem +# Schnittstellenbetreiber gelöscht. +# +# masterpubkey_btc: BIP44-xpub-Schlüssel oder electrum v1 Seed +# offset_btc: Ganzzahl (Voreingestellt auf 0) +# feeamount: Zahl mit bis zu 8 Nachkommastellen +# feecurrency: BTC, XBT, USD, EUR oder GBP +# Nutzen Sie diese Variablen, wenn Sie von den Absendern eine Zahlung +# verlangen. Wenn diese Option eingeschaltet ist und Sie eine E-Mail von einer +# noch nicht bekannten E-Mail-Addresse erhalten, wird die E-Mail abgelehnt und +# der Absender erhällt eine Zahlungsaufforderung in der spezifizierten Höhe. Da +# diese Methode deterministische öffentliche Schlüssel verwendet, erhalten Sie +# die Zahlungen direkt. Um die Funktion wieder auszuschalten, ändern Sie die +# "feeamount"-Variable auf 0. Erfordert Abonnement. + + + MainWindow - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - Eine Ihrer Adressen, %1, ist eine alte Version 1 Adresse. Version 1 Adressen werden nicht mehr unterstützt. Soll sie jetzt gelöscht werden? + + Reply to sender + Dem Absender antworten - - Reply - Antworten + + Reply to channel + Antworten in den Chan - + Add sender to your Address Book Absender zum Adressbuch hinzufügen - + + Add sender to your Blacklist + Absender in die Blacklist eintragen + + + Move to Trash In den Papierkorb verschieben - + + Undelete + Wiederherstellen + + + View HTML code as formatted text HTML als formatierten Text anzeigen - + Save message as... Nachricht speichern unter... - - New - Neu - - - - Enable - Aktivieren - - - - Disable - Deaktivieren - - - - Copy address to clipboard - Adresse in die Zwischenablage kopieren - - - - Special address behavior... - Spezielles Verhalten der Adresse... - - - - Send message to this address - Nachricht an diese Adresse senden - - - - Subscribe to this address - Diese Adresse abonnieren - - - - Add New Address - Neue Adresse hinzufügen - - - - Delete - Löschen - - - - Copy destination address to clipboard - Zieladresse in die Zwischenablage kopieren - - - - Force send - Senden erzwingen - - - - Add new entry - Neuen Eintrag erstellen - - - - Waiting for their encryption key. Will request it again soon. - Warte auf den Verschlüsselungscode. Wird bald erneut angefordert. - - - - Encryption key request queued. - Verschlüsselungscode-Anforderung steht aus. - - - - Queued. - In Warteschlange. - - - - Message sent. Waiting for acknowledgement. Sent at %1 - Nachricht gesendet. Warten auf Bestätigung. Gesendet %1 - - - - Need to do work to send message. Work is queued. - Es muss Arbeit verrichtet werden um die Nachricht zu versenden. Arbeit ist in Warteschlange. - - - - Acknowledgement of the message received %1 - Bestätigung der Nachricht erhalten %1 - - - - Broadcast queued. - Rundruf in Warteschlange. - - - - Broadcast on %1 - Rundruf um %1 - - - - Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 - Problem: Die vom Empfänger geforderte Arbeit ist schwerer als Sie bereit sind, zu berechnen. %1 - - - - Problem: The recipient's encryption key is no good. Could not encrypt message. %1 - Problem: Der Verschlüsselungscode des Empfängers ist nicht in Ordnung. Nachricht konnte nicht verschlüsselt werden. %1 - - - - Forced difficulty override. Send should start soon. - Schwierigkeitslimit überschrieben. Senden sollte bald beginnen. - - - - Unknown status: %1 %2 - Unbekannter Status: %1 %2 - - - - Since startup on %1 - Seit Start der Anwendung am %1 - - - - Not Connected - Nicht verbunden - - - - Show Bitmessage - Bitmessage anzeigen - - - - Send - Senden - - - - Subscribe - Abonnieren - - - - Address Book - Adressbuch - - - - Quit - Schließen - - - - You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. - Sie können Ihre Schlüssel verwalten, indem Sie die keys.dat Datei bearbeiten, die im gleichen Ordner wie das Programm liegt. Es ist wichtig, dass Sie diese Datei sichern. - - - - You may manage your keys by editing the keys.dat file stored in - %1 -It is important that you back up this file. - Sie können Ihre Schlüssel verwalten, indem Sie die keys.dat Datei bearbeiten, die im Ordner -%1 liegt. -Es ist wichtig, dass Sie diese Datei sichern. - - - - Open keys.dat? - Datei keys.dat öffnen? - - - - You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - Sie können Ihre Schlüssel verwalten, indem Sie die keys.dat Datei bearbeiten, die im gleichen Ordner wie das Programm liegt. Es ist wichtig, dass Sie diese Datei sichern. Möchten Sie die Datei jetzt öffnen? (Stellen Sie sicher, dass Bitmessage geschlossen ist, bevor Sie etwas ändern.) - - - - You may manage your keys by editing the keys.dat file stored in - %1 -It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - Sie können Ihre Schlüssel verwalten, indem Sie die keys.dat Datei bearbeiten, -die im Ordner %1 liegt. -Es ist wichtig, dass Sie diese Datei sichern. Möchten Sie die datei jetzt öffnen? -(Stellen Sie sicher, dass Bitmessage geschlossen ist, bevor Sie etwas ändern.) - - - - Delete trash? - Papierkorb leeren? - - - - Are you sure you want to delete all trashed messages? - Sind Sie sicher, dass Sie alle Nachrichten im Papierkorb löschen möchten? - - - - bad passphrase - Falscher Passwort-Satz - - - - You must type your passphrase. If you don't have one then this is not the form for you. - Sie müssen Ihren Passwort-Satz eingeben. Wenn Sie keinen haben, ist dies das falsche Formular für Sie. - - - - Processed %1 person-to-person messages. - %1 Person-zu-Person-Nachrichten bearbeitet. - - - - Processed %1 broadcast messages. - %1 Rundruf-Nachrichten bearbeitet. - - - - Processed %1 public keys. - %1 öffentliche Schlüssel bearbeitet. - - - - Total Connections: %1 - Verbindungen insgesamt: %1 - - - - Connection lost - Verbindung verloren - - - - Connected - Verbunden - - - - Message trashed - Nachricht in den Papierkorb verschoben - - - - Error: Bitmessage addresses start with BM- Please check %1 - Fehler: Bitmessage Adressen starten mit BM- Bitte überprüfen Sie %1 - - - - Error: The address %1 is not typed or copied correctly. Please check it. - Fehler: Die Adresse %1 wurde nicht korrekt getippt oder kopiert. Bitte überprüfen. - - - - Error: The address %1 contains invalid characters. Please check it. - Fehler: Die Adresse %1 beinhaltet ungültig Zeichen. Bitte überprüfen. - - - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - Fehler: Die Adressversion von %1 ist zu hoch. Entweder Sie müssen Ihre Bitmessage Software aktualisieren oder Ihr Bekannter ist sehr clever. - - - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - Fehler: Einige Daten die in der Adresse %1 codiert sind, sind zu kurz. Es könnte sein, dass etwas mit der Software Ihres Bekannten nicht stimmt. - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - Fehler: Einige Daten die in der Adresse %1 codiert sind, sind zu lang. Es könnte sein, dass etwas mit der Software Ihres Bekannten nicht stimmt. - - - - Error: Something is wrong with the address %1. - Fehler: Mit der Adresse %1 stimmt etwas nicht. - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - Fehler: Sie müssen eine Absenderadresse auswählen. Sollten Sie keine haben, wechseln Sie zum Reiter "Ihre Identitäten". - - - - Sending to your address - Sende zu Ihrer Adresse - - - - Error: One of the addresses to which you are sending a message, %1, is yours. Unfortunately the Bitmessage client cannot process its own messages. Please try running a second client on a different computer or within a VM. - Fehler: Eine der Adressen an die Sie eine Nachricht schreiben (%1) ist Ihre. Leider kann die Bitmessage Software ihre eigenen Nachrichten nicht verarbeiten. Bitte verwenden Sie einen zweite Installation auf einem anderen Computer oder in einer VM. - - - - Address version number - Adressversion - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - Bezüglich der Adresse %1, Bitmessage kann Adressen mit der Version %2 nicht verarbeiten. Möglicherweise müssen Sie Bitmessage auf die aktuelle Version aktualisieren. - - - - Stream number - Datenstrom Nummer - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - Bezüglich der Adresse %1, Bitmessage kann den Datenstrom mit der Version %2 nicht verarbeiten. Möglicherweise müssen Sie Bitmessage auf die aktuelle Version aktualisieren. - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - Warnung: Sie sind aktuell nicht verbunden. Bitmessage wird die nötige Arbeit zum versenden verrichten, aber erst senden, wenn Sie verbunden sind. - - - - Your 'To' field is empty. - Ihr "Empfänger"-Feld ist leer. - - - - Work is queued. - Arbeit in Warteschlange. - - - - Right click one or more entries in your address book and select 'Send message to this address'. - Klicken Sie mit rechts auf eine oder mehrere Einträge aus Ihrem Adressbuch und wählen Sie "Nachricht an diese Adresse senden". - - - - Work is queued. %1 - Arbeit in Warteschlange. %1 - - - - New Message - Neue Nachricht - - - - From - Von - - - - Address is valid. - Adresse ist gültig. - - - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - Fehler: Sie können eine Adresse nicht doppelt im Adressbuch speichern. Wenn Sie möchten, benennen Sie den existierenden Eintrag um. - - - - The address you entered was invalid. Ignoring it. - Die von Ihnen eingegebene Adresse ist ungültig, sie wird ignoriert. - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - Fehler: Sie können eine Adresse nicht doppelt abonnieren. Wenn Sie möchten, benennen Sie den existierenden Eintrag um. - - - - Restart - Neustart - - - - You must restart Bitmessage for the port number change to take effect. - Sie müssen Bitmessage neu starten, um den geänderten Port zu verwenden. - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections. - Bitmessage wird den Proxy-Server ab jetzt verwenden, möglicherweise möchten Sie Bitmessage neu starten um bestehende Verbindungen zu schließen. - - - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - Fehler: Sie können eine Adresse nicht doppelt zur Liste hinzufügen. Wenn Sie möchten, benennen Sie den existierenden Eintrag um. - - - - Passphrase mismatch - Kennwortsatz nicht identisch - - - - The passphrase you entered twice doesn't match. Try again. - Die von Ihnen eingegebenen Kennwortsätze sind nicht identisch. Bitte neu versuchen. - - - - Choose a passphrase - Wählen Sie einen Kennwortsatz - - - - You really do need a passphrase. - Sie benötigen wirklich einen Kennwortsatz. - - - - All done. Closing user interface... - Alles fertig. Benutzer interface wird geschlossen... - - - - Address is gone - Adresse ist verloren - - - - Bitmessage cannot find your address %1. Perhaps you removed it? - Bitmassage kann Ihre Adresse %1 nicht finden. Haben Sie sie gelöscht? - - - - Address disabled - Adresse deaktiviert - - - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - Fehler: Die Adresse von der Sie versuchen zu senden ist deaktiviert. Sie müssen sie unter dem Reiter "Ihre Identitäten" aktivieren bevor Sie fortfahren. - - - - Entry added to the Address Book. Edit the label to your liking. - Eintrag dem Adressbuch hinzugefügt. Editieren Sie den Eintrag nach Belieben. - - - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - Objekt in den Papierkorb verschoben. Es gibt kein Benutzerinterface für den Papierkorb, aber die Daten sind noch auf Ihrer Festplatte wenn Sie sie wirklich benötigen. - - - - Save As... - Speichern unter... - - - - Write error. - Fehler beim speichern. - - - - No addresses selected. - Keine Adresse ausgewählt. - - - - Options have been disabled because they either aren't applicable or because they haven't yet been implemented for your operating system. - -Optionen wurden deaktiviert, da sie für Ihr Betriebssystem nicht relevant, oder noch nicht implementiert sind. - - - - The address should start with ''BM-'' - Die Adresse sollte mit "BM-" beginnen - - - - The address is not typed or copied correctly (the checksum failed). - Die Adresse wurde nicht korrekt getippt oder kopiert (Prüfsumme falsch). - - - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - Die Versionsnummer dieser Adresse ist höher als diese Software unterstützt. Bitte installieren Sie die neuste Bitmessage Version. - - - - The address contains invalid characters. - Diese Adresse beinhaltet ungültige Zeichen. - - - - Some data encoded in the address is too short. - Die in der Adresse codierten Daten sind zu kurz. - - - - Some data encoded in the address is too long. - Die in der Adresse codierten Daten sind zu lang. - - - - You are using TCP port %1. (This can be changed in the settings). - Sie benutzen TCP-Port %1 (Dieser kann in den Einstellungen verändert werden). - - - - Bitmessage - Bitmessage - - - - To - An - - - - From - Von - - - - Subject - Betreff - - - - Received - Erhalten - - - - Inbox - Posteingang - - - - Load from Address book - Aus Adressbuch wählen - - - - Message: - Nachricht: - - - - Subject: - Betreff: - - - - Send to one or more specific people - Nachricht an eine oder mehrere spezifische Personen - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - To: - An: - - - - From: - Von: - - - - Broadcast to everyone who is subscribed to your address - Rundruf an jeden, der Ihre Adresse abonniert hat - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - Beachten Sie, dass Rundrufe nur mit Ihrer Adresse verschlüsselt werden. Jeder, der Ihre Adresse kennt, kann diese Nachrichten lesen. - - - - Status - Status - - - - Sent - Gesendet - - - - Label (not shown to anyone) - Bezeichnung (wird niemandem gezeigt) - - - - Address - Adresse - - - - Stream - Datenstrom - - - - Your Identities - Ihre Identitäten - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - Hier können Sie "Rundruf Nachrichten" abonnieren, die von anderen Benutzern versendet werden. Die Nachrichten tauchen in Ihrem Posteingang auf. (Die Adressen hier überschreiben die auf der Blacklist). - - - - Add new Subscription - Neues Abonnement anlegen - - - - Label - Bezeichnung - - - - Subscriptions - Abonnements - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - 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 "Neuen Eintrag erstellen" hinzufügen, oder über einen Rechtsklick auf eine Nachricht im Posteingang. - - - - Name or Label - Name oder Bezeichnung - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - Liste als Blacklist verwenden (Erlaubt alle eingehenden Nachrichten, außer von Adressen auf der Blacklist) - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - Liste als Whitelist verwenden (Erlaubt keine eingehenden Nachrichten, außer von Adressen auf der Whitelist) - - - - Blacklist - Blacklist - - - - Stream # - Datenstrom # - - - - Connections - Verbindungen - - - - Total connections: 0 - Verbindungen insgesamt: 0 - - - - Since startup at asdf: - Seit start um asdf: - - - - Processed 0 person-to-person message. - 0 Person-zu-Person-Nachrichten verarbeitet. - - - - Processed 0 public key. - 0 öffentliche Schlüssel verarbeitet. - - - - Processed 0 broadcast. - 0 Rundrufe verarbeitet. - - - - Network Status - Netzwerk status - - - - File - Datei - - - - Settings - Einstellungen - - - - Help - Hilfe - - - - Import keys - Schlüssel importieren - - - - Manage keys - Schlüssel verwalten - - - - About - Über - - - - Regenerate deterministic addresses - Deterministische Adressen neu generieren - - - - Delete all trashed messages - Alle Nachrichten im Papierkorb löschen - - - - Message sent. Sent at %1 - Nachricht gesendet. gesendet am %1 - - - - Chan name needed - Chan name benötigt - - - - You didn't enter a chan name. - Sie haben keinen Chan-Namen eingegeben. - - - - Address already present - Adresse bereits vorhanden - - - - Could not add chan because it appears to already be one of your identities. - Chan konnte nicht erstellt werden, da es sich bereits um eine Ihrer Identitäten handelt. - - - - Success - Erfolgreich - - - - Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. - Chan erfolgreich erstellt. Um andere diesem Chan beitreten zu lassen, geben Sie ihnen den Chan-Namen und die Bitmessage-Adresse: %1. Diese Adresse befindet sich auch unter "Ihre Identitäten". - - - - Address too new - Adresse zu neu - - - - Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. - Obwohl diese Bitmessage-Adresse gültig ist, ist ihre Versionsnummer zu hoch um verarbeitet zu werden. Vermutlich müssen Sie eine neuere Version von Bitmessage installieren. - - - - Address invalid - Adresse ungültig - - - - That Bitmessage address is not valid. - Diese Bitmessage-Adresse ist nicht gültig. - - - - Address does not match chan name - Adresse stimmt nicht mit dem Chan-Namen überein - - - - Although the Bitmessage address you entered was valid, it doesn't match the chan name. - Obwohl die Bitmessage-Adresse die Sie eingegeben haben gültig ist, stimmt diese nicht mit dem Chan-Namen überein. - - - - Successfully joined chan. - Chan erfolgreich beigetreten. - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). - Bitmessage wird ab sofort den Proxy-Server verwenden, aber eventuell möchten Sie Bitmessage neu starten um bereits bestehende Verbindungen zu schließen. - - - - This is a chan address. You cannot use it as a pseudo-mailing list. - Dies ist eine Chan-Adresse. Sie können sie nicht als Pseudo-Mailingliste verwenden. - - - - Search - Suchen - - - - All - Alle - - - - Message - Nachricht - - - - Join / Create chan - Chan beitreten / erstellen - - - - Encryption key was requested earlier. - Verschlüsselungscode wurde bereits angefragt. - - - - Sending a request for the recipient's encryption key. - Sende eine Anfrage für den Verschlüsselungscode des Empfängers. - - - - Doing work necessary to request encryption key. - Verrichte die benötigte Arbeit um den Verschlüsselungscode anzufragen. - - - - Broacasting the public key request. This program will auto-retry if they are offline. - Anfrage für den Verschlüsselungscode versendet (wird automatisch periodisch neu verschickt). - - - - Sending public key request. Waiting for reply. Requested at %1 - Anfrag für den Verschlüsselungscode gesendet. Warte auf Antwort. Angefragt am %1 - - - + Mark Unread Als ungelesen markieren - - Fetched address from namecoin identity. - Adresse aus Namecoin Identität geholt. + + New + Neu - - Testing... - teste... + + Enable + Aktivieren - - Fetch Namecoin ID - Hole Namecoin ID + + Disable + Deaktivieren - - Ctrl+Q - Strg+Q - - - - F1 - F1 - - - + Set avatar... Avatar wählen... - - Bad address version number - + + Copy address to clipboard + Adresse in die Zwischenablage kopieren - - Your address version number must be a number: either 3 or 4. - + + Special address behavior... + Spezielles Verhalten der Adresse... - - Your address version number must be either 3 or 4. - + + Email gateway + E-Mail Schnittstelle + + + + Delete + Löschen + + + + Send message to this address + Nachricht an diese Adresse senden + + + + Subscribe to this address + Diese Adresse abonnieren + + + + Add New Address + Neue Adresse hinzufügen + + + + Copy destination address to clipboard + Zieladresse in die Zwischenablage kopieren + + + + Force send + Senden erzwingen + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + Eine Ihrer Adressen, %1, ist eine alte Adresse der Version 1 und wird nicht mehr unterstützt. Soll sie jetzt gelöscht werden? + + + + Waiting for their encryption key. Will request it again soon. + Warte auf den Verschlüsselungscode. Wird bald erneut angefordert. + + + + Encryption key request queued. + Verschlüsselungscode-Anforderung steht aus. + + + + Queued. + In Warteschlange. + + + + Message sent. Waiting for acknowledgement. Sent at %1 + Nachricht gesendet. Warte auf Bestätigung. Gesendet %1 + + + + Message sent. Sent at %1 + Nachricht gesendet. Gesendet am %1 + + + + Need to do work to send message. Work is queued. + Es muss Arbeit verrichtet werden um die Nachricht zu versenden. Arbeit ist in Warteschlange. + + + + Acknowledgement of the message received %1 + Bestätigung der Nachricht erhalten %1 + + + + Broadcast queued. + Rundruf in Warteschlange. + + + + Broadcast on %1 + Rundruf um %1 + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + Problem: Die vom Empfänger geforderte Arbeit ist schwerer als Sie bereit sind, zu berechnen. %1 + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + Problem: Der Verschlüsselungscode des Empfängers ist nicht in Ordnung. Nachricht konnte nicht verschlüsselt werden. %1 + + + + Forced difficulty override. Send should start soon. + Schwierigkeitslimit überschrieben. Senden sollte bald beginnen. + + + + Unknown status: %1 %2 + Unbekannter Status: %1 %2 + + + + Not Connected + Nicht verbunden + + + + Show Bitmessage + Bitmessage anzeigen + + + + Send + Senden + + + + Subscribe + Abonnieren + + + + Channel + Chan + + + + Quit + Beenden - Inventory lookups per second: %1 - Inventory lookups pro Sekunde: %1 + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + Sie können Ihre Schlüssel verwalten, indem Sie die keys.dat bearbeiten, die im gleichen Ordner wie das Programm liegt. Es ist empfehlenswert, vorher ein Backup dieser Datei anlegen. - + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + Sie können Ihre Schlüssel verwalten, indem Sie die keys.dat bearbeiten, die im Ordner +%1 liegt. +Es ist empfehlenswert, vorher ein Backup dieser Datei anlegen. + + + + Open keys.dat? + Die keys.dat öffnen? + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Sie können Ihre Schlüssel verwalten, indem Sie die keys.dat bearbeiten, die im gleichen Ordner wie das Programm liegt. Es ist empfehlenswert, vorher ein Backup dieser Datei anlegen. Möchten Sie die Datei jetzt öffnen? (Stellen Sie sicher, dass Sie Bitmessage beendet haben, bevor Sie etwas ändern.) + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Sie können Ihre Schlüssel verwalten, indem Sie die keys.dat bearbeiten, +die im Ordner %1 liegt. +Es ist empfehlenswert, vorher ein Backup dieser Datei anlegen. Möchten Sie die Datei jetzt öffnen? +(Stellen Sie sicher, dass Sie Bitmessage beendet haben, bevor Sie etwas ändern.) + + + + Delete trash? + Papierkorb leeren? + + + + Are you sure you want to delete all trashed messages? + Sind Sie sicher, dass Sie alle Nachrichten im Papierkorb löschen möchten? + + + + bad passphrase + Falsches Passwort + + + + You must type your passphrase. If you don't have one then this is not the form for you. + Sie müssen Ihr Passwort eingeben. Wenn Sie keins haben, ist dies das falsche Formular für Sie. + + + + Bad address version number + Falsche Addressenversionsnummer + + + + Your address version number must be a number: either 3 or 4. + Die Addressenversionsnummer muss eine Zahl sein, entweder 3 oder 4. + + + + Your address version number must be either 3 or 4. + Die Addressenversionnsnummer muss entweder 3 oder 4 sein. + + + + Chan name needed + Name für den Chan benötigt + + + + You didn't enter a chan name. + Sie haben keinen Chan-Namen eingegeben. + + + + Address already present + Adresse bereits vorhanden + + + + Could not add chan because it appears to already be one of your identities. + Chan konnte nicht erstellt werden, da es sich bereits um eine Ihrer Identitäten handelt. + + + + Success + Erfolgreich + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + Chan erfolgreich erstellt. Um andere diesem Chan beitreten zu lassen, geben Sie ihnen den Chan-Namen und die Bitmessage-Adresse: %1. Diese Adresse befindet sich auch unter "Ihre Identitäten". + + + + Address too new + Adresse zu neu + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + Obwohl diese Bitmessage-Adresse gültig ist, ist ihre Versionsnummer zu hoch um verarbeitet zu werden. Vermutlich müssen Sie eine neuere Version von Bitmessage installieren. + + + + Address invalid + Adresse ungültig + + + + That Bitmessage address is not valid. + Diese Bitmessage-Adresse ist nicht gültig. + + + + Address does not match chan name + Adresse stimmt nicht mit dem Chan-Namen überein + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + Obwohl die Bitmessage-Adresse die Sie eingegeben haben gültig ist, stimmt diese nicht mit dem Chan-Namen überein. + + + + Successfully joined chan. + Chan erfolgreich beigetreten. + + + + Connection lost + Verbindung verloren + + + + Connected + Verbunden + + + + Message trashed + Nachricht in den Papierkorb verschoben + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + Die Haltbarkeit, oder Time-To-Live, ist die Dauer, für die das Netzwerk die Nachricht speichern wird. Der Empfänger muss sie während dieser Zeit empfangen. Wenn Ihr Bitmessage-Client keine Empfangsbestätigung erhält, wird die Nachricht automatisch erneut verschickt. Je länger die Time-To-Live, desto mehr Arbeit muss Ihr Rechner verrichten, um die Nachricht zu senden. Eine Time-To-Live von vier oder fünf Tagen ist meist ausreichend. + + + + Message too long + Narchricht zu lang + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + Die Nachricht, die Sie zu senden versuchen, ist %1 Byte zu lang. (Maximum 261.644 Bytes). Bitte verringern Sie ihre Größe vor dem Senden. + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + Fehler: Ihr Konto war an keiner E-Mailschnittstelle registriert. Registrierung als %1 wird versandt, bitte vor einem erneutem Sendeversuch auf die Registrierungsverarbeitung warten. + + + + Error: Bitmessage addresses start with BM- Please check %1 + Fehler: Bitmessage Adressen starten mit BM- Bitte überprüfen Sie %1 + + + + Error: The address %1 is not typed or copied correctly. Please check it. + Fehler: Die Adresse %1 wurde nicht korrekt getippt oder kopiert. Bitte überprüfen. + + + + Error: The address %1 contains invalid characters. Please check it. + Fehler: Die Adresse %1 beinhaltet ungültig Zeichen. Bitte überprüfen. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + Fehler: Die Adressversion von %1 ist zu hoch. Entweder Sie müssen Ihre Bitmessage Software aktualisieren oder Ihr Bekannter ist sehr clever. + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + Fehler: Einige Daten die in der Adresse %1 codiert sind, sind zu kurz. Es könnte sein, dass etwas mit der Software Ihres Bekannten nicht stimmt. + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + Fehler: Einige Daten die in der Adresse %1 codiert sind, sind zu lang. Es könnte sein, dass etwas mit der Software Ihres Bekannten nicht stimmt. + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + Fehler: Einige codierte Daten in der Adresse %1 sind ungültig. Es könnte etwas mit der Software Ihres Bekannten sein. + + + + Error: Something is wrong with the address %1. + Fehler: Mit der Adresse %1 stimmt etwas nicht. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Fehler: Sie müssen eine Absenderadresse auswählen. Sollten Sie keine haben, wechseln Sie zum Reiter "Ihre Identitäten". + + + + Address version number + Adressversion + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Aufgrund der Adresse %1 kann Bitmessage Adressen mit der Version %2 nicht verarbeiten. Möglicherweise müssen Sie Bitmessage auf die aktuelle Version aktualisieren. + + + + Stream number + Datenstrom Nummer + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Aufgrund der Adresse %1 kann Bitmessage den Datenstrom mit der Version %2 nicht verarbeiten. Möglicherweise müssen Sie Bitmessage auf die aktuelle Version aktualisieren. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Warnung: Sie sind aktuell nicht verbunden. Bitmessage wird die nötige Arbeit zum versenden verrichten, aber erst senden, wenn Sie verbunden sind. + + + + Message queued. + Nachricht befindet sich in der Warteschleife. + + + + Your 'To' field is empty. + Ihr "Empfänger"-Feld ist leer. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Klicken Sie mit rechts auf einen oder mehrere Einträge aus Ihrem Adressbuch und wählen Sie "Nachricht an diese Adresse senden". + + + + Fetched address from namecoin identity. + Adresse aus Namecoin Identität geholt. + + + + New Message + Neue Nachricht + + + + From + Von + + + + Sending email gateway registration request + Der Registrierungsantrag für die E-Mail Schnittstelle wird versandt. + + + + Address is valid. + Adresse ist gültig. + + + + The address you entered was invalid. Ignoring it. + Die von Ihnen eingegebene Adresse ist ungültig, sie wird ignoriert. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Fehler: Sie können eine Adresse nicht doppelt im Adressbuch speichern. Sie können jedoch die bereits eingetragene umbenennen. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + Fehler: Dieselbe Adresse kann nicht doppelt in die Abonnements eingetragen werden. Sie können jedoch die bereits eingetragene umbenennen. + + + + Restart + Neustart + + + + You must restart Bitmessage for the port number change to take effect. + Sie müssen Bitmessage neu starten, um den geänderten Port zu verwenden. + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + Bitmessage wird ab sofort den Proxy-Server verwenden, aber eventuell möchten Sie Bitmessage neu starten um bereits bestehende Verbindungen zu schließen. + + + + Number needed + Zahl erforderlich + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + Ihre maximale Herungerlade- und Hochladegeschwindigkeit müssen Zahlen sein. Die eingetragenen Werte werden ignoriert. + + + Will not resend ever - + Wird nie wiederversendet - + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. - + Bitte beachten Sie, dass der eingetratene Dauer kürzer ist als die, die Bitmessage auf das erste Wiederversenden wartet. Deswegen werden Ihre Nachrichten nie wiederversendet. - + + Sending email gateway unregistration request + E-Mail Schnittestellen-Abmeldeantrag wird versandt + + + + Sending email gateway status request + E-Mail Schnittestellen Statusantrag wird versandt + + + + Passphrase mismatch + Kennwort stimmt nicht überein + + + + The passphrase you entered twice doesn't match. Try again. + Die von Ihnen eingegebenen Kennwörter sind nicht identisch. Bitte neu versuchen. + + + + Choose a passphrase + Wählen Sie ein Kennwort + + + + You really do need a passphrase. + Sie benötigen wirklich ein Kennwort. + + + + Address is gone + Adresse ist verloren + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmessage kann Ihre Adresse %1 nicht finden. Haben Sie sie gelöscht? + + + + Address disabled + Adresse deaktiviert + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Fehler: Die Adresse von der Sie versuchen zu senden ist deaktiviert. Sie müssen sie unter dem Reiter "Ihre Identitäten" aktivieren bevor Sie fortfahren. + + + + Entry added to the Address Book. Edit the label to your liking. + Eintrag dem Adressbuch hinzugefügt. Editieren Sie den Eintrag nach Belieben. + + + + Entry added to the blacklist. Edit the label to your liking. + Eintrag in die Blacklist hinzugefügt. Die Beschriftung können Sie ändern. + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + Fehler: Dieselbe Addresse kann nicht doppelt in die Blacklist eingetragen werden. Sie können jedoch die bereits eingetragene umbenennen. + + + + Moved items to trash. + Objekt(e) in den Papierkorb verschoben. + + + + Undeleted item. + Nachricht wiederhergestellt. + + + + Save As... + Speichern unter... + + + + Write error. + Fehler beim Speichern. + + + + No addresses selected. + Keine Adresse ausgewählt. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + Wenn Sie das Abonnement löschen, werden bereits erhaltene Nachrichten unaufrufbar. Vielleicht deaktivieren Sie das Abonnement lieber? Deaktivierte Abonnements erhalten keine neue Nachrichten, aber Sie können die bereits erhaltene aufrufen. + +Sind Sie sicher, dass Sie das Abonnement löschen möchten? + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + Wenn Sie das Chan löschen, die bereits erhaltene Nachrichten werden unaufrufbar. Vielleicht deaktivieren Sie den Chan lieber?. Deaktivierte Chans erhalten keine neue Nachrichten, aber Sie können die bereits erhaltene aufrufen. + +Sind Sie sicher, dass Sie das Chan löschen möchten? + + + Do you really want to remove this avatar? Wollen Sie diesen Avatar wirklich entfernen? - + You have already set an avatar for this address. Do you really want to overwrite it? Sie haben bereits einen Avatar für diese Adresse gewählt. Wollen Sie ihn wirklich überschreiben? - + Start-on-login not yet supported on your OS. - Mit Betriebssystem starten, noch nicht unterstützt + Mit Betriebssystem starten, noch nicht von Ihrem Betriebssystem unterstützt - + Minimize-to-tray not yet supported on your OS. - + Ins System Tray minimieren von Ihrem Betriebssytem noch nicht unterstützt. - + Tray notifications not yet supported on your OS. - + Trach-Benachrichtigungen von Ihrem Betriebssystem noch nicht unterstützt. - + + Testing... + teste... + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + Dies ist eine Chan-Adresse. Sie können sie nicht als Pseudo-Mailingliste verwenden. + + + + The address should start with ''BM-'' + Die Adresse sollte mit "BM-" beginnen + + + + The address is not typed or copied correctly (the checksum failed). + Die Adresse wurde nicht korrekt getippt oder kopiert (Prüfsumme falsch). + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + Die Versionsnummer dieser Adresse ist höher als diese Software unterstützt. Bitte installieren Sie die neuste Bitmessage Version. + + + + The address contains invalid characters. + Diese Adresse beinhaltet ungültige Zeichen. + + + + Some data encoded in the address is too short. + Die in der Adresse codierten Daten sind zu kurz. + + + + Some data encoded in the address is too long. + Die in der Adresse codierten Daten sind zu lang. + + + + Some data encoded in the address is malformed. + Einige in der Adresse kodierten Daten sind ungültig. + + + Enter an address above. - + Eine Addresse oben ausfüllen. - + Address is an old type. We cannot display its past broadcasts. - + Alter Addressentyp. Wir können deren vorige Rundrufe nicht anzeigen. - + There are no recent broadcasts from this address to display. - + Es gibt keine neuen Rundrufe von dieser Adresse die angezeigt werden können. - - Display the %1 recent broadcast from this address. - + + You are using TCP port %1. (This can be changed in the settings). + Sie benutzen TCP-Port %1 (Dieser kann in den Einstellungen verändert werden). - - Display the %1 recent broadcasts from this address. - + + Bitmessage + Bitmessage - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - + + Identities + Identitäten - - Inventory lookups per second: 0 - Inventory lookups pro Sekunde: 0 + + New Identity + Neue Identität + + + + Search + Suchen + + + + All + Alle + + + + To + An + + + + From + Von + + + + Subject + Betreff + + + + Message + Nachricht + + + + Received + Erhalten + + + + Messages + Nachrichten + + + + Address book + Addressbuch + + + + Address + Adresse + + + + Add Contact + Kontakt hinzufügen + + + + Fetch Namecoin ID + Hole Namecoin ID + + + + Subject: + Betreff: + + + + From: + Von: + + + + To: + An: + + + + Send ordinary Message + Ordentliche Nachricht senden + + + + Send Message to your Subscribers + Rundruf an Ihre Abonnenten senden + + + + TTL: + Ablauf: + + + + Subscriptions + Abonnements + + + + Add new Subscription + Neues Abonnement anlegen + + + + Chans + Chans + + + + Add Chan + Chan hinzufügen + + + + File + Datei + + + + Settings + Einstellungen + + + + Help + Hilfe + + + + Import keys + Schlüssel importieren + + + + Manage keys + Schlüssel verwalten + + + + Ctrl+Q + Strg+Q + + + + F1 + F1 + + + + Contact support + Unterstütung anfordern + + + + About + Über + + + + Regenerate deterministic addresses + Deterministische Adressen neu generieren + + + + Delete all trashed messages + Alle Nachrichten im Papierkorb löschen + + + + Join / Create chan + Chan beitreten / erstellen + + + + All accounts + Alle Identitäten + + + + Zoom level %1% + Zoom-Stufe %1% + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + Fehler: Sie können eine Adresse nicht doppelt zur Liste hinzufügen. Wenn Sie möchten, benennen Sie den existierenden Eintrag um. + + + + Add new entry + Neuen Eintrag erstellen + + + + Display the %1 recent broadcast(s) from this address. + Die letzten %1 Rundruf(e) von dieser Addresse anzeigen. + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + Neue Version von PyBitmessage steht zur Verfügung: %1. Sie können sie von https://github.com/Bitmessage/PyBitmessage/releases/latest herunterladen. + + + + Waiting for PoW to finish... %1% + Warte auf Achluss von Berechnungen (PoW)... %1% + + + + Shutting down Pybitmessage... %1% + PyBitmessage wird beendet... %1% + + + + Waiting for objects to be sent... %1% + Warte auf Versand von Objekten... %1% + + + + Saving settings... %1% + Einstellungen werden gespeichert... %1% + + + + Shutting down core... %1% + Kern wird beendet... %1% + + + + Stopping notifications... %1% + Beende Benachrichtigungen... %1% + + + + Shutdown imminent... %1% + Unmittelbar vor Beendung... %1% + + + + %n hour(s) + %n Stunde%n Stunden + + + + %n day(s) + %n Tag%n Tage + + + + Shutting down PyBitmessage... %1% + PyBitmessage wird beendet... %1% + + + + Sent + Gesendet + + + + Generating one new address + Neue Addresse wird erstellt + + + + Done generating address. Doing work necessary to broadcast it... + Die Addresse wurde erstellt. Arbeit wird verrichtet, um sie zu versenden... + + + + Generating %1 new addresses. + Erzeuge %1 neue Addressen. + + + + %1 is already in 'Your Identities'. Not adding it again. + %1 befindet sich bereits unter Ihren Identitäten, wird nicht doppelt hinzugefügt. + + + + Done generating address + Addresse fertiggestellt. + + + + SOCKS5 Authentication problem: %1 + SOCKS5-Authentizierung fehlgeschlagen: %1 + + + + Disk full + Datenträger voll + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + Warnung: Ihr Datenträger oder Datenspeichervolumen ist voll. Bitmessage wird jetzt beendet. + + + + Error! Could not find sender address (your address) in the keys.dat file. + Fehler! Konnte die Absenderadresse (Ihre Adresse) in der keys.dat-Datei nicht finden. + + + + Doing work necessary to send broadcast... + Arbeit wird verrichtet, um einen Rundruf zu verschicken... + + + + Broadcast sent on %1 + Rundruf verschickt um %1 + + + + Encryption key was requested earlier. + Verschlüsselungsschlüssel wurde früher angefordert. + + + + Sending a request for the recipient's encryption key. + Anfrage nach dem Verschlüsselungsschlüssel des Empfängers wird versendet. + + + + Looking up the receiver's public key + Suche nach dem öffentlichen Schlüssel des Empfängers + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + Problem: Der Empfänger benutzt ein mobiles Gerät und erfordert eine unverschlüsselte Empfängeraddresse. Dies ist in Ihren Einstellungen jedoch nicht zulässig. 1% + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + Arbeit für Nachrichtenversand wird verrichtet. +Version-2-Addressen wie die des Empfängers haben keine Schweirigkeitserforderungen. + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + Arbeit für Nachrichtenversand wird errichtet. Vom Empfänger erforderliche Schwierigkeit: %1 und %2 + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + Problem: Die vom Empfänger verlangte Arbeit (%1 und %2) ist schwieriger, als Sie in den Einstellungen erlaubt haben. %3 + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + Problem: Sie versuchen, eine Nachricht an sich zu versenden, aber Ihr Schlüssel befindet sich nicht in der keys.dat-Datei. Die Nachricht kann nicht verschlüsselt werden. 1% + + + + Doing work necessary to send message. + Arbeit wird verrichtet, um die Nachricht zu verschicken... + + + + Message sent. Waiting for acknowledgement. Sent on %1 + Nachricht versendet. Auf Bestätigung wird gewartet. Versendet am 1% + + + + Doing work necessary to request encryption key. + Arbeit wird verrichtet, um den Schlüssel nachzufragen... + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + Anfrage nach dem öffentlichen Schlüssel läuft. Wenn der Besitzer nicht mit dem Netzwerk verbunden ist, wird ein Wiederholungsversuch unternommen. + + + + Sending public key request. Waiting for reply. Requested at %1 + Nachfrage nach dem öffentlichen Schlüssel läuft, auf Antwort wird gewartet. Nachgefragt am %1 + + + + UPnP port mapping established on port %1 + UPnP Port-Mapping eingerichtet auf Port %1 + + + + UPnP port mapping removed + UPnP Port-Mapping entfernt @@ -1084,8 +1358,8 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei - Address version number: 3 - Adress-Versionsnummer: 3 + Address version number: 4 + Adress-Versionsnummer: 4 @@ -1142,11 +1416,6 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei (saves you some bandwidth and processing power) (Dies erspart Ihnen etwas an Bandbreite und Rechenleistung) - - - Address version number: 4 - Adress-Versionsnummer: 4 - NewSubscriptionDialog @@ -1167,8 +1436,8 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei - CheckBox - + Enter an address above. + Bitte geben Sie oben eine Adresse ein. @@ -1191,7 +1460,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). - Nachrichten an eine Pseudo-Mailinglistenadresse werden automatisch zu allen Abbonenten weitergeleitet (Der Inhalt ist dann öffentlich). + Nachrichten an eine Pseudo-Mailinglistenadresse werden automatisch an alle Abonnenten weitergeleitet (Der Inhalt ist dann öffentlich). @@ -1216,11 +1485,6 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei version ? Version ? - - - Copyright © 2013 Jonathan Warren - Copyright © 2013 Jonathan Warren - <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> @@ -1233,8 +1497,46 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 The Bitmessage Developers</p></body></html> - + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 Die Bitmessage-Entwickler</p></body></html> + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + Liste als Blacklist verwenden (Erlaubt alle eingehenden Nachrichten, außer von Adressen auf der Blacklist) + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + Liste als Whitelist verwenden (Erlaubt keine eingehenden Nachrichten, außer von Adressen auf der Whitelist) + + + + Add new entry + Neuen Eintrag erstellen + + + + Name or Label + Name oder Bezeichnung + + + + Address + Adresse + + + + Blacklist + Blacklist + + + + Whitelist + Whitelist @@ -1269,8 +1571,8 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> @@ -1306,6 +1608,119 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei Sie haben Verbindungen mit anderen Netzwerkteilnehmern und Ihre Firewall ist richtig konfiguriert. + + networkstatus + + + Total connections: + Verbindungen insgesamt: + + + + Since startup: + Seit Start: + + + + Processed 0 person-to-person messages. + 0 Person-zu-Person-Nachrichten verarbeitet. + + + + Processed 0 public keys. + 0 öffentliche Schlüssel verarbeitet. + + + + Processed 0 broadcasts. + 0 Rundrufe verarbeitet. + + + + Inventory lookups per second: 0 + Inventory lookups pro Sekunde: 0 + + + + Objects to be synced: + Zu synchronisierende Objektanzahl: + + + + Stream # + Datenstrom # + + + + Connections + Verbindungen + + + + Since startup on %1 + Seit Start der Anwendung am %1 + + + + Down: %1/s Total: %2 + Herunter: %1/s Insg.: %2 + + + + Up: %1/s Total: %2 + Hoch: %1/s Insg.: %2 + + + + Total Connections: %1 + Verbindungen insgesamt: %1 + + + + Inventory lookups per second: %1 + Inventory lookups pro Sekunde: %1 + + + + Up: 0 kB/s + Hoch: 0 kB/s + + + + Down: 0 kB/s + Herunter: 0 kB/s + + + + Network Status + Netzwerkstatus + + + + byte(s) + ByteBytes + + + + Object(s) to be synced: %n + %n Objekt zu synchronisieren.%n Objekte zu synchronisieren. + + + + Processed %n person-to-person message(s). + %n Person-zu-Person-Nachricht bearbeitet.%n Person-zu-Person-Nachrichten bearbeitet. + + + + Processed %n broadcast message(s). + %n Rundruf-Nachricht bearbeitet.%n Rundruf-Nachrichten bearbeitet. + + + + Processed %n public key(s). + %n öffentlicher Schlüssel verarbeitet.%n öffentliche Schlüssel verarbeitet. + + newChanDialog @@ -1328,6 +1743,11 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei Create a chan Chan erstellen + + + <html><head/><body><p>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.</p></body></html> + <html><head/><body><p>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.</p><br></body></html> + Chan name: @@ -1343,11 +1763,6 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei Chan bitmessage address: Chan-Bitmessage-Adresse: - - - <html><head/><body><p>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.</p></body></html> - <html><head/><body><p>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.</p><br></body></html> - regenerateAddressesDialog @@ -1372,14 +1787,9 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei Anzahl der Adressen, die basierend auf diesem Kennwortsatz erzeugt werden sollen: - - Address version Number: - Adress-Versionsnummer: - - - - 3 - 3 + + Address version number: + Adress-Versionsnummer: @@ -1406,343 +1816,299 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei 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. 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. - - - Address version number: - Adress-Versionsnummer: - settingsDialog - + Settings Einstellungen - + Start Bitmessage on user login Bitmessage nach dem Hochfahren automatisch starten - + + Tray + Infobereich (Taskleiste) + + + Start Bitmessage in the tray (don't show main window) Bitmessage minimiert starten (zeigt das Hauptfenster nicht an) - + Minimize to tray In den Systemtray minimieren - + + Close to tray + Schliessen ins Infobereich + + + Show notification when message received Benachrichtigung anzeigen, wenn eine Nachricht eintrifft - + Run in Portable Mode Im portablen Modus arbeiten - + 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. 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. - - User Interface - Benutzerinterface - - - - Listening port - TCP-Port - - - - Listen for connections on port: - Wartet auf Verbindungen auf Port: - - - - Proxy server / Tor - Proxy-Server / Tor - - - - Type: - Typ: - - - - none - keiner - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - - Server hostname: - Servername: - - - - Port: - Port: - - - - Authentication - Authentifizierung - - - - Username: - Benutzername: - - - - Pass: - Kennwort: - - - - Network Settings - Netzwerkeinstellungen - - - - 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. - 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. - - - - Total difficulty: - Gesamtschwierigkeit: - - - - Small message difficulty: - Schwierigkeit für kurze Nachrichten: - - - - 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. - Die "Schwierigkeit für kurze Nachrichten" 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. - - - - The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - Die "Gesamtschwierigkeit" beeinflusst die absolute Menge Arbeit, die ein Sender verrichten muss. Verdoppelung dieses Wertes verdoppelt die Menge der Arbeit. - - - - Demanded difficulty - Geforderte Schwierigkeit - - - - 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. - Hier setzen Sie die maximale Arbeit, die Sie bereit sind zu verrichten, um eine Nachricht an eine andere Person zu versenden. Ein Wert von 0 bedeutet, dass Sie jede Arbeit akzeptieren. - - - - Maximum acceptable total difficulty: - Maximale akzeptierte Gesamtschwierigkeit: - - - - Maximum acceptable small message difficulty: - Maximale akzeptierte Schwierigkeit für kurze Nachrichten: - - - - Max acceptable difficulty - Maximale akzeptierte Schwierigkeit - - - - Listen for incoming connections when using proxy - Auf eingehende Verbindungen warten, auch wenn ein Proxy-Server verwendet wird - - - + Willingly include unencrypted destination address when sending to a mobile device Willentlich die unverschlüsselte Adresse des Empfängers übertragen, wenn an ein mobiles Gerät gesendet wird - - - <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> - <html><head/><body><p>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 <span style=" font-style:italic;">test </span>senden.</p><p> (Ihre Bitmessage-Adresse in Namecoin zu speichern ist noch sehr umständlich)</p><p>Bitmessage kann direkt namecoind verwenden, oder eine nmcontrol Instanz.</p></body></html> - - - - Host: - Server: - - - - Password: - Kennwort: - - - - Test - Verbindung testen - - - - Connect to: - Verbinde mit: - - - - Namecoind - Namecoind - - - - NMControl - NMControl - - - - Namecoin integration - Namecoin Integration - - - - Override automatic language localization (use countycode or language code, e.g. 'en_US' or 'en'): - Automatische Sprachauswahl überschreiben (verwenden Sie den Landescode oder Sprachcode, z.B. "de_DE" oder "de"): - - - - Use Identicons - Benutze Identicons (Automatisch generierte Icons zu einer Bitcoinadresse) - - - - Interface Language - Sprachauswahl - - - - System Settings - system - - - - - English - en - - - - - Esperanto - eo - - - - - Français - fr - - - - - Deutsch - de - - - - - Españl - es - - - - - русский язык - ru - - - - - Norsk - no - - - - - Pirate English - en_pirate - - - - - Other (set in keys.dat) - other - - - - - <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> - <html><head/><body><p>Wurde eine Nachricht innerhalb von zwei Tagen nicht bestätigt, wird sie in zwei Tagen noch einmal gesendet. Schlägt dies wieder fehl, wird es in 5, dann in 10, dann in 20 usw. Tagen wieder versucht. Sendet der Empfänger keine Bestätigung, geht dies unendlich so weiter.</p><p>Dieses Verhalten kann hier begrenzt werden.</p></body></html> - - Give up after - Gib auf nach + Use Identicons + Benutze Identicons (Automatisch generierte Icons zu einer Bitmessageadresse) - and - und - - - - days - Tagen - - - - months. - Monaten - - - - Resends Expire - Neusendung - - - Reply below Quote Antworte unter zitierter Nachricht - + + Interface Language + Sprachauswahl + + + + System Settings + system + Vom System übernehmen + + + + User Interface + Benutzerinterface + + + + Listening port + TCP-Port + + + + Listen for connections on port: + Wartet auf Verbindungen auf Port: + + + + UPnP: + UPnP: + + + Bandwidth limit Bandbreite begrenzen - + Maximum download rate (kB/s): [0: unlimited] Maximale Downloadrate in kB/s, 0 bedeutet kein Limit - + Maximum upload rate (kB/s): [0: unlimited] Maximale Uploadrate in kB/s, 0 bedeutet kein Limit + + + Proxy server / Tor + Proxy-Server / Tor + + + + Type: + Typ: + + + + Server hostname: + Servername: + + + + Port: + Port: + + + + Authentication + Authentifizierung + + + + Username: + Benutzername: + + + + Pass: + Kennwort: + + + + Listen for incoming connections when using proxy + Auf eingehende Verbindungen warten, auch wenn ein Proxy-Server verwendet wird + + + + none + keiner + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Netzwerkeinstellungen + + + + Total difficulty: + Gesamtschwierigkeit: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + Die "Gesamtschwierigkeit" beeinflusst die absolute Menge Arbeit, die ein Sender verrichten muss. Verdoppelung dieses Wertes verdoppelt die Menge der Arbeit. + + + + Small message difficulty: + Schwierigkeit für kurze Nachrichten: + + + + 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. + 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. + + + + 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. + Die "Schwierigkeit für kurze Nachrichten" 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. + + + + Demanded difficulty + Geforderte Schwierigkeit + + + + 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. + Hier setzen Sie die maximale Arbeit, die Sie bereit sind zu verrichten, um eine Nachricht an eine andere Person zu versenden. Ein Wert von 0 bedeutet, dass Sie jede Arbeit akzeptieren. + + + + Maximum acceptable total difficulty: + Maximale akzeptierte Gesamtschwierigkeit: + + + + Maximum acceptable small message difficulty: + Maximale akzeptierte Schwierigkeit für kurze Nachrichten: + + + + Max acceptable difficulty + Maximale akzeptierte Schwierigkeit + + + + Hardware GPU acceleration (OpenCL) + Hardwaregrafikkartenbeschleunigung (OpenCL) + + + + <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> + <html><head/><body><p>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 <span style=" font-style:italic;">test </span>senden.</p><p> (Ihre Bitmessage-Adresse in Namecoin zu speichern ist noch sehr umständlich)</p><p>Bitmessage kann direkt namecoind verwenden, oder eine nmcontrol Instanz.</p></body></html> + + + + Host: + Server: + + + + Password: + Kennwort: + + + + Test + Verbindung testen + + + + Connect to: + Verbinde mit: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Namecoin Integration + + + + <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> + <html><head/><body><p>Wenn der Empfänger eine Nachricht nicht bis zum Ablauf herunterlädt, zum Beisplel weil er für längere Zeit nicht mit dem Netz verbunden ist, wird die Nachricht erneut versendet. Dies passiert solange, bis eine Empfangsbestätigung erhalten wird. Hier können Sie dieses Verhalten ändern, indem Sie Bitmessage die Viederersandversuche nach einer bestimmten Anzahl von Tagen oder Monaten aufgeben lassen.</p><p>Für die Standardeinstellung (ohne zeitliche Einschränkung) lassen Sie diese Eingabefelder leer.</p></body></html> + + + + Give up after + Gib auf nach + + + + and + und + + + + days + Tagen + + + + months. + Monaten. + + + + Resends Expire + Neusendungsablauf + - + \ No newline at end of file diff --git a/src/translations/bitmessage_en.qm b/src/translations/bitmessage_en.qm new file mode 100644 index 00000000..2bc73900 Binary files /dev/null and b/src/translations/bitmessage_en.qm differ diff --git a/src/translations/bitmessage_en.ts b/src/translations/bitmessage_en.ts new file mode 100644 index 00000000..9751ae33 --- /dev/null +++ b/src/translations/bitmessage_en.ts @@ -0,0 +1,2112 @@ + + + AddAddressDialog + + + Add new entry + Add new entry + + + + Label + Label + + + + Address + Address + + + + EmailGatewayDialog + + + Email gateway + Email gateway + + + + Register on email gateway + Register on email gateway + + + + Account status at email gateway + Account status at email gateway + + + + Change account settings at email gateway + Change account settings at email gateway + + + + Unregister from email gateway + Unregister from email gateway + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + Desired email address (including @mailchuck.com): + Desired email address (including @mailchuck.com): + + + + EmailGatewayRegistrationDialog + + + Registration failed: + Registration failed: + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + Email gateway registration + Email gateway registration + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + # 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + + MainWindow + + + Reply to sender + Reply to sender + + + + Reply to channel + Reply to channel + + + + Add sender to your Address Book + Add sender to your Address Book + + + + Add sender to your Blacklist + Add sender to your Blacklist + + + + Move to Trash + Move to Trash + + + + Undelete + Undelete + + + + View HTML code as formatted text + View HTML code as formatted text + + + + Save message as... + Save message as... + + + + Mark Unread + Mark Unread + + + + New + New + + + + Enable + Enable + + + + Disable + Disable + + + + Set avatar... + Set avatar... + + + + Copy address to clipboard + Copy address to clipboard + + + + Special address behavior... + Special address behavior... + + + + Email gateway + Email gateway + + + + Delete + Delete + + + + Send message to this address + Send message to this address + + + + Subscribe to this address + Subscribe to this address + + + + Add New Address + Add New Address + + + + Copy destination address to clipboard + Copy destination address to clipboard + + + + Force send + Force send + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + + + + Waiting for their encryption key. Will request it again soon. + Waiting for their encryption key. Will request it again soon. + + + + Encryption key request queued. + Encryption key request queued. + + + + Queued. + Queued. + + + + Message sent. Waiting for acknowledgement. Sent at %1 + Message sent. Waiting for acknowledgement. Sent at %1 + + + + Message sent. Sent at %1 + Message sent. Sent at %1 + + + + Need to do work to send message. Work is queued. + Need to do work to send message. Work is queued. + + + + Acknowledgement of the message received %1 + Acknowledgement of the message received %1 + + + + Broadcast queued. + Broadcast queued. + + + + Broadcast on %1 + Broadcast on %1 + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + + + + Forced difficulty override. Send should start soon. + Forced difficulty override. Send should start soon. + + + + Unknown status: %1 %2 + Unknown status: %1 %2 + + + + Not Connected + Not Connected + + + + Show Bitmessage + Show Bitmessage + + + + Send + Send + + + + Subscribe + Subscribe + + + + Channel + Channel + + + + Quit + Quit + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + + + + Open keys.dat? + Open keys.dat? + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + Delete trash? + Delete trash? + + + + Are you sure you want to delete all trashed messages? + Are you sure you want to delete all trashed messages? + + + + bad passphrase + bad passphrase + + + + You must type your passphrase. If you don't have one then this is not the form for you. + You must type your passphrase. If you don't have one then this is not the form for you. + + + + Bad address version number + Bad address version number + + + + Your address version number must be a number: either 3 or 4. + Your address version number must be a number: either 3 or 4. + + + + Your address version number must be either 3 or 4. + Your address version number must be either 3 or 4. + + + + Chan name needed + Chan name needed + + + + You didn't enter a chan name. + You didn't enter a chan name. + + + + Address already present + Address already present + + + + Could not add chan because it appears to already be one of your identities. + Could not add chan because it appears to already be one of your identities. + + + + Success + Success + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + + + + Address too new + Address too new + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + + + + Address invalid + Address invalid + + + + That Bitmessage address is not valid. + That Bitmessage address is not valid. + + + + Address does not match chan name + Address does not match chan name + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + + + + Successfully joined chan. + Successfully joined chan. + + + + Connection lost + Connection lost + + + + Connected + Connected + + + + Message trashed + Message trashed + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + Message too long + Message too long + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + Error: Bitmessage addresses start with BM- Please check %1 + Error: Bitmessage addresses start with BM- Please check %1 + + + + Error: The address %1 is not typed or copied correctly. Please check it. + Error: The address %1 is not typed or copied correctly. Please check it. + + + + Error: The address %1 contains invalid characters. Please check it. + Error: The address %1 contains invalid characters. Please check it. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + Error: Something is wrong with the address %1. + Error: Something is wrong with the address %1. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + + + + Address version number + Address version number + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + Stream number + Stream number + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + + + + Message queued. + Message queued. + + + + Your 'To' field is empty. + Your 'To' field is empty. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Right click one or more entries in your address book and select 'Send message to this address'. + + + + Fetched address from namecoin identity. + Fetched address from namecoin identity. + + + + New Message + New Message + + + + From + From + + + + Sending email gateway registration request + Sending email gateway registration request + + + + Address is valid. + Address is valid. + + + + The address you entered was invalid. Ignoring it. + The address you entered was invalid. Ignoring it. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + Restart + Restart + + + + You must restart Bitmessage for the port number change to take effect. + You must restart Bitmessage for the port number change to take effect. + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + + + + Number needed + Number needed + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + Will not resend ever + Will not resend ever + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + Sending email gateway unregistration request + Sending email gateway unregistration request + + + + Sending email gateway status request + Sending email gateway status request + + + + Passphrase mismatch + Passphrase mismatch + + + + The passphrase you entered twice doesn't match. Try again. + The passphrase you entered twice doesn't match. Try again. + + + + Choose a passphrase + Choose a passphrase + + + + You really do need a passphrase. + You really do need a passphrase. + + + + Address is gone + Address is gone + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmessage cannot find your address %1. Perhaps you removed it? + + + + Address disabled + Address disabled + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + + + + Entry added to the Address Book. Edit the label to your liking. + Entry added to the Address Book. Edit the label to your liking. + + + + Entry added to the blacklist. Edit the label to your liking. + Entry added to the blacklist. Edit the label to your liking. + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + Moved items to trash. + Moved items to trash. + + + + Undeleted item. + Undeleted item. + + + + Save As... + Save As... + + + + Write error. + Write error. + + + + No addresses selected. + No addresses selected. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + Do you really want to remove this avatar? + Do you really want to remove this avatar? + + + + You have already set an avatar for this address. Do you really want to overwrite it? + You have already set an avatar for this address. Do you really want to overwrite it? + + + + Start-on-login not yet supported on your OS. + Start-on-login not yet supported on your OS. + + + + Minimize-to-tray not yet supported on your OS. + Minimize-to-tray not yet supported on your OS. + + + + Tray notifications not yet supported on your OS. + Tray notifications not yet supported on your OS. + + + + Testing... + Testing... + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + This is a chan address. You cannot use it as a pseudo-mailing list. + + + + The address should start with ''BM-'' + The address should start with ''BM-'' + + + + The address is not typed or copied correctly (the checksum failed). + The address is not typed or copied correctly (the checksum failed). + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + + + + The address contains invalid characters. + The address contains invalid characters. + + + + Some data encoded in the address is too short. + Some data encoded in the address is too short. + + + + Some data encoded in the address is too long. + Some data encoded in the address is too long. + + + + Some data encoded in the address is malformed. + Some data encoded in the address is malformed. + + + + Enter an address above. + Enter an address above. + + + + Address is an old type. We cannot display its past broadcasts. + Address is an old type. We cannot display its past broadcasts. + + + + There are no recent broadcasts from this address to display. + There are no recent broadcasts from this address to display. + + + + You are using TCP port %1. (This can be changed in the settings). + You are using TCP port %1. (This can be changed in the settings). + + + + Bitmessage + Bitmessage + + + + Identities + Identities + + + + New Identity + New Identity + + + + Search + Search + + + + All + All + + + + To + To + + + + From + From + + + + Subject + Subject + + + + Message + Message + + + + Received + Received + + + + Messages + Messages + + + + Address book + Address book + + + + Address + Address + + + + Add Contact + Add Contact + + + + Fetch Namecoin ID + Fetch Namecoin ID + + + + Subject: + Subject: + + + + From: + From: + + + + To: + To: + + + + Send ordinary Message + Send ordinary Message + + + + Send Message to your Subscribers + Send Message to your Subscribers + + + + TTL: + TTL: + + + + Subscriptions + Subscriptions + + + + Add new Subscription + Add new Subscription + + + + Chans + Chans + + + + Add Chan + Add Chan + + + + File + File + + + + Settings + Settings + + + + Help + Help + + + + Import keys + Import keys + + + + Manage keys + Manage keys + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + Contact support + + + + About + About + + + + Regenerate deterministic addresses + Regenerate deterministic addresses + + + + Delete all trashed messages + Delete all trashed messages + + + + Join / Create chan + Join / Create chan + + + + All accounts + All accounts + + + + Zoom level %1% + Zoom level %1% + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + Add new entry + Add new entry + + + + Display the %1 recent broadcast(s) from this address. + Display the %1 recent broadcast(s) from this address. + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + Waiting for PoW to finish... %1% + Waiting for PoW to finish... %1% + + + + Shutting down Pybitmessage... %1% + Shutting down Pybitmessage... %1% + + + + Waiting for objects to be sent... %1% + Waiting for objects to be sent... %1% + + + + Saving settings... %1% + Saving settings... %1% + + + + Shutting down core... %1% + Shutting down core... %1% + + + + Stopping notifications... %1% + Stopping notifications... %1% + + + + Shutdown imminent... %1% + Shutdown imminent... %1% + + + + %n hour(s) + %n hour%n hours + + + + %n day(s) + %n day%n days + + + + Shutting down PyBitmessage... %1% + Shutting down PyBitmessage... %1% + + + + Sent + Sent + + + + Generating one new address + Generating one new address + + + + Done generating address. Doing work necessary to broadcast it... + Done generating address. Doing work necessary to broadcast it... + + + + Generating %1 new addresses. + Generating %1 new addresses. + + + + %1 is already in 'Your Identities'. Not adding it again. + %1 is already in 'Your Identities'. Not adding it again. + + + + Done generating address + Done generating address + + + + SOCKS5 Authentication problem: %1 + SOCKS5 Authentication problem: %1 + + + + Disk full + Disk full + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + Error! Could not find sender address (your address) in the keys.dat file. + Error! Could not find sender address (your address) in the keys.dat file. + + + + Doing work necessary to send broadcast... + Doing work necessary to send broadcast... + + + + Broadcast sent on %1 + Broadcast sent on %1 + + + + Encryption key was requested earlier. + Encryption key was requested earlier. + + + + Sending a request for the recipient's encryption key. + Sending a request for the recipient's encryption key. + + + + Looking up the receiver's public key + Looking up the receiver's public key + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + Doing work necessary to send message. + Doing work necessary to send message. + + + + Message sent. Waiting for acknowledgement. Sent on %1 + Message sent. Waiting for acknowledgement. Sent on %1 + + + + Doing work necessary to request encryption key. + Doing work necessary to request encryption key. + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + Sending public key request. Waiting for reply. Requested at %1 + Sending public key request. Waiting for reply. Requested at %1 + + + + UPnP port mapping established on port %1 + UPnP port mapping established on port %1 + + + + UPnP port mapping removed + UPnP port mapping removed + + + + NewAddressDialog + + + Create new Address + Create new Address + + + + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + + + + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + + + + Use a random number generator to make an address + Use a random number generator to make an address + + + + Use a passphrase to make addresses + Use a passphrase to make addresses + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + Make deterministic addresses + Make deterministic addresses + + + + Address version number: 4 + Address version number: 4 + + + + In addition to your passphrase, you must remember these numbers: + In addition to your passphrase, you must remember these numbers: + + + + Passphrase + Passphrase + + + + Number of addresses to make based on your passphrase: + Number of addresses to make based on your passphrase: + + + + Stream number: 1 + Stream number: 1 + + + + Retype passphrase + Retype passphrase + + + + Randomly generate address + Randomly generate address + + + + Label (not shown to anyone except you) + Label (not shown to anyone except you) + + + + Use the most available stream + Use the most available stream + + + + (best if this is the first of many addresses you will create) + (best if this is the first of many addresses you will create) + + + + Use the same stream as an existing address + Use the same stream as an existing address + + + + (saves you some bandwidth and processing power) + (saves you some bandwidth and processing power) + + + + NewSubscriptionDialog + + + Add new entry + Add new entry + + + + Label + Label + + + + Address + Address + + + + Enter an address above. + Enter an address above. + + + + SpecialAddressBehaviorDialog + + + Special Address Behavior + Special Address Behavior + + + + Behave as a normal address + Behave as a normal address + + + + Behave as a pseudo-mailing-list address + Behave as a pseudo-mailing-list address + + + + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + + + + Name of the pseudo-mailing-list: + Name of the pseudo-mailing-list: + + + + aboutDialog + + + About + About + + + + PyBitmessage + PyBitmessage + + + + version ? + version ? + + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + + + + This is Beta software. + This is Beta software. + + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + Add new entry + Add new entry + + + + Name or Label + Name or Label + + + + Address + Address + + + + Blacklist + Blacklist + + + + Whitelist + Whitelist + + + + connectDialog + + + Bitmessage + Bitmessage + + + + Bitmessage won't connect to anyone until you let it. + Bitmessage won't connect to anyone until you let it. + + + + Connect now + Connect now + + + + Let me configure special network settings first + Let me configure special network settings first + + + + helpDialog + + + Help + Help + + + + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + + + + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + + + + iconGlossaryDialog + + + Icon Glossary + Icon Glossary + + + + You have no connections with other peers. + You have no connections with other peers. + + + + 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'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. + 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'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. + + + + You are using TCP port ?. (This can be changed in the settings). + You are using TCP port ?. (This can be changed in the settings). + + + + You do have connections with other peers and your firewall is correctly configured. + You do have connections with other peers and your firewall is correctly configured. + + + + networkstatus + + + Total connections: + Total connections: + + + + Since startup: + Since startup: + + + + Processed 0 person-to-person messages. + Processed 0 person-to-person messages. + + + + Processed 0 public keys. + Processed 0 public keys. + + + + Processed 0 broadcasts. + Processed 0 broadcasts. + + + + Inventory lookups per second: 0 + Inventory lookups per second: 0 + + + + Objects to be synced: + Objects to be synced: + + + + Stream # + Stream # + + + + Connections + Connections + + + + Since startup on %1 + Since startup on %1 + + + + Down: %1/s Total: %2 + Down: %1/s Total: %2 + + + + Up: %1/s Total: %2 + Up: %1/s Total: %2 + + + + Total Connections: %1 + Total Connections: %1 + + + + Inventory lookups per second: %1 + Inventory lookups per second: %1 + + + + Up: 0 kB/s + Up: 0 kB/s + + + + Down: 0 kB/s + Down: 0 kB/s + + + + Network Status + Network Status + + + + byte(s) + bytebytes + + + + Object(s) to be synced: %n + Object to be synced: %nObjects to be synced: %n + + + + Processed %n person-to-person message(s). + Processed %n person-to-person message.Processed %n person-to-person messages. + + + + Processed %n broadcast message(s). + Processed %n broadcast message.Processed %n broadcast messages. + + + + Processed %n public key(s). + Processed %n public key.Processed %n public keys. + + + + newChanDialog + + + Dialog + Dialog + + + + Create a new chan + Create a new chan + + + + Join a chan + Join a chan + + + + Create a chan + Create a chan + + + + <html><head/><body><p>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.</p></body></html> + <html><head/><body><p>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.</p></body></html> + + + + Chan name: + Chan name: + + + + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + + + + Chan bitmessage address: + Chan bitmessage address: + + + + regenerateAddressesDialog + + + Regenerate Existing Addresses + Regenerate Existing Addresses + + + + Regenerate existing addresses + Regenerate existing addresses + + + + Passphrase + Passphrase + + + + Number of addresses to make based on your passphrase: + Number of addresses to make based on your passphrase: + + + + Address version number: + Address version number: + + + + Stream number: + Stream number: + + + + 1 + 1 + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + + + + 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. + 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. + + + + settingsDialog + + + Settings + Settings + + + + Start Bitmessage on user login + Start Bitmessage on user login + + + + Tray + Tray + + + + Start Bitmessage in the tray (don't show main window) + Start Bitmessage in the tray (don't show main window) + + + + Minimize to tray + Minimize to tray + + + + Close to tray + Close to tray + + + + Show notification when message received + Show notification when message received + + + + Run in Portable Mode + Run in Portable Mode + + + + 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. + 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. + + + + Willingly include unencrypted destination address when sending to a mobile device + Willingly include unencrypted destination address when sending to a mobile device + + + + Use Identicons + Use Identicons + + + + Reply below Quote + Reply below Quote + + + + Interface Language + Interface Language + + + + System Settings + system + System Settings + + + + User Interface + User Interface + + + + Listening port + Listening port + + + + Listen for connections on port: + Listen for connections on port: + + + + UPnP: + UPnP: + + + + Bandwidth limit + Bandwidth limit + + + + Maximum download rate (kB/s): [0: unlimited] + Maximum download rate (kB/s): [0: unlimited] + + + + Maximum upload rate (kB/s): [0: unlimited] + Maximum upload rate (kB/s): [0: unlimited] + + + + Proxy server / Tor + Proxy server / Tor + + + + Type: + Type: + + + + Server hostname: + Server hostname: + + + + Port: + Port: + + + + Authentication + Authentication + + + + Username: + Username: + + + + Pass: + Pass: + + + + Listen for incoming connections when using proxy + Listen for incoming connections when using proxy + + + + none + none + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Network Settings + + + + Total difficulty: + Total difficulty: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + + + + Small message difficulty: + Small message difficulty: + + + + 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. + 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. + + + + 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. + 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. + + + + Demanded difficulty + Demanded difficulty + + + + 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. + 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. + + + + Maximum acceptable total difficulty: + Maximum acceptable total difficulty: + + + + Maximum acceptable small message difficulty: + Maximum acceptable small message difficulty: + + + + Max acceptable difficulty + Max acceptable difficulty + + + + Hardware GPU acceleration (OpenCL) + Hardware GPU acceleration (OpenCL) + + + + <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> + <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> + + + + Host: + Host: + + + + Password: + Password: + + + + Test + Test + + + + Connect to: + Connect to: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Namecoin integration + + + + <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> + <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> + + + + Give up after + Give up after + + + + and + and + + + + days + days + + + + months. + months. + + + + Resends Expire + Resends Expire + + + \ No newline at end of file diff --git a/src/translations/bitmessage_en_pirate.pro b/src/translations/bitmessage_en_pirate.pro deleted file mode 100644 index acc712ee..00000000 --- a/src/translations/bitmessage_en_pirate.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_outgoingSynSender.py\ - ../class_objectProcessor.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_en_pirate.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_en_pirate.qm b/src/translations/bitmessage_en_pirate.qm index 24feb4b9..264e952f 100644 Binary files a/src/translations/bitmessage_en_pirate.qm and b/src/translations/bitmessage_en_pirate.qm differ diff --git a/src/translations/bitmessage_en_pirate.ts b/src/translations/bitmessage_en_pirate.ts index ba97978a..d788ffc3 100644 --- a/src/translations/bitmessage_en_pirate.ts +++ b/src/translations/bitmessage_en_pirate.ts @@ -1,977 +1,1265 @@ - - + AddAddressDialog Add new entry - Add yee new entry + Add yee new entry Label - Label + Label Address - Address + Address + + + + EmailGatewayDialog + + + Email gateway + + + + + Register on email gateway + + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + MainWindow - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - + + Reply to sender + - - Reply - + + Reply to channel + - + Add sender to your Address Book - + - + + Add sender to your Blacklist + + + + Move to Trash - + - + + Undelete + + + + View HTML code as formatted text - + - + Save message as... - + - + Mark Unread - + - + New - + - + Enable - + - + Disable - + - - Copy address to clipboard - - - - - Special address behavior... - - - - - Send message to this address - - - - - Subscribe to this address - - - - - Add New Address - - - - - Delete - - - - - Copy destination address to clipboard - - - - - Force send - - - - - Add new entry - Add yee new entry - - - - Since startup on %1 - - - - - Waiting for their encryption key. Will request it again soon. - - - - - Encryption key request queued. - - - - - Queued. - - - - - Message sent. Waiting for acknowledgement. Sent at %1 - - - - - Message sent. Sent at %1 - - - - - Need to do work to send message. Work is queued. - - - - - Acknowledgement of the message received %1 - - - - - Broadcast queued. - - - - - Broadcast on %1 - - - - - Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 - - - - - Problem: The recipient's encryption key is no good. Could not encrypt message. %1 - - - - - Forced difficulty override. Send should start soon. - - - - - Unknown status: %1 %2 - - - - - Not Connected - - - - - Show Bitmessage - - - - - Send - - - - - Subscribe - - - - - Address Book - - - - - Quit - - - - - You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. - - - - - You may manage your keys by editing the keys.dat file stored in - %1 -It is important that you back up this file. - - - - - Open keys.dat? - - - - - You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - - - - - You may manage your keys by editing the keys.dat file stored in - %1 -It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - - - - - Delete trash? - - - - - Are you sure you want to delete all trashed messages? - - - - - bad passphrase - - - - - You must type your passphrase. If you don't have one then this is not the form for you. - - - - - Chan name needed - - - - - You didn't enter a chan name. - - - - - Address already present - - - - - Could not add chan because it appears to already be one of your identities. - - - - - Success - - - - - Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. - - - - - Address too new - - - - - Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. - - - - - Address invalid - - - - - That Bitmessage address is not valid. - - - - - Address does not match chan name - - - - - Although the Bitmessage address you entered was valid, it doesn't match the chan name. - - - - - Successfully joined chan. - - - - - Processed %1 person-to-person messages. - - - - - Processed %1 broadcast messages. - - - - - Processed %1 public keys. - - - - - Total Connections: %1 - - - - - Connection lost - - - - - Connected - - - - - Message trashed - - - - - Error: Bitmessage addresses start with BM- Please check %1 - - - - - Error: The address %1 is not typed or copied correctly. Please check it. - - - - - Error: The address %1 contains invalid characters. Please check it. - - - - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - - - - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - - - - - Error: Something is wrong with the address %1. - - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - - - - - Address version number - - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - - - - - Stream number - - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - - - - - Your 'To' field is empty. - - - - - Right click one or more entries in your address book and select 'Send message to this address'. - - - - - Fetched address from namecoin identity. - - - - - Work is queued. %1 - - - - - New Message - - - - - From - - - - - Address is valid. - - - - - The address you entered was invalid. Ignoring it. - - - - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - - - - - Restart - - - - - You must restart Bitmessage for the port number change to take effect. - - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). - - - - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - - - - - Passphrase mismatch - - - - - The passphrase you entered twice doesn't match. Try again. - - - - - Choose a passphrase - - - - - You really do need a passphrase. - - - - - All done. Closing user interface... - - - - - Address is gone - - - - - Bitmessage cannot find your address %1. Perhaps you removed it? - - - - - Address disabled - - - - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - - - - - Entry added to the Address Book. Edit the label to your liking. - - - - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - - - - - Save As... - - - - - Write error. - - - - - No addresses selected. - - - - - Testing... - - - - - This is a chan address. You cannot use it as a pseudo-mailing list. - - - - - The address should start with ''BM-'' - - - - - The address is not typed or copied correctly (the checksum failed). - - - - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - - - - - The address contains invalid characters. - - - - - Some data encoded in the address is too short. - - - - - Some data encoded in the address is too long. - - - - - You are using TCP port %1. (This can be changed in the settings). - - - - - Bitmessage - - - - - Search - - - - - All - - - - - To - - - - - From - - - - - Subject - - - - - Message - - - - - Received - - - - - Inbox - - - - - Load from Address book - - - - - Fetch Namecoin ID - - - - - Message: - - - - - Subject: - - - - - Send to one or more specific people - - - - - To: - - - - - From: - - - - - Broadcast to everyone who is subscribed to your address - - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - - - - - Status - - - - - Sent - - - - - Label (not shown to anyone) - - - - - Address - Address - - - - Stream - - - - - Your Identities - - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - - - - - Add new Subscription - - - - - Label - Label - - - - Subscriptions - - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - - - - - Name or Label - - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - - - - - Blacklist - - - - - Stream # - - - - - Connections - - - - - Total connections: 0 - - - - - Since startup at asdf: - - - - - Processed 0 person-to-person message. - - - - - Processed 0 public key. - - - - - Processed 0 broadcast. - - - - - Network Status - - - - - File - - - - - Settings - Settings - - - - Help - Help - - - - Import keys - - - - - Manage keys - - - - - Ctrl+Q - Ctrrl+Q - - - - F1 - - - - - About - - - - - Regenerate deterministic addresses - - - - - Delete all trashed messages - - - - - Join / Create chan - - - - + Set avatar... - + - - Bad address version number - + + Copy address to clipboard + - - Your address version number must be a number: either 3 or 4. - + + Special address behavior... + - - Your address version number must be either 3 or 4. - + + Email gateway + + + + + Delete + + + + + Send message to this address + + + + + Subscribe to this address + + + + + Add New Address + + + + + Copy destination address to clipboard + + + + + Force send + + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + + + + + Waiting for their encryption key. Will request it again soon. + + + + + Encryption key request queued. + + + + + Queued. + + + + + Message sent. Waiting for acknowledgement. Sent at %1 + + + + + Message sent. Sent at %1 + + + + + Need to do work to send message. Work is queued. + + + + + Acknowledgement of the message received %1 + + + + + Broadcast queued. + + + + + Broadcast on %1 + + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + + + + + Forced difficulty override. Send should start soon. + + + + + Unknown status: %1 %2 + + + + + Not Connected + + + + + Show Bitmessage + + + + + Send + + + + + Subscribe + + + + + Channel + + + + + Quit + - Inventory lookups per second: %1 - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + - + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + + + + + Open keys.dat? + + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + Delete trash? + + + + + Are you sure you want to delete all trashed messages? + + + + + bad passphrase + + + + + You must type your passphrase. If you don't have one then this is not the form for you. + + + + + Bad address version number + + + + + Your address version number must be a number: either 3 or 4. + + + + + Your address version number must be either 3 or 4. + + + + + Chan name needed + + + + + You didn't enter a chan name. + + + + + Address already present + + + + + Could not add chan because it appears to already be one of your identities. + + + + + Success + + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + + + + + Address too new + + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + + + + + Address invalid + + + + + That Bitmessage address is not valid. + + + + + Address does not match chan name + + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + + + + + Successfully joined chan. + + + + + Connection lost + + + + + Connected + + + + + Message trashed + + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + + + + + Error: The address %1 is not typed or copied correctly. Please check it. + + + + + Error: The address %1 contains invalid characters. Please check it. + + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + + + + + Address version number + + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Stream number + + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + + + + + Message queued. + + + + + Your 'To' field is empty. + + + + + Right click one or more entries in your address book and select 'Send message to this address'. + + + + + Fetched address from namecoin identity. + + + + + New Message + + + + + From + + + + + Sending email gateway registration request + + + + + Address is valid. + + + + + The address you entered was invalid. Ignoring it. + + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + + + + + You must restart Bitmessage for the port number change to take effect. + + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + + + + + Number needed + + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + Will not resend ever - + - + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. - + - + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + + + + + The passphrase you entered twice doesn't match. Try again. + + + + + Choose a passphrase + + + + + You really do need a passphrase. + + + + + Address is gone + + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + + + + + Address disabled + + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + + + + + Entry added to the Address Book. Edit the label to your liking. + + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + + + + + Undeleted item. + + + + + Save As... + + + + + Write error. + + + + + No addresses selected. + + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + Do you really want to remove this avatar? - + - + You have already set an avatar for this address. Do you really want to overwrite it? - + - + Start-on-login not yet supported on your OS. - + - + Minimize-to-tray not yet supported on your OS. - + - + Tray notifications not yet supported on your OS. - + - + + Testing... + + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + + + + + The address should start with ''BM-'' + + + + + The address is not typed or copied correctly (the checksum failed). + + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + + + + + The address contains invalid characters. + + + + + Some data encoded in the address is too short. + + + + + Some data encoded in the address is too long. + + + + + Some data encoded in the address is malformed. + + + + Enter an address above. - + - + Address is an old type. We cannot display its past broadcasts. - + - + There are no recent broadcasts from this address to display. - + - - Display the %1 recent broadcast from this address. - + + You are using TCP port %1. (This can be changed in the settings). + - - Display the %1 recent broadcasts from this address. - + + Bitmessage + - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - + + Identities + - - Inventory lookups per second: 0 - + + New Identity + + + + + Search + + + + + All + + + + + To + + + + + From + + + + + Subject + + + + + Message + + + + + Received + + + + + Messages + + + + + Address book + + + + + Address + Address + + + + Add Contact + + + + + Fetch Namecoin ID + + + + + Subject: + + + + + From: + + + + + To: + + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + Subscriptions + + + + + Add new Subscription + + + + + Chans + + + + + Add Chan + + + + + File + + + + + Settings + Settings + + + + Help + Help + + + + Import keys + + + + + Manage keys + + + + + Ctrl+Q + + + + + F1 + + + + + Contact support + + + + + About + + + + + Regenerate deterministic addresses + + + + + Delete all trashed messages + + + + + Join / Create chan + + + + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + @@ -999,9 +1287,9 @@ T' 'Random Number' option be selected by default but deterministi Use yee random number generator to make an arrddress - - Use a passpharase to make addresses - Use yee passpharase to make arrddresses + + Use a passphrase to make addresses + @@ -1015,8 +1303,8 @@ T' 'Random Number' option be selected by default but deterministi - Address version number: 3 - Arrddress version number: 3 + Address version number: 4 + @@ -1073,16 +1361,6 @@ T' 'Random Number' option be selected by default but deterministi (saves you some bandwidth and processing power) (saves yee some bandwidth and processing powerrr) - - - Use a passphrase to make addresses - - - - - Address version number: 4 - Arrddress version number: 4 - NewSubscriptionDialog @@ -1103,8 +1381,8 @@ T' 'Random Number' option be selected by default but deterministi - CheckBox - + Enter an address above. + @@ -1137,6 +1415,11 @@ T' 'Random Number' option be selected by default but deterministi aboutDialog + + + About + + PyBitmessage @@ -1147,25 +1430,58 @@ T' 'Random Number' option be selected by default but deterministi version ? Version ? - - - About - - <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> - + This is Beta software. - + - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 The Bitmessage Developers</p></body></html> - + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + @@ -1173,22 +1489,22 @@ T' 'Random Number' option be selected by default but deterministi Bitmessage - + Bitmessage won't connect to anyone until you let it. - + Connect now - + Let me configure special network settings first - + @@ -1200,8 +1516,8 @@ T' 'Random Number' option be selected by default but deterministi - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + @@ -1222,9 +1538,9 @@ T' 'Random Number' option be selected by default but deterministi Sie haben keine Verbindung zu anderen Teilnehmern. - - 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't configured to foward 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. - Yee have made least one connection to a peer pirate usin' outgoing connection but yee not yet received any incoming connections. Yee firewall, witches nest, or home router probably shant configured to foward incoming TCP connections to yee computer. Bitmessage be workin' just fine but it help fellow pirates if yee allowed for incoming connections and will help yee be a better-connected node matey. + + 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'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. + @@ -1236,10 +1552,118 @@ T' 'Random Number' option be selected by default but deterministi You do have connections with other peers and your firewall is correctly configured. Yee have connections with other peers and pirates,yee firewall is correctly configured. + + + networkstatus - - 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'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. - + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + @@ -1247,42 +1671,42 @@ T' 'Random Number' option be selected by default but deterministi Dialog - + Create a new chan - + Join a chan - + Create a chan - + <html><head/><body><p>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.</p></body></html> - + Chan name: - + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> - + Chan bitmessage address: - + @@ -1308,14 +1732,9 @@ T' 'Random Number' option be selected by default but deterministi Number of arrddresses to make based on yee passphrase: - - Address version Number: - Arrddress version Number: - - - - 3 - 3 + + Address version number: + @@ -1342,318 +1761,299 @@ T' 'Random Number' option be selected by default but deterministi 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. If yee have previously made deterministic arrddresses but yee lost them due to an accident (like losin' yee pirate ship), yee can regenerate them here. If yee used t' random number generator to make yee addresses then this form be of no use to you. - - - Address version number: - - settingsDialog - + Settings Settings - + Start Bitmessage on user login Start yee Bitmessage on userrr login - + + Tray + + + + Start Bitmessage in the tray (don't show main window) Start yee Bitmessage in t' tray (don't show main window) - + Minimize to tray Minimize to yee tray - + + Close to tray + + + + Show notification when message received Show yee a notification when message received - + Run in Portable Mode Run in yee Portable Mode - + 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. In Portable Mode, messages and config files are stored in t' same directory as yee program rather than t' normal application-data folder. This makes it convenient to run Bitmessage from a USB thumb drive or wooden leg. - + + Willingly include unencrypted destination address when sending to a mobile device + + + + + Use Identicons + + + + + Reply below Quote + + + + + Interface Language + + + + + System Settings + system + + + + User Interface User Interface - + Listening port Listenin' port - + Listen for connections on port: Listen for connections on yee port: - + + UPnP: + + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + Proxy server / Tor Proxy server / Tor - + Type: Type: - - none - none - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - + Server hostname: Server hostname: - + Port: Port: - + Authentication Authentication - + Username: Username: - + Pass: Pass: - + + Listen for incoming connections when using proxy + + + + + none + none + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + Network Settings Network Settings - - 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. - When a pirate sends yee a message, their computer must first complete a load of work. T' difficulty of t' work, by default, is 1. Yee may raise this default for new arrddresses yee create by changin' the values here. Any new arrddresses you be createin' will require senders to meet t' higher difficulty. There be one exception: if yee add a friend or pirate to yee arrddress book, Bitmessage be automatically notifyin' them when yee next send a message that they needin' be only complete t' minimum amount of work: difficulty 1. - - - + Total difficulty: Total difficulty: - - Small message difficulty: - Small message difficulty: - - - - 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. - T' 'Small message difficulty' mostly only affects t' difficulty of sending small messages. Doubling this value be makin' it almost twice as difficult to send a small message but doesn't really affect large messages. - - - + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. T' 'Total difficulty' affects the absolute amount of work yee sender must complete. Doubling this value be doublin' t' amount of work. - + + Small message difficulty: + Small message difficulty: + + + + 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. + When a pirate sends yee a message, their computer must first complete a load of work. T' difficulty of t' work, by default, is 1. Yee may raise this default for new arrddresses yee create by changin' the values here. Any new arrddresses you be createin' will require senders to meet t' higher difficulty. There be one exception: if yee add a friend or pirate to yee arrddress book, Bitmessage be automatically notifyin' them when yee next send a message that they needin' be only complete t' minimum amount of work: difficulty 1. + + + + 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. + T' 'Small message difficulty' mostly only affects t' difficulty of sending small messages. Doubling this value be makin' it almost twice as difficult to send a small message but doesn't really affect large messages. + + + Demanded difficulty Demanded difficulty - - Willingly include unencrypted destination address when sending to a mobile device - - - - - Listen for incoming connections when using proxy - - - - + 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. - + - + Maximum acceptable total difficulty: - + - + Maximum acceptable small message difficulty: - + - + Max acceptable difficulty - + - + + Hardware GPU acceleration (OpenCL) + + + + <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> - + - + Host: - + - + Password: - + - + Test - + - + Connect to: - + - + Namecoind - + - + NMControl - + - + Namecoin integration - + - - Use Identicons - - - - - Interface Language - - - - - System Settings - system - - - - - English - en - - - - - Esperanto - eo - - - - - Français - fr - - - - - Deutsch - de - - - - - Españl - es - - - - - русский язык - ru - - - - - Norsk - no - - - - - Pirate English - en_pirate - - - - - Other (set in keys.dat) - other - - - - + <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> - + - + Give up after - + - + and - + - + days - + - + months. - + - + Resends Expire - + - + \ No newline at end of file diff --git a/src/translations/bitmessage_eo.qm b/src/translations/bitmessage_eo.qm index cfa0a6dc..b5c7135a 100644 Binary files a/src/translations/bitmessage_eo.qm and b/src/translations/bitmessage_eo.qm differ diff --git a/src/translations/bitmessage_eo.ts b/src/translations/bitmessage_eo.ts index 2f09691d..f73525f0 100644 --- a/src/translations/bitmessage_eo.ts +++ b/src/translations/bitmessage_eo.ts @@ -1,218 +1,387 @@ - - + AddAddressDialog Add new entry - Aldoni novan elementon + Aldoni novan elementon Label - Etikedo + Etikedo Address - Adreso + Adreso + + + + EmailGatewayDialog + + + Email gateway + Retpoŝta kluzo + + + + Register on email gateway + Registri je retpoŝta kluzo + + + + Account status at email gateway + Stato de retpoŝta kluza konto + + + + Change account settings at email gateway + Ŝanĝu agordojn de konto ĉe retpoŝta kluzo + + + + Unregister from email gateway + Malregistri de retpoŝta kluzo + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + Retpoŝta kluzo ebligas al vi komunikadi kun retpoŝtaj uzantoj. Nuntempe, nur la retpoŝta kluzo de Mailchuck (@mailchuck.com) estas disponebla. + + + + Desired email address (including @mailchuck.com): + Dezirata retpoŝta adreso (kune kun @mailchuck.com): + + + + EmailGatewayRegistrationDialog + + + Registration failed: + Registrado malsukcesis: + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + La dezirata retpoŝtadreso ne estas disponebla, bonvolu provi kun alia. Entajpu novan deziratan adreson (kune kun @mailchuck.com) sube: + + + + Email gateway registration + Registrado je retpoŝta kluzo + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + Retpoŝta kluzo ebligas al vi komunikadi kun retpoŝtaj uzantoj. Nuntempe, nur la retpoŝta kluzo de Mailchuck (@mailchuck.com) estas disponebla. +Bonvolu entajpi deziratan retpoŝtadreson (kune kun @mailchuck.com) sube: + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + # Tie ĉi vi povas agordi vian konton ĉe retpoŝta kluzo +# Malkomenti agordojn kiujn vi volas uzi +# Jenaj agordoj: +# +# pgp: server +# La retpoŝta kluzo kreos kaj prizorgos PGP-ŝlosilojn por vi por subskribi, +# verigi, ĉifri kaj deĉifri kiel vi. Se vi volas uzi PGP-on, sed vi estas laca, +# uzu tion. Bezonas abonon. +# +# pgp: local +# La retpoŝta kluzo ne faros PGP-operaciojn kiel vi. Vi povas aŭ ne uzi PGP-on +# ĝenerale aŭ uzi ĝin loke. +# +# attachments: yes +# Alvenaj kunsendaĵoj en retmesaĝoj estos alŝutitaj al MEGA.nz, kaj vi povos +# elŝuti ilin de tie per alklaki ligilon. Bezonas abonon. +# +# attachments: no +# Oni ignoros kunsendaĵojn. +# +# archive: yes +# Viaj alvenontaj retmesaĝoj estos arĥivitaj en la servilo. Uzu tion, se vi +# bezonas helpon kun senerarigado aŭ vi bezonas ekstere-liveritan pruvon de +# retmesaĝoj. Tamen tio signifas, ke la manipulisto de servo eblos legi viajn +# retmesaĝojn eĉ kiam tiam oni estos liverinta ilin al vi. +# +# archive: no +# Alvenaj mesaĝoj estos forigitaj de la servilo tuj post ili estos liveritaj al vi. +# +# masterpubkey_btc: BIP44 xpub ŝlosilo aŭ electrum v1 publika fontsendo (seed) +# offset_btc: entjera (integer) datumtipo (implicite 0) +# feeamount: nombro kun maksimume 8 decimalaj lokoj +# feecurrency: BTC, XBT, USD, EUR aŭ GBP +# Uzu tiujn se vi volas pagoŝarĝi homojn kiuj sendos al vi retmesaĝojn. Se tiu +# agordo estas ŝaltita kaj iu ajn sendos al vi retmesaĝon, li devos pagi difinan +# sendokoston. Por re-malaktivigi ĝin, agordu "feeamount" al 0. Bezonas abonon. + MainWindow - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - Iu de viaj adresoj, %1, estas malnova versio 1 adreso. Ĉu ni povas forviŝi ĝin? + + Reply to sender + Respondi al sendinto - - Reply - Respondi + + Reply to channel + Respondi al kanalo - + Add sender to your Address Book Aldoni sendinton al via adresaro - + + Add sender to your Blacklist + Aldoni sendinton al via nigra listo + + + Move to Trash Movi al rubujo - + + Undelete + Malforviŝi + + + View HTML code as formatted text Montri HTML-n kiel aranĝita teksto - + Save message as... Konservi mesaĝon kiel... - + + Mark Unread + Marki kiel nelegita + + + New Nova - + Enable Ŝalti - + Disable Malŝalti - + + Set avatar... + Agordi avataron... + + + Copy address to clipboard Kopii adreson al tondejo - + Special address behavior... Speciala sinteno de adreso... - + + Email gateway + Retpoŝta kluzo + + + + Delete + Forigi + + + Send message to this address Sendi mesaĝon al tiu adreso - + Subscribe to this address Aboni tiun adreson - + Add New Address Aldoni novan adreson - - Delete - Forviŝi - - - + Copy destination address to clipboard Kopii cel-adreson al tondejo - + Force send Devigi sendadon - - Add new entry - Aldoni novan elementon + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + Iu de viaj adresoj, %1, estas malnova versio 1 adreso. Versioj 1 adresoj ne estas jam subtenataj. Ĉu ni povas forviŝi ĝin? - + Waiting for their encryption key. Will request it again soon. - mi ne certas kiel traduki "their" ĉi tie. Sonas strange al mi. - Atendante al ilia ĉifroŝlosilo. Baldaŭ petos ĝin denove. + Atendante ilian ĉifroŝlosilon. Baldaŭ petos ĝin denove. - + Encryption key request queued. Peto por ĉifroŝlosilo envicigita. - + Queued. En atendovico. - + Message sent. Waiting for acknowledgement. Sent at %1 Mesaĝo sendita. Atendante konfirmon. Sendita je %1 - + + Message sent. Sent at %1 + Mesaĝo sendita. Sendita je %1 + + + Need to do work to send message. Work is queued. Devas labori por sendi mesaĝon. Laboro en atendovico. - + Acknowledgement of the message received %1 Ricevis konfirmon de la mesaĝo je %1 - + Broadcast queued. Elsendo en atendovico. - + Broadcast on %1 Elsendo je %1 - + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 Problemo: la demandita laboro de la ricevonto estas pli malfacila ol vi pretas fari. %1 - + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 Problemo: la ĉifroŝlosilo de la ricevonto estas rompita. Ne povis ĉifri la mesaĝon. %1 - + Forced difficulty override. Send should start soon. - Devigita superado de limito de malfacilaĵo. Sendado devus baldaŭ komenci. + Devigita superado de limito de malfacilaĵo. Sendado devus baldaŭ komenci. - + Unknown status: %1 %2 Nekonata stato: %1 %2 - - Since startup on %1 - Ekde lanĉo de la programo je %1 - - - + Not Connected Ne konektita - + Show Bitmessage Montri Bitmesaĝon - + Send Sendi - + Subscribe Aboni - - Address Book - Adresaro + + Channel + Kanalo - + Quit Eliri - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Vi povas administri viajn ŝlosilojn redaktante la dosieron keys.dat en la sama dosierujo kiel tiu programo. Estas grava ke vi faru savkopion de tiu dosiero. - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. @@ -221,17 +390,17 @@ It is important that you back up this file. Estas grava ke vi faru savkopion de tiu dosiero. - + Open keys.dat? - Ĉu malfermi keys.dat? + Ĉu malfermi keys.dat? - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) Vi povas administri viajn ŝlosilojn redaktante la dosieron keys.dat en la sama dosierujo kiel tiu programo. Estas grava ke vi faru savkopion de tiu dosiero. Ĉu vi volas malfermi la dosieron nun? (Bonvolu certigi ke Bitmesaĝo estas fermita antaŭ fari ŝanĝojn.) - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) @@ -240,801 +409,904 @@ It is important that you back up this file. Would you like to open the file now? Estas grava ke vi faru savkopion de tiu dosiero. Ĉu vi volas malfermi la dosieron nun? (Bonvolu certigi ke Bitmesaĝo estas fermita antaŭ fari ŝanĝojn.) - + Delete trash? - Malplenigi rubujon? + Ĉu malplenigi rubujon? - + Are you sure you want to delete all trashed messages? - Ĉu vi certas ke vi volas forviŝi ĉiujn mesaĝojn el la rubojo? + Ĉu vi certe volas forviŝi ĉiujn mesaĝojn el la rubujo? - + bad passphrase malprava pasvorto - + You must type your passphrase. If you don't have one then this is not the form for you. Vi devas tajpi vian pasvorton. Se vi ne havas pasvorton tiu ne estas la prava formularo por vi. - - Processed %1 person-to-person messages. - Pritraktis %1 inter-personajn mesaĝojn. + + Bad address version number + Malkorekta numero de adresversio - - Processed %1 broadcast messages. - Pritraktis %1 elsendojn. + + Your address version number must be a number: either 3 or 4. + Via numero de adresversio devas esti: aŭ 3 aŭ 4. - - Processed %1 public keys. - Pritraktis %1 publikajn ŝlosilojn. + + Your address version number must be either 3 or 4. + Via numero de adresversio devas esti: aŭ 3 aŭ 4. - - Total Connections: %1 - Totalaj Konektoj: %1 - - - - Connection lost - Perdis konekton - - - - Connected - Konektita - - - - Message trashed - Movis mesaĝon al rubujo - - - - Error: Bitmessage addresses start with BM- Please check %1 - Eraro: en Bitmesaĝa adresoj komencas kun BM- Bonvolu kontroli %1 - - - - Error: The address %1 is not typed or copied correctly. Please check it. - Eraro: La adreso %1 ne estis prave tajpita aŭ kopiita. Bonvolu kontroli ĝin. - - - - Error: The address %1 contains invalid characters. Please check it. - Eraro: La adreso %1 enhavas malpermesitajn simbolojn. Bonvolu kontroli ĝin. - - - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - Eraro: La adres-versio %1 estas tro alta. Eble vi devas promocii vian Bitmesaĝo programon aŭ via konato uzas alian programon. - - - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - Eraro: Kelkaj datumoj kodita en la adreso %1 estas tro mallongaj. Povus esti ke io en la programo de via konato malfunkcias. - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - Eraro: Kelkaj datumoj kodita en la adreso %1 estas tro longaj. Povus esti ke io en la programo de via konato malfunkcias. - - - - Error: Something is wrong with the address %1. - Eraro: Io malĝustas kun la adreso %1. - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - Eraro: Vi devas elekti sendontan adreson. Se vi ne havas iun, iru al langeto "Viaj identigoj". - - - - Sending to your address - Sendante al via adreso - - - - Error: One of the addresses to which you are sending a message, %1, is yours. Unfortunately the Bitmessage client cannot process its own messages. Please try running a second client on a different computer or within a VM. - Eraro: Unu el la adresoj al kiuj vi sendas mesaĝon (%1) apartenas al vi. Bedaŭrinde, la kliento de Bitmesaĝo ne povas pritrakti siajn proprajn mesaĝojn. Bonvolu uzi duan klienton ĉe alia komputilo aŭ en virtuala maŝino (VM). - - - - Address version number - Numero de adresversio - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - - - - - Stream number - Fluo numero - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - - - - - Your 'To' field is empty. - Via "Ricevonto"-kampo malplenas. - - - - Work is queued. - Laboro en atendovico. - - - - Right click one or more entries in your address book and select 'Send message to this address'. - - - - - Work is queued. %1 - Laboro en atendovico. %1 - - - - New Message - Nova mesaĝo - - - - From - De - - - - Address is valid. - Adreso estas ĝusta. - - - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - Eraro: Vi ne povas duoble aldoni la saman adreson al via adresaro. Provu renomi la jaman se vi volas. - - - - The address you entered was invalid. Ignoring it. - La adreso kiun vi enmetis estas malĝusta. Ignoras ĝin. - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - Eraro: Vi ne povas duoble aboni la saman adreson. Provu renomi la jaman se vi volas. - - - - Restart - Restartigi - - - - You must restart Bitmessage for the port number change to take effect. - Vi devas restartigi Bitmesaĝon por ke la ŝanĝo de la numero de pordo (Port Number) efektivigu. - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections. - Bitmessage wird den Proxy-Server ab jetzt verwenden, möglicherweise möchten Sie Bitmessage neu starten um bestehende Verbindungen zu schließen. - - - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - - - - - Passphrase mismatch - Pasfrazoj malsamas - - - - The passphrase you entered twice doesn't match. Try again. - La pasfrazo kiun vi duoble enmetis malsamas. Provu denove. - - - - Choose a passphrase - Elektu pasfrazon - - - - You really do need a passphrase. - Vi ja vere bezonas pasfrazon. - - - - All done. Closing user interface... - Ĉiu preta. Fermante fasadon... - - - - Address is gone - Adreso foriris - - - - Bitmessage cannot find your address %1. Perhaps you removed it? - Bitmesaĝo ne povas trovi vian adreson %1. Ĉu eble vi forviŝis ĝin? - - - - Address disabled - Adreso malŝaltita - - - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - Eraro: La adreso kun kiu vi provas sendi estas malŝaltita. Vi devos ĝin ŝalti en la langeto 'Viaj identigoj' antaŭ uzi ĝin. - - - - Entry added to the Address Book. Edit the label to your liking. - Aldonis elementon al adresaro. Redaktu la etikedo laŭvole. - - - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - Movis elementojn al rubujo. Ne estas fasado por rigardi vian rubujon, sed ankoraŭ estas sur disko se vi esperas ĝin retrovi. - - - - Save As... - Konservi kiel... - - - - Write error. - Skriberaro. - - - - No addresses selected. - Neniu adreso elektita. - - - - The address should start with ''BM-'' - La adreso komencu kun "BM-" - - - - The address is not typed or copied correctly (the checksum failed). - La adreso ne estis prave tajpita aŭ kopiita (kontrolsumo malsukcesis). - - - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - - - - - The address contains invalid characters. - La adreso enhavas malpermesitajn simbolojn. - - - - Some data encoded in the address is too short. - Kelkaj datumoj kodita en la adreso estas tro mallongaj. - - - - Some data encoded in the address is too long. - Kelkaj datumoj kodita en la adreso estas tro longaj. - - - - You are using TCP port %1. (This can be changed in the settings). - Vi estas uzanta TCP pordo %1 (Tio estas ŝanĝebla en la agordoj). - - - - Bitmessage - Bitmesaĝo - - - - To - Al - - - - From - De - - - - Subject - Temo - - - - Received - Ricevita - - - - Inbox - Ricevujo - - - - Load from Address book - Ŝarĝi el adresaro - - - - Message: - Mesaĝo: - - - - Subject: - Temo: - - - - Send to one or more specific people - Sendi al unu aŭ pli specifaj personoj - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - To: - Al: - - - - From: - De: - - - - Broadcast to everyone who is subscribed to your address - Elsendi al ĉiu kiu subskribis al via adreso - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - Sciu ke elsendoj estas sole ĉifrita kun via adreso. Iu ajn povas legi ĝin se tiu scias vian adreson. - - - - Status - Stato - - - - Sent - Sendita - - - - Label (not shown to anyone) - Etikdeo (ne montrita al iu ajn) - - - - Address - Adreso - - - - Stream - Fluo - - - - Your Identities - Via identigoj - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - Ĉi tie vi povas aboni "elsendajn mesaĝojn" elsendita de aliaj uzantoj. Adresoj ĉi tie transpasas tiujn sur la langeto "Nigara listo". - - - - Add new Subscription - Aldoni novan Abonon - - - - Label - Etikedo - - - - Subscriptions - Abonoj - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - La Adresaro estas utila por aldoni nomojn aŭ etikedojn al la Bitmesaĝa adresoj de aliaj persono por ke vi povu rekoni ilin pli facile en via ricevujo. Vi povas aldoni elementojn ĉi tie uzante la butonon 'Aldoni', aŭ en la ricevujo per dekstra klako al mesaĝo. - - - - Name or Label - Nomo aŭ Etikedo - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - Uzi Nigran Liston (permesi ĉiujn alvenintajn mesaĝojn escepte tiuj en la Nigra Listo) - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - Uzi Blankan Liston (bloki ĉiujn alvenintajn mesaĝojn escepte tiuj en la Blanka Listo) - - - - Blacklist - Nigra Listo - - - - Stream # - Fluo # - - - - Connections - Konetkoj - - - - Total connections: 0 - Totalaj konektoj: 0 - - - - Since startup at asdf: - Ekde lanĉo de la programo je asdf: - - - - Processed 0 person-to-person message. - Pritraktis 0 inter-personajn mesaĝojn. - - - - Processed 0 public key. - Pritraktis 0 publikajn ŝlosilojn. - - - - Processed 0 broadcast. - Pritraktis 0 elsendojn. - - - - Network Status - Reta Stato - - - - File - Dosiero - - - - Settings - Agordoj - - - - Help - Helpo - - - - Import keys - Importi ŝlosilojn - - - - Manage keys - Administri ŝlosilojn - - - - About - Pri - - - - Regenerate deterministic addresses - Regeneri determinisman adreson - - - - Delete all trashed messages - Forviŝi ĉiujn mesaĝojn el rubujo - - - - Message sent. Sent at %1 - Mesaĝo sendita. Sendita je %1 - - - + Chan name needed Bezonas nomon de kanalo - + You didn't enter a chan name. - Vi ne enmetis nonon de kanalo. + Vi ne enmetis nomon de kanalo. - + Address already present - Adreso jam ĉi tie + Adreso jam ĉi tie - + Could not add chan because it appears to already be one of your identities. Ne povis aldoni kanalon ĉar ŝajne jam estas unu el viaj indentigoj. - + Success Sukceso - + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. Sukcese kreis kanalon. Por ebligi al aliaj aniĝi vian kanalon, sciigu al ili la nomon de la kanalo kaj ties Bitmesaĝa adreso: %1. Tiu adreso ankaŭ aperas en 'Viaj identigoj'. - + Address too new Adreso tro nova - + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. - Kvankam tiu Bitmesaĝa adreso povus esti ĝusta, ĝia versionumero estas tro nova por pritrakti ĝin. Eble vi devas promocii vian Bitmesaĝon. + Kvankam tiu Bitmesaĝa adreso povus esti ĝusta, ĝia versionumero estas tro nova por pritrakti ĝin. Eble vi devas ĝisdatigi vian Bitmesaĝon. - + Address invalid Adreso estas malĝusta - + That Bitmessage address is not valid. - Tiu Bitmesaĝa adreso ne estas ĝusta. + Tiu Bitmesaĝa adreso ne estas ĝusta. - + Address does not match chan name Adreso ne kongruas kun kanalonomo - + Although the Bitmessage address you entered was valid, it doesn't match the chan name. - Kvankam la Bitmesaĝa adreso kiun vi enigis estas ĝusta, ĝi ne kongruas kun la kanalonomo. + Kvankam la Bitmesaĝa adreso kiun vi enigis estas ĝusta, ĝi ne kongruas kun la kanalonomo. - + Successfully joined chan. - Sukcese aniĝis al kanalo. + Sukcese aniĝis al kanalo. - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). - Bitmesaĝo uzos vian prokurilon (proxy) ekde nun sed eble vi volas permane restartigi Bitmesaĝon nun por ke ĝi fermu eblajn jamajn konektojn. + + Connection lost + Perdis konekton - - This is a chan address. You cannot use it as a pseudo-mailing list. - Tio estas kanaladreso. Vi ne povas ĝin uzi kiel pseŭdo-dissendolisto. + + Connected + Konektita - - Search - Serĉi + + Message trashed + Movis mesaĝon al rubujo - - All - Ĉio + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + La vivdaŭro signifas ĝis kiam la reto tenos la mesaĝon. La ricevonto devos elŝuti ĝin dum tiu tempo. Se via Bitmesaĝa kliento ne ricevos konfirmon, ĝi resendos mesaĝon aŭtomate. Ju pli longa vivdaŭro, des pli laboron via komputilo bezonos fari por sendi mesaĝon. Vivdaŭro proksimume kvin aŭ kvar horoj estas ofte konvena. - - Message - Mesaĝo + + Message too long + Mesaĝo tro longa - - Join / Create chan - Aniĝi / Krei kanalon + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + La mesaĝon kiun vi provis sendi estas tro longa pro %1 bitokoj. (La maksimumo estas 261644 bitokoj.) Bonvolu mallongigi ĝin antaŭ sendado. - - Encryption key was requested earlier. - Verschlüsselungscode wurde bereits angefragt. + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + Eraro: Via konto ne estas registrita je retpoŝta kluzo. Registranta nun kiel %1, bonvolu atendi ĝis la registrado finos antaŭ vi reprovos sendi iun ajn. - - Sending a request for the recipient's encryption key. - Sende eine Anfrage für den Verschlüsselungscode des Empfängers. + + Error: Bitmessage addresses start with BM- Please check %1 + Eraro: Bitmesaĝaj adresoj komencas kun BM- Bonvolu kontroli %1 - - Doing work necessary to request encryption key. - Verrichte die benötigte Arbeit um den Verschlüsselungscode anzufragen. + + Error: The address %1 is not typed or copied correctly. Please check it. + Eraro: La adreso %1 ne estis prave tajpita aŭ kopiita. Bonvolu kontroli ĝin. - - Broacasting the public key request. This program will auto-retry if they are offline. - Anfrage für den Verschlüsselungscode versendet (wird automatisch periodisch neu verschickt). + + Error: The address %1 contains invalid characters. Please check it. + Eraro: La adreso %1 enhavas malpermesitajn simbolojn. Bonvolu kontroli ĝin. - - Sending public key request. Waiting for reply. Requested at %1 - Anfrag für den Verschlüsselungscode gesendet. Warte auf Antwort. Angefragt am %1 + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + Eraro: La adresversio %1 estas tro alta. Eble vi devas ĝisdatigi vian Bitmesaĝan programon aŭ via sagaca konato uzas alian programon. - - Mark Unread - Marki nelegita + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + Eraro: Kelkaj datumoj koditaj en la adreso %1 estas tro mallongaj. Povus esti ke io en la programo de via konato malfunkcias. - + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + Eraro: Kelkaj datumoj koditaj en la adreso %1 estas tro longaj. Povus esti ke io en la programo de via konato malfunkcias. + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + Eraro: Kelkaj datumoj koditaj en la adreso %1 estas misformitaj. Povus esti ke io en la programo de via konato malfunkcias. + + + + Error: Something is wrong with the address %1. + Eraro: Io malĝustas kun la adreso %1. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Eraro: Vi devas elekti sendontan adreson. Se vi ne havas iun, iru al langeto 'Viaj identigoj'. + + + + Address version number + Numero de adresversio + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Priaboranta adreson %1, Bitmesaĝo ne povas kompreni numerojn %2 de adresversioj. Eble ĝisdatigu Bitmesaĝon al la plej nova versio. + + + + Stream number + Fluo numero + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Priaboranta adreson %1, Bitmesaĝo ne povas priservi %2 fluojn numerojn. Eble ĝisdatigu Bitmesaĝon al la plej nova versio. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Atentu: Vi ne estas nun konektita. Bitmesaĝo faros necesan laboron por sendi mesaĝon, tamen ĝi ne sendos ĝin antaŭ vi konektos. + + + + Message queued. + Mesaĝo envicigita. + + + + Your 'To' field is empty. + Via "Ricevonto"-kampo malplenas. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Dekstre alklaku kelka(j)n ero(j)n en via adresaro kaj elektu 'Sendi mesaĝon al tiu adreso'. + + + Fetched address from namecoin identity. - Venigis adreson de Namecoin identigo. + Venigis adreson de Namecoin-a identigo. - + + New Message + Nova mesaĝo + + + + From + De + + + + Sending email gateway registration request + Sendanta peton pri registrado je retpoŝta kluzo + + + + Address is valid. + Adreso estas ĝusta. + + + + The address you entered was invalid. Ignoring it. + La adreso kiun vi enmetis estas malĝusta. Ignoras ĝin. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Eraro: Vi ne povas duoble aldoni la saman adreson al via adresaro. Provu renomi la jaman se vi volas. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + Eraro: Vi ne povas aldoni duoble la saman adreson al viaj abonoj. Eble renomi la jaman se vi volas. + + + + Restart + Restartigi + + + + You must restart Bitmessage for the port number change to take effect. + Vi devas restartigi Bitmesaĝon por ke la ŝanĝo de la numero de pordo (Port Number) efektivigu. + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + Bitmesaĝo uzos vian prokurilon (proxy) ekde nun sed eble vi volas permane restartigi Bitmesaĝon nun por ke ĝi fermu eblajn jamajn konektojn. + + + + Number needed + Numero bezonata + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + Maksimumaj elŝutrapido kaj alŝutrapido devas esti numeroj. Ignoras kion vi enmetis. + + + + Will not resend ever + Resendos neniam + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + Rigardu, ke la templimon vi enmetis estas pli malgrandan ol tempo dum kiu Bitmesaĝo atendas por resendi unuafoje, do viaj mesaĝoj estos senditaj neniam. + + + + Sending email gateway unregistration request + Sendanta peton pri malregistrado de retpoŝta kluzo + + + + Sending email gateway status request + Sendanta peton pri stato de retpoŝta kluzo + + + + Passphrase mismatch + Pasfrazoj malsamas + + + + The passphrase you entered twice doesn't match. Try again. + La pasfrazo kiun vi duoble enmetis malsamas. Provu denove. + + + + Choose a passphrase + Elektu pasfrazon + + + + You really do need a passphrase. + Vi ja vere bezonas pasfrazon. + + + + Address is gone + Adreso foriris + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmesaĝo ne povas trovi vian adreson %1. Ĉu eble vi forviŝis ĝin? + + + + Address disabled + Adreso malŝaltita + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Eraro: La adreso kun kiu vi provas sendi estas malŝaltita. Vi devos ĝin ŝalti en la langeto 'Viaj identigoj' antaŭ uzi ĝin. + + + + Entry added to the Address Book. Edit the label to your liking. + Aldonis elementon al adresaro. Redaktu la etikedon laŭvole. + + + + Entry added to the blacklist. Edit the label to your liking. + Aldonis elementon al la nigra listo. Redaktu la etikedon laŭvole. + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + Eraro: Vi ne povas duoble aldoni la saman adreson al via nigra listo. Provu renomi la jaman se vi volas. + + + + Moved items to trash. + Movis elementojn al rubujo. + + + + Undeleted item. + Malforviŝis elementon. + + + + Save As... + Konservi kiel... + + + + Write error. + Skriberaro. + + + + No addresses selected. + Neniu adreso elektita. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + Se vi forviŝos abonon, mesaĝojn kiujn vi jam ricevis igos neatingeblajn. Eble vi devus anstataŭ malaktivigi abonon. Malaktivaj abonoj ne ricevos novajn mesaĝojn, tamen vi plu povos legi mesaĝojn kiujn ci jam ricevis. + +Ĉu vi certe volas forviŝi la abonon? + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + Se vi forviŝos kanalon, mesaĝojn kiujn vi jam ricevis igos neatingeblajn. Eble vi devus anstataŭ malaktivigi kanalon. Malaktivaj kanaloj ne ricevos novajn mesaĝojn, tamen vi plu povos legi mesaĝojn kiujn ci jam ricevis. + +Ĉu vi certe volas forviŝi la kanalon? + + + + Do you really want to remove this avatar? + Ĉu vi certe volas forviŝi tiun avataron? + + + + You have already set an avatar for this address. Do you really want to overwrite it? + Vi jam agordis avataron por tiu adreso. Ĉu vi vere volas superskribi ĝin? + + + + Start-on-login not yet supported on your OS. + Starto-dum-ensaluto ne estas ankoraŭ ebla en via operaciumo. + + + + Minimize-to-tray not yet supported on your OS. + Plejetigo al taskopleto ne estas ankoraŭ ebla en via operaciumo. + + + + Tray notifications not yet supported on your OS. + Taskopletaj sciigoj ne estas ankoraŭ eblaj en via operaciumo. + + + Testing... Testante... - + + This is a chan address. You cannot use it as a pseudo-mailing list. + Tio estas kanaladreso. Vi ne povas ĝin uzi kiel kvazaŭ-dissendolisto. + + + + The address should start with ''BM-'' + La adreso komencu kun "BM-" + + + + The address is not typed or copied correctly (the checksum failed). + La adreso ne estis prave tajpita aŭ kopiita (kontrolsumo malsukcesis). + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + La numero de adresversio estas pli alta ol tiun, kiun la programo poveblas subteni. Bonvolu ĝisdatigi Bitmesaĝon. + + + + The address contains invalid characters. + La adreso enhavas malpermesitajn simbolojn. + + + + Some data encoded in the address is too short. + Kelkaj datumoj kodita en la adreso estas tro mallongaj. + + + + Some data encoded in the address is too long. + Kelkaj datumoj kodita en la adreso estas tro longaj. + + + + Some data encoded in the address is malformed. + Kelkaj datumoj koditaj en la adreso estas misformitaj. + + + + Enter an address above. + Enmetu adreson supre. + + + + Address is an old type. We cannot display its past broadcasts. + Malnova speco de adreso. Ne povas montri ĝiajn antaŭajn elsendojn. + + + + There are no recent broadcasts from this address to display. + Neniaj lastatempaj elsendoj de tiu adreso por montri. + + + + You are using TCP port %1. (This can be changed in the settings). + Vi estas uzanta TCP pordo %1 (Tio estas ŝanĝebla en la agordoj). + + + + Bitmessage + Bitmesaĝo + + + + Identities + Identigoj + + + + New Identity + Nova identigo + + + + Search + Serĉi + + + + All + Ĉio + + + + To + Al + + + + From + De + + + + Subject + Temo + + + + Message + Mesaĝo + + + + Received + Ricevita je + + + + Messages + Mesaĝoj + + + + Address book + Adresaro + + + + Address + Adreso + + + + Add Contact + Aldoni kontakton + + + Fetch Namecoin ID Venigu Namecoin ID - - Ctrl+Q - Stir+Q + + Subject: + Temo: - + + From: + De: + + + + To: + Al: + + + + Send ordinary Message + Sendi ordinaran mesaĝon + + + + Send Message to your Subscribers + Sendi mesaĝon al viaj abonantoj + + + + TTL: + Vivdaŭro: + + + + Subscriptions + Abonoj + + + + Add new Subscription + Aldoni novan abonon + + + + Chans + Kanaloj + + + + Add Chan + Aldoni kanalon + + + + File + Dosiero + + + + Settings + Agordoj + + + + Help + Helpo + + + + Import keys + Enporti ŝlosilojn + + + + Manage keys + Administri ŝlosilojn + + + + Ctrl+Q + Stir+Q + + + F1 F1 - - Set avatar... - + + Contact support + Peti pri helpo - - Bad address version number - + + About + Pri - - Your address version number must be a number: either 3 or 4. - + + Regenerate deterministic addresses + Regeneri determinisman adreson - - Your address version number must be either 3 or 4. - + + Delete all trashed messages + Forviŝi ĉiujn mesaĝojn el rubujo - - Inventory lookups per second: %1 - + + Join / Create chan + Aniĝi / Krei kanalon - - Will not resend ever - + + All accounts + Ĉiuj kontoj - - Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. - + + Zoom level %1% + Pligrandigo: %1 - - Do you really want to remove this avatar? - + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + Eraro: Vi ne povas aldoni duoble la saman adreson al via listo. Eble renomi la jaman se vi volas. - - You have already set an avatar for this address. Do you really want to overwrite it? - + + Add new entry + Aldoni novan elementon - - Start-on-login not yet supported on your OS. - + + Display the %1 recent broadcast(s) from this address. + Montri la %1 lasta(j)n elsendo(j)n de tiu adreso. - - Minimize-to-tray not yet supported on your OS. - + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + La nova versio de PyBitmessage estas disponebla: %1. Elŝutu ĝin de https://github.com/Bitmessage/PyBitmessage/releases/latest - - Tray notifications not yet supported on your OS. - + + Waiting for PoW to finish... %1% + Atendanta ĝis laborpruvo finos... %1% - - Enter an address above. - + + Shutting down Pybitmessage... %1% + Fermanta na PyBitmessage... %1% - - Address is an old type. We cannot display its past broadcasts. - + + Waiting for objects to be sent... %1% + Atendanta ĝis objektoj estos senditaj... %1% - - There are no recent broadcasts from this address to display. - + + Saving settings... %1% + Konservanta agordojn... %1% - - Display the %1 recent broadcast from this address. - + + Shutting down core... %1% + Fermanta kernon... %1% - - Display the %1 recent broadcasts from this address. - + + Stopping notifications... %1% + Haltiganta sciigojn... %1% - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - + + Shutdown imminent... %1% + Fermanta tuj... %1% + + + + %n hour(s) + %n horo%n horoj + + + + %n day(s) + %n tago%n tagoj - - Inventory lookups per second: 0 - + + Shutting down PyBitmessage... %1% + Fermanta na PyBitmessage... %1% + + + + Sent + Senditaj + + + + Generating one new address + Kreanta unu novan adreson + + + + Done generating address. Doing work necessary to broadcast it... + Adreso kreita. Faranta laborpruvon endan por elsendi ĝin... + + + + Generating %1 new addresses. + Kreanta %1 novajn adresojn. + + + + %1 is already in 'Your Identities'. Not adding it again. + %1 jam estas en 'Viaj Identigoj'. Ĝi ne estos aldonita ree. + + + + Done generating address + Ĉiuj adresoj estas kreitaj + + + + SOCKS5 Authentication problem: %1 + SOCKS5 eraro kun aŭtentigado: %1 + + + + Disk full + Disko plenplena + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + Atentu: Via disko aŭ subdisko estas plenplena. Bitmesaĝo fermiĝos. + + + + Error! Could not find sender address (your address) in the keys.dat file. + Eraro! Ne povas trovi adreson de sendanto (vian adreson) en la dosiero keys.dat. + + + + Doing work necessary to send broadcast... + Faranta laborpruvon endan por sendi elsendon... + + + + Broadcast sent on %1 + Elsendo sendita je %1 + + + + Encryption key was requested earlier. + Peto pri ĉifroŝlosilo jam sendita. + + + + Sending a request for the recipient's encryption key. + Sendanta peton pri ĉifroŝlosilo de ricevonto. + + + + Looking up the receiver's public key + Serĉanta publikan ĉifroŝlosilon de ricevonto + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + Eraro: Celadreso estas portebla aparato kiu necesas, ke la celadreso estu enhavita en la mesaĝo, sed tio estas malpermesita ne viaj agordoj. %1 + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + Faranta laborpruvon endan por sendi mesaĝon. +Malfacilaĵo ne estas bezonata por adresoj versioj 2, kiel tiu ĉi adreso. + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + Faranta laborpruvon endan por sendi mesaĝon. +Ricevonto postulas malfacilaĵon: %1 kaj %2 + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + Eraro: la demandita laboro de la ricevonto (%1 kaj %2) estas pli malfacila ol vi pretas fari. %3 + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + Eraro: Vi provis sendi mesaĝon al vi mem aŭ al kanalo, tamen via ĉifroŝlosilo ne estas trovebla en la dosiero keys.dat. Mesaĝo ne povis esti ĉifrita. %1 + + + + Doing work necessary to send message. + Faranta laborpruvon endan por sendi mesaĝon. + + + + Message sent. Waiting for acknowledgement. Sent on %1 + Mesaĝo sendita. Atendante konfirmon. Sendita je %1 + + + + Doing work necessary to request encryption key. + Faranta laborpruvon endan por peti pri ĉifroŝlosilo. + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + Elsendanta peton pri publika ĉifroŝlosilo. La programo reprovos se ili estas eksterrete. + + + + Sending public key request. Waiting for reply. Requested at %1 + Sendanta peton pri publika ĉifroŝlosilo. Atendanta respondon. Petis je %1 + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + @@ -1042,98 +1314,99 @@ p, li { white-space: pre-wrap; } Create new Address - Krei novan Adreson + Krei novan adreson Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: - + Tie ĉi vi povas generi tiom adresojn, kiom vi volas. Ververe kreado kaj forlasado de adresoj estas konsilinda. Vi povas krei adresojn uzante hazardajn nombrojn aŭ pasfrazon. Se vi uzos pasfrazon, la adreso estas nomita kiel 'determinisma' adreso. +La 'hazardnombra' adreso estas antaŭagordita, sed determinismaj adresoj havas kelkajn bonaĵojn kaj malbonaĵojn: <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Bonaĵoj:<br/></span>Vi poveblas rekrei viajn adresojn per iu ajn komputilo elkape.<br/>Vi ne devas klopodi fari savkopion de keys.dat dosiero tiel longe dum vi memoras vian pasfrazon.<br/><span style=" font-weight:600;">Malbonaĵoj:<br/></span>Vi devas memori (aŭ konservi) vian pasfrazon se vi volas rekrei viajn ŝlosilojn kiam vi perdos ilin.<br/>Vi devas memori nombro de adresversio kaj de fluo kune kun vian pasfrazon.<br/>Se vi elektos malfortan pasfrazon kaj iu ajn Interrete eblos brutforti ĝin, li povos legi ĉiujn viajn mesaĝojn kaj sendi mesaĝojn kiel vi.</p></body></html> Use a random number generator to make an address - + Uzi hazardnombran generilon por krei adreson Use a passphrase to make addresses - + Uzi pasfrazon por krei adreson Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter - + Pasigi kelkajn minutojn aldone kompute por fari la adreso(j)n 1 aŭ 2 signoj pli mallongaj Make deterministic addresses - - - - - In addition to your passphrase, you must remember these numbers: - - - - - Passphrase - Pasfrazo - - - - Number of addresses to make based on your passphrase: - Kvanto de farotaj adresoj bazante sur via pasfrazo: - - - - Stream number: 1 - - - - - Retype passphrase - - - - - Randomly generate address - - - - - Label (not shown to anyone except you) - - - - - Use the most available stream - - - - - (best if this is the first of many addresses you will create) - - - - - Use the same stream as an existing address - - - - - (saves you some bandwidth and processing power) - + Fari determinisman adreson Address version number: 4 - + Numero de adresversio: 4 + + + + In addition to your passphrase, you must remember these numbers: + Kune kun vian pasfrazon vi devas memori jenajn numerojn: + + + + Passphrase + Pasfrazo + + + + Number of addresses to make based on your passphrase: + Kvanto de farotaj adresoj bazante sur via pasfrazo: + + + + Stream number: 1 + Fluo numero: 1 + + + + Retype passphrase + Reenmeti pasfrazon + + + + Randomly generate address + Hazardnombra adreso + + + + Label (not shown to anyone except you) + Etikedo (ne montrata al iu ajn escepte de vi) + + + + Use the most available stream + Uzi la plej disponeblan fluon + + + + (best if this is the first of many addresses you will create) + (plej bone se tiun estas la unuan de ĉiuj adresojn vi kreos) + + + + Use the same stream as an existing address + Uzi saman fluon kiel jama adreso + + + + (saves you some bandwidth and processing power) + (konservas iomete rettrafikon kaj komputopovon) @@ -1141,22 +1414,22 @@ The 'Random Number' option is selected by default but deterministic ad Add new entry - Aldoni novan elementon + Aldoni novan elementon Label - Etikedo + Etikedo Address - Adreso + Adreso - CheckBox - + Enter an address above. + Enmetu adreson supre. @@ -1164,27 +1437,27 @@ The 'Random Number' option is selected by default but deterministic ad Special Address Behavior - + Speciala sinteno de adreso Behave as a normal address - + Sintenadi kiel normala adreso Behave as a pseudo-mailing-list address - + Sintenadi kiel kvazaŭ-elsendlista adreso Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). - + Mesaĝoj alvenintaj al kvazaŭ-dissendlisto estos aŭtomate dissenditaj al abonantoj (do ili estos publikaj). Name of the pseudo-mailing-list: - + Nomo de la kvazaŭ-dissendlisto: @@ -1202,12 +1475,7 @@ The 'Random Number' option is selected by default but deterministic ad version ? - Veriso ? - - - - Copyright © 2013 Jonathan Warren - Kopirajto © 2013 Jonathan Warren + versio ? @@ -1221,8 +1489,46 @@ The 'Random Number' option is selected by default but deterministic ad - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 The Bitmessage Developers</p></body></html> - + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + Uzi nigran liston (Permesas ĉiujn alvenajn mesaĝojn escepte tiujn en la nigra listo) + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + Uzi blankan liston (Blokas ĉiujn alvenajn mesaĝojn escepte tiujn en la blanka listo) + + + + Add new entry + Aldoni novan elementon + + + + Name or Label + Nomo aŭ etikedo + + + + Address + Adreso + + + + Blacklist + Nigra Listo + + + + Whitelist + Blanka Listo @@ -1235,12 +1541,12 @@ The 'Random Number' option is selected by default but deterministic ad Bitmessage won't connect to anyone until you let it. - Bitmesaĝo ne konektos antaŭ vi permesas al ĝi. + Bitmesaĝo ne konektos antaŭ vi permesos al ĝi. Connect now - Kenekti nun + Konekti nun @@ -1257,8 +1563,8 @@ The 'Random Number' option is selected by default but deterministic ad - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help (angle)</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> @@ -1281,12 +1587,12 @@ The 'Random Number' option is selected by default but deterministic ad 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'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. - Vi konektis almenaŭ al unu smtavolano uzante eliranta konekto, sed vi ankoraŭ ne ricevis enirantajn konetkojn. Via fajroŝirmilo (firewall) aŭ hejma enkursigilo (router) verŝajne estas agordita ne plusendi enirantajn TCP konektojn al via komputilo. Bitmesaĝo funkcios sufiĉe bone sed helpus al la Bitmesaĝa reto se vi permesus enirantajn konektojn kaj tiel estus pli bone konektita nodo. + Vi konektis almenaŭ al unu samtavolano uzante eliranta konekto, sed vi ankoraŭ ne ricevis enirantajn konetkojn. Via fajroŝirmilo (firewall) aŭ hejma enkursigilo (router) verŝajne estas agordita ne plusendi enirantajn TCP konektojn al via komputilo. Bitmesaĝo funkcios sufiĉe bone sed helpus al la Bitmesaĝa reto se vi permesus enirantajn konektojn kaj tiel estus pli bone konektita nodo. You are using TCP port ?. (This can be changed in the settings). - Vi estas uzanta TCP pordo ?. (Tio estas ŝanĝebla en la agordoj). + Ĉu vi estas uzanta TCP pordon ?. (Tio estas ŝanĝebla en la agordoj). @@ -1294,6 +1600,119 @@ The 'Random Number' option is selected by default but deterministic ad Vi havas konektojn al aliaj samtavolanoj kaj via fajroŝirmilo estas ĝuste agordita. + + networkstatus + + + Total connections: + Ĉiuj konektoj: + + + + Since startup: + Ekde starto: + + + + Processed 0 person-to-person messages. + Pritraktis 0 inter-personajn mesaĝojn. + + + + Processed 0 public keys. + Pritraktis 0 publikajn ŝlosilojn. + + + + Processed 0 broadcasts. + Pritraktis 0 elsendojn. + + + + Inventory lookups per second: 0 + Petoj pri inventaro en sekundo: 0 + + + + Objects to be synced: + Samtempigotaj eroj: + + + + Stream # + Fluo # + + + + Connections + Konektoj + + + + Since startup on %1 + Ekde lanĉo de la programo je %1 + + + + Down: %1/s Total: %2 + Elŝuto: %1/s Entute: %2 + + + + Up: %1/s Total: %2 + Alŝuto: %1/s Entute: %2 + + + + Total Connections: %1 + Ĉiuj konektoj: %1 + + + + Inventory lookups per second: %1 + Petoj pri inventaro en sekundo: %1 + + + + Up: 0 kB/s + Alŝuto: 0 kB/s + + + + Down: 0 kB/s + Elŝuto: 0 kB/s + + + + Network Status + Reta Stato + + + + byte(s) + bitokobitokoj + + + + Object(s) to be synced: %n + Objekto por samtempigi: %nObjektoj por samtempigi: %n + + + + Processed %n person-to-person message(s). + Pritraktis %n inter-personan mesaĝon.Pritraktis %n inter-personajn mesaĝojn. + + + + Processed %n broadcast message(s). + Pritraktis %n elsendon.Pritraktis %n elsendojn. + + + + Processed %n public key(s). + Pritraktis %n publikan ŝlosilon.Pritraktis %n publikajn ŝlosilojn. + + newChanDialog @@ -1316,6 +1735,11 @@ The 'Random Number' option is selected by default but deterministic ad Create a chan Krei kanalon + + + <html><head/><body><p>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.</p></body></html> + <html><head/><body><p>Enmetu nomon por via kanalo. Se vi elektas sufiĉe ampleksan kanalnomon (kiel fortan kaj unikan pasfrazon) kaj neniu el viaj amikoj komunikas ĝin publike la kanalo estos sekura kaj privata. Se vi kaj iu ajn kreas kanalon kun la sama nomo tiam en la momento estas tre verŝajne ke estos la sama kanalo.</p></body></html> + Chan name: @@ -1324,18 +1748,13 @@ The 'Random Number' option is selected by default but deterministic ad <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> - <html><head/><body><p>Kanalo ekzistas kiam grupo de personoj havas komunajn malĉifrajn ŝlosilojn. La ŝlosiloj kaj Bitmesaĝa adreso uzita de kanalo estas generita el homlegebla vorto aŭ frazo (la nomo de la kanalo). Por sendi mesaĝon al ĉiu en la kanalo, sendu normalan person-al-persona mesaĝon al la adreso de la kanalo.</p><p>Kanaloj estas eksperimentaj kaj tute malkontroleblaj.</p></body></html> + <html><head/><body><p>Kanalo ekzistas kiam grupo de personoj havas komunajn malĉifrajn ŝlosilojn. La ŝlosiloj kaj Bitmesaĝa adreso uzita de kanalo estas generita el hom-legebla vorto aŭ frazo (la nomo de la kanalo). Por sendi mesaĝon al ĉiu en la kanalo, sendu normalan inter-personan mesaĝon al la adreso de la kanalo.</p><p>Kanaloj estas eksperimentaj kaj tute malkontroleblaj.</p></body></html> Chan bitmessage address: Bitmesaĝa adreso de kanalo: - - - <html><head/><body><p>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.</p></body></html> - <html><head/><body><p>Enmetu nomon por via kanalo. Se vi elektas sufiĉe ampleksan kanalnomon (kiel fortan kaj unikan pasfrazon) kaj neniu el viaj amikoj komunikas ĝin publike la kanalo estos sekura kaj privata. Se vi kaj iu ajn kreas kanalon kun la sama nomo tiam en la momento estas tre verŝajne ke estos la sama kanalo.</p></body></html> - regenerateAddressesDialog @@ -1347,7 +1766,7 @@ The 'Random Number' option is selected by default but deterministic ad Regenerate existing addresses - Regeneri ekzistantajn Adresojn + Regeneri ekzistantajn adresojn @@ -1360,14 +1779,9 @@ The 'Random Number' option is selected by default but deterministic ad Kvanto de farotaj adresoj bazante sur via pasfrazo: - - Address version Number: - Adresa versio numero: - - - - 3 - 3 + + Address version number: + Numero de adresversio: @@ -1382,335 +1796,311 @@ The 'Random Number' option is selected by default but deterministic ad Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter - Elspezi kelkajn minutojn per aldona tempo de komputila kalkulado por fari adreso(j)n 1 aŭ 2 simbolojn pli mallonge + Pasigi kelkajn minutojn aldone kompute por krei la adreso(j)n 1 aŭ 2 signoj pli mallongaj You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. - Vi devas marki (aŭ ne marki) tiun markobutono samkiel vi faris kiam vi generis vian adreson la unuan fojon. + Vi devas marki (aŭ ne marki) tiun markobutono samkiel vi faris kiam vi generis vian adreson unuafoje. 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. - Se vi antaŭe kreis determinismajn adresojn sed perdis ĝin akcidente (ekz. en diska paneo), vi povas regeneri ilin ĉi tie. Se vi uzis la generilo de hazardaj numeroj por krei vian adreson tiu formularo ne taŭgos por vi. - - - - Address version number: - + Se vi antaŭe kreis determinismajn adresojn sed perdis ilin akcidente (ekz. en diska paneo), vi povas regeneri ilin ĉi tie. Se vi uzis la generilo de hazardnombroj por krei vian adreson tiu formularo ne taŭgos por vi. settingsDialog - + Settings - Agordoj - - - - Start Bitmessage on user login - Startigi Bitmesaĝon dum ensaluto de uzanto - - - - Start Bitmessage in the tray (don't show main window) - Startigi Bitmesaĝon en la taskopleto (tray) ne montrante tiun fenestron - - - - Minimize to tray - Plejetigi al taskopleto - - - - Show notification when message received - Montri sciigon kiam mesaĝo alvenas - - - - Run in Portable Mode - Ekzekucii en Portebla Reĝimo - - - - 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. - En Portebla Reĝimo, mesaĝoj kaj agordoj estas enmemorigitaj en la sama dosierujo kiel la programo mem anstataŭ en la dosierujo por datumoj de aplikaĵoj. Tio igas ĝin komforta ekzekucii Bitmesaĝon el USB poŝmemorilo. - - - - User Interface - Fasado - - - - Listening port - Aŭskultanta pordo (port) - - - - Listen for connections on port: - Aŭskultu pri konektoj ĉe pordo: - - - - Proxy server / Tor - Prokurila (proxy) servilo / Tor - - - - Type: - Tipo: - - - - none - Neniu - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - - Server hostname: - Servilo gastiga nomo (hostname): + Agordoj - Port: - Pordo (port): - - - - Authentication - Aŭtentigo + Start Bitmessage on user login + Startigi Bitmesaĝon dum ensaluto de uzanto - Username: - Uzantnomo: - - - - Pass: - Pas: - - - - Network Settings - Retaj agordoj - - - - 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. - - - - - Total difficulty: - - - - - Small message difficulty: - - - - - 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. - - - - - The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - - - - - Demanded difficulty - - - - - 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. - - - - - Maximum acceptable total difficulty: - - - - - Maximum acceptable small message difficulty: - - - - - Max acceptable difficulty - - - - - Listen for incoming connections when using proxy - - - - - Willingly include unencrypted destination address when sending to a mobile device - - - - - <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> - - - - - Host: - Gastiga servilo: + Tray + Taskopleto - Password: - Pasvorto: + Start Bitmessage in the tray (don't show main window) + Startigi Bitmesaĝon en la taskopleto (tray) ne montrante tiun fenestron - Test - Testo + Minimize to tray + Plejetigi al taskopleto - Connect to: - Kenekti al: + Close to tray + Fermi al taskopleto - Namecoind - Namecoind + Show notification when message received + Montri sciigon kiam mesaĝo alvenas - NMControl - NMControl + Run in Portable Mode + Ekzekucii en Portebla Reĝimo - Namecoin integration - Integrigo de Namecoin - - - - Override automatic language localization (use countycode or language code, e.g. 'en_US' or 'en'): - Transpasi la automatan reconon de locala lingvo (uzu landokodon aŭ lingvokodon, ekz. 'en_US' aŭ 'en'): - - - - Use Identicons - - - - - Interface Language - - - - - System Settings - system - - - - - English - en - - - - - Esperanto - eo - - - - - Français - fr - - - - - Deutsch - de - - - - - Españl - es - - - - - русский язык - ru - - - - - Norsk - no - - - - - Pirate English - en_pirate - - - - - Other (set in keys.dat) - other - + 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. + En Portebla Reĝimo, mesaĝoj kaj agordoj estas enmemorigitaj en la sama dosierujo kiel la programo mem anstataŭ en la dosierujo por datumoj de aplikaĵoj. Tio igas ĝin komforta ekzekucii Bitmesaĝon el USB poŝmemorilo. - <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> - + Willingly include unencrypted destination address when sending to a mobile device + Volonte inkluzivi malĉifritan cel-adreson dum sendado al portebla aparato. - Give up after - + Use Identicons + Uzi ID-avatarojn - and - + Reply below Quote + Respondi sub citaĵo - days - + Interface Language + Fasada lingvo - months. - + System Settings + system + Sistemaj agordoj + User Interface + Fasado + + + + Listening port + Aŭskultanta pordo (port) + + + + Listen for connections on port: + Aŭskulti pri konektoj ĉe pordo: + + + + UPnP: + UPnP: + + + + Bandwidth limit + Rettrafika limo + + + + Maximum download rate (kB/s): [0: unlimited] + Maksimuma rapido de elŝuto (kB/s): [0: senlima] + + + + Maximum upload rate (kB/s): [0: unlimited] + Maksimuma rapido de alŝuto (kB/s): [0: senlima] + + + + Proxy server / Tor + Prokurila (proxy) servilo / Tor + + + + Type: + Speco: + + + + Server hostname: + Servilo gastiga nomo (hostname): + + + + Port: + Pordo (port): + + + + Authentication + Aŭtentigo + + + + Username: + Uzantnomo: + + + + Pass: + Pasvorto: + + + + Listen for incoming connections when using proxy + Aŭskulti pri alvenaj konektoj kiam dum uzado de prokurilo + + + + none + neniu + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Retaj agordoj + + + + Total difficulty: + Tuta malfacilaĵo: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + La 'Tuta malfacilaĵo' efikas sur la tuta kvalito da laboro kiu la sendonto devos fari. Duobligo de tiu valoro, duobligas la kvanton de laboro. + + + + Small message difficulty: + Et-mesaĝa malfacilaĵo: + + + + 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. + Kiam iu ajn sendas al vi mesaĝon, lia komputilo devas unue fari iom da laboro. La malfacilaĵo de tiu laboro implicite estas 1. Vi povas pligrandigi tiun valoron por novaj adresoj kiuj vi generos per ŝanĝo de ĉi-tiaj valoroj. Ĉiuj novaj adresoj kreotaj de vi bezonos por ke sendontoj akceptu pli altan malfacilaĵon. Estas unu escepto: se vi aldonos kolegon al vi adresaro, Bitmesaĝo aŭtomate sciigos lin kiam vi sendos mesaĝon, ke li bezonos fari nur minimuman kvaliton da laboro: malfacilaĵo 1. + + + + 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. + La 'Et-mesaĝa malfacilaĵo' ĉefe efikas malfacilaĵon por sendi malgrandajn mesaĝojn. Duobligo de tiu valoro, preskaŭ duobligas malfacilaĵon por sendi malgrandajn mesaĝojn, sed preskaŭ ne efikas grandajn mesaĝojn. + + + + Demanded difficulty + Postulata malfacilaĵo + + + + 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. + Tie ĉi vi povas agordi maksimuman kvanton da laboro kiun vi faru por sendi mesaĝon al alian persono. Se vi agordos ilin al 0, ĉiuj valoroj estos akceptitaj. + + + + Maximum acceptable total difficulty: + Maksimuma akceptata tuta malfacilaĵo: + + + + Maximum acceptable small message difficulty: + Maksimuma akceptata malfacilaĵo por et-mesaĝoj: + + + + Max acceptable difficulty + Maksimuma akcepta malfacilaĵo + + + + Hardware GPU acceleration (OpenCL) + Aparatara GPU-a plirapidigo (OpenCL) + + + + <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> + <html><head/><body><p>Bitmesaĝo povas apliki alian Bitmono-bazitan programon - Namecoin - por fari adresojn hom-legeblajn. Ekzemple anstataŭ diri al via amiko longan Bitmesaĝan adreson, vi povas simple peti lin pri sendi mesaĝon al <span style=" font-style:italic;">testo. </span></p><p>(Kreado de sia propra Bitmesaĝa adreso en Namecoin-on estas ankoraŭ ete malfacila).</p><p>Bitmesaĝo eblas uzi aŭ na namecoind rekte aŭ jaman aktivan aperon de nmcontrol.</p></body></html> + + + + Host: + Gastiga servilo: + + + + Password: + Pasvorto: + + + + Test + Testo + + + + Connect to: + Konekti al: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Integrigo kun Namecoin + + + + <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> + <html><head/><body><p>Defaŭlte se vi sendas mesaĝon al iu kaj li estos eksterrete por iomete da tempo, Bitmesaĝo provos resendi mesaĝon iam poste, kaj iam pli poste. La programo pluigos resendi mesaĝon ĝis sendonto konfirmos liveron. Tie ĉi vi eblas ŝanĝi kiam Bitmesaĝo devos rezigni je sendado.</p><p>Lasu tiujn kampojn malplenaj por antaŭagordita sinteno.</p></body></html> + + + + Give up after + Rezigni post + + + + and + kaj + + + + days + tagoj + + + + months. + monatoj. + + + Resends Expire - + Resenda fortempiĝo - + \ No newline at end of file diff --git a/src/translations/bitmessage_fr.pro b/src/translations/bitmessage_fr.pro deleted file mode 100644 index 0e56c016..00000000 --- a/src/translations/bitmessage_fr.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_objectProcessor.py\ - ../class_outgoingSynSender.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_fr.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_fr.qm b/src/translations/bitmessage_fr.qm index 12247227..09db1866 100644 Binary files a/src/translations/bitmessage_fr.qm and b/src/translations/bitmessage_fr.qm differ diff --git a/src/translations/bitmessage_fr.ts b/src/translations/bitmessage_fr.ts index e32eb5ef..1ea9d449 100644 --- a/src/translations/bitmessage_fr.ts +++ b/src/translations/bitmessage_fr.ts @@ -1,1106 +1,1274 @@ - - + AddAddressDialog Add new entry - Ajouter une nouvelle entrée + Legg til ny oppføring Label - Label + Etiquette Address - Adresse + Adresse + + + + EmailGatewayDialog + + + Email gateway + Passerelle Email + + + + Register on email gateway + S'inscrire sur la passerelle Email + + + + Account status at email gateway + Statut du compte sur la passerelle Email + + + + Change account settings at email gateway + Changer les paramètres de compte sur la passerelle Email + + + + Unregister from email gateway + Se désabonner de la passerelle Email + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + La passerelle Email vous permet de communiquer avec des utilisateurs d'Email. Actuellement, seulement la passerelle de courrier électronique de Mailchuck (@mailchuck.com) est disponible. + + + + Desired email address (including @mailchuck.com): + Adresse Email désirée (incluant @mailchuck.com) : + + + + EmailGatewayRegistrationDialog + + + Registration failed: + L'inscription a échouée : + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + L'adresse Email demandée n'est pas disponible, veuillez en essayer une nouvelle. Saisissez ci-dessous la nouvelle adresse Email désirée (incluant @mailchuck.com) : + + + + Email gateway registration + Inscription de passerelle Email + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + La passerelle Email vous permet de communiquer avec des utilisateurs d'Emails. Actuellement, seulement la passerelle de courrier électronique de Mailchuck (@mailchuck.com) est disponible. +Veuillez taper l'adresse email désirée (incluant @mailchuck.com) : + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + MainWindow - - Bitmessage - Bitmessage + + Reply to sender + Répondre à l'expéditeur - - To - Vers + + Reply to channel + Répondre à la chaîne - - From - De + + Add sender to your Address Book + Legg til sender i adresseboka - - Subject - Sujet + + Add sender to your Blacklist + Ajouter l'expéditeur à votre liste noire - - Received - Reçu + + Move to Trash + Kast - - Inbox - Boîte de réception + + Undelete + Restaurer - - Load from Address book - Charger depuis carnet d'adresses + + View HTML code as formatted text + Vis HTML-koden som formatert tekst - - Message: - Message : + + Save message as... + Lagre beskjed som ... - - Subject: - Sujet : + + Mark Unread + Merk som ulest - - Send to one or more specific people - Envoyer à une ou plusieurs personne(s) - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - To: - Vers : - - - - From: - De : - - - - Broadcast to everyone who is subscribed to your address - Diffuser à chaque abonné de cette adresse - - - - Send - Envoyer - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - Gardez en tête que les diffusions sont seulement chiffrées avec votre adresse. Quiconque disposant de votre adresse peut les lire. - - - - Status - Statut - - - - Sent - Envoyé - - - + New Nouveau - - Label (not shown to anyone) - Label (seulement visible par vous) - - - - Address - Adresse - - - - Stream - Flux - - - - Your Identities - Vos identités - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - Vous pouvez ici souscrire aux 'messages de diffusion' envoyés par d'autres utilisateurs. Les messages apparaîtront dans votre boîte de récption. Les adresses placées ici outrepassent la liste noire. - - - - Add new Subscription - Ajouter un nouvel abonnement - - - - Label - Label - - - - Subscriptions - Abonnements - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - Le carnet d'adresses est utile pour mettre un nom sur une adresse Bitmessage et ainsi faciliter la gestion de votre boîte de réception. Vous pouvez ajouter des entrées ici en utilisant le bouton 'Ajouter', ou depuis votre boîte de réception en faisant un clic-droit sur un message. - - - - Add new entry - Ajouter une nouvelle entrée - - - - Name or Label - Nom ou Label - - - - Address Book - Carnet d'adresses - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - Utiliser une liste noire (autoriser tous les messages entrants exceptés ceux sur la liste noire) - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - Utiliser une liste blanche (refuser tous les messages entrants exceptés ceux sur la liste blanche) - - - - Blacklist - Liste noire - - - - Stream Number - Numéro de flux - - - - Number of Connections - Nombre de connexions - - - - Total connections: 0 - Nombre de connexions total : 0 - - - - Since startup at asdf: - Depuis le lancement à asdf : - - - - Processed 0 person-to-person message. - 0 message de pair à pair traité. - - - - Processed 0 public key. - 0 clé publique traitée. - - - - Processed 0 broadcast. - 0 message de diffusion traité. - - - - Network Status - État du réseau - - - - File - Fichier - - - - Settings - Paramètres - - - - Help - Aide - - - - Import keys - Importer les clés - - - - Manage keys - Gérer les clés - - - - Quit - Quitter - - - - About - À propos - - - - Regenerate deterministic addresses - Regénérer les clés déterministes - - - - Delete all trashed messages - Supprimer tous les messages dans la corbeille - - - - Total Connections: %1 - Nombre total de connexions : %1 - - - - Not Connected - Déconnecté - - - - Connected - Connecté - - - - Show Bitmessage - Afficher Bitmessage - - - - Subscribe - S'abonner - - - - Processed %1 person-to-person messages. - %1 messages de pair à pair traités. - - - - Processed %1 broadcast messages. - %1 messages de diffusion traités. - - - - Processed %1 public keys. - %1 clés publiques traitées. - - - - Since startup on %1 - Depuis lancement le %1 - - - - Waiting for their encryption key. Will request it again soon. - En attente de la clé de chiffrement. Une nouvelle requête sera bientôt lancée. - - - - Encryption key request queued. - Demande de clé de chiffrement en attente. - - - - Queued. - En attente. - - - - Need to do work to send message. Work is queued. - Travail nécessaire pour envoyer le message. Travail en attente. - - - - Acknowledgement of the message received %1 - Accusé de réception reçu le %1 - - - - Broadcast queued. - Message de diffusion en attente. - - - - Broadcast on %1 - Message de diffusion à %1 - - - - Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 - Problème : Le travail demandé par le destinataire est plus difficile que ce que vous avez paramétré. %1 - - - - Forced difficulty override. Send should start soon. - Neutralisation forcée de la difficulté. L'envoi devrait bientôt commencer. - - - - Message sent. Waiting for acknowledgement. Sent at %1 - Message envoyé. En attente de l'accusé de réception. Envoyé le %1 - - - - You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. - Vous pouvez éditer vos clés en éditant le fichier keys.dat stocké dans le même répertoire que ce programme. Il est important de faire des sauvegardes de ce fichier. - - - - You may manage your keys by editing the keys.dat file stored in - %1 -It is important that you back up this file. - Vous pouvez éditer vos clés en éditant le fichier keys.dat stocké dans le répertoire - %1. -Il est important de faire des sauvegardes de ce fichier. - - - - You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - Vous pouvez éditer vos clés en éditant le fichier keys.dat stocké dans le même répertoire que ce programme. Il est important de faire des sauvegardes de ce fichier. Souhaitez-vous l'ouvrir maintenant ? (Assurez-vous de fermer Bitmessage avant d'effectuer des changements.) - - - - You may manage your keys by editing the keys.dat file stored in - %1 -It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - Vous pouvez éditer vos clés en éditant le fichier keys.dat stocké dans le répertoire - %1. -Il est important de faire des sauvegardes de ce fichier. Souhaitez-vous l'ouvrir maintenant ? (Assurez-vous de fermer Bitmessage avant d'effectuer des changements.) - - - - Add sender to your Address Book - Ajouter l'expéditeur au carnet d'adresses - - - - Move to Trash - Envoyer à la Corbeille - - - - View HTML code as formatted text - Voir le code HTML comme du texte formaté - - - + Enable Activer - + Disable Désactiver - + + Set avatar... + Configurer l'avatar + + + Copy address to clipboard Copier l'adresse dans le presse-papier - + Special address behavior... Comportement spécial de l'adresse... - - Send message to this address - Envoyer un message à cette adresse + + Email gateway + Passerelle Email - - Add New Address - Ajouter nouvelle adresse - - - + Delete - Supprimer + Effacer - + + Send message to this address + Send beskjed til denne adressen + + + + Subscribe to this address + Abonner på denne adressen + + + + Add New Address + Legg til ny adresse + + + Copy destination address to clipboard - Copier l'adresse de destination dans le presse-papier + Kopier destinasjonsadresse til utklippstavlen - + Force send Forcer l'envoi - - Are you sure you want to delete all trashed messages? - Êtes-vous sûr de vouloir supprimer tous les messages dans la corbeille ? + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + En av dine gamle adresser er av den første typen og derfor ikke lenger støttet: %1. Derfor kan den vel slettes? - - You must type your passphrase. If you don't have one then this is not the form for you. - Vous devez taper votre phrase secrète. Si vous n'en avez pas, ce formulaire n'est pas pour vous. + + Waiting for their encryption key. Will request it again soon. + En attente de la clé de chiffrement. Une nouvelle requête sera bientôt lancée. - - Delete trash? - Supprimer la corbeille ? + + Encryption key request queued. + Forespørsel for å finne krypteringsnøkkel er satt i kø. - + + Queued. + Satt i kø. + + + + Message sent. Waiting for acknowledgement. Sent at %1 + Beskjed sendt. Venter på bekreftelse. Sendt %1 + + + + Message sent. Sent at %1 + Beskjed sendt. Sendt %1 + + + + Need to do work to send message. Work is queued. + Trenger å utføre arbeidsoppgave for sende beskjed. Denne er satt i kø. + + + + Acknowledgement of the message received %1 + Bekreftelse på beskjeden mottatt %1 + + + + Broadcast queued. + Kringkasting satt i kø. + + + + Broadcast on %1 + Kringkasting på %1 + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + Problème : Le travail demandé par le destinataire est plus difficile que ce que vous avez paramétré. %1 + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + Problem: Mottakerens nøkkel kunne ikke brukes til å kryptere beskjeden. %1 + + + + Forced difficulty override. Send should start soon. + Tvunget vanskelighet overstyrt. Sender snart. + + + + Unknown status: %1 %2 + Ukjent status: %1 %2 + + + + Not Connected + Ikke tilkoblet + + + + Show Bitmessage + Vis Bitmessage + + + + Send + Envoyer + + + + Subscribe + S'abonner + + + + Channel + Chaîne + + + + Quit + Avslutt + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + Vous pouvez éditer vos clés en éditant le fichier keys.dat stocké dans le même répertoire que ce programme. Il est important de faire des sauvegardes de ce fichier. + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + Vous pouvez éditer vos clés en éditant le fichier keys.dat stocké dans le répertoire %1. +Il est important de faire des sauvegardes de ce fichier. + + + Open keys.dat? Ouvrir keys.dat ? - + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Vous pouvez éditer vos clés en éditant le fichier keys.dat stocké dans le même répertoire que ce programme. Il est important de faire des sauvegardes de ce fichier. Souhaitez-vous l'ouvrir maintenant ? (Assurez-vous de fermer Bitmessage avant d'effectuer des changements.) + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Du kan administrere dine nøkler ved å endre på filen keys.dat lagret i + %1 +Det er viktig at du tar sikkerhetskopi av denne filen. Vil du åpne denne filen nå? (Vær sikker på å få avsluttet Bitmessage før du gjør endringer.) + + + + Delete trash? + Vil du slette kastet innhold? + + + + Are you sure you want to delete all trashed messages? + Er du sikker på at du vil slette alle kastede beskjeder? + + + bad passphrase - Mauvaise phrase secrète + Dårlig passordfrase - - Restart - Redémarrer + + You must type your passphrase. If you don't have one then this is not the form for you. + Du må skrive inn passordfrasen din. Hvis du ikke har en kan du ikke bruke dette skjemaet. - - You must restart Bitmessage for the port number change to take effect. - Vous devez redémarrer Bitmessage pour que le changement de port prenne effet. + + Bad address version number + Feil adresseversjonsnummer - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections. - Bitmessage utilisera votre proxy à partir de maintenant mais il vous faudra redémarrer Bitmessage pour fermer les connexions existantes. + + Your address version number must be a number: either 3 or 4. + Ditt adressetypenummer må være et nummer: Enten 3 eller 4. - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - Erreur : Vous ne pouvez pas ajouter une adresse déjà présente dans votre liste. Essayez de renommer l'adresse existante. + + Your address version number must be either 3 or 4. + Ditt adressetypenummer må enten være 3 eller 4. - - The address you entered was invalid. Ignoring it. - L'adresse que vous avez entrée est invalide. Adresse ignorée. + + Chan name needed + Kanalnavn nødvendig - - Passphrase mismatch - Phrases secrètes différentes + + You didn't enter a chan name. + Du oppga ikke noe kanalnavn. - - The passphrase you entered twice doesn't match. Try again. - Les phrases secrètes entrées sont différentes. Réessayez. + + Address already present + Adressen eksisterer allerede - - Choose a passphrase - Choisissez une phrase secrète + + Could not add chan because it appears to already be one of your identities. + Kunne ikke legge til kanal siden den ser ut til å allerede være lagret som en av dine identiteter. - - You really do need a passphrase. - Vous devez vraiment utiliser une phrase secrète. + + Success + Suksess - - All done. Closing user interface... - Terminé. Fermeture de l'interface... + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + Opprettet ny kanal. For å la andre delta i din nye kanal gir du dem dem kanalnavnet og denne Bitmessage-adressen: %1. Denne adressen vises også i 'Dine identiteter'. - - Address is gone - L'adresse a disparu + + Address too new + Adressen er for ny - - Bitmessage cannot find your address %1. Perhaps you removed it? - Bitmessage ne peut pas trouver votre adresse %1. Peut-être l'avez-vous supprimée ? + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + Selv om Bitmessage-adressen kanskje er gyldig så er tilhørende typenummer for nytt til å håndteres. Kanskje du trenger å oppgradere Bitmessage. - - Address disabled - Adresse désactivée + + Address invalid + Ugyldig adresse - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - Erreur : L'adresse avec laquelle vous essayez de communiquer est désactivée. Vous devez d'abord l'activer dans l'onglet 'Vos identités' avant de l'utiliser. + + That Bitmessage address is not valid. + Bitmessage-adressen er ikke gyldig. - - Entry added to the Address Book. Edit the label to your liking. - Entrée ajoutée au carnet d'adresses. Éditez le label selon votre souhait. + + Address does not match chan name + Adresse stemmer ikke med kanalnavnet - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - Erreur : Vous ne pouvez pas ajouter une adresse déjà présente dans votre carnet d'adresses. Essayez de renommer l'adresse existante. + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + Selv om Bitmessage-adressen du oppga var gyldig stemmer den ikke med kanalnavnet. - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - Messages déplacés dans la corbeille. Il n'y a pas d'interface utilisateur pour voir votre corbeille, mais ils sont toujours présents sur le disque si vous souhaitez les récupérer. + + Successfully joined chan. + Deltar nå i kanal. - - No addresses selected. - Aucune adresse sélectionnée. + + Connection lost + Mistet tilkobling - - Options have been disabled because they either aren't applicable or because they haven't yet been implimented for your operating system. - Certaines options ont été désactivées car elles n'étaient pas applicables ou car elles n'ont pas encore été implémentées pour votre système d'exploitation. + + Connected + Tilkoblet - - The address should start with ''BM-'' - L'adresse devrait commencer avec "BM-" + + Message trashed + Beskjed kastet - - The address is not typed or copied correctly (the checksum failed). - L'adresse n'est pas correcte (la somme de contrôle a échoué). + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + Le TTL, ou Time-To-Live (temps à vivre) est la durée de temps durant laquelle le réseau va détenir le message. +Le destinataire doit l'obtenir avant ce temps. Si votre client Bitmessage ne reçoit pas de confirmation de réception, il va le ré-envoyer automatiquement. Plus le Time-To-Live est long, plus grand est le travail que votre ordinateur doit effectuer pour envoyer le message. Un Time-To-Live de quatre ou cinq jours est souvent approprié. - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - Le numéro de version de cette adresse est supérieur à celui que le programme peut supporter. Veuiller mettre Bitmessage à jour. + + Message too long + Message trop long - - The address contains invalid characters. - L'adresse contient des caractères invalides. + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + Le message que vous essayez d'envoyer est trop long de %1 octets (le maximum est 261644 octets). Veuillez le réduire avant de l'envoyer. - - Some data encoded in the address is too short. - Certaines données encodées dans l'adresse sont trop courtes. + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + Erreur : votre compte n'a pas été inscrit à une passerelle de courrier électronique. Envoi de l'inscription maintenant en tant que %1, veuillez patienter tandis que l'inscription est en cours de traitement, avant de retenter l'envoi. - - Some data encoded in the address is too long. - Certaines données encodées dans l'adresse sont trop longues. + + Error: Bitmessage addresses start with BM- Please check %1 + Feil: Bitmessage-adresser begynner med BM-. Vennligst sjekk %1 - + + Error: The address %1 is not typed or copied correctly. Please check it. + Feil: Adressen %1 er skrevet eller kopiert inn feil. Vennligst sjekk den. + + + + Error: The address %1 contains invalid characters. Please check it. + Feil: Adressen %1 innerholder ugyldige tegn. Vennligst sjekk den. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + Feil: Typenummeret for adressen %1 er for høy. Enten trenger du å oppgradere Bitmessaage-programvaren eller så er det fordi kontakten din har funnet på noe smart. + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + Feil: Noen av de kodede dataene i adressen %1 er for korte. Det kan hende det er noe galt med programvaren til kontakten din. + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + Feil: Noen av de kodede dataene i adressen %1 er for lange. Det kan hende det er noe galt med programvaren til kontakten din. + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + Erreur : quelques données codées dans l'adresse %1 sont mal formées. Il pourrait y avoir un soucis avec le logiciel de votre connaissance. + + + + Error: Something is wrong with the address %1. + Feil: Noe er galt med adressen %1. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Feil: Du må oppgi en avsenderadresse. Hvis du ikke har en gå til 'Dine identiteter'-fanen. + + + + Address version number + Adressetypenummer + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Angående adressen %1, Bitmessage forstår ikke adressetypenumre for %2. Oppdater Bitmessage til siste versjon. + + + + Stream number + Strømnummer + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Angående adressen %1, Bitmessage kan ikke håndtere strømnumre for %2. Oppdater Bitmessage til siste utgivelse. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Advarsel: Du er ikke tilkoblet. Bitmessage vil utføre nødvendige arbeidsoppgaver for å sende beskjeder, men ingen vil bli sendt før du kobler til igjen. + + + + Message queued. + Message mis en file d'attente. + + + + Your 'To' field is empty. + Ditt 'Til'-felt er tomt. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Høyreklikk på en eller flere oppføringer i adresseboka og velg 'Send beskjed til denne adressen'. + + + + Fetched address from namecoin identity. + Hentet adresse fra Namecoin-identitet. + + + + New Message + Ny beskjed + + + + From + De + + + + Sending email gateway registration request + Envoi de la demande d'inscription de la passerelle email + + + Address is valid. L'adresse est valide. - - You are using TCP port %1. (This can be changed in the settings). - Vous utilisez le port TCP %1. (Ceci peut être changé dans les paramètres). + + The address you entered was invalid. Ignoring it. + Adressen du oppga var ugyldig og vil derfor bli ignorert. - - Error: Bitmessage addresses start with BM- Please check %1 - Erreur : Les adresses Bitmessage commencent avec BM- Merci de vérifier %1 + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Feil: Du kan ikke legge til samme adresse i adresseboka flere ganger. - - Error: The address %1 contains invalid characters. Please check it. - Erreur : L'adresse %1 contient des caractères invalides. Veuillez la vérifier. + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + Erreur : vous ne pouvez pas ajouter la même adresse deux fois à vos abonnements. Peut-être que vous pouvez renommer celle qui existe si vous le souhaitez. - - Error: The address %1 is not typed or copied correctly. Please check it. - Erreur : L'adresse %1 n'est pas correctement recopiée. Veuillez la vérifier. + + Restart + Omstart - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - Erreur : La version de l'adresse %1 est trop grande. Pensez à mettre à jour Bitmessage. + + You must restart Bitmessage for the port number change to take effect. + Du må ta omstart av Bitmessage for at endringen av portnummer skal tre i kraft. - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - Erreur : Certaines données encodées dans l'adresse %1 sont trop courtes. Il peut y avoir un problème avec le logiciel ou votre connaissance. - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - Erreur : Certaines données encodées dans l'adresse %1 sont trop longues. Il peut y avoir un problème avec le logiciel ou votre connaissance. - - - - Error: Something is wrong with the address %1. - Erreur : Problème avec l'adresse %1. - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - Erreur : Vous devez spécifier une adresse d'expéditeur. Si vous n'en avez pas, rendez-vous dans l'onglet 'Vos identités'. - - - - Sending to your address - Envoi vers votre adresse - - - - Error: One of the addresses to which you are sending a message, %1, is yours. Unfortunately the Bitmessage client cannot process its own messages. Please try running a second client on a different computer or within a VM. - Erreur : Une des adresses vers lesquelles vous envoyez un message, %1, est vôtre. Malheureusement, Bitmessage ne peut pas traiter ses propres messages. Essayez de lancer un second client sur une machine différente. - - - - Address version number - Numéro de version de l'adresse - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - Concernant l'adresse %1, Bitmessage ne peut pas comprendre les numéros de version de %2. Essayez de mettre à jour Bitmessage vers la dernière version. - - - - Stream number - Numéro de flux - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - Concernant l'adresse %1, Bitmessage ne peut pas supporter les nombres de flux de %2. Essayez de mettre à jour Bitmessage vers la dernière version. - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - Avertissement : Vous êtes actuellement déconnecté. Bitmessage fera le travail nécessaire pour envoyer le message mais il ne sera pas envoyé tant que vous ne vous connecterez pas. - - - - Your 'To' field is empty. - Votre champ 'Vers' est vide. - - - - Right click one or more entries in your address book and select 'Send message to this address'. - Cliquez droit sur une ou plusieurs entrées dans votre carnet d'adresses et sélectionnez 'Envoyer un message à ces adresses'. - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - Erreur : Vous ne pouvez pas ajouter une même adresse à vos abonnements deux fois. Essayez de renommer l'adresse existante. - - - - Message trashed - Message envoyé à la corbeille - - - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - Une de vos adresses, %1, est une vieille adresse de la version 1. Les adresses de la version 1 ne sont plus supportées. Nous pourrions la supprimer maintenant ? - - - - Unknown status: %1 %2 - Statut inconnu : %1 %2 - - - - Connection lost - Connexion perdue - - - - SOCKS5 Authentication problem: %1 - Problème d'authentification SOCKS5 : %1 - - - - Reply - Répondre - - - - Generating one new address - Génération d'une nouvelle adresse - - - - Done generating address. Doing work necessary to broadcast it... - Génération de l'adresse terminée. Travail pour la diffuser en cours... - - - - Done generating address - Génération de l'adresse terminée - - - - Message sent. Waiting for acknowledgement. Sent on %1 - Message envoyé. En attente de l'accusé de réception. Envoyé le %1 - - - - Error! Could not find sender address (your address) in the keys.dat file. - Erreur ! L'adresse de l'expéditeur (vous) n'a pas pu être trouvée dans le fichier keys.dat. - - - - Doing work necessary to send broadcast... - Travail pour envoyer la diffusion en cours... - - - - Broadcast sent on %1 - Message de diffusion envoyé le %1 - - - - Looking up the receiver's public key - Recherche de la clé publique du destinataire - - - - Doing work necessary to send message. (There is no required difficulty for version 2 addresses like this.) - Travail nécessaire pour envoyer le message en cours. (Il n'y a pas de difficulté requise pour ces adresses de version 2.) - - - - Doing work necessary to send message. -Receiver's required difficulty: %1 and %2 - Travail nécessaire pour envoyer le message. -Difficulté requise par le destinataire : %1 et %2 - - - - Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. - Problème : Le travail demandé par le destinataire (%1 et %2) est plus difficile que ce que vous souhaitez faire. - - - - Work is queued. - Travail en attente. - - - - Work is queued. %1 - Travail en attente. %1 - - - - Doing work necessary to send message. -There is no required difficulty for version 2 addresses like this. - Travail nécessaire pour envoyer le message en cours. -Il n'y a pas de difficulté requise pour ces adresses de version 2. - - - - Problem: The recipient's encryption key is no good. Could not encrypt message. %1 - - - - - Save message as... - - - - - Mark Unread - - - - - Subscribe to this address - - - - - Message sent. Sent at %1 - - - - - Chan name needed - - - - - You didn't enter a chan name. - - - - - Address already present - - - - - Could not add chan because it appears to already be one of your identities. - - - - - Success - - - - - Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. - - - - - Address too new - - - - - Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. - - - - - Address invalid - - - - - That Bitmessage address is not valid. - - - - - Address does not match chan name - - - - - Although the Bitmessage address you entered was valid, it doesn't match the chan name. - - - - - Successfully joined chan. - - - - - Fetched address from namecoin identity. - - - - - New Message - - - - - From - - - - + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). - + Bitmessage vil bruke proxy fra nå av. Hvis du vil kan du omstart av programmet for å lukke eksisterende tilkoblinger (hvis det finnes noen). - - Save As... - + + Number needed + Nombre requis - - Write error. - + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + Vos taux maximum de téléchargement et de téléversement doivent être des nombres. Ce que vous avez tapé est ignoré. - - Testing... - + + Will not resend ever + Vil ikke igjensende noensinne - - This is a chan address. You cannot use it as a pseudo-mailing list. - + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + Legg merke til at utløpstiden du oppga er kortere enn det Bitmessage venter for første igjensendingsforsøk, dine beskjeder vil derfor aldri bli igjensendt. - - Search - + + Sending email gateway unregistration request + Envoi de la demande de désinscription de la passerelle email - - All - + + Sending email gateway status request + Envoi à la passerelle email d'une demande de statut - - Message - + + Passphrase mismatch + Passordfrase stemmer ikke - - Fetch Namecoin ID - + + The passphrase you entered twice doesn't match. Try again. + Passordfrasene er ikke like. Vennligst prøv igjen. - - Stream # - + + Choose a passphrase + Velg en passordfrase - - Connections - + + You really do need a passphrase. + Du trenger sårt en passordfrase. - - Ctrl+Q - Ctrl+Q + + Address is gone + Adressen er borte - - F1 - + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmessage kan ikke finne adressen %1. Kanskje du fjernet den? - - Join / Create chan - + + Address disabled + Adressen er deaktivert + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Feil: Adressen du prøver å sende med er deaktivert. Du må aktivere den fra 'Dine identiteter' før du kan bruke den. + + + + Entry added to the Address Book. Edit the label to your liking. + Ny oppføring lagt til i adresseboka. Du kan forandre etiketten til det du måtte ønske. - Set avatar... - + Entry added to the blacklist. Edit the label to your liking. + Entrée ajoutée à la liste noire. Éditez l'étiquette à votre convenance. - - Bad address version number - + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + Erreur : vous ne pouvez pas ajouter la même adresse deux fois à votre liste noire. Essayez de renommer celle qui existe si vous le souhaitez. - - Your address version number must be a number: either 3 or 4. - + + Moved items to trash. + Kastet innholdet. - - Your address version number must be either 3 or 4. - + + Undeleted item. + Articles restaurés. - - Inventory lookups per second: %1 - + + Save As... + Lagre som ... - - Will not resend ever - + + Write error. + Skrivefeil. - - Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. - + + No addresses selected. + Ingen adresse valgt. - + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + Si vous supprimez cet abonnement, les messages que vous avez déjà reçus deviendront inaccessibles. Peut-être que vous devriez considérez d'abord de désactiver l'abonnement. Les abonnements désactivés ne reçoivent pas de nouveaux messages, mais vous pouvez encore voir ceux que vous avez déjà reçus. + +Êtes-vous sur de vouloir supprimer cet abonnement ? + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + Si vous supprimez ce Chan (canal), les messages que vous avez déjà reçus deviendront inaccessibles. Peut-être que vous devriez considérez d'abord de désactiver le Chan (canal). Les Chans (canaux) désactivés ne reçoivent pas de nouveaux messages, mais vous pouvez encore voir ceux que vous avez déjà reçus. + +Êtes-vous sur(e) de vouloir supprimer ce Chan (canal) ? + + + Do you really want to remove this avatar? - + Vil du virkelig fjerne dette avataret? - + You have already set an avatar for this address. Do you really want to overwrite it? - + Du har allerede satt ett avatar for denne adressen. Vil du virkelig overskrive det? - + Start-on-login not yet supported on your OS. - + Start ved innlogging er ikke støttet enda for ditt OS. - + Minimize-to-tray not yet supported on your OS. - + Minimering til systemstatusfeltet er ikke støttet enda for ditt OS. - + Tray notifications not yet supported on your OS. - + Varslinger via systemstatusfeltet er ikke støttet enda for ditt OS. - + + Testing... + Tester ... + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + Dette er en kanaladresse. Du kan ikke bruke den som en pseudo-epostliste. + + + + The address should start with ''BM-'' + Adressen bør starte med ''BM-'' + + + + The address is not typed or copied correctly (the checksum failed). + Adressen er ikke skrevet eller kopiert inn riktig (sjekksummen feilet). + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + Typenummeret for denne adressen er høyere enn det programvaren støtter. Vennligst oppgrader Bitmessage. + + + + The address contains invalid characters. + Adressen inneholder ugyldige tegn. + + + + Some data encoded in the address is too short. + Noen av de kodede dataene i adressen er for korte. + + + + Some data encoded in the address is too long. + Noen av de kodede dataene i adressen er for lange. + + + + Some data encoded in the address is malformed. + Quelques données codées dans l'adresse sont mal formées. + + + Enter an address above. - + Oppgi inn en adresse over. - + Address is an old type. We cannot display its past broadcasts. - + Adressen er av gammel type. Vi kan ikke vise dens tidligere kringkastninger. - + There are no recent broadcasts from this address to display. - + Det er ingen nylige kringkastninger fra denne adressen å vise frem. - - Display the %1 recent broadcast from this address. - + + You are using TCP port %1. (This can be changed in the settings). + Du benytter TCP-port %1. (Dette kan endres på i innstillingene). - - Display the %1 recent broadcasts from this address. - + + Bitmessage + Bitmessage - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - + + Identities + Identités - - Inventory lookups per second: 0 - + + New Identity + Nouvelle identité - - - MainWindows - - Address is valid. - L'adresse est valide. + + Search + Søk + + + + All + Alle + + + + To + Til + + + + From + Fra + + + + Subject + Emne + + + + Message + Beskjed + + + + Received + Mottatt + + + + Messages + Messages + + + + Address book + Carnet d'adresses + + + + Address + Adresse + + + + Add Contact + Ajouter un contact + + + + Fetch Namecoin ID + Hent Namecoin-id + + + + Subject: + Emne: + + + + From: + Fra: + + + + To: + Til: + + + + Send ordinary Message + Envoyer un message ordinaire + + + + Send Message to your Subscribers + Envoyer un message à vos abonnés + + + + TTL: + TTL: + + + + Subscriptions + Abonnement + + + + Add new Subscription + Legg til nytt abonnement + + + + Chans + Chans (canaux) + + + + Add Chan + Ajouter un Chan (canal) + + + + File + Fil + + + + Settings + Innstillinger + + + + Help + Hjelp + + + + Import keys + Importer inn nøkler + + + + Manage keys + Administrer nøkler + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + Contacter support + + + + About + Om + + + + Regenerate deterministic addresses + Regenerer deterministiske adresser + + + + Delete all trashed messages + Slett alle kastede meldinger + + + + Join / Create chan + Delta i / opprett kanal + + + + All accounts + Tous comptes + + + + Zoom level %1% + Niveau de zomm %1% + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + Erreur : vous ne pouvez pas ajouter la même adresse deux fois à votre liste. Peut-être que vous pouvez renommer celle qui existe si vous le souhaitez. + + + + Add new entry + Ajouter nouvelle entrée + + + + Display the %1 recent broadcast(s) from this address. + Montre les %1 plus récentes émission(s) issues de cette adresse. + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + @@ -1108,104 +1276,99 @@ p, li { white-space: pre-wrap; } Create new Address - Créer une nouvelle adresse + Opprett ny adresse Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: - Vous pouvez générer autant d'adresses que vous le souhaitez. En effet, nous vous encourageons à créer et à délaisser vos adresses. Vous pouvez générer des adresses en utilisant des nombres aléatoires ou en utilisant une phrase secrète. Si vous utilisez une phrase secrète, l'adresse sera une adresse "déterministe". -L'option 'Nombre Aléatoire' est sélectionnée par défaut mais les adresses déterministes ont certains avantages et inconvénients : + Her kan du generere så mange adresser du vil. Du oppfordres til å ta i bruk nye adresser med jevne mellomrom. Du kan generere nye adresser enten ved å bruke tilfeldige numre eller en passordfrase. Hvis du bruker passordfrase får du en såkalt 'deterministisk' adresse. +'Tilfeldig nummer'-valget er valgt som standard. En deterministisk adresse har både fordeler og ulemper: <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">Avantages :<br/></span>Vous pouvez recréer vos adresses sur n'importe quel ordinateur. <br/>Vous n'avez pas à vous inquiéter à propos de la sauvegarde de votre fichier keys.dat tant que vous vous rappelez de votre phrase secrète. <br/><span style=" font-weight:600;">Inconvénients :<br/></span>Vous devez vous rappeler (ou noter) votre phrase secrète si vous souhaitez être capable de récréer vos clés si vous les perdez. <br/>Vous devez vous rappeler du numéro de version de l'adresse et du numéro de flux en plus de votre phrase secrète. <br/>Si vous choisissez une phrase secrète faible et que quelqu'un sur Internet parvient à la brute-forcer, il pourra lire vos messages et vous en envoyer.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Fordeler:<br/></span>Du kan gjenskape adressene dine på hvilken som helst datamaskin ved hjelp av hukommelsen. <br/>Du trenger ikke ta noen sikkerhetskopi av keys.dat-filen så lenge du husker passordfrasen din. <br/><span style=" font-weight:600;">Ulemper:<br/></span>Du må huske (eller skrive ned) din passordfrase hvis du forventer å måtte gjenopprette nøklene dine fordi de går tapt. <br/>Du må huske adresseversjonsnummeret og strømnummeret i tillegg til passordfrasen. <br/>Hvis du velger en svak passordfrase og noen andre på Internett klarer å knekke den kan de lese beskjedene dine og sende nye beskjeder på vegne av deg.</p></body></html> Use a random number generator to make an address - Utiliser un générateur de nombres aléatoires pour créer une adresse + Opprett en adresse ved å bruke generatoren som lager tilfeldige tall Use a passphrase to make addresses - Utiliser une phrase secrète pour créer une adresse + Bruk en passordfrase for å opprette adresser Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter - Créer une adresse plus courte d'un ou deux caractères (nécessite plusieurs minutes de temps de calcul supplémentaires) + Bruk ekstra tid på å få adressen(e) en eller to tegn kortere Make deterministic addresses - Créer une adresse déterministe - - - - Address version number: 3 - Numéro de version de l'adresse : 3 - - - - In addition to your passphrase, you must remember these numbers: - En plus de votre phrase secrète, vous devez vous rappeler ces numéros : - - - - Passphrase - Phrase secrète - - - - Number of addresses to make based on your passphrase: - Nombre d'adresses à créer sur base de votre phrase secrète : - - - - Stream number: 1 - Nombre de flux : 1 - - - - Retype passphrase - Retapez la phrase secrète - - - - Randomly generate address - Générer une adresse de manière aléatoire - - - - Label (not shown to anyone except you) - Label (seulement visible par vous) - - - - Use the most available stream - Utiliser le flux le plus disponible - - - - (best if this is the first of many addresses you will create) - (préférable si vous générez votre première adresse) - - - - Use the same stream as an existing address - Utiliser le même flux qu'une adresse existante - - - - (saves you some bandwidth and processing power) - (économise de la bande passante et de la puissance de calcul) + Opprett deterministisk adresse Address version number: 4 - Numéro de version de l'adresse : 4 + Adressetypenummer: 4 + + + + In addition to your passphrase, you must remember these numbers: + I tillegg til passordfrasen må du huske disse numrene: + + + + Passphrase + Passordfrase + + + + Number of addresses to make based on your passphrase: + Antall adresser som skal opprettes basert på din passordfrase: + + + + Stream number: 1 + Strømnummer: 1 + + + + Retype passphrase + Gjenta passordfrase + + + + Randomly generate address + Generer tilfeldig adresse + + + + Label (not shown to anyone except you) + Etikett (ikke vist til noen andre enn deg) + + + + Use the most available stream + Bruk den mest tilgjengelige strømmen + + + + (best if this is the first of many addresses you will create) + (best hvis dette er de første av mange adresser du kommer til å opprette) + + + + Use the same stream as an existing address + Bruk samme strøm som en eksisterende adresse + + + + (saves you some bandwidth and processing power) + (sparer deg for litt båndbredde og prosesseringskraft) @@ -1213,12 +1376,12 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais Add new entry - Ajouter une nouvelle entrée + Legg til ny oppføring Label - Label + Etikett @@ -1227,8 +1390,8 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais - CheckBox - + Enter an address above. + Entrez ci-dessus une adresse. @@ -1236,31 +1399,36 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais Special Address Behavior - Comportement spécial de l'adresse + Spesiell adresseoppførsel Behave as a normal address - Se comporter comme une adresse normale + Oppførsel som vanlig adresse Behave as a pseudo-mailing-list address - Se comporter comme une adresse d'une pseudo liste de diffusion + Oppførsel som adresse på pseudo-epostliste Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). - Un mail reçu sur une adresse d'une pseudo liste de diffusion sera automatiquement diffusé aux abonnés (et sera donc public). + E-post mottatt med en adresse oppført på en pseudo-epostliste vil automatisk bli kringkastet til abonnenter (og vil derfor bli offentlig tilgjengelig). Name of the pseudo-mailing-list: - Nom de la pseudo liste de diffusion : + Navnet på pseudo-epostlista: aboutDialog + + + About + Om + PyBitmessage @@ -1269,32 +1437,60 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais version ? - version ? - - - - About - À propos - - - - Copyright © 2013 Jonathan Warren - Copyright © 2013 Jonathan Warren + versjon ? <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> - <html><head/><body><p>Distribué sous la licence logicielle MIT/X11; voir <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + <html><head/><body><p>Distribuert under MIT/X11-programvarelisens, se <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> This is Beta software. - Version bêta. + Dette er betaprogramvare. - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 The Bitmessage Developers</p></body></html> - + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + Utiliser une liste noire (Blacklist. Cela autorise tous les messages entrants sauf ceux présents sur la liste noire) + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + Utiliser une liste blanch (Whitelist. Bloque tous les messages entrants sauf ceux présents sur cette liste blanche) + + + + Add new entry + Ajouter nouvelle entrée + + + + Name or Label + Nom ou étiquette + + + + Address + Adresse + + + + Blacklist + Liste noire + + + + Whitelist + Liste blanche @@ -1302,22 +1498,22 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais Bitmessage - Bitmessage + Bitmessage Bitmessage won't connect to anyone until you let it. - + Bitmessage kobler ikke til noen før du lar den. Connect now - + Koble til nå Let me configure special network settings first - + La meg konfigurere spesielle nettverksinnstillinger først @@ -1325,17 +1521,17 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais Help - Aide + Hjelp - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">Wiki d'aide de PyBitmessage</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: - Bitmessage étant un projet collaboratif, une aide peut être trouvée en ligne sur le Wiki de Bitmessage : + Bitmessage er et samarbeidsprosjekt, hjelp kan bli funnet på nettet i Bitmessage-wikien: @@ -1343,27 +1539,140 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais Icon Glossary - Glossaire des icônes + Statusoversikt You have no connections with other peers. - Vous n'avez aucune connexion avec d'autres pairs. + Du har ingen tilkoblinger til andre. 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'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. - Vous avez au moins une connexion sortante avec un pair mais vous n'avez encore reçu aucune connexion entrante. Votre pare-feu ou routeur n'est probablement pas configuré pour transmettre les connexions TCP vers votre ordinateur. Bitmessage fonctionnera correctement, mais le réseau Bitmessage se portera mieux si vous autorisez les connexions entrantes. Cela vous permettra d'être un nœud mieux connecté. + Du har opprettet minst en utgående tilkobling til andre, men ikke mottatt noen innkommende tilkoblinger enda. Din brannmur eller ruter er antagelig ikke konfigurert til å videreformidle innkommende TCP-tilkoblinger frem til datamaskinen din. Bitmessage vil fungere helt fint, men det ville hjelpe Bitmessage-nettverket hvis du tillot innkommende tilkoblinger. Det vil også hjelpe deg å bli en bedre tilkoblet node. You are using TCP port ?. (This can be changed in the settings). - Vous utilisez le port TCP ?. (Peut être changé dans les paramètres). + Du bruker TCP port ?. (Dette kan endres på fra innstillingene). You do have connections with other peers and your firewall is correctly configured. - Vous avez des connexions avec d'autres pairs et votre pare-feu est configuré correctement. + Du har aktive tilkoblinger til andre og riktig konfigurert brannmur. + + + + networkstatus + + + Total connections: + Total de connexions : + + + + Since startup: + Depuis le démarrage : + + + + Processed 0 person-to-person messages. + Traité 0 messages de personne à personne. + + + + Processed 0 public keys. + Traité 0 clés publiques. + + + + Processed 0 broadcasts. + Traité 0 diffusions (broadcasts). + + + + Inventory lookups per second: 0 + Consultations d'inventaire par seconde : 0 + + + + Objects to be synced: + Objets à synchroniser : + + + + Stream # + Flux # + + + + Connections + Connexions + + + + Since startup on %1 + Depuis le démarrage sur %1 + + + + Down: %1/s Total: %2 + Téléchargées : %1/s Total : %2 + + + + Up: %1/s Total: %2 + Téléversées : %1/s Total : %2 + + + + Total Connections: %1 + Total de connexions : %1 + + + + Inventory lookups per second: %1 + Consultations d'inventaire par seconde : %1 + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + @@ -1371,42 +1680,42 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais Dialog - + Opprett ny kanal Create a new chan - + Opprett en ny kanal Join a chan - + Delta i kanal Create a chan - + Opprett en kanal <html><head/><body><p>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.</p></body></html> - + <html><head/><body><p>Skriv inn et navn for kanalen din. Hvis du velger et komplisert nok kanalnavn (et som er langt nok og unikt som passfrase) og ingen av dine kontakter deler det offentlig vil kanalen være sikker og privat. Hvis du og noen andre begge oppretter en kanal med samme kanalnavnet vil dette bli samme kanalen</p></body></html> Chan name: - + Kanalnavn: <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> - + <html><head/><body><p>En kanal eksisterer når en gruppe personer deler de samme dekrypteringsnøklene. Nøklene og Bitmessage-adressen brukt av kanalen er generert fra et menneskevennlig ord eller en frase (kanalnavnet). For å sende en beskjed til alle som er i kanalen sender man en vanlig beskjed av typen person-til-person til kanaladressen.</p><p>Kanaler er fullstendig umodererbare og eksperimentelle.</p></body></html> Chan bitmessage address: - + Bitmessage-kanaladresse: @@ -1414,37 +1723,32 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais Regenerate Existing Addresses - Regénérer des adresses existantes + Regenerer eksisterende adresser Regenerate existing addresses - Regénérer des adresses existantes + Regenerer eksisterende adresser Passphrase - Phrase secrète + Passordfrase Number of addresses to make based on your passphrase: - Nombre d'adresses basées sur votre phrase secrète à créer : + Antall adresser som skal opprettes basert på din passordfrase: - - Address version Number: - Numéro de version de l'adresse : - - - - 3 - 3 + + Address version number: + Adressetypenummer: Stream number: - Numéro du flux : + Strømnummer: @@ -1454,330 +1758,311 @@ L'option 'Nombre Aléatoire' est sélectionnée par défaut mais Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter - Créer une adresse plus courte d'un ou deux caractères (nécessite plusieurs minutes de temps de calcul supplémentaires) + Bruk ekstra tid på å få adressen(e) en eller to tegn kortere You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. - Vous devez cocher (ou décocher) cette case comme vous l'aviez fait (ou non) lors de la création de vos adresses la première fois. + Du må krysse av for (eller ikke krysse av for) i denne boksen slik du gjorde når du opprettet adressene dine første gangen. 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. - Si vous aviez généré des adresses déterministes mais les avez perdues à cause d'un accident, vous pouvez les regénérer ici. Si vous aviez utilisé le générateur de nombres aléatoires pour créer vos adresses, ce formulaire ne vous sera d'aucune utilité. - - - - Address version number: - + Hvis du tidligere har opprettet deterministiske adresser, men mistet dem p.g.a. et uhell (f.eks. harddiskkræsj) så kan de regenereres her. Hvis du derimot brukte generatoren for generering av tilfeldige tall vil ikke dette skjemaet være til hjelp for deg. settingsDialog - + Settings - Paramètres + Innstillinger - + Start Bitmessage on user login - Démarrer Bitmessage à la connexion de l'utilisateur + Start Bitmessage ved brukerpålogging - + + Tray + Zone de notification + + + Start Bitmessage in the tray (don't show main window) - Démarrer Bitmessage dans la barre des tâches (ne pas montrer la fenêtre principale) + Start Bitmessage i systemstatusfeltet (ikke vis hovedvinduet) - + Minimize to tray - Minimiser dans la barre des tâches + Minimiser til systemstatusfeltet - + + Close to tray + Fermer vers la zone de notification + + + Show notification when message received - Montrer une notification lorsqu'un message est reçu + Vis varsel når beskjed mottas - + Run in Portable Mode - Lancer en Mode Portable + Kjør i flyttbar modus - + 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. - En Mode Portable, les messages et les fichiers de configuration sont stockés dans le même dossier que le programme plutôt que le dossier de l'application. Cela rend l'utilisation de Bitmessage plus facile depuis une clé USB. + I flyttbar modus blir beskjeder og konfigurasjonsfiler oppbevart i samme katalog som programmet istedet for den vanlige applikasjonsdatamappen. Dette gjør Bitmessage enkel å kjøre fra f.eks. minnepinne. - + + Willingly include unencrypted destination address when sending to a mobile device + Inkluder med vilje ukrypterte destinasjonadresser når mobil enhet er mottaker + + + + Use Identicons + Bruk identikoner + + + + Reply below Quote + Réponse en dessous de la citation + + + + Interface Language + Grensesnittspråk + + + + System Settings + system + Systeminnstillinger + + + User Interface - Interface utilisateur + Brukergrensesnitt - + Listening port - Port d'écoute + Lyttende port - + Listen for connections on port: - Écouter les connexions sur le port : + Lytt etter tilkoblinger på port: - + + UPnP: + UPnP : + + + + Bandwidth limit + Limite de bande passante + + + + Maximum download rate (kB/s): [0: unlimited] + Taux maximum de téléchargement (kO/s) : [0: illimité] + + + + Maximum upload rate (kB/s): [0: unlimited] + Taux maximum de téléversement (kO/s) : [0: illimité] + + + Proxy server / Tor - Serveur proxy / Tor + Proxytjener / Tor - + Type: - Type : + Type: - + + Server hostname: + Tjenernavn: + + + + Port: + Port: + + + + Authentication + Autentisering + + + + Username: + Brukernavn: + + + + Pass: + Passord: + + + + Listen for incoming connections when using proxy + Lytt etter innkommende tilkoblinger når proxy benyttes + + + none - aucun + ingen - + SOCKS4a SOCKS4a - + SOCKS5 SOCKS5 - - Server hostname: - Nom du serveur : - - - - Port: - Port : - - - - Authentication - Authentification - - - - Username: - Utilisateur : - - - - Pass: - Mot de passe : - - - + Network Settings - Paramètres réseau + Nettverksinnstillinger - - 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. - Lorsque quelqu'un vous envoie un message, son ordinateur doit d'abord effectuer un travail. La difficulté de ce travail, par défaut, est de 1. Vous pouvez augmenter cette valeur pour les adresses que vous créez en changeant la valeur ici. Chaque nouvelle adresse que vous créez requerra à l'envoyeur de faire face à une difficulté supérieure. Il existe une exception : si vous ajoutez un ami ou une connaissance à votre carnet d'adresses, Bitmessage les notifiera automatiquement lors du prochain message que vous leur envoyez qu'ils ne doivent compléter que la charge de travail minimale : difficulté 1. - - - + Total difficulty: - Difficulté totale : + Total vanskelighet: - - Small message difficulty: - Difficulté d'un message court : - - - - 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. - La 'difficulté d'un message court' affecte principalement la difficulté d'envoyer des messages courts. Doubler cette valeur rend la difficulté à envoyer un court message presque double, tandis qu'un message plus long ne sera pas réellement affecté. - - - + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - La 'difficulté totale' affecte le montant total de travail que l'envoyeur devra compléter. Doubler cette valeur double la charge de travail. + 'Total vanskelighet' påvirker den absolutte mengden av arbeid som avsender må fullføre. Dobling av denne verdien dobler også arbeidsmengden. - + + Small message difficulty: + Vanskelighet for kort beskjed: + + + + 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. + Når noen sender deg en beskjed må først datamaskin deres fullføre en arbeidsoppgave. Vanskelighetsgraden for denne oppgaven er satt til 1 som standard. Du kan heve denne grensen for nye adresser du oppretter ved å endre på verdiene her. Alle nye adresser du oppretter vil kreve av avsender å løse enda vanskeligere oppgaver. Det finnes èt unntak: Hvis du legger til en kontakt i din adressebok vil de bli varslet neste gang du sender en beskjed om at de kun trenger å utføre enkleste form for arbeidsoppgave, denne har vanskelighetsgrad 1. + + + + 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. + 'Vanskelighet for kort beskjed' vil kun påvirke sending av korte beskjeder. Dobling av denne verdien vil også doble vanskeligheten for å sende en kort beskjed. + + + Demanded difficulty - Difficulté demandée + Krevd vanskelighet - + 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. - Vous pouvez préciser quelle charge de travail vous êtes prêt à effectuer afin d'envoyer un message à une personne. Placer cette valeur à 0 signifie que n'importe quelle valeur est acceptée. + Her kan du sette den maksimale mengden med arbeid som du er villig til å gjennomføre for å sende en beskjed til en annen person. Om disse verdiene settes til null vil alle verdier bli akseptert. - + Maximum acceptable total difficulty: - Difficulté maximale acceptée : + Maks akseptabel total vanskelighet: - + Maximum acceptable small message difficulty: - Difficulté maximale pour les messages courts acceptée : + Maks akseptabel vanskelighet for korte beskjeder: - + Max acceptable difficulty - Difficulté acceptée max + Maks akseptabel vanskelighet - - Willingly include unencrypted destination address when sending to a mobile device - + + Hardware GPU acceleration (OpenCL) + Accélération GPU matérielle (OpenCL) - - Listen for incoming connections when using proxy - - - - + <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> - + <html><head/><body><p>Bitmessage kan benytte et annet Bitcoin-basert program ved navn Namecoin for å lage menneskevennlige adresser. For eksempel, istedet for å fortelle din kontakt din lange Bitmessage-adresse så kan du enkelt fortelle vedkommende at beskjeden skal sendes til <span style=" font-style:italic;">test. </span></p><p>(å få din egen adresse inn Namecoin er fortsatt ganske vanskelig).</p><p>Bitmessage kan bruke enten namecoind direkte eller en kjørende instans av nmcontrol.</p></body></html> - + Host: - + Vert: - + Password: - + Passord: - + Test - + Test - + Connect to: - + Koble til: - + Namecoind - + Namecoind - + NMControl - + NMControl - + Namecoin integration - + Namecoin-integrasjon - - Use Identicons - - - - - Interface Language - - - - - System Settings - system - - - - - English - en - - - - - Esperanto - eo - - - - - Français - fr - - - - - Deutsch - de - - - - - Españl - es - - - - - русский язык - ru - - - - - Norsk - no - - - - - Pirate English - en_pirate - - - - - Other (set in keys.dat) - other - - - - + <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> - + <html><head/><body><p>Som standard er det slik at hvis du sender en beskjed til noen og de er frakoblet i mer enn to dager så vil Bitmessage sende beskjeden på nytt igjen etter at det er gått to ekstra dager. Sånn vil det holde på fremover med eksponentiell vekst; beskjeder sendes på nytt etter 8, 16, 32 dager o.s.v., helt til mottakeren erkjenner dem. Her kan du endre på denne oppførselen ved å få Bitmessage til å gi opp etter et bestemt antall dager eller måneder.</p><p>La disse feltene stå tomme for å få standard oppsettet. </p></body></html> - + Give up after - + Gi opp etter - + and - + og - + days - + dager - + months. - + måneder. - + Resends Expire - + Igjensending - + \ No newline at end of file diff --git a/src/translations/bitmessage_it.qm b/src/translations/bitmessage_it.qm new file mode 100644 index 00000000..77a80797 Binary files /dev/null and b/src/translations/bitmessage_it.qm differ diff --git a/src/translations/bitmessage_it.ts b/src/translations/bitmessage_it.ts new file mode 100644 index 00000000..f6e39188 --- /dev/null +++ b/src/translations/bitmessage_it.ts @@ -0,0 +1,2096 @@ + + + AddAddressDialog + + + Add new entry + Aggiungi una nuova voce + + + + Label + Etichetta + + + + Address + Indirizzo + + + + EmailGatewayDialog + + + Email gateway + Gateway di posta + + + + Register on email gateway + Registrati sul gateway di posta + + + + Account status at email gateway + Stato dell'account rispetto al gateway di posta + + + + Change account settings at email gateway + Modifica i settaggi dell'account rispetto al gateway di posta + + + + Unregister from email gateway + Rimuovi registrazione dal gateway di posta + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + Il gateway di posta permette di comunicare con gli utenti email. Per ora, solo il gateway di posta Mailchuck (@mailchuck.com) è disponibile. + + + + Desired email address (including @mailchuck.com): + Indirizzo email desiderato (incluso @mailchuck.com): + + + + EmailGatewayRegistrationDialog + + + Registration failed: + Registrazione fallita: + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + L'email richiesto non è disponibile, si prega di provarne uno nuovo. Inserisci il nuovo indirizzo email desiderato (incluso @mailchuck.com) qui sotto: + + + + Email gateway registration + Registrazione gateway email + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + # È possibile utilizzare questo per configurare il tuo gateway account di posta elettronica +# Decommentare l'impostazione che si desidera utilizzare +# Ecco le opzioni: +# +# PGP: server +# Il gateway e-mail creerà e manterrà le chiavi PGP per voi e firmerà, verificherà, +# cifrarà e decifrerà a vostro nome. Quando si desidera usare PGP, ma siete pigri, +# utilizzate questo. Richiede abbonamento. +# +# PGP: locale # +Il gateway email non condurrà operazioni PGP a vostro nome. È possibile +# o non usare PGP affatto, o utilizzarlo in locale. +# +# Allegati: sì +# gli allegati in entrata nella e-mail verranno caricati su MEGA.nz, e si può +# scaricarli da qui seguendo il link. Richiede un abbonamento. +# +# Allegati: no +# gli allegati saranno ignorati. +# +# Archivio: sì +# i vostri messaggi di posta elettronica in arrivo verranno archiviati sul server. Utilizzare questo se avete bisogno di +# aiuto per problemi di debug o avete necessità di un controllo di terze parti. +# Questo però significa che l'operatore del servizio sarà in grado di leggere i vostri messaggi di posta elettronica +# anche dopo che sono stati consegnati a voi. +# +# Archivio: no +# i messaggi di posta elettronica in arrivo verranno eliminati dal server non appena vengono inoltrati a te. +# +# masterpubkey_btc: BIP44 xpub key oppure seme electrum v1 pubblico +# offset_btc: intero (il default è 0) +# feeamount: numero con un massimo di 8 cifre decimali +# feecurrency: BTC, XBT, USD, EUR o GBP +# utilizzare questi se si vuole far pagare le persone che inviano messaggi di posta elettronica. +# Se questo è attivato una persona sconosciuta che ti invia una e-mail, sarà tenuta a pagare una commissione specificata. +# Dato che questo schema utilizza chiavi pubbliche deterministiche, si riceverà la commissione direttamente. +# Per disattivarla, impostare "feeamount" a 0. +# Richiede un abbonamento. + + + + + MainWindow + + + Reply to sender + Rispondi al mittente + + + + Reply to channel + Rispondi sul canale + + + + Add sender to your Address Book + Aggiungi mittente alla rubrica + + + + Add sender to your Blacklist + Aggiungi mittente alla blacklist + + + + Move to Trash + Sposta nel cestino + + + + Undelete + Ripristina l'eliminato + + + + View HTML code as formatted text + Vedi codice HTML come testo formattato + + + + Save message as... + Salva messaggio con nome... + + + + Mark Unread + Segna come non letto + + + + New + Nuovo + + + + Enable + Abilita + + + + Disable + Disabilita + + + + Set avatar... + Inserisci l'avatar + + + + Copy address to clipboard + Copia indirizzo negli appunti + + + + Special address behavior... + Comportamento indirizzo speciale + + + + Email gateway + Gateway di posta + + + + Delete + Cancella + + + + Send message to this address + Manda un messaggio a questo indirizzo + + + + Subscribe to this address + Sottoscrivi questo indirizzo + + + + Add New Address + Aggiungi Nuovo Indirizzo + + + + Copy destination address to clipboard + Copia indirizzo di destinazione negli appunti + + + + Force send + Forza invio + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + Uno dei tuoi indirizzi, %1, è un indirizzo vecchio versione 1. Gli indirizzi versione 1 non sono più supportati. Posso eliminarlo ora? + + + + Waiting for their encryption key. Will request it again soon. + + + + + Encryption key request queued. + + + + + Queued. + + + + + Message sent. Waiting for acknowledgement. Sent at %1 + + + + + Message sent. Sent at %1 + + + + + Need to do work to send message. Work is queued. + + + + + Acknowledgement of the message received %1 + + + + + Broadcast queued. + + + + + Broadcast on %1 + + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + + + + + Forced difficulty override. Send should start soon. + + + + + Unknown status: %1 %2 + + + + + Not Connected + Non connesso + + + + Show Bitmessage + Mostra Bitmessage + + + + Send + Invia + + + + Subscribe + Sottoscrivi + + + + Channel + Canale + + + + Quit + Chiudi + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + + + + + Open keys.dat? + Aprire keys.dat? + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + Delete trash? + Svuotare il cestino? + + + + Are you sure you want to delete all trashed messages? + Sei sicuro di voler eliminare tutti i messaggi cestinati? + + + + bad passphrase + + + + + You must type your passphrase. If you don't have one then this is not the form for you. + + + + + Bad address version number + + + + + Your address version number must be a number: either 3 or 4. + + + + + Your address version number must be either 3 or 4. + + + + + Chan name needed + + + + + You didn't enter a chan name. + + + + + Address already present + + + + + Could not add chan because it appears to already be one of your identities. + + + + + Success + + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + + + + + Address too new + + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + + + + + Address invalid + Indirizzo non valido + + + + That Bitmessage address is not valid. + L'indirizzo Bitmessage non è valido. + + + + Address does not match chan name + + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + + + + + Successfully joined chan. + + + + + Connection lost + Connessione persa + + + + Connected + Connesso + + + + Message trashed + Messaggio cestinato + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + Messaggio troppo lungo + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + + + + + Error: The address %1 is not typed or copied correctly. Please check it. + + + + + Error: The address %1 contains invalid characters. Please check it. + + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + + + + + Address version number + + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Stream number + + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + + + + + Message queued. + + + + + Your 'To' field is empty. + + + + + Right click one or more entries in your address book and select 'Send message to this address'. + + + + + Fetched address from namecoin identity. + + + + + New Message + Nuovo Messaggio + + + + From + Da + + + + Sending email gateway registration request + + + + + Address is valid. + Indirizzo valido + + + + The address you entered was invalid. Ignoring it. + + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + Riavvia + + + + You must restart Bitmessage for the port number change to take effect. + + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + + + + + Number needed + Numero richiesto + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + + Will not resend ever + + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + + + + + The passphrase you entered twice doesn't match. Try again. + + + + + Choose a passphrase + + + + + You really do need a passphrase. + + + + + Address is gone + + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + + + + + Address disabled + Indirizzo disabilitato + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + + + + + Entry added to the Address Book. Edit the label to your liking. + + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + + + + + Undeleted item. + + + + + Save As... + Salva come... + + + + Write error. + Errore di scrittura. + + + + No addresses selected. + Nessun indirizzo selezionato. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + + + + + You have already set an avatar for this address. Do you really want to overwrite it? + + + + + Start-on-login not yet supported on your OS. + + + + + Minimize-to-tray not yet supported on your OS. + + + + + Tray notifications not yet supported on your OS. + + + + + Testing... + + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + + + + + The address should start with ''BM-'' + + + + + The address is not typed or copied correctly (the checksum failed). + + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + + + + + The address contains invalid characters. + + + + + Some data encoded in the address is too short. + + + + + Some data encoded in the address is too long. + + + + + Some data encoded in the address is malformed. + + + + + Enter an address above. + + + + + Address is an old type. We cannot display its past broadcasts. + + + + + There are no recent broadcasts from this address to display. + + + + + You are using TCP port %1. (This can be changed in the settings). + + + + + Bitmessage + Bitmessage + + + + Identities + Identità + + + + New Identity + Nuova identità + + + + Search + Cerca + + + + All + + + + + To + A + + + + From + Da + + + + Subject + Soggetto + + + + Message + Messaggio + + + + Received + Ricevuto + + + + Messages + Messaggi + + + + Address book + + + + + Address + Indirizzo + + + + Add Contact + Aggiungere Contatto + + + + Fetch Namecoin ID + + + + + Subject: + Soggetto: + + + + From: + Da: + + + + To: + A: + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + TTL: + + + + Subscriptions + + + + + Add new Subscription + + + + + Chans + + + + + Add Chan + + + + + File + File + + + + Settings + Impostazioni + + + + Help + + + + + Import keys + Importa chiavi + + + + Manage keys + Gestisci chiavi + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + + + + + About + + + + + Regenerate deterministic addresses + + + + + Delete all trashed messages + + + + + Join / Create chan + + + + + All accounts + Tutti gli account + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + Aggiungi una nuova voce + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + + + + + NewAddressDialog + + + Create new Address + Crea nuovo Indirizzo + + + + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + + + + + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + + + + + Use a random number generator to make an address + + + + + Use a passphrase to make addresses + + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + Make deterministic addresses + + + + + Address version number: 4 + + + + + In addition to your passphrase, you must remember these numbers: + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Stream number: 1 + + + + + Retype passphrase + + + + + Randomly generate address + + + + + Label (not shown to anyone except you) + + + + + Use the most available stream + + + + + (best if this is the first of many addresses you will create) + + + + + Use the same stream as an existing address + + + + + (saves you some bandwidth and processing power) + + + + + NewSubscriptionDialog + + + Add new entry + Aggiungi una nuova voce + + + + Label + Etichetta + + + + Address + Indirizzo + + + + Enter an address above. + + + + + SpecialAddressBehaviorDialog + + + Special Address Behavior + + + + + Behave as a normal address + + + + + Behave as a pseudo-mailing-list address + + + + + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + + + + + Name of the pseudo-mailing-list: + + + + + aboutDialog + + + About + + + + + PyBitmessage + PyBitmessage + + + + version ? + versione ? + + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + + + + + This is Beta software. + + + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + Aggiungi una nuova voce + + + + Name or Label + + + + + Address + Indirizzo + + + + Blacklist + + + + + Whitelist + + + + + connectDialog + + + Bitmessage + Bitmessage + + + + Bitmessage won't connect to anyone until you let it. + + + + + Connect now + + + + + Let me configure special network settings first + + + + + helpDialog + + + Help + + + + + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + + + + + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + + + + + iconGlossaryDialog + + + Icon Glossary + + + + + You have no connections with other peers. + Non sei connesso ad altri peer. + + + + 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'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. + + + + + You are using TCP port ?. (This can be changed in the settings). + + + + + You do have connections with other peers and your firewall is correctly configured. + + + + + networkstatus + + + Total connections: + Connessioni totali: + + + + Since startup: + Dall'avvio: + + + + Processed 0 person-to-person messages. + Processati 0 messaggi da persona a persona + + + + Processed 0 public keys. + Processate 0 chiavi pubbliche + + + + Processed 0 broadcasts. + Processati 0 broadcast + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + Oggetti da sincronizzare: + + + + Stream # + + + + + Connections + Connessioni + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + Connessioni totali: %1 + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + + + + + newChanDialog + + + Dialog + Dialogo + + + + Create a new chan + + + + + Join a chan + + + + + Create a chan + + + + + <html><head/><body><p>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.</p></body></html> + + + + + Chan name: + + + + + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + + + + + Chan bitmessage address: + + + + + regenerateAddressesDialog + + + Regenerate Existing Addresses + Rigenera Indirizzi Esistenti + + + + Regenerate existing addresses + Rigenera indirizzi esistenti + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Address version number: + + + + + Stream number: + + + + + 1 + 1 + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + + + + + 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. + + + + + settingsDialog + + + Settings + Impostazioni + + + + Start Bitmessage on user login + + + + + Tray + + + + + Start Bitmessage in the tray (don't show main window) + + + + + Minimize to tray + + + + + Close to tray + + + + + Show notification when message received + + + + + Run in Portable Mode + + + + + 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. + + + + + Willingly include unencrypted destination address when sending to a mobile device + + + + + Use Identicons + + + + + Reply below Quote + + + + + Interface Language + + + + + System Settings + system + + + + + User Interface + + + + + Listening port + + + + + Listen for connections on port: + + + + + UPnP: + UPnP: + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + + Proxy server / Tor + Server proxy / Tor + + + + Type: + + + + + Server hostname: + + + + + Port: + Porta: + + + + Authentication + + + + + Username: + Nome utente: + + + + Pass: + + + + + Listen for incoming connections when using proxy + + + + + none + + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Impostazioni di rete + + + + Total difficulty: + Difficoltà totale: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + + + + + Small message difficulty: + + + + + 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. + + + + + 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. + + + + + Demanded difficulty + Difficoltà richiesta + + + + 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. + + + + + Maximum acceptable total difficulty: + Massima difficoltà totale accettabile: + + + + Maximum acceptable small message difficulty: + + + + + Max acceptable difficulty + Massima difficoltà accettabile + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + + + + + Host: + Host: + + + + Password: + Password: + + + + Test + Test + + + + Connect to: + Connetti a: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Integrazione Namecoin + + + + <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> + + + + + Give up after + + + + + and + e + + + + days + giorni + + + + months. + mesi. + + + + Resends Expire + + + + \ No newline at end of file diff --git a/src/translations/bitmessage_ja.pro b/src/translations/bitmessage_ja.pro deleted file mode 100644 index f6e5ad63..00000000 --- a/src/translations/bitmessage_ja.pro +++ /dev/null @@ -1,33 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_outgoingSynSender.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_ja.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_ja.qm b/src/translations/bitmessage_ja.qm index 0d78d13d..d41e09a3 100644 Binary files a/src/translations/bitmessage_ja.qm and b/src/translations/bitmessage_ja.qm differ diff --git a/src/translations/bitmessage_ja.ts b/src/translations/bitmessage_ja.ts index da9edc69..daaa0f85 100644 --- a/src/translations/bitmessage_ja.ts +++ b/src/translations/bitmessage_ja.ts @@ -1,893 +1,1266 @@ - - - + - MainWindow + AddAddressDialog - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - %1は古いバージョン1のアドレスです。バージョン1のアドレスはサポートが終了しています。すぐに削除しますか? - - - - Reply - . - 返信 - - - - Add sender to your Address Book - 送信元をアドレス帳に追加 - - - - Move to Trash - ゴミ箱へ移動 - - - - View HTML code as formatted text - HTMLコードを整形したテキストで表示 - - - - Save message as... - 形式を選択してメッセージを保存 - - - - Mark Unread - 未読にする - - - - New - 新規 - - - - Enable - 有効 - - - - Disable - 無効 - - - - Copy address to clipboard - アドレスをコピー - - - - Special address behavior... - アドレスの特別な動作 - - - - Send message to this address - このアドレスへ送信 - - - - Subscribe to this address - このアドレスを購読 - - - - Add New Address - アドレスを追加 - - - - Delete - 削除 - - - - Copy destination address to clipboard - 宛先アドレスをコピー - - - - Force send - 強制的に送信 - - - + Add new entry 新しい項目を追加 - - Since startup on %1 - 起動日時 %1 + + Label + ラベル - - Waiting on their encryption key. Will request it again soon. - 暗号化キーを待っています。再度リクエストします。 + + Address + アドレス + + + + EmailGatewayDialog + + + Email gateway + - + + Register on email gateway + + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + + + MainWindow + + + Reply to sender + + + + + Reply to channel + + + + + Add sender to your Address Book + 送信元をアドレス帳に追加 + + + + Add sender to your Blacklist + + + + + Move to Trash + ゴミ箱へ移動 + + + + Undelete + + + + + View HTML code as formatted text + HTMLコードを整形したテキストで表示 + + + + Save message as... + 形式を選択してメッセージを保存 + + + + Mark Unread + 未読にする + + + + New + 新規 + + + + Enable + 有効 + + + + Disable + 無効 + + + + Set avatar... + + + + + Copy address to clipboard + アドレスをコピー + + + + Special address behavior... + アドレスの特別な動作 + + + + Email gateway + + + + + Delete + 削除 + + + + Send message to this address + このアドレスへ送信 + + + + Subscribe to this address + このアドレスを購読 + + + + Add New Address + アドレスを追加 + + + + Copy destination address to clipboard + 宛先アドレスをコピー + + + + Force send + 強制的に送信 + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + %1は古いバージョン1のアドレスです。バージョン1のアドレスはサポートが終了しています。すぐに削除しますか? + + + + Waiting for their encryption key. Will request it again soon. + + + + Encryption key request queued. 暗号鍵のリクエストはキューに入りました。 - + Queued. キューに入りました。 - - Message sent. Waiting on acknowledgement. Sent at %1 - メッセージは送信されました。確認街です。送信先: %1 + + Message sent. Waiting for acknowledgement. Sent at %1 + - + Message sent. Sent at %1 メッセージは送信されました。送信先: %1 - + Need to do work to send message. Work is queued. 送信のために処理を行う必要があります。処理はキューに入りました。 - + Acknowledgement of the message received %1 メッセージの確認を受け取りました %1 - + Broadcast queued. Broadcastがキューに入りました。 - + Broadcast on %1 Broadcast: %1 - + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 問題: 受信者が要求している処理は現在あなたが設定しているよりも高い難易度です。 %1 - + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 問題: 受信者の暗号鍵は正当でない物です。メッセージを暗号化できません。 %1 - + Forced difficulty override. Send should start soon. 難易度を強制上書きしました。まもなく送信されます。 - + Unknown status: %1 %2 不明なステータス: %1 %2 - + Not Connected 未接続 - + Show Bitmessage Bitmessageを表示 - + Send 送る - + Subscribe 購読 - - Address Book - アドレス帳 + + Channel + - + Quit 終了 - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. プログラムを同じディレクトリに保存されているkeys.datファイルを編集することで鍵を管理できます。ファイルをバックアップしておくことも重要です。 - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. %1に保存されているkeys.datファイルを編集することで鍵を管理できます。ファイルをバックアップしておくことも重要です。 - + Open keys.dat? keys.datを開きますか? - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) プログラムを同じディレクトリに保存されているkeys.datファイルを編集することで鍵を管理できます。ファイルをバックアップしておくことも重要です。すぐにファイルを開きますか?(必ず編集する前にBitmessageを終了してください) - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) %1に保存されているkeys.datファイルを編集することで鍵を管理できます。ファイルをバックアップしておくことも重要です。すぐにファイルを開きますか?(必ず編集する前にBitmessageを終了してください) - + Delete trash? ゴミ箱を空にしますか? - + Are you sure you want to delete all trashed messages? ゴミ箱内のメッセージを全て削除してもよろしいですか? - + bad passphrase 不正なパスフレーズ - + You must type your passphrase. If you don't have one then this is not the form for you. パスフレーズを入力してください。パスフレーズがない場合は入力する必要はありません。 - + + Bad address version number + + + + + Your address version number must be a number: either 3 or 4. + + + + + Your address version number must be either 3 or 4. + + + + Chan name needed Chan名が必要です - + You didn't enter a chan name. chan名が入力されていません。 - + Address already present アドレスは既に表示されています - + Could not add chan because it appears to already be one of your identities. chanを追加できません。既にアドレス一覧に含まれています。 - + Success 成功 - + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. chanの作成に成功しました。他の人がchanに参加できるようにするには、chanの名前とBitmessageアドレスを伝えてください: %1 アドレスは「アドレス一覧」に表示されます。 - + Address too new アドレスが新しすぎます - + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. このBitmessageアドレスは正当ですが、バージョン番号が現在使用中の物より新しいです。Bitmessageをアップデートしてください。 - + Address invalid アドレスが不正です - + That Bitmessage address is not valid. このBitmessageアドレスは不正です。 - + Address does not match chan name アドレスがchan名と一致しません - + Although the Bitmessage address you entered was valid, it doesn't match the chan name. このBitmessageアドレスは正当ですが、chan名と一致していません。 - + Successfully joined chan. chanに参加しました。 - - Processed %1 person-to-person messages. - %1 通の1対1のメッセージを処理しました。 - - - - Processed %1 broadcast messages. - %1 件のBroadcastメッセージを処理しました。 - - - - Processed %1 public keys. - %1 件の公開鍵を処理しました。 - - - - Total Connections: %1 - 接続数: %1 - - - + Connection lost 接続が切断されました - + Connected 接続済み - + Message trashed メッセージが削除されました - + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + Error: Bitmessage addresses start with BM- Please check %1 エラー: Bitmessageアドレスは「BM-」で始まります。確認してください %1 - + Error: The address %1 is not typed or copied correctly. Please check it. エラー: アドレス %1 は正しく入力、またはコピーされていません。確認して下さい。 - + Error: The address %1 contains invalid characters. Please check it. エラー: アドレス %1 は不正な文字を含んでいます。確認して下さい。 - + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. エラー: アドレスのバージョン %1 は現在使用中の物より新しいです。Bitmessageをアップデートする必要があるか、連絡先がより賢いです。 - + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. エラー: アドレス %1 でエンコードされたデータが短すぎます。連絡先のソフトウェアが何かしら誤っている可能性があります。 - + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. エラー: アドレス %1 でエンコードされたデータが長すぎます。連絡先のソフトウェアが何かしら誤っている可能性があります。 - + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + Error: Something is wrong with the address %1. エラー: アドレス %1 には何かしら誤りがあります。 - + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. エラー: 送信元アドレスを指定してください。まだ作成していない場合には「アドレス一覧」のタブを開いてください。 - - Sending to your address - アドレスへ送信中 - - - - Error: One of the addresses to which you are sending a message, %1, is yours. Unfortunately the Bitmessage client cannot process its own messages. Please try running a second client on a different computer or within a VM. - エラー: 送信先アドレス %1 は自分自身のアドレスです。Bitmessageクライアントは自分自身へのメッセージを処理できません。別のPCか仮想マシン上でクライアントを立ち上げてください。 - - - + Address version number アドレスのバージョン番号 - + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. アドレス %1 に接続。%2 のバージョン番号は処理できません。Bitmessageを最新のバージョンへアップデートしてください。 - + Stream number ストリーム番号 - + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. アドレス %1 に接続。%2 のストリーム番号は処理できません。Bitmessageを最新のバージョンへアップデートしてください。 - + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. 警告: 接続されていません。Bitmessageはメッセージの処理を行いますが、ネットワークに接続するまで送信はされません。 - + + Message queued. + + + + Your 'To' field is empty. 宛先が指定されていません。 - - Work is queued. - 処理がキューに入りました。 - - - + Right click one or more entries in your address book and select 'Send message to this address'. アドレス帳から一つ、または複数のアドレスを右クリックして「このアドレスへ送信」を選んでください。 - + Fetched address from namecoin identity. namecoin IDからアドレスを取得。 - - Work is queued. %1 - 処理がキューに入りました。 %1 - - - + New Message 新規メッセージ - + From 送信元 - + + Sending email gateway registration request + + + + Address is valid. アドレスが不正です。 - + The address you entered was invalid. Ignoring it. 入力されたアドレスは不正です。無視されました。 - + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. エラー: 同じアドレスを複数アドレス帳に追加する事はできません。既存の項目をリネームしてください。 - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - エラー: 同じアドレスを複数購読リストに追加する事はできません。既存の項目をリネームしてください。 + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + - + Restart 再開 - + You must restart Bitmessage for the port number change to take effect. ポート番号の変更を有効にするにはBitmessageを再起動してください。 - + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). プロキシの設定を有効にするには手動でBitmessageを再起動してください。既に接続がある場合は切断されます。 - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - エラー: 同じアドレスを複数リストに追加する事はできません。既存の項目をリネームしてください。 + + Number needed + - + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + + Will not resend ever + + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + Passphrase mismatch パスフレーズが一致しません - + The passphrase you entered twice doesn't match. Try again. 再度入力されたパスフレーズが一致しません。再入力してください。 - + Choose a passphrase パスフレーズを選択してください - + You really do need a passphrase. パスフレーズが必要です。 - - All done. Closing user interface... - 完了しました。ユーザーインターフェースを閉じています。 - - - + Address is gone アドレスが無効になりました - + Bitmessage cannot find your address %1. Perhaps you removed it? アドレス %1 が見つかりません。既に削除していませんか? - + Address disabled アドレスが無効になりました - + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. エラー: 送信しようとしたアドレスは無効になっています。使用する前に「アドレス一覧」で有効にしてください。 - + Entry added to the Address Book. Edit the label to your liking. アドレス帳に項目が追加されました。ラベルは自由に編集できます。 - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - アイテムをゴミ箱へ移動。ゴミ箱の内容を表示する画面はありませんが、もし元に戻したくなった場合に備えてディスク上に残されます。 + + Entry added to the blacklist. Edit the label to your liking. + - + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + アイテムをゴミ箱へ移動。 + + + + Undeleted item. + + + + Save As... 形式を選択して保存 - + Write error. 書き込みエラー。 - + No addresses selected. アドレスが未選択です。 - - Options have been disabled because they either aren't applicable or because they haven't yet been implemented for your operating system. - 現在のOS上で未実装、または実装できないためオプションは無効化されました。 + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + - + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + + + + + You have already set an avatar for this address. Do you really want to overwrite it? + + + + + Start-on-login not yet supported on your OS. + + + + + Minimize-to-tray not yet supported on your OS. + + + + + Tray notifications not yet supported on your OS. + + + + Testing... テスト中 - + This is a chan address. You cannot use it as a pseudo-mailing list. chanアドレスは仮想メーリングリストのアドレスには使用できません。 - + The address should start with ''BM-'' アドレスは「BM-」から始まります - + The address is not typed or copied correctly (the checksum failed). このアドレスは正しく入力、またはコピーされていません。(チェックサムが一致しません)。 - + The version number of this address is higher than this software can support. Please upgrade Bitmessage. このアドレスのバージョン番号はこのプログラムのサポート範囲外です。Bitmessageをアップデートしてください。 - + The address contains invalid characters. 入力されたアドレスは不正な文字を含んでいます。 - + Some data encoded in the address is too short. このアドレスでエンコードされたデータが短すぎます。 - + Some data encoded in the address is too long. このアドレスでエンコードされたデータが長過ぎます。 - + + Some data encoded in the address is malformed. + + + + + Enter an address above. + + + + + Address is an old type. We cannot display its past broadcasts. + + + + + There are no recent broadcasts from this address to display. + + + + You are using TCP port %1. (This can be changed in the settings). 使用中のポート %1 (設定で変更できます)。 - + Bitmessage - + - + + Identities + + + + + New Identity + + + + Search 検索 - + All 全て - + To 宛先 - + From 送信元 - + Subject 題名 - + Message メッセージ - + Received 受信日時 - - Inbox - 受信箱 + + Messages + - - Load from Address book - アドレス帳から読み込み + + Address book + - - Fetch Namecoin ID - namecoin IDを取得 - - - - Message: - メッセージ: - - - - Subject: - 題名: - - - - Send to one or more specific people - 一人、または複数のユーザーへ送信 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - - To: - 宛先: - - - - From: - 送信元: - - - - Broadcast to everyone who is subscribed to your address - 自分のアドレスを購読しているユーザー全員へ配信する - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - broadcastはあなたのアドレスのみで暗号化されます。あなたのアドレスを知っている人は全て読むことができます。 - - - - Status - 状態 - - - - Sent - 送信済み - - - - Label (not shown to anyone) - ラベル(他の人からは見えません) - - - + Address アドレス - - Stream - ストリーム + + Add Contact + - - Your Identities - アドレス一覧 + + Fetch Namecoin ID + namecoin IDを取得 - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - 他のユーザが送信した「broadcastメッセージ」を購読できます。メッセージは受信箱に表示されます。このリストのアドレスはブラックリストより優先されます。 + + Subject: + 題名: - - Add new Subscription - 購読先を追加 + + From: + 送信元: - - Label - ラベル + + To: + 宛先: - + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + Subscriptions 購読リスト - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - アドレス帳は他のユーザのBitmessageアドレスにラベルや名前をつけることで受信箱を見やすくします。「追加」ボタンを押すか受信箱でメッセージを右クリックしてください。 + + Add new Subscription + 購読先を追加 - - Name or Label - 名前、ラベル + + Chans + - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - ブラックリストを使用(全てのメッセージを受信してブラックリストと一致する物だけ除外) + + Add Chan + - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - ホワイトリストを使用(全てのメッセージを受信拒否してホワイトリストと一致する物だけ許可) - - - - Blacklist - ブラックリスト - - - - Stream # - ストリーム # - - - - Connections - 接続 - - - - Total connections: 0 - 接続数: 0 - - - - Since startup at asdf: - 起動してから asdf: - - - - Processed 0 person-to-person message. - 0 通の1対1のメッセージを処理しました。 - - - - Processed 0 public key. - 0 件の公開鍵を処理しました。 - - - - Processed 0 broadcast. - 0 件のBroadcastメッセージを処理しました。 - - - - Network Status - ネットワークの状態 - - - + File ファイル - + Settings 設定 - + Help ヘルプ - + Import keys 鍵をインポート - + Manage keys 鍵を管理 - + Ctrl+Q Ctrrl+Q - + F1 - + - + + Contact support + + + + About 概要 - + Regenerate deterministic addresses - 「決定論的アドレス」ともヤクセルが deterministicアドレスを再生成 - + Delete all trashed messages ゴミ箱のメッセージを全て削除する - + Join / Create chan chanに参加 / 作成 + + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + + NewAddressDialog @@ -913,9 +1286,9 @@ The 'Random Number' option is selected by default but deterministic ad アドレスの生成に乱数ジェネレーターを使う - - Use a passpharase to make addresses - Use yee passpharase to make arrddresses + + Use a passphrase to make addresses + アドレスの作成にパスフレーズを使う @@ -929,8 +1302,8 @@ The 'Random Number' option is selected by default but deterministic ad - Address version number: 3 - アドレスのバージョン番号: 3 + Address version number: 4 + @@ -987,29 +1360,29 @@ The 'Random Number' option is selected by default but deterministic ad (saves you some bandwidth and processing power) (帯域と処理能力を節約する) - - - Use a passphrase to make addresses - アドレスの作成にパスフレーズを使う - NewSubscriptionDialog - + Add new entry 新しい項目を追加 - + Label ラベル - + Address アドレス + + + Enter an address above. + + SpecialAddressBehaviorDialog @@ -1042,42 +1415,80 @@ The 'Random Number' option is selected by default but deterministic ad aboutDialog - - PyBitmessage - - - - - version ? - Version ? - - - + About 概要 - - Copyright © 2013 Jonathan Warren - + + PyBitmessage + - + + version ? + Version ? + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> - + - + This is Beta software. このソフトウェアはベータ版です。 + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + + connectDialog Bitmessage - + @@ -1104,8 +1515,8 @@ The 'Random Number' option is selected by default but deterministic ad - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + @@ -1126,9 +1537,9 @@ The 'Random Number' option is selected by default but deterministic ad 他のpeerへ接続されていません。 - - 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't configured to foward 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. - Yee have made least one connection to a peer pirate usin' outgoing connection but yee not yet received any incoming connections. Yee firewall, witches nest, or home router probably shant configured to foward incoming TCP connections to yee computer. Bitmessage be workin' just fine but it help fellow pirates if yee allowed for incoming connections and will help yee be a better-connected node matey. + + 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'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. + 発信接続のために1つ以上のピアへ接続を行っていますが、まだ着信接続を受け取っていません。ファイアーウォールかホームルーターが外部からこのコンピューターへのTCP接続を受け取れるように設定されていないかも知れません。Bitmessageは正常に動作しますが、外部からの接続を許可してより良く接続されたノードになることはBitmessageネットワークへの助けになります。 @@ -1140,10 +1551,118 @@ The 'Random Number' option is selected by default but deterministic ad You do have connections with other peers and your firewall is correctly configured. ファイアーウォールを適切に設定し、他のpeerへ接続してください。 + + + networkstatus - - 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'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. - 発信接続のために1つ以上のピアへ接続を行っていますが、まだ着信接続を受け取っていません。ファイアーウォールかホームルーターが外部からこのコンピューターへのTCP接続を受け取れるように設定されていないかも知れません。Bitmessageは正常に動作しますが、外部からの接続を許可してより良く接続されたノードになることはBitmessageネットワークへの助けになります。 + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + @@ -1192,57 +1711,52 @@ The 'Random Number' option is selected by default but deterministic ad regenerateAddressesDialog - + Regenerate Existing Addresses 既存のアドレスを再生成する - + Regenerate existing addresses 既存のアドレスを再生成する - + Passphrase パスフレーズ - + Number of addresses to make based on your passphrase: パスフレーズから生成されたアドレスの数: - - Address version Number: - アドレスのバージョン番号: + + Address version number: + - - 3 - - - - + Stream number: ストリーム数: - + 1 - + - + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter アドレスを1、2文字短くするために数分間追加の計算処理を行う - + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. もしあなたが初めてアドレスを作ったのであればこのボックスをチェックする必要があります。(そうでない場合はしないでください)。 - + 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. もし以前にdeterministicアドレスを作ったことがあり、何かしらのトラブル(ハードディスクの故障のような)でそれを紛失していた場合、ここで再生成することができます。もし乱数でアドレスを作っていたのであればこのフォームは再生成には使えません。 @@ -1250,214 +1764,295 @@ The 'Random Number' option is selected by default but deterministic ad settingsDialog - + Settings 設定 - + Start Bitmessage on user login ユーザのログイン時にBitmessageを起動 - + + Tray + + + + Start Bitmessage in the tray (don't show main window) Bitmessageをトレイ内で起動する(メインウィンドウを表示しない) - + Minimize to tray タスクトレイへ最小化 - + + Close to tray + + + + Show notification when message received メッセージの受信時に通知する - + Run in Portable Mode ポータブルモードで実行 - + 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. ポータブルモード時、メッセージと設定ファイルは通常のアプリケーションデータのフォルダではなく同じディレクトリに保存されます。これによりBitmessageをUSBドライブから実行できます。 - - User Interface - ユーザインターフェース - - - - Listening port - リスニングポート - - - - Listen for connections on port: - 接続を待つポート: - - - - Proxy server / Tor - プロキシサーバー/Tor - - - - Type: - タイプ: - - - - none - 無し - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - - Server hostname: - サーバーホスト名: - - - - Port: - ポート: - - - - Authentication - 認証 - - - - Username: - ユーザー名: - - - - Pass: - パス: - - - - Network Settings - ネットワーク設定 - - - - 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. - 誰かがあなたにメッセージを送る時、相手のコンピューターはいくらか計算処理を行います。処理の難易度はデフォルトでは1です。この値を変更すると新しいアドレスではこのデフォルト値を引き上げることができます。その場合、新しいアドレスはメッセージの送信者により高い難易度を要求します。例外もあります: 友人や知り合いをアドレス帳に登録すると、Bitmessageは次にメッセージを送る際、自動的に要求される処理の難易度を最低限の1で済むように通知します。 - - - - Total difficulty: - 全体の難易度: - - - - Small message difficulty: - 小さいメッセージの難易度: - - - - 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. - 「小さいメッセージの難易度」は小さいメッセージを行う時にだけ影響します。この値を二倍にすれば小さなメッセージに必要な処理の難易度は二倍になりますが、実際にはデータ量の多いメッセージには影響しません。 - - - - The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - 「全体の難易度」は完全に全てのメッセージに影響します。この値を二倍にすると処理量も二倍になります。 - - - - Demanded difficulty - 要求される難易度 - - - + Willingly include unencrypted destination address when sending to a mobile device 携帯端末にメッセージを送る時は暗号化されていないアドレスを許可する - - Override automatic language localization (use countycode or language code, e.g. 'en_US' or 'en'): - 自動的に設定された言語・地域を上書きする(国コード、または言語コードを入力。例:「en_US」または「en」): + + Use Identicons + - + + Reply below Quote + + + + + Interface Language + + + + + System Settings + system + + + + + User Interface + ユーザインターフェース + + + + Listening port + リスニングポート + + + + Listen for connections on port: + 接続を待つポート: + + + + UPnP: + + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + + Proxy server / Tor + プロキシサーバー/Tor + + + + Type: + タイプ: + + + + Server hostname: + サーバーホスト名: + + + + Port: + ポート: + + + + Authentication + 認証 + + + + Username: + ユーザー名: + + + + Pass: + パス: + + + Listen for incoming connections when using proxy プロキシ使用時に外部からの接続を待機する - + + none + 無し + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + ネットワーク設定 + + + + Total difficulty: + 全体の難易度: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + 「全体の難易度」は完全に全てのメッセージに影響します。この値を二倍にすると処理量も二倍になります。 + + + + Small message difficulty: + 小さいメッセージの難易度: + + + + 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. + 誰かがあなたにメッセージを送る時、相手のコンピューターはいくらか計算処理を行います。処理の難易度はデフォルトでは1です。この値を変更すると新しいアドレスではこのデフォルト値を引き上げることができます。その場合、新しいアドレスはメッセージの送信者により高い難易度を要求します。例外もあります: 友人や知り合いをアドレス帳に登録すると、Bitmessageは次にメッセージを送る際、自動的に要求される処理の難易度を最低限の1で済むように通知します。 + + + + 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. + 「小さいメッセージの難易度」は小さいメッセージを行う時にだけ影響します。この値を二倍にすれば小さなメッセージに必要な処理の難易度は二倍になりますが、実際にはデータ量の多いメッセージには影響しません。 + + + + Demanded difficulty + 要求される難易度 + + + 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. ここでは他のユーザーへメッセージを送る際に行うことを許可する処理量の上限を設定します。0を設定するとどんな量でも許容します。 - + Maximum acceptable total difficulty: 許可する難易度の上限: - + Maximum acceptable small message difficulty: 小さなメッセージに許可する難易度の上限: - + Max acceptable difficulty 許可する最大の難易度 - + + Hardware GPU acceleration (OpenCL) + + + + <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> <html><head/><body><p>Bitmessageはアドレスを読みやすくするため、NamecoinというBitcoinベースの別のプログラムを利用できます。例えば、あなたの友人に長いBitmessageアドレスを伝える代わりに、単純に<span style=" font-style:italic;">テスト</span>でメッセージを送るよう伝えることができます。</p><p>(Bitmessageアドレスを独自にNamecoinにするのはかなり難しいです)。</p><p>Bitmessageは直接namecoindを使うか、nmcontrolインスタンスを使うことができます。</p></body></html> - + Host: ホスト: - + Password: パスワード: - + Test テスト - + Connect to: 接続先: - + Namecoind Namecoind - + NMControl NMControl - + Namecoin integration Namecoin連携 + + + <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> + + + + + Give up after + + + + + and + + + + + days + + + + + months. + + + + + Resends Expire + + - + \ No newline at end of file diff --git a/src/translations/bitmessage_nb.ts b/src/translations/bitmessage_nb.ts new file mode 100644 index 00000000..21f641c0 --- /dev/null +++ b/src/translations/bitmessage_nb.ts @@ -0,0 +1,1898 @@ + + + AddAddressDialog + + + Add new entry + + + + + Label + + + + + Address + + + + + EmailGatewayDialog + + + Email gateway + + + + + Register on email gateway + + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + + + MainWindow + + + Reply to sender + + + + + Reply to channel + + + + + Add sender to your Address Book + + + + + Add sender to your Blacklist + + + + + Move to Trash + + + + + Undelete + + + + + View HTML code as formatted text + + + + + Save message as... + + + + + Mark Unread + + + + + New + + + + + Enable + + + + + Disable + + + + + Set avatar... + + + + + Copy address to clipboard + + + + + Special address behavior... + + + + + Email gateway + + + + + Delete + + + + + Send message to this address + + + + + Subscribe to this address + + + + + Add New Address + + + + + Copy destination address to clipboard + + + + + Force send + + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + + + + + 1 hour + + + + + %1 hours + + + + + %1 days + + + + + Waiting for their encryption key. Will request it again soon. + + + + + Encryption key request queued. + + + + + Queued. + + + + + Message sent. Waiting for acknowledgement. Sent at %1 + + + + + Message sent. Sent at %1 + + + + + Need to do work to send message. Work is queued. + + + + + Acknowledgement of the message received %1 + + + + + Broadcast queued. + + + + + Broadcast on %1 + + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + + + + + Forced difficulty override. Send should start soon. + + + + + Unknown status: %1 %2 + + + + + Not Connected + + + + + Show Bitmessage + + + + + Send + + + + + Subscribe + + + + + Channel + + + + + Quit + + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + + + + + Open keys.dat? + + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + Delete trash? + + + + + Are you sure you want to delete all trashed messages? + + + + + bad passphrase + + + + + You must type your passphrase. If you don't have one then this is not the form for you. + + + + + Bad address version number + + + + + Your address version number must be a number: either 3 or 4. + + + + + Your address version number must be either 3 or 4. + + + + + Chan name needed + + + + + You didn't enter a chan name. + + + + + Address already present + + + + + Could not add chan because it appears to already be one of your identities. + + + + + Success + + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + + + + + Address too new + + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + + + + + Address invalid + + + + + That Bitmessage address is not valid. + + + + + Address does not match chan name + + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + + + + + Successfully joined chan. + + + + + Connection lost + + + + + Connected + + + + + Message trashed + + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + + + + + Error: The address %1 is not typed or copied correctly. Please check it. + + + + + Error: The address %1 contains invalid characters. Please check it. + + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + + + + + Address version number + + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Stream number + + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + + + + + Message queued. + + + + + Your 'To' field is empty. + + + + + Right click one or more entries in your address book and select 'Send message to this address'. + + + + + Fetched address from namecoin identity. + + + + + New Message + + + + + From + + + + + Sending email gateway registration request + + + + + Address is valid. + + + + + The address you entered was invalid. Ignoring it. + + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + + + + + You must restart Bitmessage for the port number change to take effect. + + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + + + + + Number needed + + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + + Will not resend ever + + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + + + + + The passphrase you entered twice doesn't match. Try again. + + + + + Choose a passphrase + + + + + You really do need a passphrase. + + + + + All done. Closing user interface... + + + + + Address is gone + + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + + + + + Address disabled + + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + + + + + Entry added to the Address Book. Edit the label to your liking. + + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + + + + + Undeleted item. + + + + + Save As... + + + + + Write error. + + + + + No addresses selected. + + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + + + + + You have already set an avatar for this address. Do you really want to overwrite it? + + + + + Start-on-login not yet supported on your OS. + + + + + Minimize-to-tray not yet supported on your OS. + + + + + Tray notifications not yet supported on your OS. + + + + + Testing... + + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + + + + + The address should start with ''BM-'' + + + + + The address is not typed or copied correctly (the checksum failed). + + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + + + + + The address contains invalid characters. + + + + + Some data encoded in the address is too short. + + + + + Some data encoded in the address is too long. + + + + + Some data encoded in the address is malformed. + + + + + Enter an address above. + + + + + Address is an old type. We cannot display its past broadcasts. + + + + + There are no recent broadcasts from this address to display. + + + + + You are using TCP port %1. (This can be changed in the settings). + + + + + Bitmessage + + + + + Identities + + + + + New Identity + + + + + Search + + + + + All + + + + + To + + + + + From + + + + + Subject + + + + + Message + + + + + Received + + + + + Messages + + + + + Address book + + + + + Address + + + + + Add Contact + + + + + Fetch Namecoin ID + + + + + Subject: + + + + + From: + + + + + To: + + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + X days + + + + + Subscriptions + + + + + Add new Subscription + + + + + Chans + + + + + Add Chan + + + + + Network Status + + + + + File + + + + + Settings + + + + + Help + + + + + Import keys + + + + + Manage keys + + + + + Ctrl+Q + + + + + F1 + + + + + Contact support + + + + + About + + + + + Regenerate deterministic addresses + + + + + Delete all trashed messages + + + + + Join / Create chan + + + + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + NewAddressDialog + + + Create new Address + + + + + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + + + + + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + + + + + Use a random number generator to make an address + + + + + Use a passphrase to make addresses + + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + Make deterministic addresses + + + + + Address version number: 4 + + + + + In addition to your passphrase, you must remember these numbers: + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Stream number: 1 + + + + + Retype passphrase + + + + + Randomly generate address + + + + + Label (not shown to anyone except you) + + + + + Use the most available stream + + + + + (best if this is the first of many addresses you will create) + + + + + Use the same stream as an existing address + + + + + (saves you some bandwidth and processing power) + + + + + NewSubscriptionDialog + + + Add new entry + + + + + Label + + + + + Address + + + + + Enter an address above. + + + + + SpecialAddressBehaviorDialog + + + Special Address Behavior + + + + + Behave as a normal address + + + + + Behave as a pseudo-mailing-list address + + + + + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + + + + + Name of the pseudo-mailing-list: + + + + + aboutDialog + + + About + + + + + PyBitmessage + + + + + version ? + + + + + <html><head/><body><p>Copyright © 2012-2014 Jonathan Warren<br/>Copyright © 2013-2014 The Bitmessage Developers</p></body></html> + + + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + + + + + This is Beta software. + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + + + + + connectDialog + + + Bitmessage + + + + + Bitmessage won't connect to anyone until you let it. + + + + + Connect now + + + + + Let me configure special network settings first + + + + + helpDialog + + + Help + + + + + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + + + + + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + + + + + iconGlossaryDialog + + + Icon Glossary + + + + + You have no connections with other peers. + + + + + 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'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. + + + + + You are using TCP port ?. (This can be changed in the settings). + + + + + You do have connections with other peers and your firewall is correctly configured. + + + + + networkstatus + + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Down: 0 KB/s + + + + + Up: 0 KB/s + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Objects to be synced: %1 + + + + + Processed %1 person-to-person messages. + + + + + Processed %1 broadcast messages. + + + + + Processed %1 public keys. + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + newChanDialog + + + Dialog + + + + + Create a new chan + + + + + Join a chan + + + + + Create a chan + + + + + <html><head/><body><p>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.</p></body></html> + + + + + Chan name: + + + + + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + + + + + Chan bitmessage address: + + + + + regenerateAddressesDialog + + + Regenerate Existing Addresses + + + + + Regenerate existing addresses + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Address version number: + + + + + Stream number: + + + + + 1 + + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + + + + + 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. + + + + + settingsDialog + + + Settings + + + + + Start Bitmessage on user login + + + + + Tray + + + + + Start Bitmessage in the tray (don't show main window) + + + + + Minimize to tray + + + + + Close to tray + + + + + Show notification when message received + + + + + Run in Portable Mode + + + + + 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. + + + + + Willingly include unencrypted destination address when sending to a mobile device + + + + + Use Identicons + + + + + Reply below Quote + + + + + Interface Language + + + + + System Settings + system + + + + + Pirate English + en_pirate + + + + + Other (set in keys.dat) + other + + + + + User Interface + + + + + Listening port + + + + + Listen for connections on port: + + + + + UPnP: + + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + + Proxy server / Tor + + + + + Type: + + + + + Server hostname: + + + + + Port: + + + + + Authentication + + + + + Username: + + + + + Pass: + + + + + Listen for incoming connections when using proxy + + + + + none + + + + + SOCKS4a + + + + + SOCKS5 + + + + + Network Settings + + + + + Total difficulty: + + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + + + + + Small message difficulty: + + + + + 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. + + + + + 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. + + + + + Demanded difficulty + + + + + 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. + + + + + Maximum acceptable total difficulty: + + + + + Maximum acceptable small message difficulty: + + + + + Max acceptable difficulty + + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + + + + + Host: + + + + + Password: + + + + + Test + + + + + Connect to: + + + + + Namecoind + + + + + NMControl + + + + + Namecoin integration + + + + + <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> + + + + + Give up after + + + + + and + + + + + days + + + + + months. + + + + + Resends Expire + + + + \ No newline at end of file diff --git a/src/translations/bitmessage_nl.pro b/src/translations/bitmessage_nl.pro deleted file mode 100644 index 950eefba..00000000 --- a/src/translations/bitmessage_nl.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_outgoingSynSender.py\ - ../class_objectProcessor.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_nl.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_nl.qm b/src/translations/bitmessage_nl.qm index aefebc30..3c146e12 100644 Binary files a/src/translations/bitmessage_nl.qm and b/src/translations/bitmessage_nl.qm differ diff --git a/src/translations/bitmessage_nl.ts b/src/translations/bitmessage_nl.ts index 54237fdd..5b870b0f 100644 --- a/src/translations/bitmessage_nl.ts +++ b/src/translations/bitmessage_nl.ts @@ -1,12 +1,10 @@ - - - + AddAddressDialog Add new entry - + Nieuw adres toevoegen @@ -19,960 +17,1250 @@ Adres + + EmailGatewayDialog + + + Email gateway + + + + + Register on email gateway + + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + Een e-mail gateway maakt het mogelijk te communiceren met e-mail gebruikers. Momenteel is enkel de Mailchuck e-mail gateway (@mailchuck.com) beschikbaar. + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + Registratie mislukt + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + Het opgegeven e-mail adres is niet beschikbaar, probeer een ander adres. Vul hieronder het nieuwe adres (inclusief @mailchuck.com) in: + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + Een e-mail gateway maakt het mogelijk te communiceren met e-mail gebruikers. Momenteel is enkel de Mailchuck e-mail gateway (@mailchuck.com) beschikbaar. +Voer het gewenste e-mail adres (inclusief @mailchuck.com) hieronder in: + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + MainWindow - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - + + Reply to sender + Afzender beantwoordenjavascript:; - - Reply - Reageer + + Reply to channel + - + Add sender to your Address Book - + Afzender aan uw adresboek toevoegen - + + Add sender to your Blacklist + Afzender blokkeren + + + Move to Trash Verplaats naar Prullenbak - + + Undelete + + + + View HTML code as formatted text Bekijk HTML als geformatteerde tekst - + Save message as... Bewaar bericht als - + Mark Unread Markeer Ongelezen - + New Nieuw - + Enable Inschakelen - + Disable Uitschakelen - + + Set avatar... + Avatar instellen + + + Copy address to clipboard Kopieer adres naar klembord - + Special address behavior... - + - - Send message to this address - Stuur bericht naar dit adres + + Email gateway + E-mail gateway - - Subscribe to this address - - - - - Add New Address - Nieuw adres toevoegen - - - + Delete Verwijder - + + Send message to this address + Stuur bericht naar dit adres + + + + Subscribe to this address + Abonneren op dit adres + + + + Add New Address + Nieuw adres toevoegen + + + Copy destination address to clipboard Kopieer bestemmingsadres naar klembord - + Force send Forceer zenden - - Add new entry - + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + - - Since startup on %1 - - - - + Waiting for their encryption key. Will request it again soon. - + Aan het wachten up hun encryptie sleutel. Zal binnenkort opnieuw proberen. - + Encryption key request queued. - + Encryptie sleutel aanvraag toegevoegd aan de wachtrij - + Queued. In wachtrij. - + Message sent. Waiting for acknowledgement. Sent at %1 Bericht verzonden. Wachten op bevestiging. Verzonden op %1 - + Message sent. Sent at %1 Bericht verzonden. Verzonden op %1 - + Need to do work to send message. Work is queued. - + - + Acknowledgement of the message received %1 Bevestiging van het bericht ontvangen op %1 - + Broadcast queued. - + - + Broadcast on %1 - + - + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 - + - + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 - + - + Forced difficulty override. Send should start soon. - + - + Unknown status: %1 %2 Status onbekend: %1 %2 - + Not Connected Niet Verbonden - + Show Bitmessage Toon Bitmessage - + Send Verzend - + Subscribe Abonneer - - Address Book - Adresboek + + Channel + - + Quit Sluiten - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. - + - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. - + - + Open keys.dat? keys.dat openen? - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - + - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - + - + Delete trash? Prullenbak legen? - + Are you sure you want to delete all trashed messages? - + - + bad passphrase verkeerd wachtwoord - + You must type your passphrase. If you don't have one then this is not the form for you. - + - - Chan name needed - - - - - You didn't enter a chan name. - - - - - Address already present - - - - - Could not add chan because it appears to already be one of your identities. - - - - - Success - Gelukt - - - - Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. - - - - - Address too new - Adres te nieuw - - - - Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. - - - - - Address invalid - Adres ongeldig - - - - That Bitmessage address is not valid. - Dat Bitmessage adres is niet geldig. - - - - Address does not match chan name - - - - - Although the Bitmessage address you entered was valid, it doesn't match the chan name. - - - - - Successfully joined chan. - - - - - Processed %1 person-to-person messages. - Verwerkt %1 peer-to-peer-bericht(en). - - - - Processed %1 broadcast messages. - Verwerkt %1 broadcast-bericht(en). - - - - Processed %1 public keys. - Verwerkt %1 publieke sleutel(s). - - - - Total Connections: %1 - Aantal Connecties: %1 - - - - Connection lost - Verbinding verloren - - - - Connected - Verbonden - - - - Message trashed - Bericht weggegooit - - - - Error: Bitmessage addresses start with BM- Please check %1 - - - - - Error: The address %1 is not typed or copied correctly. Please check it. - - - - - Error: The address %1 contains invalid characters. Please check it. - - - - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - - - - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - - - - - Error: Something is wrong with the address %1. - - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - - - - - Address version number - Adres versienummer - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - - - - - Stream number - - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - - - - - Your 'To' field is empty. - - - - - Right click one or more entries in your address book and select 'Send message to this address'. - - - - - Fetched address from namecoin identity. - - - - - Work is queued. %1 - - - - - New Message - Nieuw Bericht - - - - From - Van - - - - Address is valid. - Adres is geldig. - - - - The address you entered was invalid. Ignoring it. - Het ingevoerd adres is ongeldig. Worden genegeerd. - - - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - - - - - Restart - Herstarten - - - - You must restart Bitmessage for the port number change to take effect. - - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). - - - - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - - - - - Passphrase mismatch - - - - - The passphrase you entered twice doesn't match. Try again. - - - - - Choose a passphrase - - - - - You really do need a passphrase. - - - - - All done. Closing user interface... - - - - - Address is gone - - - - - Bitmessage cannot find your address %1. Perhaps you removed it? - - - - - Address disabled - - - - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - - - - - Entry added to the Address Book. Edit the label to your liking. - - - - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - - - - - Save As... - Opslaan als... - - - - Write error. - Schrijffout. - - - - No addresses selected. - Geen adressen geselecteerd. - - - - Testing... - Testen... - - - - This is a chan address. You cannot use it as a pseudo-mailing list. - - - - - The address should start with ''BM-'' - - - - - The address is not typed or copied correctly (the checksum failed). - - - - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - - - - - The address contains invalid characters. - - - - - Some data encoded in the address is too short. - - - - - Some data encoded in the address is too long. - - - - - You are using TCP port %1. (This can be changed in the settings). - - - - - Bitmessage - Bitmessage - - - - Search - Zoeken - - - - All - Alle - - - - To - Naar - - - - From - Van - - - - Subject - Onderwerp - - - - Message - Bericht - - - - Received - Ontvangen - - - - Inbox - Postvak IN - - - - Load from Address book - Laden uit adresboek - - - - Fetch Namecoin ID - Ophalen Namecoin ID - - - - Message: - Bericht: - - - - Subject: - Onderwerp: - - - - Send to one or more specific people - - - - - To: - Naar: - - - - From: - Van: - - - - Broadcast to everyone who is subscribed to your address - - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - - - - - Status - Status - - - - Sent - Verzonden - - - - Label (not shown to anyone) - - - - - Address - Adres - - - - Stream - - - - - Your Identities - Uw identiteiten - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - - - - - Add new Subscription - - - - - Label - Label - - - - Subscriptions - - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - - - - - Name or Label - - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - - - - - Blacklist - Zwarte lijst - - - - Stream # - - - - - Connections - Verbindingen - - - - Total connections: 0 - Aantal Connecties: 0 - - - - Since startup at asdf: - - - - - Processed 0 person-to-person message. - Verwerkt 0 peer-to-peer-bericht. - - - - Processed 0 public key. - Verwerkt 0 broadcast-bericht. - - - - Processed 0 broadcast. - Verwerkt 0 publieke sleutel. - - - - Network Status - netwerkstatus - - - - File - Bestand - - - - Settings - Instellingen - - - - Help - Help - - - - Import keys - Importeer sleutels - - - - Manage keys - - - - - Ctrl+Q - Ctrl+Q - - - - F1 - F1 - - - - About - Over - - - - Regenerate deterministic addresses - - - - - Delete all trashed messages - - - - - Join / Create chan - - - - - Set avatar... - - - - + Bad address version number Slechte adres versienummer - + Your address version number must be a number: either 3 or 4. - + - + Your address version number must be either 3 or 4. - + - - Inventory lookups per second: %1 - + + Chan name needed + - + + You didn't enter a chan name. + + + + + Address already present + + + + + Could not add chan because it appears to already be one of your identities. + + + + + Success + Gelukt + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + + + + + Address too new + Adres te nieuw + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + + + + + Address invalid + Adres ongeldig + + + + That Bitmessage address is not valid. + Dat Bitmessage adres is niet geldig. + + + + Address does not match chan name + + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + + + + + Successfully joined chan. + + + + + Connection lost + Verbinding verloren + + + + Connected + Verbonden + + + + Message trashed + Bericht weggegooit + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + Bericht te lang + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + + + + + Error: The address %1 is not typed or copied correctly. Please check it. + + + + + Error: The address %1 contains invalid characters. Please check it. + + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + + + + + Address version number + Adres versienummer + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Stream number + + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + + + + + Message queued. + + + + + Your 'To' field is empty. + + + + + Right click one or more entries in your address book and select 'Send message to this address'. + + + + + Fetched address from namecoin identity. + + + + + New Message + Nieuw Bericht + + + + From + Van + + + + Sending email gateway registration request + + + + + Address is valid. + Adres is geldig. + + + + The address you entered was invalid. Ignoring it. + Het ingevoerd adres is ongeldig. Worden genegeerd. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + Herstarten + + + + You must restart Bitmessage for the port number change to take effect. + + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + + + + + Number needed + + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + Will not resend ever - + - + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. - + - + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + + + + + The passphrase you entered twice doesn't match. Try again. + + + + + Choose a passphrase + + + + + You really do need a passphrase. + + + + + Address is gone + + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + + + + + Address disabled + + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + + + + + Entry added to the Address Book. Edit the label to your liking. + + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + + + + + Undeleted item. + + + + + Save As... + Opslaan als... + + + + Write error. + Schrijffout. + + + + No addresses selected. + Geen adressen geselecteerd. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + Do you really want to remove this avatar? - + - + You have already set an avatar for this address. Do you really want to overwrite it? - + - + Start-on-login not yet supported on your OS. - + - + Minimize-to-tray not yet supported on your OS. - + - + Tray notifications not yet supported on your OS. - + - + + Testing... + Testen... + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + + + + + The address should start with ''BM-'' + + + + + The address is not typed or copied correctly (the checksum failed). + + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + + + + + The address contains invalid characters. + + + + + Some data encoded in the address is too short. + + + + + Some data encoded in the address is too long. + + + + + Some data encoded in the address is malformed. + + + + Enter an address above. - + - + Address is an old type. We cannot display its past broadcasts. - + - + There are no recent broadcasts from this address to display. - + - - Display the %1 recent broadcast from this address. - + + You are using TCP port %1. (This can be changed in the settings). + - - Display the %1 recent broadcasts from this address. - + + Bitmessage + Bitmessage - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - + + Identities + - - Inventory lookups per second: 0 - + + New Identity + + + + + Search + Zoeken + + + + All + Alle + + + + To + Naar + + + + From + Van + + + + Subject + Onderwerp + + + + Message + Bericht + + + + Received + Ontvangen + + + + Messages + + + + + Address book + + + + + Address + Adres + + + + Add Contact + + + + + Fetch Namecoin ID + Ophalen Namecoin ID + + + + Subject: + Onderwerp: + + + + From: + Van: + + + + To: + Naar: + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + Subscriptions + + + + + Add new Subscription + + + + + Chans + + + + + Add Chan + + + + + File + Bestand + + + + Settings + Instellingen + + + + Help + Help + + + + Import keys + Importeer sleutels + + + + Manage keys + + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + + + + + About + Over + + + + Regenerate deterministic addresses + + + + + Delete all trashed messages + + + + + Join / Create chan + + + + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + @@ -986,12 +1274,12 @@ p, li { white-space: pre-wrap; } Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: - + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> - + @@ -999,29 +1287,29 @@ The 'Random Number' option is selected by default but deterministic ad Gebruik een willekeurige nummer generator om een adres te maken - - Use a passpharase to make addresses - Use yee passpharase to make arrddresses + + Use a passphrase to make addresses + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter - + Make deterministic addresses - + - Address version number: 3 - Arrddress version number: 3 + Address version number: 4 + Adres versienummer: 4 In addition to your passphrase, you must remember these numbers: - + @@ -1031,17 +1319,17 @@ The 'Random Number' option is selected by default but deterministic ad Number of addresses to make based on your passphrase: - + Stream number: 1 - + Retype passphrase - + @@ -1051,37 +1339,27 @@ The 'Random Number' option is selected by default but deterministic ad Label (not shown to anyone except you) - + Use the most available stream - + (best if this is the first of many addresses you will create) - + Use the same stream as an existing address - + (saves you some bandwidth and processing power) - - - - - Use a passphrase to make addresses - - - - - Address version number: 4 - Adres versienummer: 4 + @@ -1089,7 +1367,7 @@ The 'Random Number' option is selected by default but deterministic ad Add new entry - + @@ -1103,8 +1381,8 @@ The 'Random Number' option is selected by default but deterministic ad - CheckBox - + Enter an address above. + @@ -1112,31 +1390,36 @@ The 'Random Number' option is selected by default but deterministic ad Special Address Behavior - + Behave as a normal address - + Behave as a pseudo-mailing-list address - + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). - + Name of the pseudo-mailing-list: - + aboutDialog + + + About + Over + PyBitmessage @@ -1145,27 +1428,60 @@ The 'Random Number' option is selected by default but deterministic ad version ? - Versie ? - - - - About - Over + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> - + This is Beta software. - + - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 The Bitmessage Developers</p></body></html> - + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + @@ -1178,17 +1494,17 @@ The 'Random Number' option is selected by default but deterministic ad Bitmessage won't connect to anyone until you let it. - + Connect now - + Let me configure special network settings first - + @@ -1200,13 +1516,13 @@ The 'Random Number' option is selected by default but deterministic ad - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: - + @@ -1214,32 +1530,140 @@ The 'Random Number' option is selected by default but deterministic ad Icon Glossary - + You have no connections with other peers. - - - - - 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't configured to foward 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. - Yee have made least one connection to a peer pirate usin' outgoing connection but yee not yet received any incoming connections. Yee firewall, witches nest, or home router probably shant configured to foward incoming TCP connections to yee computer. Bitmessage be workin' just fine but it help fellow pirates if yee allowed for incoming connections and will help yee be a better-connected node matey. - - - - You are using TCP port ?. (This can be changed in the settings). - - - - - You do have connections with other peers and your firewall is correctly configured. - + 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'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. - + + + + + You are using TCP port ?. (This can be changed in the settings). + + + + + You do have connections with other peers and your firewall is correctly configured. + + + + + networkstatus + + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + @@ -1247,42 +1671,42 @@ The 'Random Number' option is selected by default but deterministic ad Dialog - + Create a new chan - + Join a chan - + Create a chan - + <html><head/><body><p>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.</p></body></html> - + Chan name: - + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> - + Chan bitmessage address: - + @@ -1290,12 +1714,12 @@ The 'Random Number' option is selected by default but deterministic ad Regenerate Existing Addresses - + Regenerate existing addresses - + @@ -1305,22 +1729,17 @@ The 'Random Number' option is selected by default but deterministic ad Number of addresses to make based on your passphrase: - + - - Address version Number: - Arrddress version Number: - - - - 3 - 3 + + Address version number: + Stream number: - + @@ -1330,330 +1749,311 @@ The 'Random Number' option is selected by default but deterministic ad Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter - + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. - + 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. - - - - - Address version number: - + settingsDialog - + Settings Instellingen - + Start Bitmessage on user login Start Bitmessage bij user login - - - Start Bitmessage in the tray (don't show main window) - - - - - Minimize to tray - - - - - Show notification when message received - - - - - Run in Portable Mode - - - - - 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. - - - - - User Interface - Gebruikersinterface - - - - Listening port - Luisterpoort - - - - Listen for connections on port: - Luister voor connecties op poort: - - - - Proxy server / Tor - Proxy server / Tor - - - - Type: - Type: - - - - none - geen - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - - Server hostname: - Server hostnaam: - - - - Port: - Poort: - - - - Authentication - Authenticatie - - Username: - Gebruikersnaam: - - - - Pass: - Wachtwoord: - - - - Network Settings - Netwerkinstellingen - - - - 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. - - - - - Total difficulty: - - - - - Small message difficulty: - - - - - 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. - - - - - The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - - - - - Demanded difficulty - - - - - Willingly include unencrypted destination address when sending to a mobile device - - - - - Listen for incoming connections when using proxy - - - - - 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. - - - - - Maximum acceptable total difficulty: - - - - - Maximum acceptable small message difficulty: - - - - - Max acceptable difficulty - - - - - <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> - - - - - Host: - + Tray + - Password: - Wachtwoord + Start Bitmessage in the tray (don't show main window) + - Test - + Minimize to tray + - Connect to: - + Close to tray + - Namecoind - + Show notification when message received + - NMControl - + Run in Portable Mode + - Namecoin integration - + 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. + - + + Willingly include unencrypted destination address when sending to a mobile device + + + + Use Identicons - + - + + Reply below Quote + + + + Interface Language Interface Taal - + System Settings system - + - - English - en - + + User Interface + Gebruikersinterface - - Esperanto - eo - + + Listening port + Luisterpoort - - Français - fr - + + Listen for connections on port: + Luister voor connecties op poort: - - Deutsch - de - + + UPnP: + - - Españl - es - + + Bandwidth limit + - - русский язык - ru - + + Maximum download rate (kB/s): [0: unlimited] + - - Norsk - no - + + Maximum upload rate (kB/s): [0: unlimited] + - - Pirate English - en_pirate - + + Proxy server / Tor + Proxy server / Tor - - Other (set in keys.dat) - other - + + Type: + Type: - + + Server hostname: + Server hostnaam: + + + + Port: + Poort: + + + + Authentication + Authenticatie + + + + Username: + Gebruikersnaam: + + + + Pass: + Wachtwoord: + + + + Listen for incoming connections when using proxy + + + + + none + geen + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Netwerkinstellingen + + + + Total difficulty: + + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + + + + + Small message difficulty: + + + + + 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. + + + + + 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. + + + + + Demanded difficulty + + + + + 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. + + + + + Maximum acceptable total difficulty: + + + + + Maximum acceptable small message difficulty: + + + + + Max acceptable difficulty + + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + + + + + Host: + + + + + Password: + Wachtwoord + + + + Test + + + + + Connect to: + + + + + Namecoind + + + + + NMControl + + + + + Namecoin integration + + + + <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> - + - + Give up after Opgeven na - + and en - + days dagen - + months. maanden. - + Resends Expire - + - + \ No newline at end of file diff --git a/src/translations/bitmessage_no.pro b/src/translations/bitmessage_no.pro deleted file mode 100644 index d34ad2f9..00000000 --- a/src/translations/bitmessage_no.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_objectProcessor.py\ - ../class_outgoingSynSender.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_no.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_no.qm b/src/translations/bitmessage_no.qm index e0b248c6..8a154ed4 100644 Binary files a/src/translations/bitmessage_no.qm and b/src/translations/bitmessage_no.qm differ diff --git a/src/translations/bitmessage_no.ts b/src/translations/bitmessage_no.ts index 72ce1f4f..8ab1e73b 100644 --- a/src/translations/bitmessage_no.ts +++ b/src/translations/bitmessage_no.ts @@ -1,11 +1,10 @@ - - + AddAddressDialog Add new entry - Legg til ny oppføring + Legg til ny oppføring @@ -18,1107 +17,1253 @@ Adresse + + EmailGatewayDialog + + + Email gateway + Epost portal + + + + Register on email gateway + Registrer på epost portal + + + + Account status at email gateway + Kontoinnstillinger på epost portal + + + + Change account settings at email gateway + Endre kontoinnstillinger på epost portal + + + + Unregister from email gateway + Avregistrer fra epost portal + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + Ønsket epost adresse (inkludert @mailchuck.com): + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + Epost portal registrering + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + MainWindow - - Bitmessage - Bitmessage + + Reply to sender + Svar til avsender - - To - Til + + Reply to channel + Svar til kanal - - From - Fra - - - - Subject - Emne - - - - Received - Mottatt - - - - Inbox - Innboks - - - - Load from Address book - Velg fra adresseboka - - - - Message: - Beskjed: - - - - Subject: - Emne: - - - - Send to one or more specific people - Send til en eller flere bestemte kontakter - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - To: - Til: - - - - From: - Fra: - - - - Broadcast to everyone who is subscribed to your address - Kringkast til alle som abonnerer på din adresse - - - - Send - Send - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - Vær klar over at når du kringkaster noe er beskjeden kun kryptert med adressen din. Alle som har denne kan derfor få med seg innholdet. - - - - Status - Status - - - - Sent - Sendt - - - - New - Ny - - - - Label (not shown to anyone) - Etikett (ikke vist til noen) - - - - Address - Adresse - - - - Stream - Strøm - - - - Your Identities - Dine identiteter - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - Her kan du abonnere på 'kringkastede beskjeder' sendt av andre brukere. Beskjedene vil vises i din innboks. Adressene her vil overstyre de under svartelistefanen. - - - - Add new Subscription - Legg til nytt abonnement - - - - Label - Etikett - - - - Subscriptions - Abonnement - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - Adresseboka er nyttig for å knytte navn eller etiketter mot andres BitMessage-adresser så du enklere kan gjenkjenne dem i innboksen. Du kan legge til nye oppføringer her ved å bruke 'Legg til'-knappen, eller fra innboksen din ved å høyreklikke på en beskjed. - - - - Add new entry - Legg til ny oppføring - - - - Name or Label - Navn eller etikett - - - - Address Book - Adressebok - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - Bruk svarteliste (tillat beskjeder fra alle adresser unntatt de på svartelisten) - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - Bruk hviteliste (blokker beskjeder fra alle adresser unntatt de på hvitelisten) - - - - Blacklist - Svarteliste - - - - Stream Number - Strømnummer - - - - Number of Connections - Antall tilkoblinger - - - - Total connections: 0 - Totalt antall tilkoblinger: 0 - - - - Since startup at asdf: - Siden oppstart på asdf: - - - - Processed 0 person-to-person message. - Har bearbeidet 0 beskjeder for person-til-person. - - - - Processed 0 public key. - Har bearbeidet 0 offentlige nøkler. - - - - Processed 0 broadcast. - Har bearbeidet 0 kringkastninger. - - - - Network Status - Nettverksstatus - - - - File - Fil - - - - Settings - Innstillinger - - - - Help - Hjelp - - - - Import keys - Importer inn nøkler - - - - Manage keys - Administrer nøkler - - - - Quit - Avslutt - - - - About - Om - - - - Regenerate deterministic addresses - Regenerer deterministiske adresser - - - - Delete all trashed messages - Slett alle kastede meldinger - - - - Total Connections: %1 - Totalt antall forbindelser: %1 - - - - Not Connected - Ikke tilkoblet - - - - Connected - Tilkoblet - - - - Show Bitmessage - Vis Bitmessage - - - - Subscribe - Abonner - - - - Processed %1 person-to-person messages. - Bearbeidet %1 beskjeder for person-til-person. - - - - Processed %1 broadcast messages. - Bearbeidet %1 kringkastede beskjeder. - - - - Processed %1 public keys. - Bearbeidet %1 offentlige nøkler. - - - - Since startup on %1 - Siden oppstart %1 - - - - Waiting for their encryption key. Will request it again soon. - Venter på krypteringsnøkkel. Sender straks en ny forespørsel. - - - - Encryption key request queued. - Forespørsel for å finne krypteringsnøkkel er satt i kø. - - - - Queued. - Satt i kø. - - - - Need to do work to send message. Work is queued. - Trenger å utføre arbeidsoppgave for sende beskjed. Denne er satt i kø. - - - - Acknowledgement of the message received %1 - Bekreftelse på beskjeden mottatt %1 - - - - Broadcast queued. - Kringkasting satt i kø. - - - - Broadcast on %1 - Kringkasting på %1 - - - - Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 - Problem: Det nødvendige arbeidet som kreves utført av mottaker er mer krevende enn det som er satt som akseptabelt. %1 - - - - Forced difficulty override. Send should start soon. - Tvunget vanskelighet overstyrt. Sender snart. - - - - Message sent. Waiting for acknowledgement. Sent at %1 - Beskjed sendt. Venter på bekreftelse. Sendt %1 - - - - You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. - Du kan administrere nøklene dine ved å endre filen keys.dat i samme katalog som dette programmet. Det er viktig at du tar en sikkerhetskopi av denne filen. - - - - You may manage your keys by editing the keys.dat file stored in - %1 -It is important that you back up this file. - Du kan administrere nøklene dine ved å endre filen keys.dat lagret i - %1 -Det er viktig at du tar en sikkerhetskopi av denne filen. - - - - You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - Du kan administrere nøklene dine ved å endre filen keys.dat i samme katalog som dette programmet. Det er viktig at du tar en sikkerhetskopi av denne filen. Vil du åpne denne filen nå? (Pass på å lukke Bitmessage før du gjør endringer.) - - - - You may manage your keys by editing the keys.dat file stored in - %1 -It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - Du kan administrere nøklene dine ved å endre filen keys.dat i - %1 -Det er viktig at du tar en sikkerhetskopi av denne filen. Vil du åpne denne filen nå? (Pass på å lukke Bitmessage før du gjør endringer.) - - - + Add sender to your Address Book - Legg til sender i adresseboka + Legg til avsender i adresseboka - + + Add sender to your Blacklist + Legg til avsender i svartelisten + + + Move to Trash Kast - + + Undelete + Angre sletting + + + View HTML code as formatted text Vis HTML-koden som formatert tekst - - Enable - Aktiver - - - - Disable - Deaktiver - - - - Copy address to clipboard - Kopier adressen til utklippstavlen - - - - Special address behavior... - Spesieladressebehandling ... - - - - Send message to this address - Send beskjed til denne adressen - - - - Add New Address - Legg til ny adresse - - - - Delete - Slett - - - - Copy destination address to clipboard - Kopier destinasjonsadresse til utklippstavlen - - - - Force send - Tving sending - - - - Are you sure you want to delete all trashed messages? - Er du sikker på at du vil slette alle kastede beskjeder? - - - - You must type your passphrase. If you don't have one then this is not the form for you. - Du må skrive inn passordfrasen din. Hvis du ikke har en kan du ikke bruke dette skjemaet. - - - - Delete trash? - Vil du slette kastet innhold? - - - - Open keys.dat? - Åpne keys.dat? - - - - bad passphrase - Dårlig passordfrase - - - - Restart - Omstart - - - - You must restart Bitmessage for the port number change to take effect. - Du må ta omstart av Bitmessage for at endringen av portnummer skal tre i kraft. - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections. - Bitmessage vil bruke proxy fra nå av, ta en omstart hvis du vil lukke alle eksisterende tilkoblinger. - - - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - Feil: Du kan ikke legge til samme adresse flere ganger. - - - - The address you entered was invalid. Ignoring it. - Adressen du oppga var ugyldig og vil derfor bli ignorert. - - - - Passphrase mismatch - Passordfrase stemmer ikke - - - - The passphrase you entered twice doesn't match. Try again. - Passordfrasene er ikke like. Vennligst prøv igjen. - - - - Choose a passphrase - Velg en passordfrase - - - - You really do need a passphrase. - Du trenger sårt en passordfrase. - - - - All done. Closing user interface... - Ferdig. Lukker brukergrensesnittet... - - - - Address is gone - Adressen er borte - - - - Bitmessage cannot find your address %1. Perhaps you removed it? - Bitmessage kan ikke finne adressen %1. Kanskje du fjernet den? - - - - Address disabled - Adressen er deaktivert - - - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - Feil: Adressen du prøver å sende med er deaktivert. Du må aktivere den fra 'Dine identiteter' før du kan bruke den. - - - - Entry added to the Address Book. Edit the label to your liking. - Ny oppføring lagt til i adresseboka. Du kan forandre etiketten til det du måtte ønske. - - - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - Feil: Du kan ikke legge til samme adresse i adresseboka flere ganger. - - - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - Kastet innholdet. Det finnes ikke noe brukergrensesnitt enda for kastet innhold, men ingenting er slettet enda. Alt ligger fortsatt på disken hvis du er interessert i å få det tilbake. - - - - No addresses selected. - Ingen adresse valgt. - - - - Options have been disabled because they either aren't applicable or because they haven't yet been implimented for your operating system. - Alternativer har blitt deaktivert fordi de enten ikke er gjeldende eller fordi de ikke har blitt implementert for ditt operativsystem. - - - - The address should start with ''BM-'' - Adressen bør starte med ''BM-'' - - - - The address is not typed or copied correctly (the checksum failed). - Adressen er ikke skrevet eller kopiert inn riktig (sjekksummen feilet). - - - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - Typenummeret for denne adressen er høyere enn det programvaren støtter. Vennligst oppgrader Bitmessage. - - - - The address contains invalid characters. - Adressen inneholder ugyldige tegn. - - - - Some data encoded in the address is too short. - Noen av de kodede dataene i adressen er for korte. - - - - Some data encoded in the address is too long. - Noen av de kodede dataene i adressen er for lange. - - - - Address is valid. - Adressen er gyldig. - - - - You are using TCP port %1. (This can be changed in the settings). - Du benytter TCP-port %1. (Dette kan endres på i innstillingene). - - - - Error: Bitmessage addresses start with BM- Please check %1 - Feil: Bitmessage-adresser begynner med BM-. Vennligst sjekk %1 - - - - Error: The address %1 contains invalid characters. Please check it. - Feil: Adressen %1 innerholder ugyldige tegn. Vennligst sjekk den. - - - - Error: The address %1 is not typed or copied correctly. Please check it. - Feil: Adressen %1 er skrevet eller kopiert inn feil. Vennligst sjekk den. - - - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - Feil: Typenummeret for adressen %1 er for høy. Enten trenger du å oppgradere Bitmessaage-programvaren eller så er det fordi kontakten din har funnet på noe smart. - - - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - Feil: Noen av de kodede dataene i adressen %1 er for korte. Det kan hende det er noe galt med programvaren til kontakten din. - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - Feil: Noen av de kodede dataene i adressen %1 er for lange. Det kan hende det er noe galt med programvaren til kontakten din. - - - - Error: Something is wrong with the address %1. - Feil: Noe er galt med adressen %1. - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - Feil: Du må oppgi en avsenderadresse. Hvis du ikke har en gå til 'Dine identiteter'-fanen. - - - - Sending to your address - Sender til din adresse - - - - Error: One of the addresses to which you are sending a message, %1, is yours. Unfortunately the Bitmessage client cannot process its own messages. Please try running a second client on a different computer or within a VM. - Feil: En av adressene du sender en beskjed til er dine: %1. Dessverre kan ikke Bitmessage-klienten bearbeide sine egne beskjeder. Du kan benytte Bitmessage-klienten på en annen datamaskin eller kjøre den i en virtuell datamaskin. - - - - Address version number - Adressetypenummer - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - Angående adressen %1, Bitmessage forstår ikke adressetypenumre for %2. Oppdater Bitmessage til siste versjon. - - - - Stream number - Strømnummer - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - Angående adressen %1, Bitmessage kan ikke håndtere strømnumre for %2. Oppdater Bitmessage til siste utgivelse. - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - Advarsel: Du er ikke tilkoblet. Bitmessage vil utføre nødvendige arbeidsoppgaver for å sende beskjeder, men ingen vil bli sendt før du kobler til igjen. - - - - Your 'To' field is empty. - Ditt 'Til'-felt er tomt. - - - - Right click one or more entries in your address book and select 'Send message to this address'. - Høyreklikk på en eller flere oppføringer i adresseboka og velg 'Send beskjed til denne adressen'. - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - Feil: Du kan ikke legge til samme adresse flere ganger i abonnementlista. - - - - Message trashed - Beskjed kastet - - - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - En av dine gamle adresser er av den første typen og derfor ikke lenger støttet: %1. Derfor kan den vel slettes? - - - - Unknown status: %1 %2 - Ukjent status: %1 %2 - - - - Connection lost - Mistet tilkobling - - - - SOCKS5 Authentication problem: %1 - Autentiseringsproblem med SOCKS5: %1 - - - - Reply - Svar - - - - Generating one new address - Genererer en ny adresse - - - - Done generating address. Doing work necessary to broadcast it... - Ferdig med å generere adresse. Utfører nødvendig arbeidsoppgave for å kringkaste den ... - - - - Done generating address - Ferdig med å generere adresse - - - - Message sent. Waiting on acknowledgement. Sent on %1 - Beskjed sendt, venter på bekreftelse. Sendt %1 - - - - Error! Could not find sender address (your address) in the keys.dat file. - Feil! Kunne ikke finne avsenderadresse (din adresse) i nøkkelfilen som er keys.dat. - - - - Doing work necessary to send broadcast... - Utfører nødvendig arbeidsoppgave for å kringkaste ... - - - - Broadcast sent on %1 - Kringkastet på %1 - - - - Looking up the receiver's public key - Gjør oppslag for å finne mottakers offentlige nøkkel - - - - Doing work necessary to send message. (There is no required difficulty for version 2 addresses like this.) - Utfører nødvendig arbeidsoppgave for å sende beskjeden. (Det er ikke noe krav til vanskelighet for adresser av type to som benyttet her.) - - - - Doing work necessary to send message. -Receiver's required difficulty: %1 and %2 - Utfører nødvendig arbeidsoppgave for å sende beskjeden. -Mottakernes krav til vanskelighet: %1 og %2 - - - - Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. - Problem: Arbeidsoppgaven som kreves utført av mottaker (%1 og %2) er mer krevende enn det du har satt som akseptabelt. - - - - Work is queued. - Arbeidsoppgave er satt i kø. - - - - Work is queued. %1 - Arbeidsoppgave er satt i kø. %1 - - - - Doing work necessary to send message. -There is no required difficulty for version 2 addresses like this. - Utfører nødvendig arbeidsoppgave for å sende beskjeden. -Det er ingen krevd vanskelighet for adresser av type to som benyttet her. - - - - Problem: The recipient's encryption key is no good. Could not encrypt message. %1 - Problem: Mottakerens nøkkel kunne ikke brukes til å kryptere beskjeden. %1 - - - + Save message as... Lagre beskjed som ... - + Mark Unread Merk som ulest - - Subscribe to this address - Abonner på denne adressen + + New + Ny - - Message sent. Sent at %1 - Beskjed sendt. Sendt %1 + + Enable + Aktiver - - Chan name needed - Kanalnavn nødvendig + + Disable + Deaktiver - - You didn't enter a chan name. - Du oppga ikke noe kanalnavn. - - - - Address already present - Adressen eksisterer allerede - - - - Could not add chan because it appears to already be one of your identities. - Kunne ikke legge til kanal siden den ser ut til å allerede være lagret som en av dine identiteter. - - - - Success - Suksess - - - - Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. - Opprettet ny kanal. For å la andre delta i din nye kanal gir du dem dem kanalnavnet og denne Bitmessage-adressen: %1. Denne adressen vises også i 'Dine identiteter'. - - - - Address too new - Adressen er for ny - - - - Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. - Selv om Bitmessage-adressen kanskje er gyldig så er tilhørende typenummer for nytt til å håndteres. Kanskje du trenger å oppgradere Bitmessage. - - - - Address invalid - Ugyldig adresse - - - - That Bitmessage address is not valid. - Bitmessage-adressen er ikke gyldig. - - - - Address does not match chan name - Adresse stemmer ikke med kanalnavnet - - - - Although the Bitmessage address you entered was valid, it doesn't match the chan name. - Selv om Bitmessage-adressen du oppga var gyldig stemmer den ikke med kanalnavnet. - - - - Successfully joined chan. - Deltar nå i kanal. - - - - Fetched address from namecoin identity. - Hentet adresse fra Namecoin-identitet. - - - - New Message - Ny beskjed - - - - From - Fra - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). - Bitmessage vil bruke proxy fra nå av. Hvis du vil kan du omstart av programmet for å lukke eksisterende tilkoblinger (hvis det finnes noen). - - - - Save As... - Lagre som ... - - - - Write error. - Skrivefeil. - - - - Options have been disabled because they either aren't applicable or because they haven't yet been implemented for your operating system. - Alternativer har blitt deaktivert fordi de enten ikke er gjeldende eller fordi de ikke har blitt implementert for ditt operativsystem. - - - - Testing... - Tester ... - - - - This is a chan address. You cannot use it as a pseudo-mailing list. - Dette er en kanaladresse. Du kan ikke bruke den som en pseudo-epostliste. - - - - Search - Søk - - - - All - Alle - - - - Message - Beskjed - - - - Fetch Namecoin ID - Hent Namecoin-id - - - - Stream # - Strøm # - - - - Connections - Tilkoblinger - - - - Ctrl+Q - Ctrl+Q - - - - F1 - F1 - - - - Join / Create chan - Delta i / opprett kanal - - - + Set avatar... Sett ett avatar... - + + Copy address to clipboard + Kopier adressen til utklippstavlen + + + + Special address behavior... + Spesieladressebehandling ... + + + + Email gateway + Epost portal + + + + Delete + Slett + + + + Send message to this address + Send beskjed til denne adressen + + + + Subscribe to this address + Abonner på denne adressen + + + + Add New Address + Legg til ny adresse + + + + Copy destination address to clipboard + Kopier destinasjonsadresse til utklippstavlen + + + + Force send + Tving sending + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + En av dine gamle adresser er av den første typen og derfor ikke lenger støttet: %1. Derfor kan den vel slettes? + + + + Waiting for their encryption key. Will request it again soon. + Venter på krypteringsnøkkel. Sender straks en ny forespørsel. + + + + Encryption key request queued. + Forespørsel for å finne krypteringsnøkkel er satt i kø. + + + + Queued. + Satt i kø. + + + + Message sent. Waiting for acknowledgement. Sent at %1 + Beskjed sendt. Venter på bekreftelse. Sendt %1 + + + + Message sent. Sent at %1 + Beskjed sendt. Sendt %1 + + + + Need to do work to send message. Work is queued. + Trenger å utføre arbeidsoppgave for sende beskjed. Denne er satt i kø. + + + + Acknowledgement of the message received %1 + Bekreftelse på beskjeden mottatt %1 + + + + Broadcast queued. + Kringkasting satt i kø. + + + + Broadcast on %1 + Kringkasting på %1 + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + Problem: Det nødvendige arbeidet som kreves utført av mottaker er mer krevende enn det som er satt som akseptabelt. %1 + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + Problem: Mottakerens nøkkel kunne ikke brukes til å kryptere beskjeden. %1 + + + + Forced difficulty override. Send should start soon. + Tvunget vanskelighet overstyrt. Sender snart. + + + + Unknown status: %1 %2 + Ukjent status: %1 %2 + + + + Not Connected + Ikke tilkoblet + + + + Show Bitmessage + Vis Bitmessage + + + + Send + Send + + + + Subscribe + Abonner + + + + Channel + Kanal + + + + Quit + Avslutt + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + Du kan administrere nøklene dine ved å endre filen keys.dat i samme katalog som dette programmet. Det er viktig at du tar en sikkerhetskopi av denne filen. + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + Du kan administrere nøklene dine ved å endre filen keys.dat lagret i + %1 +Det er viktig at du tar en sikkerhetskopi av denne filen. + + + + Open keys.dat? + Åpne keys.dat? + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Du kan administrere nøklene dine ved å endre filen keys.dat i samme katalog som dette programmet. Det er viktig at du tar en sikkerhetskopi av denne filen. Vil du åpne denne filen nå? (Pass på å lukke Bitmessage før du gjør endringer.) + + + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) - Du kan administrere dine nøkler ved å endre på filen keys.dat lagret i + Du kan administrere dine nøkler ved å endre på filen keys.dat lagret i %1 -Det er viktig at du tar sikkerhetskopi av denne filen. Vil du åpne denne filen nå? (Vær sikker på å få avsluttet Bitmessage før du gjør endringer.) +Det er viktig at du tar sikkerhetskopi av denne filen. Vil du åpne denne filen nå? (Vær sikker på å få avsluttet Bitmessage før du gjør endringer.) - + + Delete trash? + Vil du slette kastet innhold? + + + + Are you sure you want to delete all trashed messages? + Er du sikker på at du vil slette alle kastede beskjeder? + + + + bad passphrase + Dårlig passordfrase + + + + You must type your passphrase. If you don't have one then this is not the form for you. + Du må skrive inn passordfrasen din. Hvis du ikke har en kan du ikke bruke dette skjemaet. + + + Bad address version number Feil adresseversjonsnummer - + Your address version number must be a number: either 3 or 4. - Ditt adressetypenummer må være et nummer: Enten 3 eller 4. + Ditt adressetypenummer må være et nummer: Enten 3 eller 4. - + Your address version number must be either 3 or 4. - Ditt adressetypenummer må enten være 3 eller 4. + Ditt adressetypenummer må enten være 3 eller 4. - - Inventory lookups per second: %1 - Inventaroppslag per sekund: %1 + + Chan name needed + Kanalnavn nødvendig - + + You didn't enter a chan name. + Du oppga ikke noe kanalnavn. + + + + Address already present + Adressen eksisterer allerede + + + + Could not add chan because it appears to already be one of your identities. + Kunne ikke legge til kanal siden den ser ut til å allerede være lagret som en av dine identiteter. + + + + Success + Suksess + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + Opprettet ny kanal. For å la andre delta i din nye kanal gir du dem dem kanalnavnet og denne Bitmessage-adressen: %1. Denne adressen vises også i 'Dine identiteter'. + + + + Address too new + Adressen er for ny + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + Selv om Bitmessage-adressen kanskje er gyldig så er tilhørende typenummer for nytt til å håndteres. Kanskje du trenger å oppgradere Bitmessage. + + + + Address invalid + Ugyldig adresse + + + + That Bitmessage address is not valid. + Bitmessage-adressen er ikke gyldig. + + + + Address does not match chan name + Adresse stemmer ikke med kanalnavnet + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + Selv om Bitmessage-adressen du oppga var gyldig stemmer den ikke med kanalnavnet. + + + + Successfully joined chan. + Deltar nå i kanal. + + + + Connection lost + Mistet tilkobling + + + + Connected + Tilkoblet + + + + Message trashed + Beskjed kastet + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + Meldingen er for lang + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + Feil: Bitmessage-adresser begynner med BM-. Vennligst sjekk %1 + + + + Error: The address %1 is not typed or copied correctly. Please check it. + Feil: Adressen %1 er skrevet eller kopiert inn feil. Vennligst sjekk den. + + + + Error: The address %1 contains invalid characters. Please check it. + Feil: Adressen %1 innerholder ugyldige tegn. Vennligst sjekk den. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + Feil: Typenummeret for adressen %1 er for høy. Enten trenger du å oppgradere Bitmessaage-programvaren eller så er det fordi kontakten din har funnet på noe smart. + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + Feil: Noen av de kodede dataene i adressen %1 er for korte. Det kan hende det er noe galt med programvaren til kontakten din. + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + Feil: Noen av de kodede dataene i adressen %1 er for lange. Det kan hende det er noe galt med programvaren til kontakten din. + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + Feil: Noe er galt med adressen %1. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Feil: Du må oppgi en avsenderadresse. Hvis du ikke har en gå til 'Dine identiteter'-fanen. + + + + Address version number + Adressetypenummer + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Angående adressen %1, Bitmessage forstår ikke adressetypenumre for %2. Oppdater Bitmessage til siste versjon. + + + + Stream number + Strømnummer + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Angående adressen %1, Bitmessage kan ikke håndtere strømnumre for %2. Oppdater Bitmessage til siste utgivelse. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Advarsel: Du er ikke tilkoblet. Bitmessage vil utføre nødvendige arbeidsoppgaver for å sende beskjeder, men ingen vil bli sendt før du kobler til igjen. + + + + Message queued. + Meldingen er lagt i kø. + + + + Your 'To' field is empty. + Ditt 'Til'-felt er tomt. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Høyreklikk på en eller flere oppføringer i adresseboka og velg 'Send beskjed til denne adressen'. + + + + Fetched address from namecoin identity. + Hentet adresse fra Namecoin-identitet. + + + + New Message + Ny beskjed + + + + From + Fra + + + + Sending email gateway registration request + + + + + Address is valid. + Adressen er gyldig. + + + + The address you entered was invalid. Ignoring it. + Adressen du oppga var ugyldig og vil derfor bli ignorert. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Feil: Du kan ikke legge til samme adresse i adresseboka flere ganger. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + Omstart + + + + You must restart Bitmessage for the port number change to take effect. + Du må ta omstart av Bitmessage for at endringen av portnummer skal tre i kraft. + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + Bitmessage vil bruke proxy fra nå av. Hvis du vil kan du omstart av programmet for å lukke eksisterende tilkoblinger (hvis det finnes noen). + + + + Number needed + Trenger nummer + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + Will not resend ever Vil ikke igjensende noensinne - + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. - Legg merke til at utløpstiden du oppga er kortere enn det Bitmessage venter for første igjensendingsforsøk, dine beskjeder vil derfor aldri bli igjensendt. + Legg merke til at utløpstiden du oppga er kortere enn det Bitmessage venter for første igjensendingsforsøk, dine beskjeder vil derfor aldri bli igjensendt. - + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + Passordfrase stemmer ikke + + + + The passphrase you entered twice doesn't match. Try again. + Passordfrasene er ikke like. Vennligst prøv igjen. + + + + Choose a passphrase + Velg en passordfrase + + + + You really do need a passphrase. + Du trenger sårt en passordfrase. + + + + Address is gone + Adressen er borte + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmessage kan ikke finne adressen %1. Kanskje du fjernet den? + + + + Address disabled + Adressen er deaktivert + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Feil: Adressen du prøver å sende med er deaktivert. Du må aktivere den fra 'Dine identiteter' før du kan bruke den. + + + + Entry added to the Address Book. Edit the label to your liking. + Ny oppføring lagt til i adresseboka. Du kan forandre etiketten til det du måtte ønske. + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + Kastet innholdet. + + + + Undeleted item. + + + + + Save As... + Lagre som ... + + + + Write error. + Skrivefeil. + + + + No addresses selected. + Ingen adresse valgt. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + Do you really want to remove this avatar? Vil du virkelig fjerne dette avataret? - + You have already set an avatar for this address. Do you really want to overwrite it? Du har allerede satt ett avatar for denne adressen. Vil du virkelig overskrive det? - + Start-on-login not yet supported on your OS. - Start ved innlogging er ikke støttet enda for ditt OS. + Start ved innlogging er ikke støttet enda for ditt OS. - + Minimize-to-tray not yet supported on your OS. - Minimering til systemstatusfeltet er ikke støttet enda for ditt OS. + Minimering til systemstatusfeltet er ikke støttet enda for ditt OS. - + Tray notifications not yet supported on your OS. - Varslinger via systemstatusfeltet er ikke støttet enda for ditt OS. + Varslinger via systemstatusfeltet er ikke støttet enda for ditt OS. - + + Testing... + Tester ... + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + Dette er en kanaladresse. Du kan ikke bruke den som en pseudo-epostliste. + + + + The address should start with ''BM-'' + Adressen bør starte med ''BM-'' + + + + The address is not typed or copied correctly (the checksum failed). + Adressen er ikke skrevet eller kopiert inn riktig (sjekksummen feilet). + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + Typenummeret for denne adressen er høyere enn det programvaren støtter. Vennligst oppgrader Bitmessage. + + + + The address contains invalid characters. + Adressen inneholder ugyldige tegn. + + + + Some data encoded in the address is too short. + Noen av de kodede dataene i adressen er for korte. + + + + Some data encoded in the address is too long. + Noen av de kodede dataene i adressen er for lange. + + + + Some data encoded in the address is malformed. + + + + Enter an address above. Oppgi inn en adresse over. - + Address is an old type. We cannot display its past broadcasts. Adressen er av gammel type. Vi kan ikke vise dens tidligere kringkastninger. - + There are no recent broadcasts from this address to display. - Det er ingen nylige kringkastninger fra denne adressen å vise frem. + Det er ingen nylige kringkastninger fra denne adressen å vise frem. - - Display the %1 recent broadcast from this address. - Vis den %1 nyligste kringkastningen fra denne adressen. + + You are using TCP port %1. (This can be changed in the settings). + Du benytter TCP-port %1. (Dette kan endres på i innstillingene). - - Display the %1 recent broadcasts from this address. - Vis de %1 nyligste kringkastningene fra denne adressen. + + Bitmessage + Bitmessage - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> + + Identities + Identiteter - - Inventory lookups per second: 0 - Inventaroppslag per sekund: 0 + + New Identity + Ny identitet - - - MainWindows - - Address is valid. - Adressen er gyldig. + + Search + Søk + + + + All + Alle + + + + To + Til + + + + From + Fra + + + + Subject + Emne + + + + Message + Beskjed + + + + Received + Mottatt + + + + Messages + Meldinger + + + + Address book + Adressebok + + + + Address + Adresse + + + + Add Contact + Legg til kontakt + + + + Fetch Namecoin ID + Hent Namecoin-id + + + + Subject: + Emne: + + + + From: + Fra: + + + + To: + Til: + + + + Send ordinary Message + Send vanlig melding + + + + Send Message to your Subscribers + Send melding til dine abonnementer + + + + TTL: + TTL: + + + + Subscriptions + Abonnement + + + + Add new Subscription + Legg til nytt abonnement + + + + Chans + Kanaler + + + + Add Chan + Legg til kanal + + + + File + Fil + + + + Settings + Innstillinger + + + + Help + Hjelp + + + + Import keys + Importer inn nøkler + + + + Manage keys + Administrer nøkler + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + Kontakt support + + + + About + Om + + + + Regenerate deterministic addresses + Regenerer deterministiske adresser + + + + Delete all trashed messages + Slett alle kastede meldinger + + + + Join / Create chan + Delta i / opprett kanal + + + + All accounts + Alle kontoer + + + + Zoom level %1% + Zoom nivå %1% + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + @@ -1132,28 +1277,28 @@ p, li { white-space: pre-wrap; } Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: - Her kan du generere så mange adresser du vil. Du oppfordres til å ta i bruk nye adresser med jevne mellomrom. Du kan generere nye adresser enten ved å bruke tilfeldige numre eller en passordfrase. Hvis du bruker passordfrase får du en såkalt 'deterministisk' adresse. -'Tilfeldig nummer'-valget er valgt som standard. En deterministisk adresse har både fordeler og ulemper: + Her kan du generere så mange adresser du vil. Du oppfordres til å ta i bruk nye adresser med jevne mellomrom. Du kan generere nye adresser enten ved å bruke tilfeldige numre eller en passordfrase. Hvis du bruker passordfrase får du en såkalt 'deterministisk' adresse. +'Tilfeldig nummer'-valget er valgt som standard. En deterministisk adresse har både fordeler og ulemper: <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">Fordeler:<br/></span>Du kan gjenskape adressene dine på hvilken som helst datamaskin ved hjelp av hukommelsen. <br/>Du trenger ikke ta noen sikkerhetskopi av keys.dat-filen så lenge du husker passordfrasen din. <br/><span style=" font-weight:600;">Ulemper:<br/></span>Du må huske (eller skrive ned) din passordfrase hvis du forventer å måtte gjenopprette nøklene dine fordi de går tapt. <br/>Du må huske adresseversjonsnummeret og strømnummeret i tillegg til passordfrasen. <br/>Hvis du velger en svak passordfrase og noen andre på Internett klarer å knekke den kan de lese beskjedene dine og sende nye beskjeder på vegne av deg.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Fordeler:<br/></span>Du kan gjenskape adressene dine på hvilken som helst datamaskin ved hjelp av hukommelsen. <br/>Du trenger ikke ta noen sikkerhetskopi av keys.dat-filen så lenge du husker passordfrasen din. <br/><span style=" font-weight:600;">Ulemper:<br/></span>Du må huske (eller skrive ned) din passordfrase hvis du forventer å måtte gjenopprette nøklene dine fordi de går tapt. <br/>Du må huske adresseversjonsnummeret og strømnummeret i tillegg til passordfrasen. <br/>Hvis du velger en svak passordfrase og noen andre på Internett klarer å knekke den kan de lese beskjedene dine og sende nye beskjeder på vegne av deg.</p></body></html> Use a random number generator to make an address - Opprett en adresse ved å bruke generatoren som lager tilfeldige tall + Opprett en adresse ved å bruke generatoren som lager tilfeldige tall Use a passphrase to make addresses - Bruk en passordfrase for å opprette adresser + Bruk en passordfrase for å opprette adresser Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter - Bruk ekstra tid på å få adressen(e) en eller to tegn kortere + Bruk ekstra tid på å få adressen(e) en eller to tegn kortere @@ -1162,13 +1307,13 @@ The 'Random Number' option is selected by default but deterministic ad - Address version number: 3 - Adressetypenummer: 3 + Address version number: 4 + Adressetypenummer: 4 In addition to your passphrase, you must remember these numbers: - I tillegg til passordfrasen må du huske disse numrene: + I tillegg til passordfrasen må du huske disse numrene: @@ -1178,12 +1323,12 @@ The 'Random Number' option is selected by default but deterministic ad Number of addresses to make based on your passphrase: - Antall adresser som skal opprettes basert på din passordfrase: + Antall adresser som skal opprettes basert på din passordfrase: Stream number: 1 - Strømnummer: 1 + Strømnummer: 1 @@ -1203,27 +1348,22 @@ The 'Random Number' option is selected by default but deterministic ad Use the most available stream - Bruk den mest tilgjengelige strømmen + Bruk den mest tilgjengelige strømmen (best if this is the first of many addresses you will create) - (best hvis dette er de første av mange adresser du kommer til å opprette) + (best hvis dette er de første av mange adresser du kommer til å opprette) Use the same stream as an existing address - Bruk samme strøm som en eksisterende adresse + Bruk samme strøm som en eksisterende adresse (saves you some bandwidth and processing power) - (sparer deg for litt båndbredde og prosesseringskraft) - - - - Address version number: 4 - Adressetypenummer: 4 + (sparer deg for litt båndbredde og prosesseringskraft) @@ -1231,7 +1371,7 @@ The 'Random Number' option is selected by default but deterministic ad Add new entry - Legg til ny oppføring + Legg til ny oppføring @@ -1245,8 +1385,8 @@ The 'Random Number' option is selected by default but deterministic ad - CheckBox - Avkryssningsboks + Enter an address above. + Oppgi inn en adresse ovenfor. @@ -1254,31 +1394,36 @@ The 'Random Number' option is selected by default but deterministic ad Special Address Behavior - Spesiell adresseoppførsel + Spesiell adresseoppførsel Behave as a normal address - Oppførsel som vanlig adresse + Oppførsel som vanlig adresse Behave as a pseudo-mailing-list address - Oppførsel som adresse på pseudo-epostliste + Oppførsel som adresse på pseudo-epostliste Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). - E-post mottatt med en adresse oppført på en pseudo-epostliste vil automatisk bli kringkastet til abonnenter (og vil derfor bli offentlig tilgjengelig). + E-post mottatt med en adresse oppført på en pseudo-epostliste vil automatisk bli kringkastet til abonnenter (og vil derfor bli offentlig tilgjengelig). Name of the pseudo-mailing-list: - Navnet på pseudo-epostlista: + Navnet på pseudo-epostlista: aboutDialog + + + About + Om + PyBitmessage @@ -1289,16 +1434,6 @@ The 'Random Number' option is selected by default but deterministic ad version ? versjon ? - - - About - Om - - - - Copyright © 2013 Jonathan Warren - Kopirett © 2013 Jonathan Warren - <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> @@ -1311,8 +1446,46 @@ The 'Random Number' option is selected by default but deterministic ad - <html><head/><body><p>Copyright © 2012-2014 Jonathan Warren<br/>Copyright © 2013-2014 The Bitmessage Developers</p></body></html> - <html><head/><body><p>Kopirett © 2012-2014 Jonathan Warren<br/>Kopirett © 2013-2014 Bitmessage-utviklerne</p></body></html> + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + Navn eller Etikett + + + + Address + Adresse + + + + Blacklist + Svarteliste + + + + Whitelist + Hviteliste @@ -1325,17 +1498,17 @@ The 'Random Number' option is selected by default but deterministic ad Bitmessage won't connect to anyone until you let it. - Bitmessage kobler ikke til noen før du lar den. + Bitmessage kobler ikke til noen før du lar den. Connect now - Koble til nå + Koble til nå Let me configure special network settings first - La meg konfigurere spesielle nettverksinnstillinger først + La meg konfigurere spesielle nettverksinnstillinger først @@ -1347,13 +1520,13 @@ The 'Random Number' option is selected by default but deterministic ad - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">PyBitmessage-hjelp</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: - Bitmessage er et samarbeidsprosjekt, hjelp kan bli funnet på nettet i Bitmessage-wikien: + Bitmessage er et samarbeidsprosjekt, hjelp kan bli funnet på nettet i Bitmessage-wikien: @@ -1371,12 +1544,12 @@ The 'Random Number' option is selected by default but deterministic ad 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'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. - Du har opprettet minst en utgående tilkobling til andre, men ikke mottatt noen innkommende tilkoblinger enda. Din brannmur eller ruter er antagelig ikke konfigurert til å videreformidle innkommende TCP-tilkoblinger frem til datamaskinen din. Bitmessage vil fungere helt fint, men det ville hjelpe Bitmessage-nettverket hvis du tillot innkommende tilkoblinger. Det vil også hjelpe deg å bli en bedre tilkoblet node. + Du har opprettet minst en utgående tilkobling til andre, men ikke mottatt noen innkommende tilkoblinger enda. Din brannmur eller ruter er antagelig ikke konfigurert til å videreformidle innkommende TCP-tilkoblinger frem til datamaskinen din. Bitmessage vil fungere helt fint, men det ville hjelpe Bitmessage-nettverket hvis du tillot innkommende tilkoblinger. Det vil også hjelpe deg å bli en bedre tilkoblet node. You are using TCP port ?. (This can be changed in the settings). - Du bruker TCP port ?. (Dette kan endres på fra innstillingene). + Du bruker TCP port ?. (Dette kan endres på fra innstillingene). @@ -1384,12 +1557,125 @@ The 'Random Number' option is selected by default but deterministic ad Du har aktive tilkoblinger til andre og riktig konfigurert brannmur. + + networkstatus + + + Total connections: + Antall tilkoblinger: + + + + Since startup: + Siden oppstart: + + + + Processed 0 person-to-person messages. + Behandlet 0 person-til-person meldinger. + + + + Processed 0 public keys. + Behandlet 0 offentlige nøkler. + + + + Processed 0 broadcasts. + Behandlet 0 meldinger. + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + Objekter som skal synkroniseres: + + + + Stream # + + + + + Connections + Tilkoblinger + + + + Since startup on %1 + Siden oppstart på %1 + + + + Down: %1/s Total: %2 + Ned: %1/s Totalt: %2 + + + + Up: %1/s Total: %2 + Opp: %1/s Totalt: %2 + + + + Total Connections: %1 + Antall tilkoblinger: %1 + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + + + newChanDialog Dialog - Opprett ny kanal + Dialog @@ -1409,7 +1695,7 @@ The 'Random Number' option is selected by default but deterministic ad <html><head/><body><p>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.</p></body></html> - <html><head/><body><p>Skriv inn et navn for kanalen din. Hvis du velger et komplisert nok kanalnavn (et som er langt nok og unikt som passfrase) og ingen av dine kontakter deler det offentlig vil kanalen være sikker og privat. Hvis du og noen andre begge oppretter en kanal med samme kanalnavnet vil dette bli samme kanalen</p></body></html> + <html><head/><body><p>Skriv inn et navn for kanalen din. Hvis du velger et komplisert nok kanalnavn (et som er langt nok og unikt som passfrase) og ingen av dine kontakter deler det offentlig vil kanalen være sikker og privat. Hvis du og noen andre begge oppretter en kanal med samme kanalnavnet vil dette bli samme kanalen</p></body></html> @@ -1419,7 +1705,7 @@ The 'Random Number' option is selected by default but deterministic ad <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> - <html><head/><body><p>En kanal eksisterer når en gruppe personer deler de samme dekrypteringsnøklene. Nøklene og Bitmessage-adressen brukt av kanalen er generert fra et menneskevennlig ord eller en frase (kanalnavnet). For å sende en beskjed til alle som er i kanalen sender man en vanlig beskjed av typen person-til-person til kanaladressen.</p><p>Kanaler er fullstendig umodererbare og eksperimentelle.</p></body></html> + <html><head/><body><p>En kanal eksisterer når en gruppe personer deler de samme dekrypteringsnøklene. Nøklene og Bitmessage-adressen brukt av kanalen er generert fra et menneskevennlig ord eller en frase (kanalnavnet). For å sende en beskjed til alle som er i kanalen sender man en vanlig beskjed av typen person-til-person til kanaladressen.</p><p>Kanaler er fullstendig umodererbare og eksperimentelle.</p></body></html> @@ -1447,22 +1733,17 @@ The 'Random Number' option is selected by default but deterministic ad Number of addresses to make based on your passphrase: - Antall adresser som skal opprettes basert på din passordfrase: + Antall adresser som skal opprettes basert på din passordfrase: - - Address version Number: - Adressetypenummer: - - - - 3 - 3 + + Address version number: + Adressetypenummer: Stream number: - Strømnummer: + Strømnummer: @@ -1472,335 +1753,311 @@ The 'Random Number' option is selected by default but deterministic ad Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter - Bruk ekstra tid på å få adressen(e) en eller to tegn kortere + Bruk ekstra tid på å få adressen(e) en eller to tegn kortere You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. - Du må krysse av for (eller ikke krysse av for) i denne boksen slik du gjorde når du opprettet adressene dine første gangen. + Du må krysse av for (eller ikke krysse av for) i denne boksen slik du gjorde når du opprettet adressene dine første gangen. 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. - Hvis du tidligere har opprettet deterministiske adresser, men mistet dem p.g.a. et uhell (f.eks. harddiskkræsj) så kan de regenereres her. Hvis du derimot brukte generatoren for generering av tilfeldige tall vil ikke dette skjemaet være til hjelp for deg. - - - - Address version number: - Adressetypenummer: + Hvis du tidligere har opprettet deterministiske adresser, men mistet dem p.g.a. et uhell (f.eks. harddiskkræsj) så kan de regenereres her. Hvis du derimot brukte generatoren for generering av tilfeldige tall vil ikke dette skjemaet være til hjelp for deg. settingsDialog - + Settings Innstillinger - + Start Bitmessage on user login - Start Bitmessage ved brukerpålogging + Start Bitmessage ved brukerpålogging - + + Tray + + + + Start Bitmessage in the tray (don't show main window) Start Bitmessage i systemstatusfeltet (ikke vis hovedvinduet) - + Minimize to tray Minimiser til systemstatusfeltet - - - Show notification when message received - Vis varsel når beskjed mottas - - - - Run in Portable Mode - Kjør i flyttbar modus - - - - 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. - I flyttbar modus blir beskjeder og konfigurasjonsfiler oppbevart i samme katalog som programmet istedet for den vanlige applikasjonsdatamappen. Dette gjør Bitmessage enkel å kjøre fra f.eks. minnepinne. - - - - User Interface - Brukergrensesnitt - - - - Listening port - Lyttende port - - - - Listen for connections on port: - Lytt etter tilkoblinger på port: - - - - Proxy server / Tor - Proxytjener / Tor - - - - Type: - Type: - - - - none - ingen - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - - Server hostname: - Tjenernavn: - - - - Port: - Port: - - - - Authentication - Autentisering - - - - Username: - Brukernavn: - - - - Pass: - Passord: - - - - Network Settings - Nettverksinnstillinger - - - - 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. - Når noen sender deg en beskjed må først datamaskin deres fullføre en arbeidsoppgave. Vanskelighetsgraden for denne oppgaven er satt til 1 som standard. Du kan heve denne grensen for nye adresser du oppretter ved å endre på verdiene her. Alle nye adresser du oppretter vil kreve av avsender å løse enda vanskeligere oppgaver. Det finnes èt unntak: Hvis du legger til en kontakt i din adressebok vil de bli varslet neste gang du sender en beskjed om at de kun trenger å utføre enkleste form for arbeidsoppgave, denne har vanskelighetsgrad 1. - - - - Total difficulty: - Total vanskelighet: - - - - Small message difficulty: - Vanskelighet for kort beskjed: - - - - 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. - 'Vanskelighet for kort beskjed' vil kun påvirke sending av korte beskjeder. Dobling av denne verdien vil også doble vanskeligheten for å sende en kort beskjed. - - - - The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - 'Total vanskelighet' påvirker den absolutte mengden av arbeid som avsender må fullføre. Dobling av denne verdien dobler også arbeidsmengden. - - - - Demanded difficulty - Krevd vanskelighet - - - - 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. - Her kan du sette den maksimale mengden med arbeid som du er villig til å gjennomføre for å sende en beskjed til en annen person. Om disse verdiene settes til null vil alle verdier bli akseptert. - - - - Maximum acceptable total difficulty: - Maks akseptabel total vanskelighet: - - - - Maximum acceptable small message difficulty: - Maks akseptabel vanskelighet for korte beskjeder: - - - - Max acceptable difficulty - Maks akseptabel vanskelighet - - - - Willingly include unencrypted destination address when sending to a mobile device - Inkluder med vilje ukrypterte destinasjonadresser når mobil enhet er mottaker - - - - Override automatic language localization (use countycode or language code, e.g. 'en_US' or 'en'): - Overstyr automatisk språklokalisering (bruk land- eller språkkode, f.eks. 'en_US' eller 'en'):) - - - - Listen for incoming connections when using proxy - Lytt etter innkommende tilkoblinger når proxy benyttes - - - - <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> - <html><head/><body><p>Bitmessage kan benytte et annet Bitcoin-basert program ved navn Namecoin for å lage menneskevennlige adresser. For eksempel, istedet for å fortelle din kontakt din lange Bitmessage-adresse så kan du enkelt fortelle vedkommende at beskjeden skal sendes til <span style=" font-style:italic;">test. </span></p><p>(å få din egen adresse inn Namecoin er fortsatt ganske vanskelig).</p><p>Bitmessage kan bruke enten namecoind direkte eller en kjørende instans av nmcontrol.</p></body></html> - - - - Host: - Vert: - - - - Password: - Passord: - - - - Test - Test - - Connect to: - Koble til: + Close to tray + - Namecoind - Namecoind + Show notification when message received + Vis varsel når beskjed mottas - NMControl - NMControl + Run in Portable Mode + Kjør i flyttbar modus - Namecoin integration - Namecoin-integrasjon + 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. + I flyttbar modus blir beskjeder og konfigurasjonsfiler oppbevart i samme katalog som programmet istedet for den vanlige applikasjonsdatamappen. Dette gjør Bitmessage enkel å kjøre fra f.eks. minnepinne. - + + Willingly include unencrypted destination address when sending to a mobile device + Inkluder med vilje ukrypterte destinasjonadresser når mobil enhet er mottaker + + + Use Identicons Bruk identikoner - - Interface Language - Grensesnittspråk + + Reply below Quote + Svar under sitat - + + Interface Language + Grensesnittspråk + + + System Settings system Systeminnstillinger - - English - en - Engelsk + + User Interface + Brukergrensesnitt - - Esperanto - eo - Esperanto + + Listening port + Lyttende port - - Français - fr - Fransk + + Listen for connections on port: + Lytt etter tilkoblinger på port: - - Deutsch - de - Tysk + + UPnP: + UPnP: - - Españl - es - Spansk + + Bandwidth limit + Båndbredde grense - - русский язык - ru - Russisk + + Maximum download rate (kB/s): [0: unlimited] + - - Norwegian - no - Norsk + + Maximum upload rate (kB/s): [0: unlimited] + - - Pirate English - en_pirate - Piratengelsk + + Proxy server / Tor + Proxytjener / Tor - - Other (set in keys.dat) - other - Annet (sett inn keys.dat) + + Type: + Type: - + + Server hostname: + Tjenernavn: + + + + Port: + Port: + + + + Authentication + Autentisering + + + + Username: + Brukernavn: + + + + Pass: + Passord: + + + + Listen for incoming connections when using proxy + Lytt etter innkommende tilkoblinger når proxy benyttes + + + + none + ingen + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Nettverksinnstillinger + + + + Total difficulty: + Total vanskelighet: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + 'Total vanskelighet' påvirker den absolutte mengden av arbeid som avsender må fullføre. Dobling av denne verdien dobler også arbeidsmengden. + + + + Small message difficulty: + Vanskelighet for kort beskjed: + + + + 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. + Når noen sender deg en beskjed må først datamaskin deres fullføre en arbeidsoppgave. Vanskelighetsgraden for denne oppgaven er satt til 1 som standard. Du kan heve denne grensen for nye adresser du oppretter ved å endre på verdiene her. Alle nye adresser du oppretter vil kreve av avsender å løse enda vanskeligere oppgaver. Det finnes èt unntak: Hvis du legger til en kontakt i din adressebok vil de bli varslet neste gang du sender en beskjed om at de kun trenger å utføre enkleste form for arbeidsoppgave, denne har vanskelighetsgrad 1. + + + + 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. + 'Vanskelighet for kort beskjed' vil kun påvirke sending av korte beskjeder. Dobling av denne verdien vil også doble vanskeligheten for å sende en kort beskjed. + + + + Demanded difficulty + Krevd vanskelighet + + + + 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. + Her kan du sette den maksimale mengden med arbeid som du er villig til å gjennomføre for å sende en beskjed til en annen person. Om disse verdiene settes til null vil alle verdier bli akseptert. + + + + Maximum acceptable total difficulty: + Maks akseptabel total vanskelighet: + + + + Maximum acceptable small message difficulty: + Maks akseptabel vanskelighet for korte beskjeder: + + + + Max acceptable difficulty + Maks akseptabel vanskelighet + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + <html><head/><body><p>Bitmessage kan benytte et annet Bitcoin-basert program ved navn Namecoin for å lage menneskevennlige adresser. For eksempel, istedet for å fortelle din kontakt din lange Bitmessage-adresse så kan du enkelt fortelle vedkommende at beskjeden skal sendes til <span style=" font-style:italic;">test. </span></p><p>(å få din egen adresse inn Namecoin er fortsatt ganske vanskelig).</p><p>Bitmessage kan bruke enten namecoind direkte eller en kjørende instans av nmcontrol.</p></body></html> + + + + Host: + Vert: + + + + Password: + Passord: + + + + Test + Test + + + + Connect to: + Koble til: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Namecoin-integrasjon + + + <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> - <html><head/><body><p>Som standard er det slik at hvis du sender en beskjed til noen og de er frakoblet i mer enn to dager så vil Bitmessage sende beskjeden på nytt igjen etter at det er gått to ekstra dager. Sånn vil det holde på fremover med eksponentiell vekst; beskjeder sendes på nytt etter 8, 16, 32 dager o.s.v., helt til mottakeren erkjenner dem. Her kan du endre på denne oppførselen ved å få Bitmessage til å gi opp etter et bestemt antall dager eller måneder.</p><p>La disse feltene stå tomme for å få standard oppsettet. </p></body></html> + <html><head/><body><p>Som standard er det slik at hvis du sender en beskjed til noen og de er frakoblet i mer enn to dager så vil Bitmessage sende beskjeden på nytt igjen etter at det er gått to ekstra dager. Sånn vil det holde på fremover med eksponentiell vekst; beskjeder sendes på nytt etter 8, 16, 32 dager o.s.v., helt til mottakeren erkjenner dem. Her kan du endre på denne oppførselen ved å få Bitmessage til å gi opp etter et bestemt antall dager eller måneder.</p><p>La disse feltene stå tomme for å få standard oppsettet. </p></body></html> - + Give up after Gi opp etter - + and og - + days dager - + months. - måneder. + måneder. - + Resends Expire Igjensending - + \ No newline at end of file diff --git a/src/translations/bitmessage_pl.ts b/src/translations/bitmessage_pl.ts new file mode 100644 index 00000000..a72e9db7 --- /dev/null +++ b/src/translations/bitmessage_pl.ts @@ -0,0 +1,2058 @@ + + + AddAddressDialog + + + Add new entry + + + + + Label + + + + + Address + + + + + EmailGatewayDialog + + + Email gateway + + + + + Register on email gateway + + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + + + MainWindow + + + Reply to sender + + + + + Reply to channel + + + + + Add sender to your Address Book + + + + + Add sender to your Blacklist + + + + + Move to Trash + + + + + Undelete + + + + + View HTML code as formatted text + + + + + Save message as... + + + + + Mark Unread + + + + + New + + + + + Enable + + + + + Disable + + + + + Set avatar... + + + + + Copy address to clipboard + + + + + Special address behavior... + + + + + Email gateway + + + + + Delete + + + + + Send message to this address + + + + + Subscribe to this address + + + + + Add New Address + + + + + Copy destination address to clipboard + + + + + Force send + + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + + + + + Waiting for their encryption key. Will request it again soon. + + + + + Encryption key request queued. + + + + + Queued. + + + + + Message sent. Waiting for acknowledgement. Sent at %1 + + + + + Message sent. Sent at %1 + + + + + Need to do work to send message. Work is queued. + + + + + Acknowledgement of the message received %1 + + + + + Broadcast queued. + + + + + Broadcast on %1 + + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + + + + + Forced difficulty override. Send should start soon. + + + + + Unknown status: %1 %2 + + + + + Not Connected + + + + + Show Bitmessage + + + + + Send + + + + + Subscribe + + + + + Channel + + + + + Quit + + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + + + + + Open keys.dat? + + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + Delete trash? + + + + + Are you sure you want to delete all trashed messages? + + + + + bad passphrase + + + + + You must type your passphrase. If you don't have one then this is not the form for you. + + + + + Bad address version number + + + + + Your address version number must be a number: either 3 or 4. + + + + + Your address version number must be either 3 or 4. + + + + + Chan name needed + + + + + You didn't enter a chan name. + + + + + Address already present + + + + + Could not add chan because it appears to already be one of your identities. + + + + + Success + + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + + + + + Address too new + + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + + + + + Address invalid + + + + + That Bitmessage address is not valid. + + + + + Address does not match chan name + + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + + + + + Successfully joined chan. + + + + + Connection lost + + + + + Connected + + + + + Message trashed + + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + + + + + Error: The address %1 is not typed or copied correctly. Please check it. + + + + + Error: The address %1 contains invalid characters. Please check it. + + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + + + + + Address version number + + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Stream number + + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + + + + + Message queued. + + + + + Your 'To' field is empty. + + + + + Right click one or more entries in your address book and select 'Send message to this address'. + + + + + Fetched address from namecoin identity. + + + + + New Message + + + + + From + + + + + Sending email gateway registration request + + + + + Address is valid. + + + + + The address you entered was invalid. Ignoring it. + + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + + + + + You must restart Bitmessage for the port number change to take effect. + + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + + + + + Number needed + + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + + Will not resend ever + + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + + + + + The passphrase you entered twice doesn't match. Try again. + + + + + Choose a passphrase + + + + + You really do need a passphrase. + + + + + Address is gone + + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + + + + + Address disabled + + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + + + + + Entry added to the Address Book. Edit the label to your liking. + + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + + + + + Undeleted item. + + + + + Save As... + + + + + Write error. + + + + + No addresses selected. + + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + + + + + You have already set an avatar for this address. Do you really want to overwrite it? + + + + + Start-on-login not yet supported on your OS. + + + + + Minimize-to-tray not yet supported on your OS. + + + + + Tray notifications not yet supported on your OS. + + + + + Testing... + + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + + + + + The address should start with ''BM-'' + + + + + The address is not typed or copied correctly (the checksum failed). + + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + + + + + The address contains invalid characters. + + + + + Some data encoded in the address is too short. + + + + + Some data encoded in the address is too long. + + + + + Some data encoded in the address is malformed. + + + + + Enter an address above. + + + + + Address is an old type. We cannot display its past broadcasts. + + + + + There are no recent broadcasts from this address to display. + + + + + You are using TCP port %1. (This can be changed in the settings). + + + + + Bitmessage + + + + + Identities + + + + + New Identity + + + + + Search + + + + + All + + + + + To + + + + + From + + + + + Subject + + + + + Message + + + + + Received + + + + + Messages + + + + + Address book + + + + + Address + + + + + Add Contact + + + + + Fetch Namecoin ID + + + + + Subject: + + + + + From: + + + + + To: + + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + Subscriptions + + + + + Add new Subscription + + + + + Chans + + + + + Add Chan + + + + + File + + + + + Settings + + + + + Help + + + + + Import keys + + + + + Manage keys + + + + + Ctrl+Q + + + + + F1 + + + + + Contact support + + + + + About + + + + + Regenerate deterministic addresses + + + + + Delete all trashed messages + + + + + Join / Create chan + + + + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + + + + + NewAddressDialog + + + Create new Address + + + + + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + + + + + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + + + + + Use a random number generator to make an address + + + + + Use a passphrase to make addresses + + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + Make deterministic addresses + + + + + Address version number: 4 + + + + + In addition to your passphrase, you must remember these numbers: + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Stream number: 1 + + + + + Retype passphrase + + + + + Randomly generate address + + + + + Label (not shown to anyone except you) + + + + + Use the most available stream + + + + + (best if this is the first of many addresses you will create) + + + + + Use the same stream as an existing address + + + + + (saves you some bandwidth and processing power) + + + + + NewSubscriptionDialog + + + Add new entry + + + + + Label + + + + + Address + + + + + Enter an address above. + + + + + SpecialAddressBehaviorDialog + + + Special Address Behavior + + + + + Behave as a normal address + + + + + Behave as a pseudo-mailing-list address + + + + + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + + + + + Name of the pseudo-mailing-list: + + + + + aboutDialog + + + About + + + + + PyBitmessage + + + + + version ? + + + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + + + + + This is Beta software. + + + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + + + + + connectDialog + + + Bitmessage + + + + + Bitmessage won't connect to anyone until you let it. + + + + + Connect now + + + + + Let me configure special network settings first + + + + + helpDialog + + + Help + + + + + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + + + + + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + + + + + iconGlossaryDialog + + + Icon Glossary + + + + + You have no connections with other peers. + + + + + 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'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. + + + + + You are using TCP port ?. (This can be changed in the settings). + + + + + You do have connections with other peers and your firewall is correctly configured. + + + + + networkstatus + + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + + + + + newChanDialog + + + Dialog + + + + + Create a new chan + + + + + Join a chan + + + + + Create a chan + + + + + <html><head/><body><p>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.</p></body></html> + + + + + Chan name: + + + + + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + + + + + Chan bitmessage address: + + + + + regenerateAddressesDialog + + + Regenerate Existing Addresses + + + + + Regenerate existing addresses + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Address version number: + + + + + Stream number: + + + + + 1 + + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + + + + + 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. + + + + + settingsDialog + + + Settings + + + + + Start Bitmessage on user login + + + + + Tray + + + + + Start Bitmessage in the tray (don't show main window) + + + + + Minimize to tray + + + + + Close to tray + + + + + Show notification when message received + + + + + Run in Portable Mode + + + + + 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. + + + + + Willingly include unencrypted destination address when sending to a mobile device + + + + + Use Identicons + + + + + Reply below Quote + + + + + Interface Language + + + + + System Settings + system + + + + + User Interface + + + + + Listening port + + + + + Listen for connections on port: + + + + + UPnP: + + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + + Proxy server / Tor + + + + + Type: + + + + + Server hostname: + + + + + Port: + + + + + Authentication + + + + + Username: + + + + + Pass: + + + + + Listen for incoming connections when using proxy + + + + + none + + + + + SOCKS4a + + + + + SOCKS5 + + + + + Network Settings + + + + + Total difficulty: + + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + + + + + Small message difficulty: + + + + + 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. + + + + + 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. + + + + + Demanded difficulty + + + + + 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. + + + + + Maximum acceptable total difficulty: + + + + + Maximum acceptable small message difficulty: + + + + + Max acceptable difficulty + + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + + + + + Host: + + + + + Password: + + + + + Test + + + + + Connect to: + + + + + Namecoind + + + + + NMControl + + + + + Namecoin integration + + + + + <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> + + + + + Give up after + + + + + and + + + + + days + + + + + months. + + + + + Resends Expire + + + + \ No newline at end of file diff --git a/src/translations/bitmessage_pt.ts b/src/translations/bitmessage_pt.ts new file mode 100644 index 00000000..05be735a --- /dev/null +++ b/src/translations/bitmessage_pt.ts @@ -0,0 +1,2058 @@ + + + AddAddressDialog + + + Add new entry + Adiciona nova entrada + + + + Label + Rótulo + + + + Address + Morada + + + + EmailGatewayDialog + + + Email gateway + + + + + Register on email gateway + Registar na email gateway + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + + + MainWindow + + + Reply to sender + + + + + Reply to channel + + + + + Add sender to your Address Book + + + + + Add sender to your Blacklist + + + + + Move to Trash + + + + + Undelete + + + + + View HTML code as formatted text + + + + + Save message as... + + + + + Mark Unread + + + + + New + + + + + Enable + + + + + Disable + + + + + Set avatar... + + + + + Copy address to clipboard + + + + + Special address behavior... + + + + + Email gateway + + + + + Delete + Apagar + + + + Send message to this address + Enviar mensagem para esta morada + + + + Subscribe to this address + Subscrever esta morada + + + + Add New Address + Adiciona nova morada + + + + Copy destination address to clipboard + Copia morada de destino para o clipboard + + + + Force send + + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + + + + + Waiting for their encryption key. Will request it again soon. + Aguardando chave de encriptação. Novo pedido em breve. + + + + Encryption key request queued. + + + + + Queued. + Em fila + + + + Message sent. Waiting for acknowledgement. Sent at %1 + Mensagem enviada. Aguardando confirmação. Enviada a %1 + + + + Message sent. Sent at %1 + Mensagem enviada. Enviada a 1% + + + + Need to do work to send message. Work is queued. + + + + + Acknowledgement of the message received %1 + + + + + Broadcast queued. + + + + + Broadcast on %1 + + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + + + + + Forced difficulty override. Send should start soon. + + + + + Unknown status: %1 %2 + + + + + Not Connected + Não está ligado + + + + Show Bitmessage + Mostra Bitmessage + + + + Send + Enviar + + + + Subscribe + Subscrever + + + + Channel + Canal + + + + Quit + Desligar + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + + + + + Open keys.dat? + + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + Delete trash? + Esvaziar lixo? + + + + Are you sure you want to delete all trashed messages? + + + + + bad passphrase + + + + + You must type your passphrase. If you don't have one then this is not the form for you. + + + + + Bad address version number + + + + + Your address version number must be a number: either 3 or 4. + + + + + Your address version number must be either 3 or 4. + + + + + Chan name needed + + + + + You didn't enter a chan name. + + + + + Address already present + + + + + Could not add chan because it appears to already be one of your identities. + + + + + Success + + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + + + + + Address too new + + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + + + + + Address invalid + + + + + That Bitmessage address is not valid. + + + + + Address does not match chan name + + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + + + + + Successfully joined chan. + + + + + Connection lost + + + + + Connected + + + + + Message trashed + + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + + + + + Error: The address %1 is not typed or copied correctly. Please check it. + + + + + Error: The address %1 contains invalid characters. Please check it. + + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + + + + + Address version number + + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Stream number + + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + + + + + Message queued. + + + + + Your 'To' field is empty. + + + + + Right click one or more entries in your address book and select 'Send message to this address'. + + + + + Fetched address from namecoin identity. + + + + + New Message + + + + + From + + + + + Sending email gateway registration request + + + + + Address is valid. + + + + + The address you entered was invalid. Ignoring it. + + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + + + + + You must restart Bitmessage for the port number change to take effect. + + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + + + + + Number needed + + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + + Will not resend ever + + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + + + + + The passphrase you entered twice doesn't match. Try again. + + + + + Choose a passphrase + + + + + You really do need a passphrase. + + + + + Address is gone + + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + + + + + Address disabled + + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + + + + + Entry added to the Address Book. Edit the label to your liking. + + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + + + + + Undeleted item. + + + + + Save As... + + + + + Write error. + + + + + No addresses selected. + + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + + + + + You have already set an avatar for this address. Do you really want to overwrite it? + + + + + Start-on-login not yet supported on your OS. + + + + + Minimize-to-tray not yet supported on your OS. + + + + + Tray notifications not yet supported on your OS. + + + + + Testing... + + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + + + + + The address should start with ''BM-'' + + + + + The address is not typed or copied correctly (the checksum failed). + + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + + + + + The address contains invalid characters. + + + + + Some data encoded in the address is too short. + + + + + Some data encoded in the address is too long. + + + + + Some data encoded in the address is malformed. + + + + + Enter an address above. + + + + + Address is an old type. We cannot display its past broadcasts. + + + + + There are no recent broadcasts from this address to display. + + + + + You are using TCP port %1. (This can be changed in the settings). + + + + + Bitmessage + + + + + Identities + + + + + New Identity + + + + + Search + + + + + All + + + + + To + + + + + From + + + + + Subject + + + + + Message + + + + + Received + + + + + Messages + + + + + Address book + + + + + Address + + + + + Add Contact + + + + + Fetch Namecoin ID + + + + + Subject: + + + + + From: + + + + + To: + + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + Subscriptions + + + + + Add new Subscription + + + + + Chans + + + + + Add Chan + + + + + File + + + + + Settings + + + + + Help + + + + + Import keys + Importar chaves + + + + Manage keys + Gerir chaves + + + + Ctrl+Q + Ctrl+Q + + + + F1 + + + + + Contact support + + + + + About + Acerca + + + + Regenerate deterministic addresses + + + + + Delete all trashed messages + + + + + Join / Create chan + + + + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + + + + + NewAddressDialog + + + Create new Address + + + + + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + + + + + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + + + + + Use a random number generator to make an address + + + + + Use a passphrase to make addresses + + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + Make deterministic addresses + + + + + Address version number: 4 + + + + + In addition to your passphrase, you must remember these numbers: + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Stream number: 1 + + + + + Retype passphrase + + + + + Randomly generate address + + + + + Label (not shown to anyone except you) + + + + + Use the most available stream + + + + + (best if this is the first of many addresses you will create) + + + + + Use the same stream as an existing address + + + + + (saves you some bandwidth and processing power) + + + + + NewSubscriptionDialog + + + Add new entry + Adiciona nova entrada + + + + Label + + + + + Address + + + + + Enter an address above. + + + + + SpecialAddressBehaviorDialog + + + Special Address Behavior + + + + + Behave as a normal address + + + + + Behave as a pseudo-mailing-list address + + + + + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + + + + + Name of the pseudo-mailing-list: + + + + + aboutDialog + + + About + Acerca + + + + PyBitmessage + + + + + version ? + versão? + + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + + + + + This is Beta software. + Este software é Beta. + + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + Adiciona nova entrada + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + + + + + connectDialog + + + Bitmessage + + + + + Bitmessage won't connect to anyone until you let it. + + + + + Connect now + Ligar agora + + + + Let me configure special network settings first + + + + + helpDialog + + + Help + + + + + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + + + + + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + + + + + iconGlossaryDialog + + + Icon Glossary + + + + + You have no connections with other peers. + + + + + 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'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. + + + + + You are using TCP port ?. (This can be changed in the settings). + + + + + You do have connections with other peers and your firewall is correctly configured. + + + + + networkstatus + + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + + + + + newChanDialog + + + Dialog + + + + + Create a new chan + + + + + Join a chan + + + + + Create a chan + + + + + <html><head/><body><p>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.</p></body></html> + + + + + Chan name: + + + + + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + + + + + Chan bitmessage address: + + + + + regenerateAddressesDialog + + + Regenerate Existing Addresses + + + + + Regenerate existing addresses + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Address version number: + + + + + Stream number: + + + + + 1 + 1 + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + + + + + 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. + + + + + settingsDialog + + + Settings + Configurações + + + + Start Bitmessage on user login + + + + + Tray + + + + + Start Bitmessage in the tray (don't show main window) + + + + + Minimize to tray + + + + + Close to tray + + + + + Show notification when message received + + + + + Run in Portable Mode + + + + + 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. + + + + + Willingly include unencrypted destination address when sending to a mobile device + + + + + Use Identicons + + + + + Reply below Quote + + + + + Interface Language + + + + + System Settings + system + + + + + User Interface + + + + + Listening port + + + + + Listen for connections on port: + + + + + UPnP: + + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + + Proxy server / Tor + + + + + Type: + + + + + Server hostname: + + + + + Port: + Porta: + + + + Authentication + Autenticação + + + + Username: + Nome de utilizador: + + + + Pass: + + + + + Listen for incoming connections when using proxy + + + + + none + nenhum + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Configurações de Rede + + + + Total difficulty: + Dificuldade Máxima: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + + + + + Small message difficulty: + + + + + 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. + + + + + 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. + + + + + Demanded difficulty + + + + + 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. + + + + + Maximum acceptable total difficulty: + + + + + Maximum acceptable small message difficulty: + + + + + Max acceptable difficulty + + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + + + + + Host: + + + + + Password: + Palavra-passe: + + + + Test + Teste + + + + Connect to: + Ligar a: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Integração Namecoin + + + + <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> + + + + + Give up after + + + + + and + e + + + + days + dias + + + + months. + meses + + + + Resends Expire + + + + \ No newline at end of file diff --git a/src/translations/bitmessage_ru.pro b/src/translations/bitmessage_ru.pro deleted file mode 100644 index 5d74581c..00000000 --- a/src/translations/bitmessage_ru.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_objectProcessor.py\ - ../class_outgoingSynSender.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_ru.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_ru.qm b/src/translations/bitmessage_ru.qm index f0bd6342..f4f8dfe4 100644 Binary files a/src/translations/bitmessage_ru.qm and b/src/translations/bitmessage_ru.qm differ diff --git a/src/translations/bitmessage_ru.ts b/src/translations/bitmessage_ru.ts index e72011ca..7cf8ae01 100644 --- a/src/translations/bitmessage_ru.ts +++ b/src/translations/bitmessage_ru.ts @@ -1,6 +1,4 @@ - - - + AddAddressDialog @@ -11,209 +9,343 @@ Label - Имя + Имя Address - Адрес + Адрес + + + + EmailGatewayDialog + + + Email gateway + + + + + Register on email gateway + + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + MainWindow - - One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? - Один из Ваших адресов, %1, является устаревшим адресом версии 1. Адреса версии 1 больше не поддерживаются. Хотите ли Вы удалить его сейчас? + + Reply to sender + - - Reply - Ответить + + Reply to channel + - + Add sender to your Address Book Добавить отправителя в адресную книгу - + + Add sender to your Blacklist + + + + Move to Trash Поместить в корзину - + + Undelete + + + + View HTML code as formatted text Просмотреть HTML код как отформатированный текст - + Save message as... Сохранить сообщение как ... - + + Mark Unread + Отметить как непрочитанное + + + New Новый адрес - + Enable Включить - + Disable Выключить - + + Set avatar... + + + + Copy address to clipboard Скопировать адрес в буфер обмена - + Special address behavior... Особое поведение адресов... - - Send message to this address - Отправить сообщение на этот адрес + + Email gateway + - - Subscribe to this address - Подписаться на рассылку с этого адреса - - - - Add New Address - Добавить новый адрес - - - + Delete Удалить - + + Send message to this address + Отправить сообщение на этот адрес + + + + Subscribe to this address + Подписаться на рассылку с этого адреса + + + + Add New Address + Добавить новый адрес + + + Copy destination address to clipboard Скопировать адрес отправки в буфер обмена - + Force send Форсировать отправку - - Add new entry - Добавить новую запись + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + Один из Ваших адресов, %1, является устаревшим адресом версии 1. Адреса версии 1 больше не поддерживаются. Хотите ли Вы удалить его сейчас? - + Waiting for their encryption key. Will request it again soon. Ожидаем ключ шифрования от Вашего собеседника. Запрос будет повторен через некоторое время. - + Encryption key request queued. Запрос ключа шифрования поставлен в очередь. - + Queued. В очереди. - + Message sent. Waiting for acknowledgement. Sent at %1 Сообщение отправлено. Ожидаем подтверждения. Отправлено в %1 - + + Message sent. Sent at %1 + Сообщение отправлено в %1 + + + Need to do work to send message. Work is queued. Нужно провести требуемые вычисления, чтобы отправить сообщение. Вычисления ожидают очереди. - + Acknowledgement of the message received %1 Сообщение доставлено в %1 - + Broadcast queued. Рассылка ожидает очереди. - + Broadcast on %1 Рассылка на %1 - + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 Проблема: Ваш получатель требует более сложных вычислений, чем максимум, указанный в Ваших настройках. %1 - + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 Проблема: ключ получателя неправильный. Невозможно зашифровать сообщение. %1 - + Forced difficulty override. Send should start soon. Форсирована смена сложности. Отправляем через некоторое время. - + Unknown status: %1 %2 Неизвестный статус: %1 %2 - - Since startup on %1 - С начала работы в %1 - - - + Not Connected Не соединено - + Show Bitmessage Показать Bitmessage - + Send Отправить - + Subscribe Подписки - - Address Book - Адресная книга + + Channel + - + Quit Выйти - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Вы можете управлять Вашими ключами, отредактировав файл keys.dat, находящийся в той же папке, что и эта программа. Создайте резервную копию этого файла перед тем как будете его редактировать. - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. @@ -222,19 +354,19 @@ It is important that you back up this file. Создайте резервную копию этого файла перед тем как будете его редактировать. - + Open keys.dat? Открыть файл keys.dat? - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) Вы можете управлять Вашими ключами, отредактировав файл keys.dat, находящийся в той же папке, что и эта программа. Создайте резервную копию этого файла перед тем как будете его редактировать. Хотели бы Вы открыть этот файл сейчас? (пожалуйста, закройте Bitmessage до того как Вы внесёте в этот файл какие-либо изменения.) - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) @@ -244,785 +376,898 @@ It is important that you back up this file. Would you like to open the file now? (пожалуйста, закройте Bitmessage до того как Вы внесёте в этот файл какие-либо изменения.) - + Delete trash? Очистить корзину? - + Are you sure you want to delete all trashed messages? Вы уверены что хотите очистить корзину? - + bad passphrase Неподходящая секретная фраза - + You must type your passphrase. If you don't have one then this is not the form for you. Вы должны ввести секретную фразу. Если Вы не хотите этого делать, то Вы выбрали неправильную опцию. - - Processed %1 person-to-person messages. - Обработано %1 сообщений. + + Bad address version number + - - Processed %1 broadcast messages. - Обработано %1 рассылок. + + Your address version number must be a number: either 3 or 4. + - - Processed %1 public keys. - Обработано %1 открытых ключей. + + Your address version number must be either 3 or 4. + - - Total Connections: %1 - Всего соединений: %1 - - - - Connection lost - Соединение потеряно - - - - Connected - Соединено - - - - Message trashed - Сообщение удалено - - - - Error: Bitmessage addresses start with BM- Please check %1 - Ошибка: Bitmessage адреса начинаются с BM- Пожалуйста, проверьте %1 - - - - Error: The address %1 is not typed or copied correctly. Please check it. - Ошибка: адрес %1 внесен или скопирован неправильно. Пожалуйста, перепроверьте. - - - - Error: The address %1 contains invalid characters. Please check it. - Ошибка: адрес %1 содержит запрещённые символы. Пожалуйста, перепроверьте. - - - - Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. - Ошибка: версия адреса в %1 слишком новая. Либо Вам нужно обновить Bitmessage, либо Ваш собеседник дал неправильный адрес. - - - - Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. - Ошибка: некоторые данные, закодированные в адресе %1, слишком короткие. Возможно, что-то не так с программой Вашего собеседника. - - - - Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. - Ошибка: некоторые данные, закодированные в адресе %1, слишком длинные. Возможно, что-то не так с программой Вашего собеседника. - - - - Error: Something is wrong with the address %1. - Ошибка: что-то не так с адресом %1. - - - - Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. - Вы должны указать адрес в поле "От кого". Вы можете найти Ваш адрес во вкладе "Ваши Адреса". - - - - Sending to your address - Отправка на Ваш собственный адрес - - - - Error: One of the addresses to which you are sending a message, %1, is yours. Unfortunately the Bitmessage client cannot process its own messages. Please try running a second client on a different computer or within a VM. - Ошибка: Один из адресов, на который Вы отправляете сообщение, %1, принадлежит Вам. К сожалению, Bitmessage не может отправлять сообщения самому себе. Попробуйте запустить второго клиента на другом компьютере или на виртуальной машине. - - - - Address version number - Версия адреса - - - - Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. - По поводу адреса %1: Bitmessage не поддерживаем адреса версии %2. Возможно, Вам нужно обновить клиент Bitmessage. - - - - Stream number - Номер потока - - - - Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. - По поводу адреса %1: Bitmessage не поддерживаем стрим номер %2. Возможно, Вам нужно обновить клиент Bitmessage. - - - - Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. - Внимание: Вы не подключены к сети. Bitmessage проделает необходимые вычисления, чтобы отправить сообщение, но не отправит его до тех пор, пока Вы не подсоединитесь к сети. - - - - Your 'To' field is empty. - Вы не заполнили поле 'Кому'. - - - - Work is queued. - Вычисления поставлены в очередь. - - - - Right click one or more entries in your address book and select 'Send message to this address'. - Нажмите правую кнопку мыши на каком-либо адресе и выберите "Отправить сообщение на этот адрес". - - - - Work is queued. %1 - Вычисления поставлены в очередь. %1 - - - - New Message - Новое сообщение - - - - From - От - - - - Address is valid. - Адрес введен правильно. - - - - Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. - Ошибка: Вы не можете добавлять один и тот же адрес в Адресную Книгу несколько раз. Попробуйте переименовать существующий адрес. - - - - The address you entered was invalid. Ignoring it. - Вы ввели неправильный адрес. Это адрес проигнорирован. - - - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - Ошибка: Вы не можете добавлять один и тот же адрес в подписку несколько раз. Просто переименуйте существующую подписку. - - - - Restart - Перезапустить - - - - You must restart Bitmessage for the port number change to take effect. - Вы должны перезапустить Bitmessage, чтобы смена номера порта имела эффект. - - - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections. - Bitmessage будет использовать Ваш прокси в дальнейшем, тем не менее, мы рекомендуем перезапустить Bitmessage вручную, чтобы закрыть уже существующие соединения. - - - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - Ошибка: Вы не можете добавлять один и тот же адрес в список несколько раз. Просто переименуйте существующий адрес. - - - - Passphrase mismatch - Секретная фраза не подходит - - - - The passphrase you entered twice doesn't match. Try again. - Вы ввели две разные секретные фразы. Пожалуйста, повторите заново. - - - - Choose a passphrase - Придумайте секретную фразу - - - - You really do need a passphrase. - Вы действительно должны ввести секретную фразу. - - - - All done. Closing user interface... - Программа завершена. Закрываем пользовательский интерфейс... - - - - Address is gone - Адрес утерян - - - - Bitmessage cannot find your address %1. Perhaps you removed it? - Bitmessage не может найти Ваш адрес %1. Возможно Вы удалили его? - - - - Address disabled - Адрес выключен - - - - Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. - Ошибка: адрес, с которого Вы пытаетесь отправить, выключен. Вам нужно будет включить этот адрес во вкладке "Ваши адреса". - - - - Entry added to the Address Book. Edit the label to your liking. - Запись добавлена в Адресную Книгу. Вы можете её отредактировать. - - - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - Удалено в корзину. Чтобы попасть в корзину, Вам нужно будет найти файл корзины на диске. - - - - Save As... - Сохранить как ... - - - - Write error. - Ошибка записи. - - - - No addresses selected. - Вы не выбрали адрес. - - - - Options have been disabled because they either aren't applicable or because they haven't yet been implemented for your operating system. - Опции были отключены, потому что они либо не подходят, либо еще не выполнены под Вашу операционную систему. - - - - The address should start with ''BM-'' - Адрес должен начинаться с "BM-" - - - - The address is not typed or copied correctly (the checksum failed). - Адрес введен или скопирован неверно (контрольная сумма не сходится). - - - - The version number of this address is higher than this software can support. Please upgrade Bitmessage. - Версия этого адреса более поздняя, чем Ваша программа. Пожалуйста, обновите программу Bitmessage. - - - - The address contains invalid characters. - Адрес содержит запрещённые символы. - - - - Some data encoded in the address is too short. - Данные, закодированные в адресе, слишком короткие. - - - - Some data encoded in the address is too long. - Данные, закодированные в адресе, слишком длинные. - - - - You are using TCP port %1. (This can be changed in the settings). - Вы используете TCP порт %1. (Его можно поменять в настройках). - - - - Bitmessage - Bitmessage - - - - To - Кому - - - - From - От кого - - - - Subject - Тема - - - - Received - Получено - - - - Inbox - Входящие - - - - Load from Address book - Взять из адресной книги - - - - Message: - Сообщение: - - - - Subject: - Тема: - - - - Send to one or more specific people - Отправить одному или нескольким указанным получателям - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - To: - Кому: - - - - From: - От: - - - - Broadcast to everyone who is subscribed to your address - Рассылка всем, кто подписался на Ваш адрес - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - Пожалуйста, учитывайте, что рассылки шифруются лишь Вашим адресом. Любой человек, который знает Ваш адрес, сможет прочитать Вашу рассылку. - - - - Status - Статус - - - - Sent - Отправленные - - - - Label (not shown to anyone) - Имя (не показывается никому) - - - - Address - Адрес - - - - Stream - Поток - - - - Your Identities - Ваши Адреса - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - Здесь Вы можете подписаться на рассылки от других пользователей. Все рассылки будут появляться у Вас во Входящих. Вы будете следить за всеми адресами, указанными здесь, даже если они в чёрном списке. - - - - Add new Subscription - Добавить новую подписку - - - - Label - Имя - - - - Subscriptions - Подписки - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - Адресная книга удобна для присвоения осмысленных имен Bitmessage адресам Ваших друзей. Вы можете добавлять новые записи с помощью кнопки "Добавить новую запись", или же правым кликом мыши на сообщения. - - - - Name or Label - Имя - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - Использовать чёрный список (Разрешить все входящие сообщения, кроме указанных в чёрном списке) - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - Использовать белый список (блокировать все входящие сообщения, кроме указанных в белом списке) - - - - Blacklist - Чёрный список - - - - Stream # - № потока - - - - Connections - Соединений - - - - Total connections: 0 - Всего соединений: 0 - - - - Since startup at asdf: - С начала работы программы в asdf: - - - - Processed 0 person-to-person message. - Обработано 0 сообщений. - - - - Processed 0 public key. - Обработано 0 открытых ключей. - - - - Processed 0 broadcast. - Обработано 0 рассылок. - - - - Network Status - Статус сети - - - - File - Файл - - - - Settings - Настройки - - - - Help - Помощь - - - - Import keys - Импортировать ключи - - - - Manage keys - Управлять ключами - - - - About - О программе - - - - Regenerate deterministic addresses - Сгенерировать заново все адреса - - - - Delete all trashed messages - Стереть все сообщения из корзины - - - - Message sent. Sent at %1 - Сообщение отправлено в %1 - - - + Chan name needed Требуется имя chan-а - + You didn't enter a chan name. Вы не ввели имя chan-a. - + Address already present Адрес уже существует - + Could not add chan because it appears to already be one of your identities. Не могу добавить chan, потому что это один из Ваших уже существующих адресов. - + Success Отлично - + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. Chan был успешно создан. Чтобы добавить других в сhan, сообщите им имя chan-а и этот Bitmessage адрес: %1. Этот адрес также отображается во вкладке "Ваши Адреса". - + Address too new Адрес слишком новый - + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. Этот Bitmessage адрес похож на правильный, но версия этого адреса слишком новая. Возможно, Вам необходимо обновить программу Bitmessage. - + Address invalid Неправильный адрес - + That Bitmessage address is not valid. Этот Bitmessage адрес введен неправильно. - + Address does not match chan name Адрес не сходится с именем chan-а - + Although the Bitmessage address you entered was valid, it doesn't match the chan name. Вы ввели верный адрес Bitmessage, но он не сходится с именем chan-а. - + Successfully joined chan. Успешно присоединились к chan-у. - - Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). - Bitmessage будет использовать Ваш прокси, начиная прямо сейчас. Тем не менее Вам имеет смысл перезапустить Bitmessage, чтобы закрыть уже существующие соединения. + + Connection lost + Соединение потеряно - - This is a chan address. You cannot use it as a pseudo-mailing list. - Это адрес chan-а. Вы не можете его использовать как адрес рассылки. + + Connected + Соединено - - Search - Поиск + + Message trashed + Сообщение удалено - - All - По всем полям + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + - - Message - Текст сообщения + + Message too long + - - Join / Create chan - Подсоединиться или создать chan + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + - - Mark Unread - Отметить как непрочитанное + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + - + + Error: Bitmessage addresses start with BM- Please check %1 + Ошибка: Bitmessage адреса начинаются с BM- Пожалуйста, проверьте %1 + + + + Error: The address %1 is not typed or copied correctly. Please check it. + Ошибка: адрес %1 внесен или скопирован неправильно. Пожалуйста, перепроверьте. + + + + Error: The address %1 contains invalid characters. Please check it. + Ошибка: адрес %1 содержит запрещённые символы. Пожалуйста, перепроверьте. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + Ошибка: версия адреса в %1 слишком новая. Либо Вам нужно обновить Bitmessage, либо Ваш собеседник дал неправильный адрес. + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + Ошибка: некоторые данные, закодированные в адресе %1, слишком короткие. Возможно, что-то не так с программой Вашего собеседника. + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + Ошибка: некоторые данные, закодированные в адресе %1, слишком длинные. Возможно, что-то не так с программой Вашего собеседника. + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + Ошибка: что-то не так с адресом %1. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Вы должны указать адрес в поле "От кого". Вы можете найти Ваш адрес во вкладе "Ваши Адреса". + + + + Address version number + Версия адреса + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + По поводу адреса %1: Bitmessage не поддерживаем адреса версии %2. Возможно, Вам нужно обновить клиент Bitmessage. + + + + Stream number + Номер потока + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + По поводу адреса %1: Bitmessage не поддерживаем стрим номер %2. Возможно, Вам нужно обновить клиент Bitmessage. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Внимание: Вы не подключены к сети. Bitmessage проделает необходимые вычисления, чтобы отправить сообщение, но не отправит его до тех пор, пока Вы не подсоединитесь к сети. + + + + Message queued. + + + + + Your 'To' field is empty. + Вы не заполнили поле 'Кому'. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Нажмите правую кнопку мыши на каком-либо адресе и выберите "Отправить сообщение на этот адрес". + + + Fetched address from namecoin identity. Получить адрес через Namecoin. - + + New Message + Новое сообщение + + + + From + От + + + + Sending email gateway registration request + + + + + Address is valid. + Адрес введен правильно. + + + + The address you entered was invalid. Ignoring it. + Вы ввели неправильный адрес. Это адрес проигнорирован. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Ошибка: Вы не можете добавлять один и тот же адрес в Адресную Книгу несколько раз. Попробуйте переименовать существующий адрес. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + Перезапустить + + + + You must restart Bitmessage for the port number change to take effect. + Вы должны перезапустить Bitmessage, чтобы смена номера порта имела эффект. + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + Bitmessage будет использовать Ваш прокси, начиная прямо сейчас. Тем не менее Вам имеет смысл перезапустить Bitmessage, чтобы закрыть уже существующие соединения. + + + + Number needed + + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + + Will not resend ever + + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + Секретная фраза не подходит + + + + The passphrase you entered twice doesn't match. Try again. + Вы ввели две разные секретные фразы. Пожалуйста, повторите заново. + + + + Choose a passphrase + Придумайте секретную фразу + + + + You really do need a passphrase. + Вы действительно должны ввести секретную фразу. + + + + Address is gone + Адрес утерян + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmessage не может найти Ваш адрес %1. Возможно Вы удалили его? + + + + Address disabled + Адрес выключен + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Ошибка: адрес, с которого Вы пытаетесь отправить, выключен. Вам нужно будет включить этот адрес во вкладке "Ваши адреса". + + + + Entry added to the Address Book. Edit the label to your liking. + Запись добавлена в Адресную Книгу. Вы можете её отредактировать. + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + Удалено в корзину. + + + + Undeleted item. + + + + + Save As... + Сохранить как ... + + + + Write error. + Ошибка записи. + + + + No addresses selected. + Вы не выбрали адрес. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + + + + + You have already set an avatar for this address. Do you really want to overwrite it? + + + + + Start-on-login not yet supported on your OS. + + + + + Minimize-to-tray not yet supported on your OS. + + + + + Tray notifications not yet supported on your OS. + + + + Testing... Проверяем... - + + This is a chan address. You cannot use it as a pseudo-mailing list. + Это адрес chan-а. Вы не можете его использовать как адрес рассылки. + + + + The address should start with ''BM-'' + Адрес должен начинаться с "BM-" + + + + The address is not typed or copied correctly (the checksum failed). + Адрес введен или скопирован неверно (контрольная сумма не сходится). + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + Версия этого адреса более поздняя, чем Ваша программа. Пожалуйста, обновите программу Bitmessage. + + + + The address contains invalid characters. + Адрес содержит запрещённые символы. + + + + Some data encoded in the address is too short. + Данные, закодированные в адресе, слишком короткие. + + + + Some data encoded in the address is too long. + Данные, закодированные в адресе, слишком длинные. + + + + Some data encoded in the address is malformed. + + + + + Enter an address above. + + + + + Address is an old type. We cannot display its past broadcasts. + + + + + There are no recent broadcasts from this address to display. + + + + + You are using TCP port %1. (This can be changed in the settings). + Вы используете TCP порт %1. (Его можно поменять в настройках). + + + + Bitmessage + Bitmessage + + + + Identities + + + + + New Identity + + + + + Search + Поиск + + + + All + По всем полям + + + + To + Кому + + + + From + От кого + + + + Subject + Тема + + + + Message + Текст сообщения + + + + Received + Получено + + + + Messages + + + + + Address book + + + + + Address + Адрес + + + + Add Contact + + + + Fetch Namecoin ID Получить Namecoin ID - + + Subject: + Тема: + + + + From: + От: + + + + To: + Кому: + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + Subscriptions + Подписки + + + + Add new Subscription + Добавить новую подписку + + + + Chans + + + + + Add Chan + + + + + File + Файл + + + + Settings + Настройки + + + + Help + Помощь + + + + Import keys + Импортировать ключи + + + + Manage keys + Управлять ключами + + + Ctrl+Q Ctrl+Q - + F1 F1 - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> + + Contact support + - - Set avatar... - + + About + О программе - - Bad address version number - + + Regenerate deterministic addresses + Сгенерировать заново все адреса - - Your address version number must be a number: either 3 or 4. - + + Delete all trashed messages + Стереть все сообщения из корзины - - Your address version number must be either 3 or 4. - + + Join / Create chan + Подсоединиться или создать chan - - Inventory lookups per second: %1 - + + All accounts + - - Will not resend ever - + + Zoom level %1% + - - Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. - + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + - - Do you really want to remove this avatar? - + + Add new entry + - - You have already set an avatar for this address. Do you really want to overwrite it? - + + Display the %1 recent broadcast(s) from this address. + - - Start-on-login not yet supported on your OS. - + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + - - Minimize-to-tray not yet supported on your OS. - + + Waiting for PoW to finish... %1% + - - Tray notifications not yet supported on your OS. - + + Shutting down Pybitmessage... %1% + - - Enter an address above. - + + Waiting for objects to be sent... %1% + - - Address is an old type. We cannot display its past broadcasts. - + + Saving settings... %1% + - - There are no recent broadcasts from this address to display. - + + Shutting down core... %1% + - - Display the %1 recent broadcast from this address. - + + Stopping notifications... %1% + - - Display the %1 recent broadcasts from this address. - + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + - - Inventory lookups per second: 0 - + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + @@ -1065,8 +1310,8 @@ The 'Random Number' option is selected by default but deterministic ad - Address version number: 3 - Версия адреса: 3 + Address version number: 4 + @@ -1123,54 +1368,6 @@ The 'Random Number' option is selected by default but deterministic ad (saves you some bandwidth and processing power) (немного сэкономит Вам пропускную способность сети и вычислительную мощь) - - - Address version number: 4 - Версия адреса: 4 - - - - NewChanDialog - - - Dialog - Новый chan - - - - Create a new chan - Создать новый chan - - - - Join a chan - Присоединиться к chan - - - - <html><head/><body><p>A chan is a set of encryption keys that is shared by a group of people. The keys and bitmessage address used by a chan is generated from a human-friendly word or phrase (the chan name).</p><p>Chans are experimental and are unmoderatable.</p></body></html> - <html><head/><body><p>Chan - это набор ключей шифрования, которые известны некоторой группе людей. Ключи и Bitmessage-адрес используемый chan-ом генерируется из слова или фразы (имя chan-а).</p><p>Chan-ы - это экспериментальная новинка.</p></body></html> - - - - Chan name: - Имя chan: - - - - Chan bitmessage address: - Bitmessage адрес chan: - - - - Create a chan - Создать chan - - - - 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. - Введите имя Вашего chan-a. Если Вы выберете достаточно сложное имя для chan-а (например, сложную и необычную секретную фразу) и никто из Ваших друзей не опубликует эту фразу, то Ваш chan будет надёжно зашифрован. - NewSubscriptionDialog @@ -1191,8 +1388,8 @@ The 'Random Number' option is selected by default but deterministic ad - CheckBox - + Enter an address above. + @@ -1240,11 +1437,6 @@ The 'Random Number' option is selected by default but deterministic ad version ? версия ? - - - Copyright © 2013 Jonathan Warren - Копирайт © 2013 Джонатан Уоррен - <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> @@ -1257,8 +1449,46 @@ The 'Random Number' option is selected by default but deterministic ad - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 The Bitmessage Developers</p></body></html> - + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + @@ -1293,8 +1523,8 @@ The 'Random Number' option is selected by default but deterministic ad - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + @@ -1330,6 +1560,119 @@ The 'Random Number' option is selected by default but deterministic ad Вы установили соединение с другими участниками сети и ваш файрвол настроен правильно. + + networkstatus + + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + + + newChanDialog @@ -1353,9 +1696,9 @@ The 'Random Number' option is selected by default but deterministic ad Создать chan - - 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. - Введите имя Вашего chan-a. Если Вы выберете достаточно сложное имя для chan-а (например, сложную и необычную секретную фразу) и никто из Ваших друзей не опубликует эту фразу, то Ваш chan будет надёжно зашифрован. + + <html><head/><body><p>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.</p></body></html> + <html><head/><body><p>Введите имя Вашего chan-a. Если Вы выберете достаточно сложное имя для chan-а (например, сложную и необычную секретную фразу) и никто из Ваших друзей не опубликует эту фразу, то Ваш chan будет надёжно зашифрован. Если Вы и кто-то другой независимо создадите chan с полностью идентичным именем, то скорее всего Вы получите в итоге один и тот же chan.</p></body></html> @@ -1372,11 +1715,6 @@ The 'Random Number' option is selected by default but deterministic ad Chan bitmessage address: Bitmessage адрес chan: - - - <html><head/><body><p>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.</p></body></html> - <html><head/><body><p>Введите имя Вашего chan-a. Если Вы выберете достаточно сложное имя для chan-а (например, сложную и необычную секретную фразу) и никто из Ваших друзей не опубликует эту фразу, то Ваш chan будет надёжно зашифрован. Если Вы и кто-то другой независимо создадите chan с полностью идентичным именем, то скорее всего Вы получите в итоге один и тот же chan.</p></body></html> - regenerateAddressesDialog @@ -1401,14 +1739,9 @@ The 'Random Number' option is selected by default but deterministic ad Кол-во адресов, которые Вы хотите получить из Вашей секретной фразы: - - Address version Number: - Версия адреса: - - - - 3 - 3 + + Address version number: + @@ -1435,330 +1768,299 @@ The 'Random Number' option is selected by default but deterministic ad 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. Если Вы ранее создавали детерминистические адреса, но случайно потеряли их, Вы можете их восстановить здесь. Если же Вы использовали генератор случайных чисел чтобы создать Ваши адреса, то Вы не сможете их здесь восстановить. - - - Address version number: - - settingsDialog - + Settings Настройки - + Start Bitmessage on user login Запускать Bitmessage при входе в систему - + + Tray + + + + Start Bitmessage in the tray (don't show main window) Запускать Bitmessage в свернутом виде (не показывать главное окно) - + Minimize to tray Сворачивать в трей - + + Close to tray + + + + Show notification when message received Показывать уведомления при получении новых сообщений - + Run in Portable Mode Запустить в переносном режиме - + 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. В переносном режиме, все сообщения и конфигурационные файлы сохраняются в той же самой папке что и сама программа. Это делает более удобным использование Bitmessage с USB-флэшки. - - User Interface - Пользовательские - - - - Listening port - Порт прослушивания - - - - Listen for connections on port: - Прослушивать соединения на порту: - - - - Proxy server / Tor - Прокси сервер / Tor - - - - Type: - Тип: - - - - none - отсутствует - - - - SOCKS4a - SOCKS4a - - - - SOCKS5 - SOCKS5 - - - - Server hostname: - Адрес сервера: - - - - Port: - Порт: - - - - Authentication - Авторизация - - - - Username: - Имя пользователя: - - - - Pass: - Прль: - - - - Network Settings - Сетевые настройки - - - - 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. - Когда кто-либо отправляет Вам сообщение, его компьютер должен сперва решить определённую вычислительную задачу. Сложность этой задачи по умолчанию равна 1. Вы можете повысить эту сложность для новых адресов, которые Вы создадите, здесь. Таким образом, любые новые адреса, которые Вы создадите, могут требовать от отправителей сложность большую чем 1. Однако, есть одно исключение: если Вы специально добавите Вашего собеседника в адресную книгу, то Bitmessage автоматически уведомит его о том, что для него минимальная сложность будет составлять всегда всего лишь 1. - - - - Total difficulty: - Общая сложность: - - - - Small message difficulty: - Сложность для маленьких сообщений: - - - - 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. - "Сложность для маленьких сообщений" влияет исключительно на небольшие сообщения. Увеличив это число в два раза, вы сделаете отправку маленьких сообщений в два раза сложнее, в то время как сложность отправки больших сообщений не изменится. - - - - The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. - "Общая сложность" влияет на абсолютное количество вычислений, которые отправитель должен провести, чтобы отправить сообщение. Увеличив это число в два раза, вы увеличите в два раза объем требуемых вычислений. - - - - Demanded difficulty - Требуемая сложность - - - - 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. - Здесь Вы можете установить максимальную вычислительную работу, которую Вы согласны проделать, чтобы отправить сообщение другому пользователю. Ноль означает, что любое значение допустимо. - - - - Maximum acceptable total difficulty: - Максимально допустимая общая сложность: - - - - Maximum acceptable small message difficulty: - Максимально допустимая сложность для маленький сообщений: - - - - Max acceptable difficulty - Макс допустимая сложность - - - - Listen for incoming connections when using proxy - Прослушивать входящие соединения если используется прокси - - - + Willingly include unencrypted destination address when sending to a mobile device Специально прикреплять незашифрованный адрес получателя, когда посылаем на мобильное устройство - - <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> - <html><head/><body><p>Bitmessage умеет пользоваться программой Namecoin для того, чтобы сделать адреса более дружественными для пользователей. Например, вместо того, чтобы диктовать Вашему другу длинный и нудный адрес Bitmessage, Вы можете попросить его отправить сообщение на адрес вида <span style=" font-style:italic;">test. </span></p><p>(Перенести Ваш Bitmessage адрес в Namecoin по-прежнему пока довольно сложно).</p><p>Bitmessage может использовать либо прямо namecoind, либо уже запущенную программу nmcontrol.</p></body></html> + + Use Identicons + - - Host: - Адрес: + + Reply below Quote + - - Password: - Пароль: - - - - Test - Проверить - - - - Connect to: - Подсоединиться к: - - - - Namecoind - Namecoind - - - - NMControl - NMControl - - - - Namecoin integration - Интеграция с Namecoin - - - + Interface Language Язык интерфейса - + System Settings system Язык по умолчанию - - - English - en - English - - - - Esperanto - eo - Esperanto - - - - Français - fr - Francais - - - - Deutsch - de - Deutsch - - - - Español - es - Espanol - - - - Русский - ru - Русский - - - - Pirate English - en_pirate - Pirate English - - - - Other (set in keys.dat) - other - Другие (настроено в keys.dat) - - - - Use Identicons - - - - - Españl - es - - - - - русский язык - ru - - - - - Norsk - no - - - - - <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> - - - - - Give up after - - - - - and - - - - - days - - - - - months. - - + User Interface + Пользовательские + + + + Listening port + Порт прослушивания + + + + Listen for connections on port: + Прослушивать соединения на порту: + + + + UPnP: + + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + + Proxy server / Tor + Прокси сервер / Tor + + + + Type: + Тип: + + + + Server hostname: + Адрес сервера: + + + + Port: + Порт: + + + + Authentication + Авторизация + + + + Username: + Имя пользователя: + + + + Pass: + Прль: + + + + Listen for incoming connections when using proxy + Прослушивать входящие соединения если используется прокси + + + + none + отсутствует + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Сетевые настройки + + + + Total difficulty: + Общая сложность: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + "Общая сложность" влияет на абсолютное количество вычислений, которые отправитель должен провести, чтобы отправить сообщение. Увеличив это число в два раза, вы увеличите в два раза объем требуемых вычислений. + + + + Small message difficulty: + Сложность для маленьких сообщений: + + + + 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. + Когда кто-либо отправляет Вам сообщение, его компьютер должен сперва решить определённую вычислительную задачу. Сложность этой задачи по умолчанию равна 1. Вы можете повысить эту сложность для новых адресов, которые Вы создадите, здесь. Таким образом, любые новые адреса, которые Вы создадите, могут требовать от отправителей сложность большую чем 1. Однако, есть одно исключение: если Вы специально добавите Вашего собеседника в адресную книгу, то Bitmessage автоматически уведомит его о том, что для него минимальная сложность будет составлять всегда всего лишь 1. + + + + 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. + "Сложность для маленьких сообщений" влияет исключительно на небольшие сообщения. Увеличив это число в два раза, вы сделаете отправку маленьких сообщений в два раза сложнее, в то время как сложность отправки больших сообщений не изменится. + + + + Demanded difficulty + Требуемая сложность + + + + 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. + Здесь Вы можете установить максимальную вычислительную работу, которую Вы согласны проделать, чтобы отправить сообщение другому пользователю. Ноль означает, что любое значение допустимо. + + + + Maximum acceptable total difficulty: + Максимально допустимая общая сложность: + + + + Maximum acceptable small message difficulty: + Максимально допустимая сложность для маленький сообщений: + + + + Max acceptable difficulty + Макс допустимая сложность + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + <html><head/><body><p>Bitmessage умеет пользоваться программой Namecoin для того, чтобы сделать адреса более дружественными для пользователей. Например, вместо того, чтобы диктовать Вашему другу длинный и нудный адрес Bitmessage, Вы можете попросить его отправить сообщение на адрес вида <span style=" font-style:italic;">test. </span></p><p>(Перенести Ваш Bitmessage адрес в Namecoin по-прежнему пока довольно сложно).</p><p>Bitmessage может использовать либо прямо namecoind, либо уже запущенную программу nmcontrol.</p></body></html> + + + + Host: + Адрес: + + + + Password: + Пароль: + + + + Test + Проверить + + + + Connect to: + Подсоединиться к: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Интеграция с Namecoin + + + + <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> + + + + + Give up after + + + + + and + + + + + days + + + + + months. + + + + Resends Expire - + - + \ No newline at end of file diff --git a/src/translations/bitmessage_sk.qm b/src/translations/bitmessage_sk.qm new file mode 100644 index 00000000..af53f779 Binary files /dev/null and b/src/translations/bitmessage_sk.qm differ diff --git a/src/translations/bitmessage_sk.ts b/src/translations/bitmessage_sk.ts new file mode 100644 index 00000000..25f87902 --- /dev/null +++ b/src/translations/bitmessage_sk.ts @@ -0,0 +1,2111 @@ + + + AddAddressDialog + + + Add new entry + Pridať nový záznam + + + + Label + Označenie + + + + Address + Adresa + + + + EmailGatewayDialog + + + Email gateway + E-mailová brána + + + + Register on email gateway + Registrácia na e-mailovej bráne + + + + Account status at email gateway + Stav účtu na e-mailovej bráne + + + + Change account settings at email gateway + Zmena nastavení účtu na e-mailovej bráne + + + + Unregister from email gateway + Zrušiť registráciu na e-mailovej bráne + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + E-mailové brány umožňujú komunikovať s užívateľmi e-mailu. Momentálne je k dispozícii iba e-mailová brána Mailchuck (@mailchuck.com). + + + + Desired email address (including @mailchuck.com): + Požadovaná e-mailová adresa (vrátane @ mailchuck.com): + + + + EmailGatewayRegistrationDialog + + + Registration failed: + Registrácia zlyhala: + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + Požadovaná e-mailová adresa nie je k dispozícii, skúste znova. Vyplňte novú požadovanú e-mailovú adresu (vrátane @mailchuck.com) nižšie: + + + + Email gateway registration + Registrácia na e-mailovej bráne + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + E-mailové brány umožňujú komunikovať s užívateľmi e-mailu. Momentálne je k dispozícii iba e-mailová brána Mailchuck (@mailchuck.com). +Vyplňte požadovanú e-mailovú adresu (vrátane @mailchuck.com) nižšie: + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + # Tento text môžete použiť na konfiguráciu vášho účtu na e-mailovej bráne +# odkomentujte nastavenia, ktoré chcete použiť +# Tu sú možnosti: +# +# pgp: server +# E-mailová brána bude za vás vytvárať a udržiavať PGP kľúče a podpisovať, overovať, +# šifrovať a dešifrovať vaše e-maily. Ak chcete používať PGP, ale ste leniví, +# toto je voľba pre vás. Vyžaduje predplatné. +# +# pgp: local +# E-mailová brána nebude za vás vykonávať operácie PGP. Môžete buď +# nepoužívať PGP vôbec, alebo ho použiť lokálne. +# +# attachments: yes +# Prichádzajúce prílohy v e-maile budú nahrané na MEGA.nz, a môžete si ich odtiaľ stiahnuť +# pomocou odkazu v správe. Vyžaduje predplatné. +# +# attachments: no +# Prílohy budú ignorované. +# +# archive: yes +# Prichádzajúce e-maily budú archivované na serveri. Použite, ak potrebujete +# pomoc s problémami, alebo potrebujete doklad pre tretie strán o obsahu e-mailov. Táto voľba však +# znamená, že prevádzkovateľ služby budú môcť čítať vaše e-maily +# aj potom, ako vám budú doručené +# +# archive: no +# Prichádzajúce e-maily budú odstránené zo servera, akonáhle vám budú doručené +# +# masterpubkey_btc: BIP44 xpub kľúč alebo electrum v1 základ (seed) +# offset_btc: celé číslo (predvolená 0) +# feeamount: číslo s max. 8 desatinnými miest +# feecurrency: BTC, XBT, USD, EUR alebo GBP +# Ak chcete účtovať ľuďom, ktorí vám posielať e-maily, použite tieto parametre. Ak vám potom +# neznáma osoba pošle e-mail, bude požiadaná o zaplatenie poplatku +# určeného týmito premennými. +# feeamount je výška platby +# feecurrency je mena, v ktorej sa bude počítať +# Keďže systém používa deterministické verejné kľúče, platby obdržíte priamo vy +# Ak ju chcete túto funkciu opäť vypnúť, nastavte "feeamount" na 0. Vyžaduje +# predplatné. + + + + + MainWindow + + + Reply to sender + Odpovedať odosielateľovi + + + + Reply to channel + Odpoveď na kanál + + + + Add sender to your Address Book + Pridať odosielateľa do adresára + + + + Add sender to your Blacklist + Pridať odosielateľa do svojho zoznamu zakázaných + + + + Move to Trash + Presunúť do koša + + + + Undelete + Obnoviť + + + + View HTML code as formatted text + Zobraziť HTML kód ako formátovaný text + + + + Save message as... + Uložiť správu ako... + + + + Mark Unread + Označiť ako neprečítané + + + + New + Nová + + + + Enable + Aktivovať + + + + Disable + Deaktivovať + + + + Set avatar... + Nastaviť avatar ... + + + + Copy address to clipboard + Kopírovať adresu do clipboardu + + + + Special address behavior... + Zvláštne správanie adresy... + + + + Email gateway + E-mailová brána + + + + Delete + Zmazať + + + + Send message to this address + Poslať správu na túto adresu + + + + Subscribe to this address + Prihlásiť sa k odberu tejto adresy + + + + Add New Address + Pridať novú adresu + + + + Copy destination address to clipboard + Kopírovať cieľovú adresu do clipboardu + + + + Force send + Vynútiť odoslanie + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + Jedna z vašich adries, %1, je stará verzia adresy, 1. Verzie adresy 1 už nie sú podporované. Odstrániť ju teraz? + + + + Waiting for their encryption key. Will request it again soon. + Čakanie na šifrovací kľúč príjemcu. Čoskoro bude vyžiadaný znova. + + + + Encryption key request queued. + Požiadavka na šifrovací kľúč je vo fronte. + + + + Queued. + Vo fronte. + + + + Message sent. Waiting for acknowledgement. Sent at %1 + Správa odoslaná. Čakanie na potvrdenie. Odoslaná %1 + + + + Message sent. Sent at %1 + Správa odoslaná. Odoslaná %1 + + + + Need to do work to send message. Work is queued. + Potrebné vykonať prácu pre odoslanie správy. Práca je vo fronte. + + + + Acknowledgement of the message received %1 + Potvrdenie prijatia správy %1 + + + + Broadcast queued. + Rozoslanie vo fronte. + + + + Broadcast on %1 + Rozoslané 1% + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + Problém: práca požadovná príjemcom je oveľa ťažšia, než je povolené v nastaveniach. %1 + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + Problém: šifrovací kľúč príjemcu je nesprávny. Nie je možné zašifrovať správu. %1 + + + + Forced difficulty override. Send should start soon. + Obmedzenie obtiažnosti práce zrušené. Odosielanie by malo čoskoro začať. + + + + Unknown status: %1 %2 + Neznámy stav: %1 %2 + + + + Not Connected + Nepripojený + + + + Show Bitmessage + Ukázať Bitmessage + + + + Send + Odoslať + + + + Subscribe + Prihlásiť sa k odberu + + + + Channel + Kanál + + + + Quit + Ukončiť + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + Kľúče môžete spravovať úpravou súboru keys.dat, ktorý je uložený v rovnakom adresári ako tento program. Tento súbor je dôležité zálohovať. + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + Kľúče môžete spravovať úpravou súboru keys.dat, ktorý je uložený v adresári +%1 +Tento súbor je dôležité zálohovať. + + + + Open keys.dat? + Otvoriť keys.dat? + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Kľúče môžete spravovať úpravou súboru keys.dat, ktorý je uložený v rovnakom adresári ako tento program. Tento súbor je dôležité zálohovať. Chcete tento súbor teraz otvoriť? (Nezabudnite zatvoriť Bitmessage pred vykonaním akýchkoľvek zmien.) + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + Kľúče môžete spravovať úpravou súboru keys.dat, ktorý je uložený v adresári +%1 +Tento súbor je dôležité zálohovať. Chcete tento súbor teraz otvoriť? (Nezabudnite zatvoriť Bitmessage pred vykonaním akýchkoľvek zmien.) + + + + Delete trash? + Vyprázdniť kôš? + + + + Are you sure you want to delete all trashed messages? + Ste si istí, že chcete všetky správy z koša odstrániť? + + + + bad passphrase + zlé heslo + + + + You must type your passphrase. If you don't have one then this is not the form for you. + Je nutné zadať prístupové heslo. Ak heslo nemáte, tento formulár nie je pre Vás. + + + + Bad address version number + Nesprávne číslo verzie adresy + + + + Your address version number must be a number: either 3 or 4. + Číslo verzie adresy musí byť číslo: buď 3 alebo 4. + + + + Your address version number must be either 3 or 4. + Vaše číslo verzie adresy musí byť buď 3 alebo 4. + + + + Chan name needed + Potrebný názov kanálu + + + + You didn't enter a chan name. + Nezadali ste meno kanálu. + + + + Address already present + Adresa už existuje + + + + Could not add chan because it appears to already be one of your identities. + Nemožno pridať kanál, pretože sa zdá, že už existuje ako jedna z vašich identít. + + + + Success + Úspešné + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + Úspešne vytvorený kanál. Ak chcete umožniť ostatným pripojiť váš kanál, dajte im meno kanálu a túto Bitmessage adresu: %1. Táto adresa sa objavuje aj vo "Vaše identity". + + + + Address too new + Adresa príliš nová + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + Aj keď Bitmessage adresa vyzerá byť platná, číslo verzie je príliš nové pre tento program. Možno budete musieť upgradovať Bitmessage. + + + + Address invalid + Adresa neplatná + + + + That Bitmessage address is not valid. + Táto Bitmessage adresa nie je platná. + + + + Address does not match chan name + Adresa nezodpovedá názvu kanálu + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + Hoci zadaná Bitmessage adresa je platná, nezodpovedá názvu kanálu. + + + + Successfully joined chan. + Úspešné pripojenie na kanál. + + + + Connection lost + Spojenie bolo stratené + + + + Connected + Spojený + + + + Message trashed + Správa odstránenia + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + TTL (doba životnosti) je čas, počas ktorého bude sieť udržiavať správu. Príjemca musí správu prijať počas tejto životnosti. Keď odosielateľov Bitmessage nedostane po vypršaní životnosti potvrdenie o prijatí, automaticky správu odošle znova. Čím vyššia doba životnosti, tým viac práce musí počítač odosielateľa vykonat na odoslanie správy. Zvyčajne je vhodná doba životnosti okolo štyroch-piatich dní. + + + + Message too long + Správa je príliš dlhá + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + Správa, ktorú skúšate poslať, má %1 bajtov naviac. (Maximum je 261 644 bajtov). Prosím pred odoslaním skrátiť. + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + Chyba: Váš účet nebol registrovaný na e-mailovej bráne. Skúšam registrovať ako %1, prosím počkajte na spracovanie registrácie pred opakovaným odoslaním správy. + + + + Error: Bitmessage addresses start with BM- Please check %1 + Chyba: Bitmessage adresy začínajú s BM- Prosím skontrolujte %1 + + + + Error: The address %1 is not typed or copied correctly. Please check it. + Chyba: adresa %1 nie je na správne napísaná alebo skopírovaná. Prosím skontrolujte ju. + + + + Error: The address %1 contains invalid characters. Please check it. + Chyba: adresa %1 obsahuje neplatné znaky. Prosím skontrolujte ju. + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + Chyba: verzia adresy %1 je príliš veľká. Buď budete musieť aktualizovať program Bitmessage alebo váš známy s vami žartuje. + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + Chyba: niektoré údaje zakódované v adrese %1 sú príliš krátke. Softér vášho známeho možno nefunguje správne. + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + Chyba: niektoré údaje zakódované v adrese %1 sú príliš dlhé. Softvér vášho známeho možno nefunguje správne. + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + Chyba: niektoré údaje zakódované v adrese %1 sú poškodené. Softvér vášho známeho možno nefunguje správne. + + + + Error: Something is wrong with the address %1. + Chyba: niečo s adresou %1 je nie je v poriadku. + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + Chyba: musíte zadať adresu "Od". Ak žiadnu nemáte, prejdite na kartu "Vaše identity". + + + + Address version number + Číslo verzie adresy + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Čo sa týka adresy %1, Bitmessage nepozná číslo verzie adresy %2. Možno by ste mali upgradenúť Bitmessage na najnovšiu verziu. + + + + Stream number + Číslo prúdu + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + Čo sa týka adresy %1, Bitmessage nespracováva číslo prúdu %2. Možno by ste mali upgradenúť Bitmessage na najnovšiu verziu. + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + Upozornenie: momentálne nie ste pripojení. Bitmessage vykoná prácu potrebnú na odoslanie správy, ale odoslať ju môže, až keď budete pripojení. + + + + Message queued. + Správa vo fronte. + + + + Your 'To' field is empty. + Pole "Komu" je prázdne. + + + + Right click one or more entries in your address book and select 'Send message to this address'. + Vybertie jednu alebo viacero položiek v adresári, pravým tlačidlom myši zvoľte "Odoslať správu na túto adresu". + + + + Fetched address from namecoin identity. + Prebratá adresa z namecoin-ovej identity. + + + + New Message + Nová správa + + + + From + Od + + + + Sending email gateway registration request + Odosielam požiadavku o registráciu na e-mailovej bráne + + + + Address is valid. + Adresa je platná. + + + + The address you entered was invalid. Ignoring it. + Zadaná adresa bola neplatná a bude ignorovaná. + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + Chyba: tú istú adresu nemožno pridať do adresára dvakrát. Ak chcete, môžete skúsiť premenovať existujúcu menovku. + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + Chyba: nemožno pridať rovnakú adresu k odberu dvakrát. Keď chcete, môžete premenovať existujúci záznam. + + + + Restart + Reštart + + + + You must restart Bitmessage for the port number change to take effect. + Aby sa zmena čísla portu prejavila, musíte reštartovať Bitmessage. + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + Bitmessage bude odteraz používať proxy, ale ak chcete ukončiť existujúce spojenia, musíte Bitmessage manuálne reštartovať. + + + + Number needed + Číslo potrebné + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + Maxímálna rýchlosť príjmu a odoslania musí byť uvedená v číslach. Ignorujem zadané údaje. + + + + Will not resend ever + Nikdy opätovne neodosielať + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + Upozornenie: časový limit, ktorý ste zadali, je menší ako čas, ktorý Bitmessage čaká na prvý pokus o opätovné zaslanie, a preto vaše správy nebudú nikdy opätovne odoslané. + + + + Sending email gateway unregistration request + Odosielam žiadosť o odhlásenie z e-mailovej brány + + + + Sending email gateway status request + Odosielam požiadavku o stave e-mailovej brány + + + + Passphrase mismatch + Nezhoda hesla + + + + The passphrase you entered twice doesn't match. Try again. + Zadané heslá sa rôznia. Skúste znova. + + + + Choose a passphrase + Vyberte heslo + + + + You really do need a passphrase. + Heslo je skutočne potrebné. + + + + Address is gone + Adresa zmizla + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + Bitmessage nemôže nájsť vašu adresu %1. Možno ste ju odstránili? + + + + Address disabled + Adresa deaktivovaná + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + Chyba: adresa, z ktorej sa pokúšate odoslať, je neaktívna. Pred použitím ju musíte aktivovať v karte "Vaše identity". + + + + Entry added to the Address Book. Edit the label to your liking. + Záznam pridaný do adresára. Upravte označenie podľa vašich predstáv. + + + + Entry added to the blacklist. Edit the label to your liking. + Záznam pridaný na zoznam zakázaných. Upravte označenie podľa vašich predstáv. + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + Chyba: tú istú adresu nemožno pridať na zoznam zakázaných dvakrát. Ak chcete, môžete skúsiť premenovať existujúce označenie. + + + + Moved items to trash. + Položky presunuté do koša. + + + + Undeleted item. + Položka obnovená. + + + + Save As... + Uložiť ako... + + + + Write error. + Chyba pri zapisovaní. + + + + No addresses selected. + Nevybraná žiadna adresa. + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + Ak odstránite odber, správy, ktoré ste už prijali, sa stanú nedostupné. Možno by ste mali zvážit namiesto toho odber deaktivovať. Deaktivované odbery nebudú prijímať nové správy, ale stále si môžete pozrieť správy, ktoré ste už prijali. + +Ste si istý, že chcete odber odstrániť? + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + Ak odstránite kanál, správy, ktoré ste už prijali, sa stanú nedostupné. Možno by ste mali zvážit namiesto toho kanál deaktivovať. Deaktivované kanály nebudú prijímať nové správy, ale stále si môžete pozrieť správy, ktoré ste už prijali. + +Ste si istý, že chcete kanál odstrániť? + + + + Do you really want to remove this avatar? + Naozaj chcete odstrániť tento avatar? + + + + You have already set an avatar for this address. Do you really want to overwrite it? + Pre túto adresu ste už ste nastavili avatar. Naozaj ho chcete ho zmeniť? + + + + Start-on-login not yet supported on your OS. + Spustenie pri prihlásení zatiaľ pre váš operačný systém nie je podporované. + + + + Minimize-to-tray not yet supported on your OS. + Minimalizovanie do panelu úloh zatiaľ pre váš operačný systém nie je podporované. + + + + Tray notifications not yet supported on your OS. + Oblasť oznámení zatiaľ pre váš operačný systém nie je podporovaná. + + + + Testing... + Testujem... + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + Toto je adresa kanálu. Nie je možné ju používať ako pseudo poštový zoznam. + + + + The address should start with ''BM-'' + Adresa by mala začínať ''BM-'' + + + + The address is not typed or copied correctly (the checksum failed). + Nesprávne zadaná alebo skopírovaná adresa (kontrolný súčet zlyhal). + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + Číslo verzie tejto adresy je vyššie ako tento softvér podporuje. Prosím inovujte Bitmessage. + + + + The address contains invalid characters. + Adresa obsahuje neplatné znaky. + + + + Some data encoded in the address is too short. + Niektoré dáta zakódované v adrese sú príliš krátke. + + + + Some data encoded in the address is too long. + Niektoré dáta zakódované v adrese sú príliš dlhé. + + + + Some data encoded in the address is malformed. + Niektoré dáta zakódované v adrese sú poškodené. + + + + Enter an address above. + Zadajte adresu vyššie. + + + + Address is an old type. We cannot display its past broadcasts. + Starý typ adresy. Nie je možné zobraziť jej predchádzajúce hromadné správy. + + + + There are no recent broadcasts from this address to display. + Neboli nájdené žiadne nedávne hromadé správy z tejto adresy. + + + + You are using TCP port %1. (This can be changed in the settings). + Používate port TCP %1. (Možno zmeniť v nastaveniach). + + + + Bitmessage + Bitmessage + + + + Identities + Identity + + + + New Identity + Nová identita + + + + Search + Hľadaj + + + + All + Všetky + + + + To + Príjemca + + + + From + Odosielateľ + + + + Subject + Predmet + + + + Message + Správa + + + + Received + Prijaté + + + + Messages + Správy + + + + Address book + Adresár + + + + Address + Adresa + + + + Add Contact + Pridať kontakt + + + + Fetch Namecoin ID + Získať identifikátor namecoin-u + + + + Subject: + Predmet: + + + + From: + Odosielateľ: + + + + To: + Príjemca: + + + + Send ordinary Message + Poslať obyčajnú správu + + + + Send Message to your Subscribers + Poslať správu vašim odberateľom + + + + TTL: + Doba životnosti: + + + + Subscriptions + Odbery + + + + Add new Subscription + Pridať nový odber + + + + Chans + Kanály + + + + Add Chan + Pridať kanál + + + + File + Súbor + + + + Settings + Nastavenia + + + + Help + Pomoc + + + + Import keys + Importovať kľúče + + + + Manage keys + Spravovať kľúče + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + Kontaktovať používateľskú podporu + + + + About + O + + + + Regenerate deterministic addresses + Znova vytvoriť deterministické adresy + + + + Delete all trashed messages + Odstrániť všetky správy z koša + + + + Join / Create chan + Pripojiť / vytvoriť kanál + + + + All accounts + Všetky účty + + + + Zoom level %1% + Úroveň priblíženia %1% + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + Chyba: nemožno pridať rovnakú adresu do vášho zoznamu dvakrát. Keď chcete, môžete premenovať existujúci záznam. + + + + Add new entry + Pridať nový záznam + + + + Display the %1 recent broadcast(s) from this address. + Zobraziť posledných %1 hromadných správ z tejto adresy. + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + K dispozícii je nová verzia PyBitmessage: %1. Môžete ju stiahnuť na https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + Waiting for PoW to finish... %1% + Čakám na ukončenie práce... %1% + + + + Shutting down Pybitmessage... %1% + Ukončujem PyBitmessage... %1% + + + + Waiting for objects to be sent... %1% + Čakám na odoslanie objektov... %1% + + + + Saving settings... %1% + Ukladám nastavenia... %1% + + + + Shutting down core... %1% + Ukončujem jadro... %1% + + + + Stopping notifications... %1% + Zastavujem oznámenia... %1% + + + + Shutdown imminent... %1% + Posledná fáza ukončenia... %1% + + + + %n hour(s) + %n hodina%n hodiny%n hodín + + + + %n day(s) + %n deň%n dni%n dní + + + + Shutting down PyBitmessage... %1% + Ukončujem PyBitmessage... %1% + + + + Sent + Odoslané + + + + Generating one new address + Vytváram jednu novú adresu + + + + Done generating address. Doing work necessary to broadcast it... + Vytváranie adresy ukončené. Vykonávam prácu potrebnú na rozoslanie... + + + + Generating %1 new addresses. + Vytváram %1 nových adries. + + + + %1 is already in 'Your Identities'. Not adding it again. + %1 sa už nachádza medzi vášmi identitami, nepridávam dvojmo. + + + + Done generating address + Vytváranie adresy ukončené + + + + SOCKS5 Authentication problem: %1 + Problém autentikácie SOCKS5: %1 + + + + Disk full + Disk plný + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + Upozornenie: Váš disk alebo priestor na ukladanie dát je plný. Bitmessage bude teraz ukončený. + + + + Error! Could not find sender address (your address) in the keys.dat file. + Chyba! Nemožno nájsť adresu odosielateľa (vašu adresu) v súbore keys.dat. + + + + Doing work necessary to send broadcast... + Vykonávam prácu potrebnú na rozoslanie... + + + + Broadcast sent on %1 + Rozoslané %1 + + + + Encryption key was requested earlier. + Šifrovací klúč bol vyžiadaný. + + + + Sending a request for the recipient's encryption key. + Odosielam požiadavku na kľúč príjemcu. + + + + Looking up the receiver's public key + Hľadám príjemcov verejný kľúč + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + Problém: adresa príjemcu je na mobilnom zariadení a požaduje, aby správy obsahovali nezašifrovanú adresu príjemcu. Vaše nastavenia však túto možnost nemajú povolenú. %1 + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + Vykonávam prácu potrebnú na odoslanie správy. +Adresy verzie dva, ako táto, nepožadujú obtiažnosť. + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + Vykonávam prácu potrebnú na odoslanie správy. +Priímcova požadovaná obtiažnosť: %1 a %2 + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + Problém: Práca požadovná príjemcom (%1 a %2) je obtiažnejšia, ako máte povolené. %3 + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + Problém: skúšate odslať správu sami sebe, ale nemôžem nájsť šifrovací kľúč v súbore keys.dat. Nemožno správu zašifrovať: %1 + + + + Doing work necessary to send message. + Vykonávam prácu potrebnú na odoslanie... + + + + Message sent. Waiting for acknowledgement. Sent on %1 + Správa odoslaná. Čakanie na potvrdenie. Odoslaná %1 + + + + Doing work necessary to request encryption key. + Vykonávam prácu potrebnú na vyžiadanie šifrovacieho kľúča. + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + Rozosielam požiadavku na verejný kľúč. Ak nebude príjemca spojený zo sieťou, budem skúšať znova. + + + + Sending public key request. Waiting for reply. Requested at %1 + Odosielam požiadavku na verejný kľúč. Čakám na odpoveď. Vyžiadaný %1 + + + + UPnP port mapping established on port %1 + Mapovanie portov UPnP vytvorené na porte %1 + + + + UPnP port mapping removed + Mapovanie portov UPnP zrušené + + + + NewAddressDialog + + + Create new Address + Vytvoriť novú adresu + + + + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + Tu si môžete vygenerovať toľko adries, koľko chcete. Vytváranie a opúšťanie adries je vrelo odporúčané. Adresy môžete generovať buď pomocou náhodných čísel alebo pomocou hesla. Ak používate heslo, takáto adresa sa nazýva "deterministická". +Predvoľba je pomocou generátora náhodných čísiel, ale deterministické adresy majú niekoľko výhod a nevýhod: + + + + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + <html><head/><body><p> <span style=" font-weight:600;">Pros: <br/></span>Svoje adresy môžete znovu vytvoriť na ľubovoľnom počítači z pamäte.<br/>Dokým si pamätáte heslo, nemusíte sa starať o zálohovanie keys.dat<br/> <span style=" font-weight:600;"Nevýhody: <br/></span>Ak chcete znovu vytvoriť kľúče ak ich stratíte, musíte si pamätať (alebo niekam zapísať) heslo. <br/> Zároveň si musíte si zapamätať aj číslo verzie adresy a číslo toku.<br/>Ak si zvolíte slabé prístupové heslo a niekto na internete ho uhádne, napr. hrubou silou, môže čítať vaše správy a odosielať ich za vás.</p></body></html> + + + + Use a random number generator to make an address + Vytvoriť novú adresu pomocou generátora náhodných čísel + + + + Use a passphrase to make addresses + Vytvoriť novú adresu pomocou hesla + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + Stráviť niekoľko minút výpočtového času navyše, aby adresa(y) bola o 1 alebo 2 znakov kratšia + + + + Make deterministic addresses + Vytvoriť deterministické adresy + + + + Address version number: 4 + Číslo verzie adresy: 4 + + + + In addition to your passphrase, you must remember these numbers: + Okrem svojho hesla si musíte zapamätať tiejto údaje: + + + + Passphrase + Heslo + + + + Number of addresses to make based on your passphrase: + Počet adries, ktoré majú byť na základe vášho hesla vytvorené: + + + + Stream number: 1 + Číslo prúdu: 1 + + + + Retype passphrase + Opakovať heslo + + + + Randomly generate address + Adresu generovať náhodne + + + + Label (not shown to anyone except you) + Označenie (zobrazené len vám a nikomu inému) + + + + Use the most available stream + Použiť najviac prístupný prúd + + + + (best if this is the first of many addresses you will create) + (najlepšie, ak ide o prvú z mnohých vytvorených adries) + + + + Use the same stream as an existing address + Použiť ten istý prúd ako existujúca adresa + + + + (saves you some bandwidth and processing power) + (ušetrí nejaké množstvo prenesených dát a výpočtový výkon) + + + + NewSubscriptionDialog + + + Add new entry + Pridať nový záznam + + + + Label + Označenie + + + + Address + Adresa + + + + Enter an address above. + Zadajte adresu vyššie. + + + + SpecialAddressBehaviorDialog + + + Special Address Behavior + Zvláštne správanie adresy + + + + Behave as a normal address + Správanie ako normálna adresa + + + + Behave as a pseudo-mailing-list address + Správanie ako pseudo poštový zoznam + + + + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + Správy prijaté na adresu pseudo poštového zoznamu budú automaticky rozoslaná odberateľom (a teda budú zverejnené). + + + + Name of the pseudo-mailing-list: + Meno pseudo poštového zoznamu: + + + + aboutDialog + + + About + O + + + + PyBitmessage + PyBitmessage + + + + version ? + verzia ? + + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + <html><head/><body><p>Šírený pod licenciou na softvér MIT / X11; pozri <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + + + + This is Beta software. + Toto je beta softvér. + + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 Vývojári Bitmessage</p></body></html> + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + Použiť ako zoznam zakázaných (prijať všetky prichádzajúce správy s výnimkou odosielateľov na zozname) + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + Použiť ako zoznam povolených (blokovať všetky prichádzajúce správy s výnimkou odosielateľov na zozname) + + + + Add new entry + Pridať nový záznam + + + + Name or Label + Meno alebo popis + + + + Address + Adresa + + + + Blacklist + Zoznam zakázaných + + + + Whitelist + Zoznam povolených + + + + connectDialog + + + Bitmessage + Bitmessage + + + + Bitmessage won't connect to anyone until you let it. + Bitmessage sa s nikým nespojí, dokým to nepovolíte. + + + + Connect now + Spojiť teraz + + + + Let me configure special network settings first + Najprv upraviť zvláštne sieťové nastavenia + + + + helpDialog + + + Help + Pomoc + + + + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + + + + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + Keďže Bitmessage je projekt založený na spolupráci, pomoc možno nájsť na internete v Bitmessage Wiki: + + + + iconGlossaryDialog + + + Icon Glossary + Legenda ikon + + + + You have no connections with other peers. + Nemáte žiadne spojenia s partnerskými uzlami. + + + + 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'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. + Vykonali ste aspoň jedno vychádzajúce spojenie do siete, ale ešte ste nenaviazali žiadne prichádzajúce spojenia. Váš firewall alebo domáci router pravdepodobne nie je nakonfigurovaný tak, aby presmeroval prichádzajúce TCP spojenia k vášmu počítaču. Bitmessage bude fungovať v pohode, keby ste však mali fungujúce prichádzajúce spojenia, pomôžete sieti Bitmessage a váš uzol bude lepšie pripojený. + + + + You are using TCP port ?. (This can be changed in the settings). + Používate port TCP ?. (Možno zmeniť v nastaveniach). + + + + You do have connections with other peers and your firewall is correctly configured. + Máte spojenia s partnerskými uzlami a vaša brána firewall je nastavená správne. + + + + networkstatus + + + Total connections: + Spojení spolu: + + + + Since startup: + Od spustenia: + + + + Processed 0 person-to-person messages. + Spracovaných 0 bežných správ. + + + + Processed 0 public keys. + Spracovaných 0 verejných kľúčov. + + + + Processed 0 broadcasts. + Spracovaných 0 hromadných správ. + + + + Inventory lookups per second: 0 + Vyhľadaní v inventári za sekundu: 0 + + + + Objects to be synced: + Zostáva synchronizovať objektov: + + + + Stream # + Prúd # + + + + Connections + Spojenia + + + + Since startup on %1 + Od spustenia %1 + + + + Down: %1/s Total: %2 + Prijatých: %1/s Spolu: %2 + + + + Up: %1/s Total: %2 + Odoslaných: %1/s Spolu: %2 + + + + Total Connections: %1 + Spojení spolu: %1 + + + + Inventory lookups per second: %1 + Vyhľadaní v inventári za sekundu: %1 + + + + Up: 0 kB/s + Odoslaných: 0 kB/s + + + + Down: 0 kB/s + Prijatých: 0 kB/s + + + + Network Status + Stav siete + + + + byte(s) + bajtbajtybajtov + + + + Object(s) to be synced: %n + Zostáva synchronizovať %n objektZostáva synchronizovať %n objektyZostáva synchronizovať %n objektov + + + + Processed %n person-to-person message(s). + Spracovaná %n bežná správa.Spracované %n bežné správy.Spracovaných %n bežných správ. + + + + Processed %n broadcast message(s). + Spracovaná %n hromadná správa.Spracované %n hromadné správy.Spracovaných %n hromadných správ. + + + + Processed %n public key(s). + Spracovaný %n verejný kľúč.Spracované %n verejné kľúče.Spracovaných %n verejných kľúčov. + + + + newChanDialog + + + Dialog + Kanál + + + + Create a new chan + Vytvoriť nový kanál + + + + Join a chan + Pripojiť sa na kanál + + + + Create a chan + Vytvoriť kanál + + + + <html><head/><body><p>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.</p></body></html> + <html><head/><body><p>Zadajte názov pre váš kanál. Ak zvolíte dostatočne zložitý názov kanálu (napríklad zložité a jedinečné heslo) a nikto z vašich známych ju ho nebude verejne zdieľať, potom bude kanál bezpečný a súkromný. Ak vy a niekto iný vytvoríte kanál s rovnakým názvom, bude to de facto ten istý kanál.</p></body></html> + + + + Chan name: + Meno kanálu + + + + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + <html><head/><body><p>Kanál existuje, keď skupina ľudí zdieľa tie isté dešifrovacie kľúče. Kľúče a bitmessage adresa používané v kanáli sú generované zo slova alebo frázy (názov kanálu). Ak chcete poslať správu všetkým užívateľom v kanáli, pošlite bežnú správu na adresu kanálu.</p><p>Kanály sú experimentálne a vôbec sa nedajú moderovať/cenzúrovať.</p></body></html> + + + + Chan bitmessage address: + Bitmessage adresa kanálu: + + + + regenerateAddressesDialog + + + Regenerate Existing Addresses + Znova vytvoriť existujúce adresy + + + + Regenerate existing addresses + Znova vytvoriť existujúce adresy + + + + Passphrase + Heslo + + + + Number of addresses to make based on your passphrase: + Počet adries, ktoré majú byť na základe vášho hesla vytvorené: + + + + Address version number: + Číslo verzie adresy: + + + + Stream number: + Číslo prúdu: + + + + 1 + 1 + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + Stráviť niekoľko minút výpočtového času navyše, aby adresa(y) bola o 1 alebo 2 znakov kratšia + + + + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + Je nutné začiarknuť (alebo nezačiarknuť) toto políčko tak isto, ako keď ste vytvárali svoje adresy prvýkrát. + + + + 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. + Ak ste v minulosti používali deterministické adresy, ale stratili ich kvôli nehode (ako je napráklad zlyhanie pevného disku), môžete ich vytvoriť znova. Ak ste na vytvorenie adries použili generátor náhodných čísel, potom je vám tento formulár zbytočný. + + + + settingsDialog + + + Settings + Nastavenia + + + + Start Bitmessage on user login + Spustiť Bitmessage pri prihlásení používateľa + + + + Tray + Panel úloh + + + + Start Bitmessage in the tray (don't show main window) + Spustiť Bitmessage v paneli úloh (nezobrazovať hlavné okno) + + + + Minimize to tray + Minimalizovať do panelu úloh + + + + Close to tray + Zavrieť do panelu úloh + + + + Show notification when message received + Zobraziť oznámenie, ked obdržíte správu + + + + Run in Portable Mode + Spustiť v prenosnom režime + + + + 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. + V prenosnom režime budú správy a konfiguračné súbory uložené v rovnakom priečinku ako program, namiesto v bežnom priečinku pre údaje aplikácie. Vďaka tomu je pohodlné používať Bitmessage na USB kľúči. + + + + Willingly include unencrypted destination address when sending to a mobile device + Povoliť pridanie nezašifrovanej adresy prijímateľa pri posielaní na mobilné zariadenie + + + + Use Identicons + Zobrazuj identikony (ikony automaticky vytvorené pre každú adresu) + + + + Reply below Quote + Odpovedať pod citáciou + + + + Interface Language + Jazyk rozhrania + + + + System Settings + system + Systémové nastavenia + + + + User Interface + Užívateľské rozhranie + + + + Listening port + Prijímajúci port + + + + Listen for connections on port: + Prijímať spojenia na porte: + + + + UPnP: + UPnP: + + + + Bandwidth limit + Obmedzenie šírky pásma + + + + Maximum download rate (kB/s): [0: unlimited] + Maximálna rýchlosť sťahovania (kB/s): [0: bez obmedzenia] + + + + Maximum upload rate (kB/s): [0: unlimited] + Maximálna rýchlosť odosielania (kB/s): [0: bez obmedzenia] + + + + Proxy server / Tor + Proxy server / Tor + + + + Type: + Typ: + + + + Server hostname: + Názov hostiteľského servera: + + + + Port: + Port: + + + + Authentication + Overovanie + + + + Username: + Používateľské meno: + + + + Pass: + Heslo: + + + + Listen for incoming connections when using proxy + Prijímať prichádzajúce spojenia ak je používaný proxy + + + + none + žiadny + + + + SOCKS4a + SOCKS4a + + + + SOCKS5 + SOCKS5 + + + + Network Settings + Nastavenia siete + + + + Total difficulty: + Celková obtiažnosť: + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + 'Celková obtiažnosť' ovplyvňuje celkové množstvo práce, ktorú musí odosielateľ vykonať. Zdvojnásobenie tejto hodnoty zdvojnásobí potrebné množstvo práce. + + + + Small message difficulty: + Obtiažnosť malých správ: + + + + 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. + Keď vám niekto pošle správu, ich počítač musí najprv vykonať nejakú prácu. Obtiažnosť tejto práce je predvolená na 1. Túto predvoľbu môžete zvýšiť nastavením parametrov. Každá novo vygenerovaná adresa bude od odosielateľa požadovať túto zvýšenú obtiažnosť. Existuje však výnimka: ak vášho známeho máte v adresári, pri poslaní nasledujúcej správy im Bitmessage automaticky oznámi, že im stačí minimálne množstvo práce: obtiažnosť 1. + + + + 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. + 'Obtiažnosť malých správ' ovplyvňuje najmä náročnosť odosielania malých správ. Zdvojnásobenie tejto hodnoty zdvojnásobí potrebné množstvo práce na odoslanie malých správ, ale veľké správy príliš neovplyvňuje. + + + + Demanded difficulty + Požadovaná obtiažnosť + + + + 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. + Tu môžete nastaviť maximálne množstvo práce, ktorú váš počítač je ochotný urobiť pre odoslanie správy inej osobe. Nastavenie týchto hodnôt na 0 znamená, že ľubovoľné množtvo práce je prijateľné. + + + + Maximum acceptable total difficulty: + Maximálna prijateľná celková obtiažnosť: + + + + Maximum acceptable small message difficulty: + Maximálna prijateľná obtiažnost malých správ: + + + + Max acceptable difficulty + Max. prijateľná obtiažnosť + + + + Hardware GPU acceleration (OpenCL) + Hardvérové GPU urýchľovanie (OpenCL) + + + + <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> + <html><head/><body><p>Bitmessage sa môže pripojiť k systému s názvom Namecoin, ktorý je podobný Bitcoinu, a s jeho pomocou používať používateľsky príjemné identifikátory. Napríklad namiesto zverejňovania dlhej Bitmessage adresy môžete jednoducho zverejniť meno, povedzme <span style=" font-style:italic;">test.</span></p><p>(Dostať vašu vlastnú adresu do Namecoin-u je však zatiaľ pomerne zložité).</p><p>Bitmessage sa môže pripojiť priamo na namecoind, alebo na aktívnu inštanciu nmcontrol.</p></body</html> + + + + Host: + Hostiteľ: + + + + Password: + Heslo: + + + + Test + Test + + + + Connect to: + Pripojiť ku: + + + + Namecoind + Namecoind + + + + NMControl + NMControl + + + + Namecoin integration + Integrácia namecoin-u + + + + <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> + <html><head/><body><p>Predvoľba spôsobí opätovné odoslanie správy ak nebude príjemca pripojený na sieť viac ako dva dni. Tieto pokusy budú opakované, dokým príjemca nepotvrdí obdržanie správy. Toto správanie môžete zmeniť zadaním počtu dní alebo mesiacov, po ktorých má Bitmessage s opätovným odosielaním prestať.</p><p>Vstupné polia nechajte prázdne, ak chcete predvolené správanie. </p></body></html> + + + + Give up after + Vzdať po + + + + and + a + + + + days + dňoch + + + + months. + mesiacoch. + + + + Resends Expire + Vypršanie opätovného odosielania + + + \ No newline at end of file diff --git a/src/translations/bitmessage_sv.ts b/src/translations/bitmessage_sv.ts new file mode 100644 index 00000000..015546b3 --- /dev/null +++ b/src/translations/bitmessage_sv.ts @@ -0,0 +1,2058 @@ + + + AddAddressDialog + + + Add new entry + + + + + Label + + + + + Address + + + + + EmailGatewayDialog + + + Email gateway + + + + + Register on email gateway + + + + + Account status at email gateway + + + + + Change account settings at email gateway + + + + + Unregister from email gateway + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + + + + + Desired email address (including @mailchuck.com): + + + + + EmailGatewayRegistrationDialog + + + Registration failed: + + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + + + + + Email gateway registration + + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + + + + + MainWindow + + + Reply to sender + + + + + Reply to channel + + + + + Add sender to your Address Book + + + + + Add sender to your Blacklist + + + + + Move to Trash + + + + + Undelete + + + + + View HTML code as formatted text + + + + + Save message as... + + + + + Mark Unread + + + + + New + + + + + Enable + + + + + Disable + + + + + Set avatar... + + + + + Copy address to clipboard + + + + + Special address behavior... + + + + + Email gateway + + + + + Delete + + + + + Send message to this address + + + + + Subscribe to this address + + + + + Add New Address + + + + + Copy destination address to clipboard + + + + + Force send + + + + + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? + + + + + Waiting for their encryption key. Will request it again soon. + + + + + Encryption key request queued. + + + + + Queued. + + + + + Message sent. Waiting for acknowledgement. Sent at %1 + + + + + Message sent. Sent at %1 + + + + + Need to do work to send message. Work is queued. + + + + + Acknowledgement of the message received %1 + + + + + Broadcast queued. + + + + + Broadcast on %1 + + + + + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 + + + + + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 + + + + + Forced difficulty override. Send should start soon. + + + + + Unknown status: %1 %2 + + + + + Not Connected + + + + + Show Bitmessage + + + + + Send + + + + + Subscribe + + + + + Channel + + + + + Quit + + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. + + + + + Open keys.dat? + + + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + You may manage your keys by editing the keys.dat file stored in + %1 +It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) + + + + + Delete trash? + + + + + Are you sure you want to delete all trashed messages? + + + + + bad passphrase + + + + + You must type your passphrase. If you don't have one then this is not the form for you. + + + + + Bad address version number + + + + + Your address version number must be a number: either 3 or 4. + + + + + Your address version number must be either 3 or 4. + + + + + Chan name needed + + + + + You didn't enter a chan name. + + + + + Address already present + + + + + Could not add chan because it appears to already be one of your identities. + + + + + Success + + + + + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. + + + + + Address too new + + + + + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. + + + + + Address invalid + + + + + That Bitmessage address is not valid. + + + + + Address does not match chan name + + + + + Although the Bitmessage address you entered was valid, it doesn't match the chan name. + + + + + Successfully joined chan. + + + + + Connection lost + + + + + Connected + + + + + Message trashed + + + + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + + + + + Message too long + + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + + + + + Error: Bitmessage addresses start with BM- Please check %1 + + + + + Error: The address %1 is not typed or copied correctly. Please check it. + + + + + Error: The address %1 contains invalid characters. Please check it. + + + + + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. + + + + + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. + + + + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + + + + + Error: Something is wrong with the address %1. + + + + + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. + + + + + Address version number + + + + + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Stream number + + + + + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. + + + + + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. + + + + + Message queued. + + + + + Your 'To' field is empty. + + + + + Right click one or more entries in your address book and select 'Send message to this address'. + + + + + Fetched address from namecoin identity. + + + + + New Message + + + + + From + + + + + Sending email gateway registration request + + + + + Address is valid. + + + + + The address you entered was invalid. Ignoring it. + + + + + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. + + + + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + + + + + Restart + + + + + You must restart Bitmessage for the port number change to take effect. + + + + + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). + + + + + Number needed + + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + + + + + Will not resend ever + + + + + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. + + + + + Sending email gateway unregistration request + + + + + Sending email gateway status request + + + + + Passphrase mismatch + + + + + The passphrase you entered twice doesn't match. Try again. + + + + + Choose a passphrase + + + + + You really do need a passphrase. + + + + + Address is gone + + + + + Bitmessage cannot find your address %1. Perhaps you removed it? + + + + + Address disabled + + + + + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. + + + + + Entry added to the Address Book. Edit the label to your liking. + + + + + Entry added to the blacklist. Edit the label to your liking. + + + + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + + + + + Moved items to trash. + + + + + Undeleted item. + + + + + Save As... + + + + + Write error. + + + + + No addresses selected. + + + + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + + + + + Do you really want to remove this avatar? + + + + + You have already set an avatar for this address. Do you really want to overwrite it? + + + + + Start-on-login not yet supported on your OS. + + + + + Minimize-to-tray not yet supported on your OS. + + + + + Tray notifications not yet supported on your OS. + + + + + Testing... + + + + + This is a chan address. You cannot use it as a pseudo-mailing list. + + + + + The address should start with ''BM-'' + + + + + The address is not typed or copied correctly (the checksum failed). + + + + + The version number of this address is higher than this software can support. Please upgrade Bitmessage. + + + + + The address contains invalid characters. + + + + + Some data encoded in the address is too short. + + + + + Some data encoded in the address is too long. + + + + + Some data encoded in the address is malformed. + + + + + Enter an address above. + + + + + Address is an old type. We cannot display its past broadcasts. + + + + + There are no recent broadcasts from this address to display. + + + + + You are using TCP port %1. (This can be changed in the settings). + + + + + Bitmessage + + + + + Identities + + + + + New Identity + + + + + Search + + + + + All + + + + + To + + + + + From + + + + + Subject + + + + + Message + + + + + Received + + + + + Messages + + + + + Address book + + + + + Address + + + + + Add Contact + + + + + Fetch Namecoin ID + + + + + Subject: + + + + + From: + + + + + To: + + + + + Send ordinary Message + + + + + Send Message to your Subscribers + + + + + TTL: + + + + + Subscriptions + + + + + Add new Subscription + + + + + Chans + + + + + Add Chan + + + + + File + + + + + Settings + + + + + Help + + + + + Import keys + + + + + Manage keys + + + + + Ctrl+Q + + + + + F1 + + + + + Contact support + + + + + About + + + + + Regenerate deterministic addresses + + + + + Delete all trashed messages + + + + + Join / Create chan + + + + + All accounts + + + + + Zoom level %1% + + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + + + + + Add new entry + + + + + Display the %1 recent broadcast(s) from this address. + + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + + + + + Waiting for PoW to finish... %1% + + + + + Shutting down Pybitmessage... %1% + + + + + Waiting for objects to be sent... %1% + + + + + Saving settings... %1% + + + + + Shutting down core... %1% + + + + + Stopping notifications... %1% + + + + + Shutdown imminent... %1% + + + + + %n hour(s) + + + + + %n day(s) + + + + + Shutting down PyBitmessage... %1% + + + + + Sent + + + + + Generating one new address + + + + + Done generating address. Doing work necessary to broadcast it... + + + + + Generating %1 new addresses. + + + + + %1 is already in 'Your Identities'. Not adding it again. + + + + + Done generating address + + + + + SOCKS5 Authentication problem: %1 + + + + + Disk full + + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + + + + + Error! Could not find sender address (your address) in the keys.dat file. + + + + + Doing work necessary to send broadcast... + + + + + Broadcast sent on %1 + + + + + Encryption key was requested earlier. + + + + + Sending a request for the recipient's encryption key. + + + + + Looking up the receiver's public key + + + + + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 + + + + + Doing work necessary to send message. +There is no required difficulty for version 2 addresses like this. + + + + + Doing work necessary to send message. +Receiver's required difficulty: %1 and %2 + + + + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + + + + + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 + + + + + Doing work necessary to send message. + + + + + Message sent. Waiting for acknowledgement. Sent on %1 + + + + + Doing work necessary to request encryption key. + + + + + Broadcasting the public key request. This program will auto-retry if they are offline. + + + + + Sending public key request. Waiting for reply. Requested at %1 + + + + + UPnP port mapping established on port %1 + + + + + UPnP port mapping removed + + + + + NewAddressDialog + + + Create new Address + + + + + Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a "deterministic" address. +The 'Random Number' option is selected by default but deterministic addresses have several pros and cons: + + + + + <html><head/><body><p><span style=" font-weight:600;">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=" font-weight:600;">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html> + + + + + Use a random number generator to make an address + + + + + Use a passphrase to make addresses + + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + Make deterministic addresses + + + + + Address version number: 4 + + + + + In addition to your passphrase, you must remember these numbers: + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Stream number: 1 + + + + + Retype passphrase + + + + + Randomly generate address + + + + + Label (not shown to anyone except you) + + + + + Use the most available stream + + + + + (best if this is the first of many addresses you will create) + + + + + Use the same stream as an existing address + + + + + (saves you some bandwidth and processing power) + + + + + NewSubscriptionDialog + + + Add new entry + + + + + Label + + + + + Address + + + + + Enter an address above. + + + + + SpecialAddressBehaviorDialog + + + Special Address Behavior + + + + + Behave as a normal address + + + + + Behave as a pseudo-mailing-list address + + + + + Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public). + + + + + Name of the pseudo-mailing-list: + + + + + aboutDialog + + + About + + + + + PyBitmessage + + + + + version ? + + + + + <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> + + + + + This is Beta software. + + + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + + + + + Add new entry + + + + + Name or Label + + + + + Address + + + + + Blacklist + + + + + Whitelist + + + + + connectDialog + + + Bitmessage + + + + + Bitmessage won't connect to anyone until you let it. + + + + + Connect now + + + + + Let me configure special network settings first + + + + + helpDialog + + + Help + + + + + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + + + + + As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki: + + + + + iconGlossaryDialog + + + Icon Glossary + + + + + You have no connections with other peers. + + + + + 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'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. + + + + + You are using TCP port ?. (This can be changed in the settings). + + + + + You do have connections with other peers and your firewall is correctly configured. + + + + + networkstatus + + + Total connections: + + + + + Since startup: + + + + + Processed 0 person-to-person messages. + + + + + Processed 0 public keys. + + + + + Processed 0 broadcasts. + + + + + Inventory lookups per second: 0 + + + + + Objects to be synced: + + + + + Stream # + + + + + Connections + + + + + Since startup on %1 + + + + + Down: %1/s Total: %2 + + + + + Up: %1/s Total: %2 + + + + + Total Connections: %1 + + + + + Inventory lookups per second: %1 + + + + + Up: 0 kB/s + + + + + Down: 0 kB/s + + + + + Network Status + + + + + byte(s) + + + + + Object(s) to be synced: %n + + + + + Processed %n person-to-person message(s). + + + + + Processed %n broadcast message(s). + + + + + Processed %n public key(s). + + + + + newChanDialog + + + Dialog + + + + + Create a new chan + + + + + Join a chan + + + + + Create a chan + + + + + <html><head/><body><p>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.</p></body></html> + + + + + Chan name: + + + + + <html><head/><body><p>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.</p><p>Chans are experimental and completely unmoderatable.</p></body></html> + + + + + Chan bitmessage address: + + + + + regenerateAddressesDialog + + + Regenerate Existing Addresses + + + + + Regenerate existing addresses + + + + + Passphrase + + + + + Number of addresses to make based on your passphrase: + + + + + Address version number: + + + + + Stream number: + + + + + 1 + + + + + Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter + + + + + You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time. + + + + + 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. + + + + + settingsDialog + + + Settings + + + + + Start Bitmessage on user login + + + + + Tray + + + + + Start Bitmessage in the tray (don't show main window) + + + + + Minimize to tray + + + + + Close to tray + + + + + Show notification when message received + + + + + Run in Portable Mode + + + + + 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. + + + + + Willingly include unencrypted destination address when sending to a mobile device + + + + + Use Identicons + + + + + Reply below Quote + + + + + Interface Language + + + + + System Settings + system + + + + + User Interface + + + + + Listening port + + + + + Listen for connections on port: + + + + + UPnP: + + + + + Bandwidth limit + + + + + Maximum download rate (kB/s): [0: unlimited] + + + + + Maximum upload rate (kB/s): [0: unlimited] + + + + + Proxy server / Tor + + + + + Type: + + + + + Server hostname: + + + + + Port: + + + + + Authentication + + + + + Username: + + + + + Pass: + + + + + Listen for incoming connections when using proxy + + + + + none + + + + + SOCKS4a + + + + + SOCKS5 + + + + + Network Settings + + + + + Total difficulty: + + + + + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. + + + + + Small message difficulty: + + + + + 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. + + + + + 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. + + + + + Demanded difficulty + + + + + 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. + + + + + Maximum acceptable total difficulty: + + + + + Maximum acceptable small message difficulty: + + + + + Max acceptable difficulty + + + + + Hardware GPU acceleration (OpenCL) + + + + + <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> + + + + + Host: + + + + + Password: + + + + + Test + + + + + Connect to: + + + + + Namecoind + + + + + NMControl + + + + + Namecoin integration + + + + + <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> + + + + + Give up after + + + + + and + + + + + days + + + + + months. + + + + + Resends Expire + + + + \ No newline at end of file diff --git a/src/translations/bitmessage_zh_cn.pro b/src/translations/bitmessage_zh_cn.pro deleted file mode 100644 index cde33c9f..00000000 --- a/src/translations/bitmessage_zh_cn.pro +++ /dev/null @@ -1,35 +0,0 @@ -SOURCES = ../addresses.py\ - ../bitmessagemain.py\ - ../class_addressGenerator.py\ - ../class_outgoingSynSender.py\ - ../class_objectProcessor.py\ - ../class_receiveDataThread.py\ - ../class_sendDataThread.py\ - ../class_singleCleaner.py\ - ../class_singleListener.py\ - ../class_singleWorker.py\ - ../class_sqlThread.py\ - ../helper_bitcoin.py\ - ../helper_bootstrap.py\ - ../helper_generic.py\ - ../helper_inbox.py\ - ../helper_sent.py\ - ../helper_startup.py\ - ../shared.py\ - ../bitmessageqt/__init__.py\ - ../bitmessageqt/about.py\ - ../bitmessageqt/addaddressdialog.py\ - ../bitmessageqt/bitmessageui.py\ - ../bitmessageqt/connect.py\ - ../bitmessageqt/help.py\ - ../bitmessageqt/iconglossary.py\ - ../bitmessageqt/newaddressdialog.py\ - ../bitmessageqt/newchandialog.py\ - ../bitmessageqt/newsubscriptiondialog.py\ - ../bitmessageqt/regenerateaddresses.py\ - ../bitmessageqt/settings.py\ - ../bitmessageqt/specialaddressbehavior.py - - -TRANSLATIONS = bitmessage_zh_cn.ts -CODECFORTR = UTF-8 diff --git a/src/translations/bitmessage_zh_cn.qm b/src/translations/bitmessage_zh_cn.qm index 3f894afd..b06fa55b 100644 Binary files a/src/translations/bitmessage_zh_cn.qm and b/src/translations/bitmessage_zh_cn.qm differ diff --git a/src/translations/bitmessage_zh_cn.ts b/src/translations/bitmessage_zh_cn.ts index adc055e5..356b2b56 100644 --- a/src/translations/bitmessage_zh_cn.ts +++ b/src/translations/bitmessage_zh_cn.ts @@ -1,6 +1,4 @@ - - - + AddAddressDialog @@ -19,1059 +17,1293 @@ 地址 + + EmailGatewayDialog + + + Email gateway + 电子邮件网关 + + + + Register on email gateway + 注册电子邮件网关 + + + + Account status at email gateway + 电子邮件网关帐户状态 + + + + Change account settings at email gateway + 更改电子邮件网关帐户设置 + + + + Unregister from email gateway + 取消电子邮件网关注册 + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. + 电子邮件网关允许您与电子邮件用户通信。目前,只有Mailchuck电子邮件网关(@mailchuck.com)可用。 + + + + Desired email address (including @mailchuck.com): + 所需的电子邮件地址(包括 @mailchuck.com): + + + + EmailGatewayRegistrationDialog + + + Registration failed: + 注册失败: + + + + The requested email address is not available, please try a new one. Fill out the new desired email address (including @mailchuck.com) below: + 要求的电子邮件地址不详,请尝试一个新的。填写新的所需电子邮件地址(包括 @mailchuck.com)如下: + + + + Email gateway registration + 电子邮件网关注册 + + + + Email gateway allows you to communicate with email users. Currently, only the Mailchuck email gateway (@mailchuck.com) is available. +Please type the desired email address (including @mailchuck.com) below: + 电子邮件网关允许您与电子邮件用户通信。目前,只有Mailchuck电子邮件网关(@mailchuck.com)可用。请键入所需的电子邮件地址(包括 @mailchuck.com)如下: + + + + 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, +# use this. Requires subscription. +# +# pgp: local +# The email gateway will not conduct PGP operations on your behalf. You can +# either not use PGP at all, or use it locally. +# +# attachments: yes +# Incoming attachments in the email will be uploaded to MEGA.nz, and you can +# download them from there by following the link. Requires a subscription. +# +# 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 +# however means that the operator of the service will be able to read your +# emails even after they have been delivered to you. +# +# archive: no +# Incoming emails will be deleted from the server as soon as they are relayed +# to you. +# +# masterpubkey_btc: BIP44 xpub key or electrum v1 public seed +# offset_btc: integer (defaults to 0) +# feeamount: number with up to 8 decimal places +# feecurrency: BTC, XBT, USD, EUR or GBP +# Use these if you want to charge people who send you emails. If this is on and +# an unknown person sends you an email, they will be requested to pay the fee +# specified. As this scheme uses deterministic public keys, you will receive +# the money directly. To turn it off again, set "feeamount" to 0. Requires +# subscription. + + #您可以用它来配置你的电子邮件网关帐户 +#取消您要使用的设定 +#这里的选项: +# +# pgp: server +#电子邮件网关将创建和维护PGP密钥,为您签名和验证, +#代表加密和解密。当你想使用PGP,但懒惰, +#用这个。需要订阅。 +# +# pgp: local +#电子邮件网关不会代你进行PGP操作。您可以 +#选择或者不使用PGP, 或在本地使用它。 +# +# attachement: yes +#传入附件的电子邮件将会被上传到MEGA.nz,您可以从 +# 按照那里链接下载。需要订阅。 +# +# attachement: no +#附件将被忽略。 +# +# archive: yes +#您收到的邮件将在服务器上存档。如果您有需要请使用 +#帮助调试问题,或者您需要第三方电子邮件的证明。这 +#然而,意味着服务的操作运将能够读取您的 +#电子邮件即使电子邮件已经传送给你。 +# +# archive: no +# 已传入的电子邮件将从服务器被删除只要他们已中继。 +# +# masterpubkey_btc:BIP44 XPUB键或琥珀金V1公共种子 +#offset_btc:整数(默认为0) +#feeamount:多达8位小数 +#feecurrency号:BTC,XBT,美元,欧元或英镑 +#用这些,如果你想主管谁送你的电子邮件的人。如果这是在和 +#一个不明身份的人向您发送一封电子邮件,他们将被要求支付规定的费用 +#。由于这个方案使用确定性的公共密钥,你会直接接收 +#钱。要再次将其关闭,设置“feeamount”0 +#需要订阅。 + + MainWindow - - Bitmessage - 比特信 + + Reply to sender + 回复发件人 - - Search - 搜索 + + Reply to channel + 回复通道 - - All - 全部 - - - - To - - - - - From - 来自 - - - - Subject - 标题 - - - - Message - 消息 - - - - Received - 接收时间 - - - - Inbox - 收件箱 - - - - Load from Address book - 从地址本中选择 - - - - Fetch Namecoin ID - 接收Namecoin ID - - - - Message: - 消息: - - - - Subject: - 标题: - - - - Send to one or more specific people - 发送给一个或更多指定的人 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - - - - - To: - 至: - - - - From: - 来自: - - - - Broadcast to everyone who is subscribed to your address - 广播给全部订阅到您的地址的人 - - - - Send - 发送 - - - - Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them. - 请注意,广播的消息仅仅使用您的地址加密。任何知道您的地址的人可以阅读其中的内容。 - - - - Status - 状态 - - - - Sent - 已发送 - - - - New - 新建 - - - - Label (not shown to anyone) - 标签(只有您看的到) - - - - Address - 地址 - - - - Stream - 节点流 - - - - Your Identities - 您的身份 - - - - Here you can subscribe to 'broadcast messages' that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab. - 您可以在这里订阅到广播地址,接收来自其他用户的广播。消息将出现在您的收件箱。您的黑名单对在这里的地址无效。 - - - - Add new Subscription - 添加新的订阅 - - - - Label - 标签 - - - - Subscriptions - 订阅 - - - - The Address book is useful for adding names or labels to other people's Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the 'Add' button, or from your inbox by right-clicking on a message. - 这个地址本将帮助您给其他人的地址添加名字或标签,这样的话您就可以在收件箱中更容易的认出它们。您可以在这里点“新建”,或在一条在收件箱中的消息上右击来添加条目。 - - - - Add new entry - 添加新条目 - - - - Name or Label - 名称或标签 - - - - Address Book - 地址本 - - - - Use a Blacklist (Allow all incoming messages except those on the Blacklist) - 使用黑名单(允许所有黑名单以外的人向您发送消息) - - - - Use a Whitelist (Block all incoming messages except those on the Whitelist) - 使用白名单(仅允许在白名单上的人向您发送消息) - - - - Blacklist - 黑名单 - - - - Stream # - 节点流 # - - - - Connections - 连接 - - - - Total connections: 0 - 总连接数: 0 - - - - Since startup at asdf: - 自启动于 asdf: - - - - Processed 0 person-to-person message. - 处理了 0 个点对点消息。 - - - - Processed 0 public key. - 处理了 0 个公匙。 - - - - Processed 0 broadcast. - 处理了 0 个广播。 - - - - Inventory lookups per second: 0 - 每秒种的同步请求数: 0 - - - - Network Status - 网络状态 - - - - File - 文件 - - - - Settings - 设置 - - - - Help - 帮助 - - - - Import keys - 导入密钥 - - - - Manage keys - 管理密钥 - - - - Quit - 退出 - - - - Ctrl+Q - Ctrl+Q - - - - F1 - F1 - - - - About - 关于 - - - - Regenerate deterministic addresses - 重新生成静态地址 - - - - Delete all trashed messages - 彻底删除全部回收站中的消息 - - - - Join / Create chan - 加入或创建一个频道 - - - - Reply - 回复 - - - + Add sender to your Address Book - 将发送者添加到地址本 + 将发送者添加到您的通讯簿 - + + Add sender to your Blacklist + 将发件人添加到您的黑名单 + + + Move to Trash 移入回收站 - + + Undelete + 取消删除 + + + View HTML code as formatted text 作为HTML查看 - + Save message as... 将消息保存为... - + Mark Unread 标记为未读 - + + New + 新建 + + + Enable 启用 - + Disable 禁用 - + Set avatar... 设置头像... - + Copy address to clipboard 将地址复制到剪贴板 - + Special address behavior... 特别的地址行为... - - Send message to this address - 发送消息到这个地址 + + Email gateway + 电子邮件网关 - - Subscribe to this address - 订阅到这个地址 - - - - Add New Address - 创建新地址 - - - + Delete 删除 - + + Send message to this address + 发送消息到这个地址 + + + + Subscribe to this address + 订阅到这个地址 + + + + Add New Address + 创建新地址 + + + Copy destination address to clipboard 复制目标地址到剪贴板 - + Force send 强制发送 - + One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now? 您的地址中的一个, %1,是一个过时的版本1地址. 版本1地址已经不再受到支持了. 我们可以将它删除掉么? - - Since startup on %1 - 自启动于 %1 + + Waiting for their encryption key. Will request it again soon. + 正在等待他们的加密密钥,我们会在稍后再次请求。 - - Waiting on their encryption key. Will request it again soon. - 正在等待他们的加密密钥,我们会在稍后再次请求。 - - - + Encryption key request queued. 加密密钥请求已经添加到队列中。 - + Queued. 已经添加到队列。 - - Message sent. Waiting on acknowledgement. Sent at %1 - 消息已经发送. 正在等待回执. 发送于 %1 + + Message sent. Waiting for acknowledgement. Sent at %1 + 消息已经发送. 正在等待回执. 发送于 %1 - + Message sent. Sent at %1 消息已经发送. 发送于 %1 - + Need to do work to send message. Work is queued. 发生消息需要做工。做工正在队列中等待。 - + Acknowledgement of the message received %1 消息的回执已经收到于 %1 - + Broadcast queued. 广播已经添加到队列中。 - + Broadcast on %1 已经广播于 %1 - + Problem: The work demanded by the recipient is more difficult than you are willing to do. %1 错误: 收件人要求的做工量大于我们的最大接受做工量。 %1 - + Problem: The recipient's encryption key is no good. Could not encrypt message. %1 错误: 收件人的加密密钥是无效的。不能加密消息。 %1 - + Forced difficulty override. Send should start soon. 已经忽略最大做工量限制。发送很快就会开始。 - + Unknown status: %1 %2 未知状态: %1 %2 - + Not Connected 未连接 - + Show Bitmessage 显示比特信 - + + Send + 发送 + + + Subscribe 订阅 - + + Channel + 频道 + + + + Quit + 退出 + + + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. 您可以通过编辑和程序储存在同一个目录的 keys.dat 来编辑密钥。备份这个文件十分重要。 - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. 您可以通过编辑储存在 %1 的 keys.dat 来编辑密钥。备份这个文件十分重要。 - + Open keys.dat? 打开 keys.dat ? - + You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) 您可以通过编辑和程序储存在同一个目录的 keys.dat 来编辑密钥。备份这个文件十分重要。您现在想打开这个文件么?(请在进行任何修改前关闭比特信) - + You may manage your keys by editing the keys.dat file stored in %1 It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.) 您可以通过编辑储存在 %1 的 keys.dat 来编辑密钥。备份这个文件十分重要。您现在想打开这个文件么?(请在进行任何修改前关闭比特信) - + Delete trash? 清空回收站? - + Are you sure you want to delete all trashed messages? 您确定要删除全部被回收的消息么? - + bad passphrase 错误的密钥 - + You must type your passphrase. If you don't have one then this is not the form for you. 您必须输入您的密钥。如果您没有的话,这个表单不适用于您。 - + Bad address version number 地址的版本号无效 - + Your address version number must be a number: either 3 or 4. 您的地址的版本号必须是一个数字: 3 或 4. - + Your address version number must be either 3 or 4. 您的地址的版本号必须是 3 或 4. - + Chan name needed 需要频道的名称 - + You didn't enter a chan name. 您没有输入一个频道的名称。 - + Address already present 地址已经在这里了 - + Could not add chan because it appears to already be one of your identities. 无法添加频道,因为它似乎已经是您的身份之一。 - + Success 成功 - + Successfully created chan. To let others join your chan, give them the chan name and this Bitmessage address: %1. This address also appears in 'Your Identities'. 成功的创建了频道。要让他人加入,请告诉他们频道的名称和这个比特信地址 %1 。这个比特信地址也会出现在“您的身份”中。 - + Address too new 地址太新了 - + Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage. 尽管比特信地址也许是有效的,不过比特信地址的版本号比我们能处理的要新。也许您应该升级比特信了。 - + Address invalid 地址有效 - + That Bitmessage address is not valid. 比特信地址无效。 - + Address does not match chan name 地址和频道的名称不符 - + Although the Bitmessage address you entered was valid, it doesn't match the chan name. 尽管您输入的比特信地址是有效的,不过它和频道的名称不符。 - + Successfully joined chan. 成功的加入到频道。 - - Processed %1 person-to-person messages. - 处理了 %1 个点对点消息。 - - - - Processed %1 broadcast messages. - 处理了 %1 个广播。 - - - - Processed %1 public keys. - 处理了 %1 个公匙。 - - - - Total Connections: %1 - 总连接数: %1 - - - - Inventory lookups per second: %1 - 每秒种的同步请求数: %1 - - - + Connection lost 连接已丢失 - + Connected 已经连接 - + Message trashed 消息已经移入回收站 - + + The TTL, or Time-To-Live is the length of time that the network will hold the message. + The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it + will resend the message automatically. The longer the Time-To-Live, the + more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate. + 這TTL,或Time-To-Time是保留信息网络时间的长度. +收件人必须在此期间得到它. 如果您的Bitmessage客户沒有听到确认, 它会自动重新发送信息. Time-To-Live的时间越长, 您的电脑必须要做更多工作來发送信息. 四天或五天的 Time-To-Time, 经常是合适的. + + + + Message too long + 信息太长 + + + + The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending. + 你正在尝试发送的信息已超过%1个字节太长, (最大为261644个字节). 发送前请剪下来。 + + + + Error: Your account wasn't registered at an email gateway. Sending registration now as %1, please wait for the registration to be processed before retrying sending. + 错误: 您的帐户没有在电子邮件网关注册。现在发送注册为%1​​, 注册正在处理请稍候重试发送. + + + Error: Bitmessage addresses start with BM- Please check %1 错误:比特信地址以BM-开始,请检查 %1 - + Error: The address %1 is not typed or copied correctly. Please check it. 错误:地址 %1 没有被正确的键入或复制。 请检查一下。 - + Error: The address %1 contains invalid characters. Please check it. 错误: 比特信地址 %1 包含无效的字符。请检查一下。 - + Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever. 错误:地址 %1 的版本号过高。您可能需要升级您的比特信软件或者您的朋友正在使用本程序的非主线版本。 - + Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance. 错误:在地址 %1 中编码的部分信息过短。您的朋友的软件可能有点问题。 - + Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance. 错误:在地址 %1 中编码的部分信息过长。您的朋友的软件可能有点问题。 - + + Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance. + 错误: 一些地址数据%1的格式不正确. 可能有一些错误认识您的软件 + + + Error: Something is wrong with the address %1. 错误: 地址%1 有为未知的错误。 - + Error: You must specify a From address. If you don't have one, go to the 'Your Identities' tab. 错误: 您必须指出一个表单地址, 如果您没有,请到“您的身份”标签页。 - + Address version number 地址版本号 - + Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version. 地址 %1 的地址版本号 %2 无法被比特信理解。也许你应该升级你的比特信到最新版本。 - + Stream number 节点流序号 - + Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version. 地址 %1 的节点流序号 %2 无法被比特信理解。也许你应该升级你的比特信到最新版本。 - + Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won't send until you connect. 警告: 您尚未连接。 比特信将做足够的功来发送消息,但是消息不会被发出直到您连接。 - + + Message queued. + 信息排队。 + + + Your 'To' field is empty. “收件人"是空的。 - + Right click one or more entries in your address book and select 'Send message to this address'. 在您的地址本的一个条目上右击,之后选择”发送消息到这个地址“。 - + Fetched address from namecoin identity. 已经自namecoin接收了地址。 - - Work is queued. %1 - 做工已经添加到队列中。 %1 - - - + New Message 新消息 - + From 来自 - + + Sending email gateway registration request + 发送电​​子邮件网关注册请求 + + + Address is valid. 地址有效。 - + The address you entered was invalid. Ignoring it. 您输入的地址是无效的,将被忽略。 - + Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want. 错误:您无法将一个地址添加到您的地址本两次,请尝试重命名已经存在的那个。 - - Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want. - 错误:您无法将一个地址添加到您的订阅两次,也许您想重命名已经存在的那个。 + + Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want. + 错误: 您不能在同一地址添加到您的订阅两次. 也许您可重命名现有之一. - + Restart 重启 - + You must restart Bitmessage for the port number change to take effect. 您必须重启以便使比特信对于使用的端口的改变生效。 - + Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any). 比特信将会从现在开始使用代理,但是您可能想手动重启比特信以便使之前的连接关闭(如果有的话)。 - + + Number needed + 需求数字 + + + + Your maximum download and upload rate must be numbers. Ignoring what you typed. + 您最大的下载和上传速率必须是数字. 忽略您键入的内容. + + + Will not resend ever 不尝试再次发送 - + Note that the time limit you entered is less than the amount of time Bitmessage waits for the first resend attempt therefore your messages will never be resent. 请注意,您所输入的时间限制小于比特信的最小重试时间,因此您将永远不会重发消息。 - - Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. - 错误:您无法将一个地址添加到您的列表两次,也许您想重命名已经存在的那个。 + + Sending email gateway unregistration request + 发送电​​子邮件网关注销请求 - + + Sending email gateway status request + 发送电​​子邮件网关状态请求 + + + Passphrase mismatch 密钥不匹配 - + The passphrase you entered twice doesn't match. Try again. 您两次输入的密码并不匹配,请再试一次。 - + Choose a passphrase 选择一个密钥 - + You really do need a passphrase. 您真的需要一个密码。 - - All done. Closing user interface... - 全部完成,正在关闭用户界面... - - - + Address is gone 已经失去了地址 - + Bitmessage cannot find your address %1. Perhaps you removed it? 比特信无法找到你的地址 %1。 也许你已经把它删掉了? - + Address disabled 地址已经禁用 - + Error: The address from which you are trying to send is disabled. You'll have to enable it on the 'Your Identities' tab before using it. 错误: 您想以一个您已经禁用的地址发出消息。在使用之前您需要在“您的身份”处再次启用。 - + Entry added to the Address Book. Edit the label to your liking. 条目已经添加到地址本。您可以去修改您的标签。 - - Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back. - 已经移动项目到回收站。没有图形化的界面可以查看您的回收站,不过如果您还想找回的话它还在您的硬盘上。 + + Entry added to the blacklist. Edit the label to your liking. + 条目添加到黑名单. 根据自己的喜好编辑标签. - + + Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want. + 错误: 您不能在同一地址添加到您的黑名单两次. 也许您可重命名现有之一. + + + + Moved items to trash. + 已经移动项目到回收站。 + + + + Undeleted item. + 未删除的项目。 + + + Save As... 另存为... - + Write error. 写入失败。 - + No addresses selected. 没有选择地址。 - + + If you delete the subscription, messages that you already received will become inaccessible. Maybe you can consider disabling the subscription instead. Disabled subscriptions will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the subscription? + 如果删除订阅, 您已经收到的信息将无法访问. 也许你可以考虑禁用订阅.禁用订阅将不会收到新信息, 但您仍然可以看到你已经收到的信息. + +你确定要删除订阅? + + + + If you delete the channel, messages that you already received will become inaccessible. Maybe you can consider disabling the channel instead. Disabled channels will not receive new messages, but you can still view messages you already received. + +Are you sure you want to delete the channel? + 如果您删除的频道, 你已经收到的信息将无法访问. 也许你可以考虑禁用频道. 禁用频道将不会收到新信息, 但你仍然可以看到你已经收到的信息. + +你确定要删除频道? + + + Do you really want to remove this avatar? 您真的想移除这个头像么? - + You have already set an avatar for this address. Do you really want to overwrite it? 您已经为这个地址设置了头像了。您真的想移除么? - + Start-on-login not yet supported on your OS. 登录时启动尚未支持您在使用的操作系统。 - + Minimize-to-tray not yet supported on your OS. 最小化到托盘尚未支持您的操作系统。 - + Tray notifications not yet supported on your OS. 托盘提醒尚未支持您所使用的操作系统。 - + Testing... 正在测试... - + This is a chan address. You cannot use it as a pseudo-mailing list. 这是一个频道地址,您无法把它作为伪邮件列表。 - + The address should start with ''BM-'' 地址应该以"BM-"开始 - + The address is not typed or copied correctly (the checksum failed). 地址没有被正确的键入或复制(校验码校验失败)。 - + The version number of this address is higher than this software can support. Please upgrade Bitmessage. 这个地址的版本号大于此软件的最大支持。 请升级比特信。 - + The address contains invalid characters. 这个地址中包含无效字符。 - + Some data encoded in the address is too short. 在这个地址中编码的部分信息过少。 - + Some data encoded in the address is too long. 在这个地址中编码的部分信息过长。 - + + Some data encoded in the address is malformed. + 在地址编码的某些数据格式不正确. + + + Enter an address above. 请在上方键入地址。 - + Address is an old type. We cannot display its past broadcasts. 地址没有近期的广播。我们无法显示之间的广播。 - + There are no recent broadcasts from this address to display. 没有可以显示的近期广播。 - - Display the %1 recent broadcast from this address. - 显示 %1 条近期广播。 - - - - Display the %1 recent broadcasts from this address. - 显示 %1 条近期广播。 - - - + You are using TCP port %1. (This can be changed in the settings). 您正在使用TCP端口 %1 。(可以在设置中修改)。 - - Waiting for their encryption key. Will request it again soon. - 正在等待他们的加密密钥,我们会在稍后再次请求。 + + Bitmessage + 比特信 - - Message sent. Waiting for acknowledgement. Sent at %1 - 消息已经发送. 正在等待回执. 发送于 %1 + + Identities + 身份标识 - + + New Identity + 新身份标识 + + + + Search + 搜索 + + + + All + 全部 + + + + To + + + + + From + 来自 + + + + Subject + 标题 + + + + Message + 消息 + + + + Received + 接收时间 + + + + Messages + 信息 + + + + Address book + 地址簿 + + + + Address + 地址 + + + + Add Contact + 增加联系人 + + + + Fetch Namecoin ID + 接收Namecoin ID + + + + Subject: + 标题: + + + + From: + 来自: + + + + To: + 至: + + + + Send ordinary Message + 发送普通信息 + + + + Send Message to your Subscribers + 发送信息给您的订户 + + + + TTL: + TTL: + + + + Subscriptions + 订阅 + + + + Add new Subscription + 添加新的订阅 + + + + Chans + Chans + + + + Add Chan + 添加 Chans + + + + File + 文件 + + + + Settings + 设置 + + + + Help + 帮助 + + + + Import keys + 导入密钥 + + + + Manage keys + 管理密钥 + + + + Ctrl+Q + Ctrl+Q + + + + F1 + F1 + + + + Contact support + 联系支持 + + + + About + 关于 + + + + Regenerate deterministic addresses + 重新生成静态地址 + + + + Delete all trashed messages + 彻底删除全部回收站中的消息 + + + + Join / Create chan + 加入或创建一个频道 + + + + All accounts + 所有帐户 + + + + Zoom level %1% + 缩放级别%1% + + + + Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want. + 错误: 您不能在同一地址添加到列表中两次. 也许您可重命名现有之一. + + + + Add new entry + 添加新条目 + + + + Display the %1 recent broadcast(s) from this address. + 显示从这个地址%1的最近广播 + + + + New version of PyBitmessage is available: %1. Download it from https://github.com/Bitmessage/PyBitmessage/releases/latest + PyBitmessage的新版本可用: %1. 从https://github.com/Bitmessage/PyBitmessage/releases/latest下载 + + + + Waiting for PoW to finish... %1% + 等待PoW完成...%1% + + + + Shutting down Pybitmessage... %1% + 关闭Pybitmessage ...%1% + + + + Waiting for objects to be sent... %1% + 等待要发送对象...%1% + + + + Saving settings... %1% + 保存设置...%1% + + + + Shutting down core... %1% + 关闭核心...%1% + + + + Stopping notifications... %1% + 停止通知...%1% + + + + Shutdown imminent... %1% + 关闭即将来临...%1% + + + + %n hour(s) + %n 小时 + + + + %n day(s) + %n 天 + + + + Shutting down PyBitmessage... %1% + 关闭PyBitmessage...%1% + + + + Sent + 发送 + + + + Generating one new address + 生成一个新的地址 + + + + Done generating address. Doing work necessary to broadcast it... + 完成生成地址. 做必要的工作, 以播放它... + + + + Generating %1 new addresses. + 生成%1个新地址. + + + + %1 is already in 'Your Identities'. Not adding it again. + %1已经在'您的身份'. 不必重新添加. + + + + Done generating address + 完成生成地址 + + + + SOCKS5 Authentication problem: %1 + SOCKS5 认证问题: %1 + + + + Disk full + 磁盘已满 + + + + Alert: Your disk or data storage volume is full. Bitmessage will now exit. + 警告: 您的磁盘或数据存储量已满. 比特信将立即退出. + + + Error! Could not find sender address (your address) in the keys.dat file. - 错误! 无法在文件 keys.dat 中找到发送者地址(你的地址) + 错误! 找不到在keys.dat 件发件人的地址 ( 您的地址). - + Doing work necessary to send broadcast... - 正在做一些必须的工作来发送广播. + 做必要的工作, 以发送广播... - + Broadcast sent on %1 - 广播发送于 %1 + 广播发送%1 - + Encryption key was requested earlier. - 已在更早的时候得到加密密钥. + 加密密钥已请求. - + Sending a request for the recipient's encryption key. - 正在请求收件人的加密密钥. + 发送收件人的加密密钥的请求. - + Looking up the receiver's public key - 正在查找收件人的公钥. + 展望接收方的公钥 - + Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1 - 错误: 目标是一个移动设备, 要求不加密目标地址, 但是你的设置中不允许这么做. %1 + 问题: 目标是移动电话设备所请求的目的地包括在消息中, 但是这是在你的设置禁止. %1 - + Doing work necessary to send message. There is no required difficulty for version 2 addresses like this. - 正在做一些必要的工作来发送消息. -这里要求的难度不像第2版的地址那样. + 做必要的工作, 以发送信息. +这样第2版的地址没有难度. - + Doing work necessary to send message. Receiver's required difficulty: %1 and %2 - 正在做一些必要的工作来发送消息. -接收者要求的难度为: %1 和 %2 + 做必要的工作, 以发送短信. +接收者的要求难度: %1与%2 - - Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. - 错误: 收件人要求的做工量(%1 和 %2)大于我们的最大接受做工量. + + Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do. %3 + 问题: 由接收者(%1%2)要求的工作量比您愿意做的工作量來得更困难. %3 - + Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1 - 错误: 你正在尝试发送消息到你自身或者一个频道, 但是你的加密密钥无法在文件keys.dat中找到. 无法加密消息. %1 + 问题: 您正在尝试将信息发送给自己或频道, 但您的加密密钥无法在keys.dat文件中找到. 无法加密信息. %1 - + Doing work necessary to send message. - 正在做一些必要的工作来发送消息. + 做必要的工作, 以发送信息. - - Message sent. Sent on %1 - 消息已经发送. 发送于 %1 - - - + Message sent. Waiting for acknowledgement. Sent on %1 - 消息已经发送. 正在等待回执. 发送于 %1 + 信息发送. 等待确认. 已发送%1 - + Doing work necessary to request encryption key. - 正在做一些必要的工作来请求加密密钥. + 做必要的工作以要求加密密钥. - - Broacasting the public key request. This program will auto-retry if they are offline. - 正在广播公钥请求. 如果他们不在线, 这一过程将自动重试. + + Broadcasting the public key request. This program will auto-retry if they are offline. + 广播公钥请求. 这个程序将自动重试, 如果他们处于离线状态. - + Sending public key request. Waiting for reply. Requested at %1 - 正在发送公钥请求. 等待回应中. 请求于 %1 + 发送公钥的请求. 等待回复. 请求在%1 + + + + UPnP port mapping established on port %1 + UPnP端口映射建立在端口%1 + + + + UPnP port mapping removed + UPnP端口映射被删除 @@ -1192,8 +1424,8 @@ The 'Random Number' option is selected by default but deterministic ad - CheckBox - 显示在添加之前2天内的广播 + Enter an address above. + 输入上述地址. @@ -1241,11 +1473,6 @@ The 'Random Number' option is selected by default but deterministic ad version ? 版本 ? - - - <html><head/><body><p>Copyright © 2012-2013 Jonathan Warren<br/>Copyright © 2013 The Bitmessage Developers</p></body></html> - <html><head/><body><p>版权所有 © 2012-2013 Jonathan Warren<br/>版权所有 © 2013 比特信开发者</p></body></html> - <html><head/><body><p>Distributed under the MIT/X11 software license; see <a href="http://www.opensource.org/licenses/mit-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.opensource.org/licenses/mit-license.php</span></a></p></body></html> @@ -1256,6 +1483,49 @@ The 'Random Number' option is selected by default but deterministic ad This is Beta software. 本软件处于Beta阶段。 + + + <html><head/><body><p>Copyright © 2012-2016 Jonathan Warren<br/>Copyright © 2013-2016 The Bitmessage Developers</p></body></html> + <html><head/><body><p>版权©2012-2016 Jonathan Warren<br/>版权©2013-2016的比特信开发人员</p></body></html> + + + + blacklist + + + Use a Blacklist (Allow all incoming messages except those on the Blacklist) + 使用黑名单 (允许所有传入的信息除了那些在黑名单) + + + + Use a Whitelist (Block all incoming messages except those on the Whitelist) + 使用白名单 (阻止所有传入的消息除了那些在白名单) + + + + Add new entry + 添加新条目 + + + + Name or Label + 名称或标签 + + + + Address + 地址 + + + + Blacklist + 黑名单 + + + + Whitelist + 白名单 + connectDialog @@ -1289,8 +1559,8 @@ The 'Random Number' option is selected by default but deterministic ad - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> - <a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> + <a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a> @@ -1326,6 +1596,119 @@ The 'Random Number' option is selected by default but deterministic ad 您有和其他节点的连接且您的防火墙已经正确配置。 + + networkstatus + + + Total connections: + 总连接: + + + + Since startup: + 自启动: + + + + Processed 0 person-to-person messages. + 处理0人对人的信息. + + + + Processed 0 public keys. + 处理0公钥。 + + + + Processed 0 broadcasts. + 处理0广播. + + + + Inventory lookups per second: 0 + 每秒库存查询: 0 + + + + Objects to be synced: + 对象 已同步: + + + + Stream # + 数据流 # + + + + Connections + 连接 + + + + Since startup on %1 + 自从%1启动 + + + + Down: %1/s Total: %2 + 下: %1/秒 总计: %2 + + + + Up: %1/s Total: %2 + 上: %1/秒 总计: %2 + + + + Total Connections: %1 + 总的连接数: %1 + + + + Inventory lookups per second: %1 + 每秒库存查询: %1 + + + + Up: 0 kB/s + 上载: 0 kB /秒 + + + + Down: 0 kB/s + 下载: 0 kB /秒 + + + + Network Status + 网络状态 + + + + byte(s) + 字节 + + + + Object(s) to be synced: %n + 要同步的对象: %n + + + + Processed %n person-to-person message(s). + 处理%n人对人的信息. + + + + Processed %n broadcast message(s). + 处理%n广播信息. + + + + Processed %n public key(s). + 处理%n公钥. + + newChanDialog @@ -1425,310 +1808,295 @@ The 'Random Number' option is selected by default but deterministic ad settingsDialog - + Settings 设置 - + Start Bitmessage on user login 在用户登录时启动比特信 - + + Tray + 任务栏 + + + Start Bitmessage in the tray (don't show main window) 启动比特信到托盘 (不要显示主窗口) - + Minimize to tray 最小化到托盘 - + + Close to tray + 关闭任务栏 + + + Show notification when message received 在收到消息时提示 - + Run in Portable Mode 以便携方式运行 - + 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. 在便携模式下, 消息和配置文件和程序保存在同一个目录而不是通常的程序数据文件夹。 这使在U盘中允许比特信很方便。 - + Willingly include unencrypted destination address when sending to a mobile device - It seems that this func is still at dev when translation was done. 愿意在发送到手机时使用不加密的目标地址 - + Use Identicons 用户身份 - + + Reply below Quote + 回复 引述如下 + + + Interface Language 界面语言 - + System Settings system 系统设置 - - English - en - - - - - Esperanto - eo - - - - - Français - fr - - - - - Deutsch - de - - - - - Españl - es - - - - - русский язык - ru - - - - - Norsk - no - - - - - Pirate English - en_pirate - - - - - Other (set in keys.dat) - other - 其他(在keys.dat中设置) - - - + User Interface 用户界面 - + Listening port 监听端口 - + Listen for connections on port: 监听连接于端口: - + + UPnP: + UPnP: + + + + Bandwidth limit + 带宽限制 + + + + Maximum download rate (kB/s): [0: unlimited] + 最大下载速率(kB/秒): [0: 无限制] + + + + Maximum upload rate (kB/s): [0: unlimited] + 最大上传速度 (kB/秒): [0: 无限制] + + + Proxy server / Tor 代理服务器 / Tor - + Type: 类型: - + Server hostname: 服务器主机名: - + Port: 端口: - + Authentication 认证 - + Username: 用户名: - + Pass: 密码: - + Listen for incoming connections when using proxy 在使用代理时仍然监听入站连接 - + none - + SOCKS4a SOCKS4a - + SOCKS5 SOCKS5 - + Network Settings 网络设置 - + Total difficulty: 总难度: - + The 'Total difficulty' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work. “总难度”影响发送者所需要的做工总数。当这个值翻倍时,做工的总数也翻倍。 - + Small message difficulty: 小消息难度: - + 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. 当一个人向您发送消息的时候, 他们的电脑必须先做工。这个难度的默认值是1,您可以在创建新的地址前提高这个值。任何新创建的地址都会要求更高的做工量。这里有一个例外,当您将您的朋友添加到地址本的时候,比特信将自动提示他们,当他们下一次向您发送的时候,他们需要的做功量将总是1. - + 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. “小消息困难度”几乎仅影响发送消息。当这个值翻倍时,发小消息时做工的总数也翻倍,但是并不影响大的消息。 - + Demanded difficulty 要求的难度 - + 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. 你可以在这里设置您所愿意接受的发送消息的最大难度。0代表接受任何难度。 - + Maximum acceptable total difficulty: 最大接受难度: - + Maximum acceptable small message difficulty: 最大接受的小消息难度: - + Max acceptable difficulty 最大可接受难度 - + + Hardware GPU acceleration (OpenCL) + 硬件GPU加速 (OpenCL) + + + <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> <html><head/><body><p>比特信可以利用基于比特币的Namecoin让地址更加友好。比如除了告诉您的朋友您的长长的比特信地址,您还可以告诉他们发消息给 <span style=" font-style:italic;">test. </span></p><p>把您的地址放入Namecoin还是相当的难的.</p><p>比特信可以不但直接连接到namecoin守护程序或者连接到运行中的nmcontrol实例.</p></body></html> - + Host: 主机名: - + Password: 密码: - + Test 测试 - + Connect to: 连接到: - + Namecoind - + Namecoind - + NMControl - + NMControl - + Namecoin integration Namecoin整合 - + <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> <html><head/><body><p>您发给他们的消息默认会在网络上保存两天,之后比特信会再重发一次. 重发时间会随指数上升; 消息会在5, 10, 20... 天后重发并以此类推. 直到收到收件人的回执. 你可以在这里改变这一行为,让比特信在尝试一段时间后放弃.</p><p>留空意味着默认行为. </p></body></html> - + Give up after - + and - + days - + months. 月后放弃。 - + Resends Expire 重发超时 - + \ No newline at end of file diff --git a/src/upnp.py b/src/upnp.py new file mode 100644 index 00000000..8e5fbee0 --- /dev/null +++ b/src/upnp.py @@ -0,0 +1,288 @@ +# A simple upnp module to forward port for BitMessage +# Reference: http://mattscodecave.com/posts/using-python-and-upnp-to-forward-a-port +import httplib +from random import randint +import socket +from struct import unpack, pack +import threading +import time +from helper_threading import * +import shared +import tr + +def createRequestXML(service, action, arguments=[]): + from xml.dom.minidom import Document + + doc = Document() + + # create the envelope element and set its attributes + envelope = doc.createElementNS('', 's:Envelope') + envelope.setAttribute('xmlns:s', 'http://schemas.xmlsoap.org/soap/envelope/') + envelope.setAttribute('s:encodingStyle', 'http://schemas.xmlsoap.org/soap/encoding/') + + # create the body element + body = doc.createElementNS('', 's:Body') + + # create the function element and set its attribute + fn = doc.createElementNS('', 'u:%s' % action) + fn.setAttribute('xmlns:u', 'urn:schemas-upnp-org:service:%s' % service) + + # setup the argument element names and values + # using a list of tuples to preserve order + + # container for created nodes + argument_list = [] + + # iterate over arguments, create nodes, create text nodes, + # append text nodes to nodes, and finally add the ready product + # to argument_list + for k, v in arguments: + tmp_node = doc.createElement(k) + tmp_text_node = doc.createTextNode(v) + tmp_node.appendChild(tmp_text_node) + argument_list.append(tmp_node) + + # append the prepared argument nodes to the function element + for arg in argument_list: + fn.appendChild(arg) + + # append function element to the body element + body.appendChild(fn) + + # append body element to envelope element + envelope.appendChild(body) + + # append envelope element to document, making it the root element + doc.appendChild(envelope) + + # our tree is ready, conver it to a string + return doc.toxml() + +class UPnPError(Exception): + def __init__(self, message): + self.message + +class Router: + name = "" + path = "" + address = None + routerPath = None + extPort = None + + def __init__(self, ssdpResponse, address): + import urllib2 + from xml.dom.minidom import parseString + from urlparse import urlparse + from debug import logger + + self.address = address + + row = ssdpResponse.split('\r\n') + header = {} + for i in range(1, len(row)): + part = row[i].split(': ') + if len(part) == 2: + header[part[0].lower()] = part[1] + + try: + self.routerPath = urlparse(header['location']) + if not self.routerPath or not hasattr(self.routerPath, "hostname"): + logger.error ("UPnP: no hostname: %s", header['location']) + except KeyError: + logger.error ("UPnP: missing location header") + + # get the profile xml file and read it into a variable + directory = urllib2.urlopen(header['location']).read() + + # create a DOM object that represents the `directory` document + dom = parseString(directory) + + self.name = dom.getElementsByTagName('friendlyName')[0].childNodes[0].data + # find all 'serviceType' elements + service_types = dom.getElementsByTagName('serviceType') + + for service in service_types: + if service.childNodes[0].data.find('WANIPConnection') > 0 or \ + service.childNodes[0].data.find('WANPPPConnection') > 0: + self.path = service.parentNode.getElementsByTagName('controlURL')[0].childNodes[0].data + + def AddPortMapping(self, externalPort, internalPort, internalClient, protocol, description, leaseDuration = 0, enabled = 1): + from debug import logger + resp = self.soapRequest('WANIPConnection:1', 'AddPortMapping', [ + ('NewExternalPort', str(externalPort)), + ('NewProtocol', protocol), + ('NewInternalPort', str(internalPort)), + ('NewInternalClient', internalClient), + ('NewEnabled', str(enabled)), + ('NewPortMappingDescription', str(description)), + ('NewLeaseDuration', str(leaseDuration)) + ]) + self.extPort = externalPort + logger.info("Successfully established UPnP mapping for %s:%i on external port %i", internalClient, internalPort, externalPort) + return resp + + def DeletePortMapping(self, externalPort, protocol): + from debug import logger + resp = self.soapRequest('WANIPConnection:1', 'DeletePortMapping', [ + ('NewExternalPort', str(externalPort)), + ('NewProtocol', protocol), + ]) + logger.info("Removed UPnP mapping on external port %i", externalPort) + return resp + + def GetExternalIPAddress(self): + from xml.dom.minidom import parseString + resp = self.soapRequest('WANIPConnection:1', 'GetExternalIPAddress') + dom = parseString(resp) + return dom.getElementsByTagName('NewExternalIPAddress')[0].childNodes[0].data + + def soapRequest(self, service, action, arguments=[]): + from xml.dom.minidom import parseString + from debug import logger + conn = httplib.HTTPConnection(self.routerPath.hostname, self.routerPath.port) + conn.request( + 'POST', + self.path, + createRequestXML(service, action, arguments), + { + 'SOAPAction': '"urn:schemas-upnp-org:service:%s#%s"' % (service, action), + 'Content-Type': 'text/xml' + } + ) + resp = conn.getresponse() + conn.close() + if resp.status == 500: + respData = resp.read() + try: + dom = parseString(respData) + errinfo = dom.getElementsByTagName('errorDescription') + if len(errinfo) > 0: + logger.error("UPnP error: %s", respData) + raise UPnPError(errinfo[0].childNodes[0].data) + except: + raise UPnPError("Unable to parse SOAP error: %s" %(respData)) + return resp + +class uPnPThread(threading.Thread, StoppableThread): + SSDP_ADDR = "239.255.255.250" + GOOGLE_DNS = "8.8.8.8" + SSDP_PORT = 1900 + SSDP_MX = 2 + SSDP_ST = "urn:schemas-upnp-org:device:InternetGatewayDevice:1" + + def __init__ (self): + threading.Thread.__init__(self, name="uPnPThread") + self.localPort = shared.config.getint('bitmessagesettings', 'port') + try: + self.extPort = shared.config.getint('bitmessagesettings', 'extport') + except: + self.extPort = None + self.localIP = self.getLocalIP() + self.routers = [] + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.sock.bind((self.localIP, 10000)) + self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + self.sock.settimeout(5) + self.sendSleep = 60 + self.initStop() + + def run(self): + from debug import logger + + logger.debug("Starting UPnP thread") + logger.debug("Local IP: %s", self.localIP) + lastSent = 0 + while shared.shutdown == 0 and shared.safeConfigGetBoolean('bitmessagesettings', 'upnp'): + if time.time() - lastSent > self.sendSleep and len(self.routers) == 0: + try: + self.sendSearchRouter() + except: + pass + lastSent = time.time() + try: + while shared.shutdown == 0 and shared.safeConfigGetBoolean('bitmessagesettings', 'upnp'): + resp,(ip,port) = self.sock.recvfrom(1000) + if resp is None: + continue + newRouter = Router(resp, ip) + for router in self.routers: + if router.location == newRouter.location: + break + else: + logger.debug("Found UPnP router at %s", ip) + self.routers.append(newRouter) + self.createPortMapping(newRouter) + shared.UISignalQueue.put(('updateStatusBar', tr._translate("MainWindow",'UPnP port mapping established on port %1').arg(str(self.extPort)))) + break + except socket.timeout as e: + pass + except: + logger.error("Failure running UPnP router search.", exc_info=True) + for router in self.routers: + if router.extPort is None: + self.createPortMapping(router) + try: + self.sock.shutdown(socket.SHUT_RDWR) + except: + pass + try: + self.sock.close() + except: + pass + deleted = False + for router in self.routers: + if router.extPort is not None: + deleted = True + self.deletePortMapping(router) + shared.extPort = None + if deleted: + shared.UISignalQueue.put(('updateStatusBar', tr._translate("MainWindow",'UPnP port mapping removed'))) + logger.debug("UPnP thread done") + + def getLocalIP(self): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + s.connect((uPnPThread.GOOGLE_DNS, 1)) + return s.getsockname()[0] + + def sendSearchRouter(self): + from debug import logger + ssdpRequest = "M-SEARCH * HTTP/1.1\r\n" + \ + "HOST: %s:%d\r\n" % (uPnPThread.SSDP_ADDR, uPnPThread.SSDP_PORT) + \ + "MAN: \"ssdp:discover\"\r\n" + \ + "MX: %d\r\n" % (uPnPThread.SSDP_MX, ) + \ + "ST: %s\r\n" % (uPnPThread.SSDP_ST, ) + "\r\n" + + try: + logger.debug("Sending UPnP query") + self.sock.sendto(ssdpRequest, (uPnPThread.SSDP_ADDR, uPnPThread.SSDP_PORT)) + except: + logger.exception("UPnP send query failed") + + def createPortMapping(self, router): + from debug import logger + + for i in range(50): + try: + routerIP, = unpack('>I', socket.inet_aton(router.address)) + localIP = self.localIP + if i == 0: + extPort = self.localPort # try same port first + elif i == 1 and self.extPort: + extPort = self.extPort # try external port from last time next + else: + extPort = randint(32767, 65535) + logger.debug("Attempt %i, requesting UPnP mapping for %s:%i on external port %i", i, localIP, self.localPort, extPort) + router.AddPortMapping(extPort, self.localPort, localIP, 'TCP', 'BitMessage') + shared.extPort = extPort + self.extPort = extPort + shared.config.set('bitmessagesettings', 'extport', str(extPort)) + break + except UPnPError: + logger.debug("UPnP error: ", exc_info=True) + + def deletePortMapping(self, router): + router.DeletePortMapping(router.extPort, 'TCP') + + +