"Mark Unread" in Inbox #335

Merged
nimdahk merged 8 commits from markUnread into master 2013-07-28 22:30:59 +02:00
35 changed files with 2268 additions and 445 deletions
Showing only changes of commit d9f894448d - Show all commits

View File

@ -2,6 +2,7 @@ APP=pybitmessage
VERSION=0.3.4 VERSION=0.3.4
RELEASE=1 RELEASE=1
ARCH_TYPE=`uname -m` ARCH_TYPE=`uname -m`
PREFIX?=/usr/local
all: all:
debug: debug:
@ -9,34 +10,39 @@ source:
tar -cvzf ../${APP}_${VERSION}.orig.tar.gz ../${APP}-${VERSION} --exclude-vcs tar -cvzf ../${APP}_${VERSION}.orig.tar.gz ../${APP}-${VERSION} --exclude-vcs
install: install:
mkdir -p ${DESTDIR}/usr mkdir -p ${DESTDIR}/usr
mkdir -p ${DESTDIR}/usr/bin mkdir -p ${DESTDIR}${PREFIX}
mkdir -m 755 -p ${DESTDIR}/usr/share mkdir -p ${DESTDIR}${PREFIX}/bin
mkdir -m 755 -p ${DESTDIR}/usr/share/man mkdir -m 755 -p ${DESTDIR}${PREFIX}/share
mkdir -m 755 -p ${DESTDIR}/usr/share/man/man1 mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/man
install -m 644 man/${APP}.1.gz ${DESTDIR}/usr/share/man/man1 mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/man/man1
mkdir -m 755 -p ${DESTDIR}/usr/share/${APP} install -m 644 man/${APP}.1.gz ${DESTDIR}${PREFIX}/share/man/man1
mkdir -m 755 -p ${DESTDIR}/usr/share/applications mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/${APP}
mkdir -m 755 -p ${DESTDIR}/usr/share/pixmaps mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/applications
mkdir -m 755 -p ${DESTDIR}/usr/share/icons mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/pixmaps
mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons
mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor/scalable mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor
mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor/scalable/apps mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor/scalable
mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor/24x24 mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor/scalable/apps
mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor/24x24/apps mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor/24x24
install -m 644 desktop/${APP}.desktop ${DESTDIR}/usr/share/applications/${APP}.desktop mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor/24x24/apps
install -m 644 desktop/icon24.png ${DESTDIR}/usr/share/icons/hicolor/24x24/apps/${APP}.png install -m 644 desktop/${APP}.desktop ${DESTDIR}${PREFIX}/share/applications/${APP}.desktop
cp -rf src/* ${DESTDIR}/usr/share/${APP} install -m 644 desktop/icon24.png ${DESTDIR}${PREFIX}/share/icons/hicolor/24x24/apps/${APP}.png
echo '#!/bin/sh' > ${DESTDIR}/usr/bin/${APP} cp -rf src/* ${DESTDIR}${PREFIX}/share/${APP}
echo 'cd /usr/share/pybitmessage' >> ${DESTDIR}/usr/bin/${APP} echo '#!/bin/sh' > ${DESTDIR}${PREFIX}/bin/${APP}
echo 'LD_LIBRARY_PATH="/opt/openssl-compat-bitcoin/lib/" exec python2 bitmessagemain.py' >> ${DESTDIR}/usr/bin/${APP} echo 'if [ -d /usr/local/share/${APP} ]; then' >> ${DESTDIR}${PREFIX}/bin/${APP}
chmod +x ${DESTDIR}/usr/bin/${APP} echo ' cd /usr/local/share/${APP}' >> ${DESTDIR}${PREFIX}/bin/${APP}
echo 'else' >> ${DESTDIR}${PREFIX}/bin/${APP}
echo ' cd /usr/share/pybitmessage' >> ${DESTDIR}${PREFIX}/bin/${APP}
echo 'fi' >> ${DESTDIR}${PREFIX}/bin/${APP}
echo 'LD_LIBRARY_PATH="/opt/openssl-compat-bitcoin/lib/" exec python2 bitmessagemain.py' >> ${DESTDIR}${PREFIX}/bin/${APP}
chmod +x ${DESTDIR}${PREFIX}/bin/${APP}
uninstall: uninstall:
rm -f /usr/share/man/man1/${APP}.1.gz rm -f ${PREFIX}/share/man/man1/${APP}.1.gz
rm -rf /usr/share/${APP} rm -rf ${PREFIX}/share/${APP}
rm -f /usr/bin/${APP} rm -f ${PREFIX}/bin/${APP}
rm -f /usr/share/applications/${APP}.desktop rm -f ${PREFIX}/share/applications/${APP}.desktop
rm -f /usr/share/icons/hicolor/scalable/apps/${APP}.svg rm -f ${PREFIX}/share/icons/hicolor/scalable/apps/${APP}.svg
/usr/share/pixmaps/${APP}.svg rm -f ${PREFIX}/share/pixmaps/${APP}.svg
clean: clean:
rm -f ${APP} \#* \.#* gnuplot* *.png debian/*.substvars debian/*.log rm -f ${APP} \#* \.#* gnuplot* *.png debian/*.substvars debian/*.log
rm -fr deb.* debian/${APP} rpmpackage/${ARCH_TYPE} rm -fr deb.* debian/${APP} rpmpackage/${ARCH_TYPE}

View File

@ -7,7 +7,7 @@ arch=('i686' 'x86_64')
url="https://github.com/Bitmessage/PyBitmessage" url="https://github.com/Bitmessage/PyBitmessage"
license=('MIT') license=('MIT')
groups=() groups=()
depends=('python2' 'qt4' 'python2-pyqt4' 'sqlite' 'openssl') depends=('python2' 'qt4' 'python2-pyqt4' 'sqlite' 'openssl' 'gst123')
makedepends=() makedepends=()
optdepends=('python2-gevent') optdepends=('python2-gevent')
provides=() provides=()
@ -27,5 +27,5 @@ build() {
} }
package() { package() {
cd "$srcdir/$pkgname-$pkgver" cd "$srcdir/$pkgname-$pkgver"
make DESTDIR="$pkgdir/" install make DESTDIR="$pkgdir/" PREFIX="/usr" install
} }

4
debian/control vendored
View File

@ -4,12 +4,12 @@ Maintainer: Bob Mottram (4096 bits) <bob@robotics.uk.to>
Build-Depends: debhelper (>= 9.0.0) Build-Depends: debhelper (>= 9.0.0)
Standards-Version: 3.9.4 Standards-Version: 3.9.4
Homepage: https://github.com/Bitmessage/PyBitmessage Homepage: https://github.com/Bitmessage/PyBitmessage
Vcs-Git: https://github.com/fuzzgun/fin.git Vcs-Git: https://github.com/Bitmessage/PyBitmessage.git
Package: pybitmessage Package: pybitmessage
Section: mail Section: mail
Architecture: any Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, python (>= 2.7.0), openssl, python-qt4, libqt4-dev (>= 4.8.0), python-qt4-dev, sqlite3, libsqlite3-dev Depends: ${shlibs:Depends}, ${misc:Depends}, python (>= 2.7.0), openssl, python-qt4, libqt4-dev (>= 4.8.0), python-qt4-dev, sqlite3, libsqlite3-dev, gst123
Suggests: libmessaging-menu-dev Suggests: libmessaging-menu-dev
Description: Send encrypted messages Description: Send encrypted messages
Bitmessage is a P2P communications protocol used to send encrypted Bitmessage is a P2P communications protocol used to send encrypted

3
debian/rules vendored
View File

@ -1,6 +1,7 @@
#!/usr/bin/make -f #!/usr/bin/make -f
APP=pybitmessage APP=pybitmessage
PREFIX=/usr
build: build-stamp build: build-stamp
make make
build-arch: build-stamp build-arch: build-stamp
@ -20,7 +21,7 @@ install: build clean
dh_testroot dh_testroot
dh_prep dh_prep
dh_installdirs dh_installdirs
${MAKE} install -B DESTDIR=${CURDIR}/debian/${APP} ${MAKE} install -B DESTDIR=${CURDIR}/debian/${APP} PREFIX=/usr
binary-indep: build install binary-indep: build install
dh_testdir dh_testdir
dh_testroot dh_testroot

View File

@ -1,22 +1,32 @@
# $Header: $ # $Header: $
EAPI=4 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." 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" HOMEPAGE="https://github.com/Bitmessage/PyBitmessage"
SRC_URI="${PN}/${P}.tar.gz" EGIT_REPO_URI="https://github.com/Bitmessage/PyBitmessage.git"
LICENSE="MIT" LICENSE="MIT"
SLOT="0" SLOT="0"
KEYWORDS="x86" KEYWORDS="x86"
RDEPEND="dev-libs/popt" DEPEND="dev-libs/popt
DEPEND="${RDEPEND}" ${PYTHON_DEPS}"
RDEPEND="${DEPEND}
dev-libs/openssl
dev-python/PyQt4[]"
src_configure() { src_configure() {
econf --with-popt econf --with-popt
} }
src_compile() { :; }
src_install() { src_install() {
emake DESTDIR="${D}" install emake DESTDIR="${D}" PREFIX="/usr" install
# Install README and (Debian) changelog # Install README and (Debian) changelog
dodoc README.md debian/changelog dodoc README.md debian/changelog
} }

View File

@ -4,4 +4,4 @@
rm -f Makefile rpmpackage/*.spec rm -f Makefile rpmpackage/*.spec
packagemonkey -n "PyBitmessage" --version "0.3.4" --dir "." -l "mit" -e "Bob Mottram (4096 bits) <bob@robotics.uk.to>" --brief "Send encrypted messages" --desc "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" --section "mail" --categories "Office/Email" --dependsdeb "python (>= 2.7.0), openssl, python-qt4, libqt4-dev (>= 4.8.0), python-qt4-dev, sqlite3, libsqlite3-dev" --dependsrpm "python, PyQt4, openssl-compat-bitcoin-libs" --mainscript "bitmessagemain.py" --librarypath "/opt/openssl-compat-bitcoin/lib/" --suggestsdeb "libmessaging-menu-dev" --dependspuppy "openssl, python-qt4, sqlite3, sqlite3-dev, python-openssl, python-sip" --dependsarch "python2, qt4, python2-pyqt4, sqlite, openssl" --suggestsarch "python2-gevent" --pythonversion 2 packagemonkey -n "PyBitmessage" --version "0.3.4" --dir "." -l "mit" -e "Bob Mottram (4096 bits) <bob@robotics.uk.to>" --brief "Send encrypted messages" --desc "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" --section "mail" --categories "Office/Email" --dependsdeb "python (>= 2.7.0), openssl, python-qt4, libqt4-dev (>= 4.8.0), python-qt4-dev, sqlite3, libsqlite3-dev, gst123" --dependsrpm "python, PyQt4, openssl-compat-bitcoin-libs, gst123" --mainscript "bitmessagemain.py" --librarypath "/opt/openssl-compat-bitcoin/lib/" --suggestsdeb "libmessaging-menu-dev" --dependspuppy "openssl, python-qt4, sqlite3, sqlite3-dev, python-openssl, python-sip, gst123" --dependsarch "python2, qt4, python2-pyqt4, sqlite, openssl, gst123" --suggestsarch "python2-gevent" --pythonversion 2 --dependsebuild "dev-libs/openssl, dev-python/PyQt4[${PYTHON_USEDEP}]" --buildebuild "\${PYTHON_DEPS}" --pythonreq "sqlite" --repository "https://github.com/Bitmessage/PyBitmessage.git"

View File

@ -27,7 +27,7 @@ mkdir -p ${PROJECTDIR}
# Build the project # Build the project
make clean make clean
make make
make install -B DESTDIR=${PROJECTDIR} make install -B DESTDIR=${PROJECTDIR} PREFIX=/usr
# Alter the desktop file categories # Alter the desktop file categories
sed -i "s/Categories=Office;Email;/Categories=Internet;mailnews;/g" ${PROJECTDIR}/usr/share/applications/${APP}.desktop sed -i "s/Categories=Office;Email;/Categories=Internet;mailnews;/g" ${PROJECTDIR}/usr/share/applications/${APP}.desktop

View File

@ -1 +1 @@
pybitmessage-0.3.4-1|PyBitmessage|0.3.4|1|Internet;mailnews;|5.1M||pybitmessage-0.3.4-1.pet|+openssl,+python-qt4,+sqlite3,+sqlite3-dev,+python-openssl,+python-sip|Send encrypted messages|ubuntu|precise|5| pybitmessage-0.3.4-1|PyBitmessage|0.3.4|1|Internet;mailnews;|5.8M||pybitmessage-0.3.4-1.pet|+openssl,+python-qt4,+sqlite3,+sqlite3-dev,+python-openssl,+python-sip,+gst123|Send encrypted messages|ubuntu|precise|5|

View File

@ -8,7 +8,7 @@ Packager: Bob Mottram (4096 bits) <bob@robotics.uk.to>
Source0: http://yourdomainname.com/src/%{name}_%{version}.orig.tar.gz Source0: http://yourdomainname.com/src/%{name}_%{version}.orig.tar.gz
Group: Office/Email Group: Office/Email
Requires: python, PyQt4, openssl-compat-bitcoin-libs Requires: python, PyQt4, openssl-compat-bitcoin-libs, gst123
%description %description
@ -48,7 +48,7 @@ mkdir -p %{buildroot}/usr/share/pixmaps
mkdir -p %{buildroot}/usr/share/icons/hicolor/scalable mkdir -p %{buildroot}/usr/share/icons/hicolor/scalable
mkdir -p %{buildroot}/usr/share/icons/hicolor/scalable/apps mkdir -p %{buildroot}/usr/share/icons/hicolor/scalable/apps
# Make install but to the RPM BUILDROOT directory # Make install but to the RPM BUILDROOT directory
make install -B DESTDIR=%{buildroot} make install -B DESTDIR=%{buildroot} PREFIX=/usr
%files %files
%doc README.md LICENSE %doc README.md LICENSE

View File

@ -28,7 +28,7 @@ mkdir -p ${PROJECTDIR}
# Build the project # Build the project
make clean make clean
make make
make install -B DESTDIR=${PROJECTDIR} make install -B DESTDIR=${PROJECTDIR} PREFIX=/usr
# Copy the slack-desc and doinst.sh files into the build install directory # Copy the slack-desc and doinst.sh files into the build install directory
mkdir ${PROJECTDIR}/install mkdir ${PROJECTDIR}/install

View File

@ -9,7 +9,7 @@
# The software version variable is now held in shared.py # The software version variable is now held in shared.py
#import ctypes # import ctypes
try: try:
from gevent import monkey from gevent import monkey
monkey.patch_all() monkey.patch_all()
@ -36,7 +36,7 @@ import helper_bootstrap
import sys import sys
if sys.platform == 'darwin': if sys.platform == 'darwin':
if float( "{1}.{2}".format(*sys.version_info) ) < 7.5: if float("{1}.{2}".format(*sys.version_info)) < 7.5:
print "You should use python 2.7.5 or greater." print "You should use python 2.7.5 or greater."
print "Your version: {0}.{1}.{2}".format(*sys.version_info) print "Your version: {0}.{1}.{2}".format(*sys.version_info)
sys.exit(0) sys.exit(0)
@ -56,8 +56,6 @@ def connectToStream(streamNumber):
# This is one of several classes that constitute the API # This is one of several classes that constitute the API
# This class was written by Vaibhav Bhatia. Modified by Jonathan Warren (Atheros). # 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/ # http://code.activestate.com/recipes/501148-xmlrpc-serverclient-which-does-cookie-handling-and/
class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def do_POST(self): def do_POST(self):
@ -342,7 +340,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
msgid, toAddress, fromAddress, subject, received, message, encodingtype = row msgid, toAddress, fromAddress, subject, received, message, encodingtype = row
subject = shared.fixPotentiallyInvalidUTF8Data(subject) subject = shared.fixPotentiallyInvalidUTF8Data(subject)
message = shared.fixPotentiallyInvalidUTF8Data(message) 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},indent=4, separators=(',', ': ')) 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 += ']}' data += ']}'
return data return data
elif method == 'getAllSentMessages': elif method == 'getAllSentMessages':
@ -358,7 +356,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
message = shared.fixPotentiallyInvalidUTF8Data(message) message = shared.fixPotentiallyInvalidUTF8Data(message)
if len(data) > 25: if len(data) > 25:
data += ',' 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':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 += ']}' data += ']}'
return data return data
elif method == 'getInboxMessagesByAddress': elif method == 'getInboxMessagesByAddress':
@ -373,12 +371,12 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
shared.sqlLock.release() shared.sqlLock.release()
data = '{"inboxMessages":[' data = '{"inboxMessages":['
for row in queryreturn: for row in queryreturn:
msgid, toAddress, fromAddress, subject, received, message, encodingtype= row msgid, toAddress, fromAddress, subject, received, message, encodingtype = row
subject = shared.fixPotentiallyInvalidUTF8Data(subject) subject = shared.fixPotentiallyInvalidUTF8Data(subject)
message = shared.fixPotentiallyInvalidUTF8Data(message) message = shared.fixPotentiallyInvalidUTF8Data(message)
if len(data) > 25: if len(data) > 25:
data += ',' 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':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'receivedTime':received}, indent=4, separators=(',', ': '))
data += ']}' data += ']}'
return data return data
elif method == 'getSentMessageById': elif method == 'getSentMessageById':
@ -396,7 +394,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
subject = shared.fixPotentiallyInvalidUTF8Data(subject) subject = shared.fixPotentiallyInvalidUTF8Data(subject)
message = shared.fixPotentiallyInvalidUTF8Data(message) 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':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 += ']}' data += ']}'
return data return data
elif method == 'getSentMessagesByAddress': elif method == 'getSentMessagesByAddress':
@ -416,7 +414,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
message = shared.fixPotentiallyInvalidUTF8Data(message) message = shared.fixPotentiallyInvalidUTF8Data(message)
if len(data) > 25: if len(data) > 25:
data += ',' 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':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 += ']}' data += ']}'
return data return data
elif method == 'getSentMessageByAckData': elif method == 'getSentMessageByAckData':
@ -434,7 +432,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
subject = shared.fixPotentiallyInvalidUTF8Data(subject) subject = shared.fixPotentiallyInvalidUTF8Data(subject)
message = shared.fixPotentiallyInvalidUTF8Data(message) 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':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 += ']}' data += ']}'
return data return data
elif (method == 'trashMessage') or (method == 'trashInboxMessage'): elif (method == 'trashMessage') or (method == 'trashInboxMessage'):
@ -454,7 +452,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
shared.sqlReturnQueue.get() shared.sqlReturnQueue.get()
shared.sqlSubmitQueue.put('commit') shared.sqlSubmitQueue.put('commit')
shared.sqlLock.release() shared.sqlLock.release()
#shared.UISignalQueue.put(('removeSentRowByMsgid',msgid)) This function doesn't exist yet. # shared.UISignalQueue.put(('removeSentRowByMsgid',msgid)) This function doesn't exist yet.
return 'Trashed sent message (assuming message existed).' return 'Trashed sent message (assuming message existed).'
elif method == 'sendMessage': elif method == 'sendMessage':
if len(params) == 0: if len(params) == 0:
@ -719,8 +717,6 @@ if __name__ == "__main__":
# signal.signal(signal.SIGINT, signal.SIG_DFL) # signal.signal(signal.SIGINT, signal.SIG_DFL)
helper_bootstrap.knownNodes() helper_bootstrap.knownNodes()
helper_bootstrap.dns()
# Start the address generation thread # Start the address generation thread
addressGeneratorThread = addressGenerator() addressGeneratorThread = addressGenerator()
addressGeneratorThread.daemon = True # close the main program even if there are threads left addressGeneratorThread.daemon = True # close the main program even if there are threads left
@ -758,13 +754,6 @@ if __name__ == "__main__":
singleAPIThread = singleAPI() singleAPIThread = singleAPI()
singleAPIThread.daemon = True # close the main program even if there are threads left singleAPIThread.daemon = True # close the main program even if there are threads left
singleAPIThread.start() singleAPIThread.start()
# self.singleAPISignalHandlerThread = singleAPISignalHandler()
# self.singleAPISignalHandlerThread.start()
# QtCore.QObject.connect(self.singleAPISignalHandlerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
# QtCore.QObject.connect(self.singleAPISignalHandlerThread, QtCore.SIGNAL("passAddressGeneratorObjectThrough(PyQt_PyObject)"), self.connectObjectToAddressGeneratorSignals)
# QtCore.QObject.connect(self.singleAPISignalHandlerThread,
# QtCore.SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),
# self.displayNewSentMessage)
connectToStream(1) connectToStream(1)
@ -784,6 +773,7 @@ if __name__ == "__main__":
import bitmessageqt import bitmessageqt
bitmessageqt.run() bitmessageqt.run()
else: else:
shared.config.remove_option('bitmessagesettings', 'dontconnect')
with shared.printLock: with shared.printLock:
print 'Running as a daemon. You can use Ctrl+C to exit.' print 'Running as a daemon. You can use Ctrl+C to exit.'

View File

@ -17,11 +17,13 @@ from bitmessageui import *
from newaddressdialog import * from newaddressdialog import *
from newsubscriptiondialog import * from newsubscriptiondialog import *
from regenerateaddresses import * from regenerateaddresses import *
from newchandialog import *
from specialaddressbehavior import * from specialaddressbehavior import *
from settings import * from settings import *
from about import * from about import *
from help import * from help import *
from iconglossary import * from iconglossary import *
from connect import *
import sys import sys
from time import strftime, localtime, gmtime from time import strftime, localtime, gmtime
import time import time
@ -29,11 +31,16 @@ import os
from pyelliptic.openssl import OpenSSL from pyelliptic.openssl import OpenSSL
import pickle import pickle
import platform import platform
import debug
from debug import logger
import subprocess
try: try:
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import * from PyQt4.QtCore import *
from PyQt4.QtGui import * from PyQt4.QtGui import *
except Exception as err: 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 '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 print 'Error message:', err
@ -50,7 +57,16 @@ def _translate(context, text):
class MyForm(QtGui.QMainWindow): class MyForm(QtGui.QMainWindow):
# sound type constants
SOUND_NONE = 0
SOUND_KNOWN = 1
SOUND_UNKNOWN = 2
SOUND_CONNECTED = 3
SOUND_DISCONNECTED = 4
SOUND_CONNECTION_GREEN = 5
str_broadcast_subscribers = '[Broadcast subscribers]' str_broadcast_subscribers = '[Broadcast subscribers]'
str_chan = '[chan]'
def __init__(self, parent=None): def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
@ -103,6 +119,8 @@ class MyForm(QtGui.QMainWindow):
"triggered()"), self.click_actionDeleteAllTrashedMessages) "triggered()"), self.click_actionDeleteAllTrashedMessages)
QtCore.QObject.connect(self.ui.actionRegenerateDeterministicAddresses, QtCore.SIGNAL( QtCore.QObject.connect(self.ui.actionRegenerateDeterministicAddresses, QtCore.SIGNAL(
"triggered()"), self.click_actionRegenerateDeterministicAddresses) "triggered()"), self.click_actionRegenerateDeterministicAddresses)
QtCore.QObject.connect(self.ui.actionJoinChan, QtCore.SIGNAL(
"triggered()"), self.click_actionJoinChan) # also used for creating chans.
QtCore.QObject.connect(self.ui.pushButtonNewAddress, QtCore.SIGNAL( QtCore.QObject.connect(self.ui.pushButtonNewAddress, QtCore.SIGNAL(
"clicked()"), self.click_NewAddressDialog) "clicked()"), self.click_NewAddressDialog)
QtCore.QObject.connect(self.ui.comboBoxSendFrom, QtCore.SIGNAL( QtCore.QObject.connect(self.ui.comboBoxSendFrom, QtCore.SIGNAL(
@ -291,6 +309,8 @@ class MyForm(QtGui.QMainWindow):
newItem = QtGui.QTableWidgetItem(addressInKeysFile) newItem = QtGui.QTableWidgetItem(addressInKeysFile)
newItem.setFlags( newItem.setFlags(
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
if shared.safeConfigGetBoolean(addressInKeysFile, 'chan'):
newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange
if not isEnabled: if not isEnabled:
newItem.setTextColor(QtGui.QColor(128, 128, 128)) newItem.setTextColor(QtGui.QColor(128, 128, 128))
if shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist'): if shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist'):
@ -405,6 +425,8 @@ class MyForm(QtGui.QMainWindow):
self.rerenderComboBoxSendFrom() self.rerenderComboBoxSendFrom()
# Show or hide the application window after clicking an item within the # Show or hide the application window after clicking an item within the
# tray icon or, on Windows, the try icon itself. # tray icon or, on Windows, the try icon itself.
def appIndicatorShowOrHideWindow(self): def appIndicatorShowOrHideWindow(self):
@ -592,6 +614,9 @@ class MyForm(QtGui.QMainWindow):
elif status == 'msgsent': elif status == 'msgsent':
statusText = _translate("MainWindow", "Message sent. Waiting on acknowledgement. Sent at %1").arg( statusText = _translate("MainWindow", "Message sent. Waiting on acknowledgement. Sent at %1").arg(
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8')) unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
elif status == 'msgsentnoackexpected':
statusText = _translate("MainWindow", "Message sent. Sent at %1").arg(
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
elif status == 'doingmsgpow': elif status == 'doingmsgpow':
statusText = _translate( statusText = _translate(
"MainWindow", "Need to do work to send message. Work is queued.") "MainWindow", "Need to do work to send message. Work is queued.")
@ -707,6 +732,8 @@ class MyForm(QtGui.QMainWindow):
newItem.setData(Qt.UserRole, str(toAddress)) newItem.setData(Qt.UserRole, str(toAddress))
if shared.safeConfigGetBoolean(toAddress, 'mailinglist'): if shared.safeConfigGetBoolean(toAddress, 'mailinglist'):
newItem.setTextColor(QtGui.QColor(137, 04, 177)) newItem.setTextColor(QtGui.QColor(137, 04, 177))
if shared.safeConfigGetBoolean(str(toAddress), 'chan'):
newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange
self.ui.tableWidgetInbox.setItem(0, 0, newItem) self.ui.tableWidgetInbox.setItem(0, 0, newItem)
if fromLabel == '': if fromLabel == '':
newItem = QtGui.QTableWidgetItem( newItem = QtGui.QTableWidgetItem(
@ -952,6 +979,57 @@ class MyForm(QtGui.QMainWindow):
# update the menu entries # update the menu entries
self.ubuntuMessagingMenuUnread(drawAttention) self.ubuntuMessagingMenuUnread(drawAttention)
# play a sound
def playSound(self, category, label):
soundFilename = None
if label is not None:
# does a sound file exist for this particular contact?
if (os.path.isfile(shared.appdata + 'sounds/' + label + '.wav') or
os.path.isfile(shared.appdata + 'sounds/' + label + '.mp3')):
soundFilename = shared.appdata + 'sounds/' + label
if soundFilename is None:
if category is self.SOUND_KNOWN:
soundFilename = shared.appdata + 'sounds/known'
elif category is self.SOUND_UNKNOWN:
soundFilename = shared.appdata + 'sounds/unknown'
elif category is self.SOUND_CONNECTED:
soundFilename = shared.appdata + 'sounds/connected'
elif category is self.SOUND_DISCONNECTED:
soundFilename = shared.appdata + 'sounds/disconnected'
elif category is self.SOUND_CONNECTION_GREEN:
soundFilename = shared.appdata + 'sounds/green'
if soundFilename is not None:
# if not wav then try mp3 format
if not os.path.isfile(soundFilename + '.wav'):
soundFilename = soundFilename + '.mp3'
else:
soundFilename = soundFilename + '.wav'
if os.path.isfile(soundFilename):
if 'linux' in sys.platform:
# Note: QSound was a nice idea but it didn't work
if '.mp3' in soundFilename:
try:
subprocess.call(["gst123", soundFilename],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
except:
print "WARNING: gst123 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"
elif sys.platform[0:3] == 'win':
# use winsound on Windows
import winsound
winsound.PlaySound(soundFilename, winsound.SND_FILENAME)
# initialise the message notifier # initialise the message notifier
def notifierInit(self): def notifierInit(self):
global withMessagingMenu global withMessagingMenu
@ -959,8 +1037,11 @@ class MyForm(QtGui.QMainWindow):
Notify.init('pybitmessage') Notify.init('pybitmessage')
# shows a notification # shows a notification
def notifierShow(self, title, subtitle): def notifierShow(self, title, subtitle, fromCategory, label):
global withMessagingMenu global withMessagingMenu
self.playSound(fromCategory, label);
if withMessagingMenu: if withMessagingMenu:
n = Notify.Notification.new( n = Notify.Notification.new(
title, subtitle, 'notification-message-email') title, subtitle, 'notification-message-email')
@ -1030,6 +1111,68 @@ class MyForm(QtGui.QMainWindow):
), self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(), self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked())) ), self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(), self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked()))
self.ui.tabWidget.setCurrentIndex(3) self.ui.tabWidget.setCurrentIndex(3)
def click_actionJoinChan(self):
self.newChanDialogInstance = newChanDialog(self)
if self.newChanDialogInstance.exec_():
if self.newChanDialogInstance.ui.radioButtonCreateChan.isChecked():
if self.newChanDialogInstance.ui.lineEditChanNameCreate.text() == "":
QMessageBox.about(self, _translate("MainWindow", "Chan name needed"), _translate(
"MainWindow", "You didn't enter a chan name."))
return
shared.apiAddressGeneratorReturnQueue.queue.clear()
shared.addressGeneratorQueue.put(('createChan', 3, 1, self.str_chan + ' ' + str(self.newChanDialogInstance.ui.lineEditChanNameCreate.text().toUtf8()), self.newChanDialogInstance.ui.lineEditChanNameCreate.text().toUtf8()))
addressGeneratorReturnValue = shared.apiAddressGeneratorReturnQueue.get()
print 'addressGeneratorReturnValue', 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."))
return
createdAddress = addressGeneratorReturnValue[0]
self.addEntryToAddressBook(createdAddress, self.str_chan + ' ' + str(self.newChanDialogInstance.ui.lineEditChanNameCreate.text().toUtf8()))
QMessageBox.about(self, _translate("MainWindow", "Success"), _translate(
"MainWindow", "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'.").arg(createdAddress))
self.ui.tabWidget.setCurrentIndex(3)
elif self.newChanDialogInstance.ui.radioButtonJoinChan.isChecked():
if self.newChanDialogInstance.ui.lineEditChanNameJoin.text() == "":
QMessageBox.about(self, _translate("MainWindow", "Chan name needed"), _translate(
"MainWindow", "You didn't enter a chan name."))
return
if decodeAddress(self.newChanDialogInstance.ui.lineEditChanBitmessageAddress.text())[0] == 'versiontoohigh':
QMessageBox.about(self, _translate("MainWindow", "Address too new"), _translate(
"MainWindow", "Although that Bitmessage address might be valid, its version number is too new for us to handle. Perhaps you need to upgrade Bitmessage."))
return
if decodeAddress(self.newChanDialogInstance.ui.lineEditChanBitmessageAddress.text())[0] != 'success':
QMessageBox.about(self, _translate("MainWindow", "Address invalid"), _translate(
"MainWindow", "That Bitmessage address is not valid."))
return
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
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."))
return
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."))
return
createdAddress = addressGeneratorReturnValue[0]
self.addEntryToAddressBook(createdAddress, self.str_chan + ' ' + str(self.newChanDialogInstance.ui.lineEditChanNameJoin.text()))
QMessageBox.about(self, _translate("MainWindow", "Success"), _translate(
"MainWindow", "Successfully joined chan. "))
self.ui.tabWidget.setCurrentIndex(3)
def showConnectDialog(self):
self.connectDialogInstance = connectDialog(self)
if self.connectDialogInstance.exec_():
if self.connectDialogInstance.ui.radioButtonConnectNow.isChecked():
shared.config.remove_option('bitmessagesettings', 'dontconnect')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
else:
self.click_actionSettings()
def openKeysFile(self): def openKeysFile(self):
if 'linux' in sys.platform: if 'linux' in sys.platform:
subprocess.call(["xdg-open", shared.appdata + 'keys.dat']) subprocess.call(["xdg-open", shared.appdata + 'keys.dat'])
@ -1133,7 +1276,8 @@ class MyForm(QtGui.QMainWindow):
# if the connection is lost then show a notification # if the connection is lost then show a notification
if self.connected: if self.connected:
self.notifierShow('Bitmessage', unicode(_translate( self.notifierShow('Bitmessage', unicode(_translate(
"MainWindow", "Connection lost").toUtf8(),'utf-8')) "MainWindow", "Connection lost").toUtf8(),'utf-8'),
self.SOUND_DISCONNECTED, None)
self.connected = False self.connected = False
if self.actionStatus is not None: if self.actionStatus is not None:
@ -1150,7 +1294,8 @@ class MyForm(QtGui.QMainWindow):
# if a new connection has been established then show a notification # if a new connection has been established then show a notification
if not self.connected: if not self.connected:
self.notifierShow('Bitmessage', unicode(_translate( self.notifierShow('Bitmessage', unicode(_translate(
"MainWindow", "Connected").toUtf8(),'utf-8')) "MainWindow", "Connected").toUtf8(),'utf-8'),
self.SOUND_CONNECTED, None)
self.connected = True self.connected = True
if self.actionStatus is not None: if self.actionStatus is not None:
@ -1166,7 +1311,8 @@ class MyForm(QtGui.QMainWindow):
shared.statusIconColor = 'green' shared.statusIconColor = 'green'
if not self.connected: if not self.connected:
self.notifierShow('Bitmessage', unicode(_translate( self.notifierShow('Bitmessage', unicode(_translate(
"MainWindow", "Connected").toUtf8(),'utf-8')) "MainWindow", "Connected").toUtf8(),'utf-8'),
self.SOUND_CONNECTION_GREEN, None)
self.connected = True self.connected = True
if self.actionStatus is not None: if self.actionStatus is not None:
@ -1273,7 +1419,7 @@ class MyForm(QtGui.QMainWindow):
self.ui.tableWidgetInbox.item(i, 0).setTextColor(QtGui.QColor(137, 04, 177)) self.ui.tableWidgetInbox.item(i, 0).setTextColor(QtGui.QColor(137, 04, 177))
else: else:
self.ui.tableWidgetInbox.item( self.ui.tableWidgetInbox.item(
i, 0).setTextColor(QtGui.QColor(0, 0, 0)) i, 0).setTextColor(QApplication.palette().text().color())
def rerenderSentFromLabels(self): def rerenderSentFromLabels(self):
for i in range(self.ui.tableWidgetSent.rowCount()): for i in range(self.ui.tableWidgetSent.rowCount()):
@ -1377,9 +1523,8 @@ class MyForm(QtGui.QMainWindow):
toAddress = addBMIfNotPresent(toAddress) toAddress = addBMIfNotPresent(toAddress)
try: try:
shared.config.get(toAddress, 'enabled') shared.config.get(toAddress, 'enabled')
# The toAddress is one owned by me. We cannot send # The toAddress is one owned by me.
# messages to ourselves without significant changes if not shared.safeConfigGetBoolean(toAddress, 'chan'):
# to the codebase.
QMessageBox.about(self, _translate("MainWindow", "Sending to your address"), _translate( QMessageBox.about(self, _translate("MainWindow", "Sending to your address"), _translate(
"MainWindow", "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.").arg(toAddress)) "MainWindow", "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.").arg(toAddress))
continue continue
@ -1515,6 +1660,16 @@ class MyForm(QtGui.QMainWindow):
def redrawLabelFrom(self, index): def redrawLabelFrom(self, index):
self.ui.labelFrom.setText( self.ui.labelFrom.setText(
self.ui.comboBoxSendFrom.itemData(index).toPyObject()) self.ui.comboBoxSendFrom.itemData(index).toPyObject())
self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(self.ui.comboBoxSendFrom.itemData(index).toPyObject())
def setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(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)
else:
self.ui.radioButtonBroadcast.setEnabled(True)
def rerenderComboBoxSendFrom(self): def rerenderComboBoxSendFrom(self):
self.ui.comboBoxSendFrom.clear() self.ui.comboBoxSendFrom.clear()
@ -1631,6 +1786,8 @@ class MyForm(QtGui.QMainWindow):
newItem.setData(Qt.UserRole, str(toAddress)) newItem.setData(Qt.UserRole, str(toAddress))
if shared.safeConfigGetBoolean(str(toAddress), 'mailinglist'): if shared.safeConfigGetBoolean(str(toAddress), 'mailinglist'):
newItem.setTextColor(QtGui.QColor(137, 04, 177)) newItem.setTextColor(QtGui.QColor(137, 04, 177))
if shared.safeConfigGetBoolean(str(toAddress), 'chan'):
newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange
self.ui.tableWidgetInbox.insertRow(0) self.ui.tableWidgetInbox.insertRow(0)
self.ui.tableWidgetInbox.setItem(0, 0, newItem) self.ui.tableWidgetInbox.setItem(0, 0, newItem)
@ -1638,12 +1795,12 @@ class MyForm(QtGui.QMainWindow):
newItem = QtGui.QTableWidgetItem(unicode(fromAddress, 'utf-8')) newItem = QtGui.QTableWidgetItem(unicode(fromAddress, 'utf-8'))
newItem.setToolTip(unicode(fromAddress, 'utf-8')) newItem.setToolTip(unicode(fromAddress, 'utf-8'))
if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'): 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.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(fromAddress, 'utf-8'), self.SOUND_UNKNOWN, None)
else: else:
newItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8')) newItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8'))
newItem.setToolTip(unicode(unicode(fromLabel, 'utf-8'))) newItem.setToolTip(unicode(unicode(fromLabel, 'utf-8')))
if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'): 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.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.setData(Qt.UserRole, str(fromAddress))
newItem.setFont(font) newItem.setFont(font)
self.ui.tableWidgetInbox.setItem(0, 1, newItem) self.ui.tableWidgetInbox.setItem(0, 1, newItem)
@ -1670,9 +1827,17 @@ class MyForm(QtGui.QMainWindow):
# First we must check to see if the address is already in the # 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 # address book. The user cannot add it again or else it will
# cause problems when updating and deleting the entry. # cause problems when updating and deleting the entry.
address = addBMIfNotPresent(str(
self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text()))
label = self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8()
self.addEntryToAddressBook(address,label)
else:
self.statusBar().showMessage(_translate(
"MainWindow", "The address you entered was invalid. Ignoring it."))
def addEntryToAddressBook(self,address,label):
shared.sqlLock.acquire() shared.sqlLock.acquire()
t = (addBMIfNotPresent(str( t = (address,)
self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())),)
shared.sqlSubmitQueue.put( shared.sqlSubmitQueue.put(
'''select * from addressbook where address=?''') '''select * from addressbook where address=?''')
shared.sqlSubmitQueue.put(t) shared.sqlSubmitQueue.put(t)
@ -1681,17 +1846,14 @@ class MyForm(QtGui.QMainWindow):
if queryreturn == []: if queryreturn == []:
self.ui.tableWidgetAddressBook.setSortingEnabled(False) self.ui.tableWidgetAddressBook.setSortingEnabled(False)
self.ui.tableWidgetAddressBook.insertRow(0) self.ui.tableWidgetAddressBook.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode( newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8'))
self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8(), 'utf-8'))
self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) self.ui.tableWidgetAddressBook.setItem(0, 0, newItem)
newItem = QtGui.QTableWidgetItem(addBMIfNotPresent( newItem = QtGui.QTableWidgetItem(address)
self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text()))
newItem.setFlags( newItem.setFlags(
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.ui.tableWidgetAddressBook.setItem(0, 1, newItem) self.ui.tableWidgetAddressBook.setItem(0, 1, newItem)
self.ui.tableWidgetAddressBook.setSortingEnabled(True) self.ui.tableWidgetAddressBook.setSortingEnabled(True)
t = (str(self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8()), addBMIfNotPresent( t = (str(label), address)
str(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())))
shared.sqlLock.acquire() shared.sqlLock.acquire()
shared.sqlSubmitQueue.put( shared.sqlSubmitQueue.put(
'''INSERT INTO addressbook VALUES (?,?)''') '''INSERT INTO addressbook VALUES (?,?)''')
@ -1704,11 +1866,8 @@ class MyForm(QtGui.QMainWindow):
else: else:
self.statusBar().showMessage(_translate( 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.")) "MainWindow", "Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want."))
else:
self.statusBar().showMessage(_translate(
"MainWindow", "The address you entered was invalid. Ignoring it."))
def addSubscription(self, label, address): def addSubscription(self, address, label):
address = addBMIfNotPresent(address) address = addBMIfNotPresent(address)
#This should be handled outside of this function, for error displaying and such, but it must also be checked here. #This should be handled outside of this function, for error displaying and such, but it must also be checked here.
if shared.isAddressInMySubscriptionsList(address): if shared.isAddressInMySubscriptionsList(address):
@ -1745,7 +1904,7 @@ class MyForm(QtGui.QMainWindow):
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 subsciptions twice. Perhaps rename the existing one if you want."))
return return
label = self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8() label = self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8()
self.addSubscription(label, address) self.addSubscription(address, label)
def loadBlackWhiteList(self): def loadBlackWhiteList(self):
# Initialize the Blacklist or Whitelist table # Initialize the Blacklist or Whitelist table
@ -1800,6 +1959,7 @@ class MyForm(QtGui.QMainWindow):
shared.config.set('bitmessagesettings', 'startintray', str( shared.config.set('bitmessagesettings', 'startintray', str(
self.settingsDialogInstance.ui.checkBoxStartInTray.isChecked())) self.settingsDialogInstance.ui.checkBoxStartInTray.isChecked()))
if int(shared.config.get('bitmessagesettings', 'port')) != int(self.settingsDialogInstance.ui.lineEditTCPPort.text()): if int(shared.config.get('bitmessagesettings', 'port')) != int(self.settingsDialogInstance.ui.lineEditTCPPort.text()):
if not shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate( QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate(
"MainWindow", "You must restart Bitmessage for the port number change to take effect.")) "MainWindow", "You must restart Bitmessage for the port number change to take effect."))
shared.config.set('bitmessagesettings', 'port', str( shared.config.set('bitmessagesettings', 'port', str(
@ -1807,7 +1967,7 @@ class MyForm(QtGui.QMainWindow):
if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none' and str(self.settingsDialogInstance.ui.comboBoxProxyType.currentText())[0:5] == 'SOCKS': if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none' and str(self.settingsDialogInstance.ui.comboBoxProxyType.currentText())[0:5] == 'SOCKS':
if shared.statusIconColor != 'red': if shared.statusIconColor != 'red':
QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate( QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate(
"MainWindow", "Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections.")) "MainWindow", "Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections (if any)."))
if shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS' and str(self.settingsDialogInstance.ui.comboBoxProxyType.currentText()) == 'none': if shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS' and str(self.settingsDialogInstance.ui.comboBoxProxyType.currentText()) == 'none':
self.statusBar().showMessage('') self.statusBar().showMessage('')
shared.config.set('bitmessagesettings', 'socksproxytype', str( shared.config.set('bitmessagesettings', 'socksproxytype', str(
@ -1822,6 +1982,8 @@ class MyForm(QtGui.QMainWindow):
self.settingsDialogInstance.ui.lineEditSocksUsername.text())) self.settingsDialogInstance.ui.lineEditSocksUsername.text()))
shared.config.set('bitmessagesettings', 'sockspassword', str( shared.config.set('bitmessagesettings', 'sockspassword', str(
self.settingsDialogInstance.ui.lineEditSocksPassword.text())) self.settingsDialogInstance.ui.lineEditSocksPassword.text()))
shared.config.set('bitmessagesettings', 'sockslisten', str(
self.settingsDialogInstance.ui.checkBoxSocksListen.isChecked()))
if float(self.settingsDialogInstance.ui.lineEditTotalDifficulty.text()) >= 1: if float(self.settingsDialogInstance.ui.lineEditTotalDifficulty.text()) >= 1:
shared.config.set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(int(float( shared.config.set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(int(float(
self.settingsDialogInstance.ui.lineEditTotalDifficulty.text()) * shared.networkDefaultProofOfWorkNonceTrialsPerByte))) self.settingsDialogInstance.ui.lineEditTotalDifficulty.text()) * shared.networkDefaultProofOfWorkNonceTrialsPerByte)))
@ -1874,7 +2036,14 @@ class MyForm(QtGui.QMainWindow):
shared.knownNodesLock.release() shared.knownNodesLock.release()
os.remove(shared.appdata + 'keys.dat') os.remove(shared.appdata + 'keys.dat')
os.remove(shared.appdata + 'knownnodes.dat') os.remove(shared.appdata + 'knownnodes.dat')
previousAppdataLocation = shared.appdata
shared.appdata = '' shared.appdata = ''
debug.restartLoggingInUpdatedAppdataLocation()
try:
os.remove(previousAppdataLocation + 'debug.log')
os.remove(previousAppdataLocation + 'debug.log.1')
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 == '' 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() shared.appdata = shared.lookupAppdataFolder()
@ -1894,6 +2063,12 @@ class MyForm(QtGui.QMainWindow):
shared.knownNodesLock.release() shared.knownNodesLock.release()
os.remove('keys.dat') os.remove('keys.dat')
os.remove('knownnodes.dat') os.remove('knownnodes.dat')
debug.restartLoggingInUpdatedAppdataLocation()
try:
os.remove('debug.log')
os.remove('debug.log.1')
except:
pass
def click_radioButtonBlacklist(self): def click_radioButtonBlacklist(self):
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white': if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white':
@ -1973,13 +2148,16 @@ class MyForm(QtGui.QMainWindow):
currentRow = self.ui.tableWidgetYourIdentities.currentRow() currentRow = self.ui.tableWidgetYourIdentities.currentRow()
addressAtCurrentRow = str( addressAtCurrentRow = str(
self.ui.tableWidgetYourIdentities.item(currentRow, 1).text()) self.ui.tableWidgetYourIdentities.item(currentRow, 1).text())
if shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'):
return
if self.dialog.ui.radioButtonBehaveNormalAddress.isChecked(): if self.dialog.ui.radioButtonBehaveNormalAddress.isChecked():
shared.config.set(str( shared.config.set(str(
addressAtCurrentRow), 'mailinglist', 'false') addressAtCurrentRow), 'mailinglist', 'false')
# Set the color to either black or grey # Set the color to either black or grey
if shared.config.getboolean(addressAtCurrentRow, 'enabled'): if shared.config.getboolean(addressAtCurrentRow, 'enabled'):
self.ui.tableWidgetYourIdentities.item( self.ui.tableWidgetYourIdentities.item(
currentRow, 1).setTextColor(QtGui.QColor(0, 0, 0)) currentRow, 1).setTextColor(QApplication.palette()
.text().color())
else: else:
self.ui.tableWidgetYourIdentities.item( self.ui.tableWidgetYourIdentities.item(
currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128))
@ -2006,12 +2184,6 @@ class MyForm(QtGui.QMainWindow):
# address.' # address.'
streamNumberForAddress = addressStream( streamNumberForAddress = addressStream(
self.dialog.ui.comboBoxExisting.currentText()) self.dialog.ui.comboBoxExisting.currentText())
# self.addressGenerator = addressGenerator()
# self.addressGenerator.setup(3,streamNumberForAddress,str(self.dialog.ui.newaddresslabel.text().toUtf8()),1,"",self.dialog.ui.checkBoxEighteenByteRipe.isChecked())
# QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
# QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
# self.addressGenerator.start()
shared.addressGeneratorQueue.put(('createRandomAddress', 3, streamNumberForAddress, str( shared.addressGeneratorQueue.put(('createRandomAddress', 3, streamNumberForAddress, str(
self.dialog.ui.newaddresslabel.text().toUtf8()), 1, "", self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) self.dialog.ui.newaddresslabel.text().toUtf8()), 1, "", self.dialog.ui.checkBoxEighteenByteRipe.isChecked()))
else: else:
@ -2023,11 +2195,6 @@ class MyForm(QtGui.QMainWindow):
"MainWindow", "Choose a passphrase"), _translate("MainWindow", "You really do need a passphrase.")) "MainWindow", "Choose a passphrase"), _translate("MainWindow", "You really do need a passphrase."))
else: else:
streamNumberForAddress = 1 # this will eventually have to be replaced by logic to determine the most available stream number. streamNumberForAddress = 1 # this will eventually have to be replaced by logic to determine the most available stream number.
# self.addressGenerator = addressGenerator()
# self.addressGenerator.setup(3,streamNumberForAddress,"unused address",self.dialog.ui.spinBoxNumberOfAddressesToMake.value(),self.dialog.ui.lineEditPassphrase.text().toUtf8(),self.dialog.ui.checkBoxEighteenByteRipe.isChecked())
# QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
# QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
# self.addressGenerator.start()
shared.addressGeneratorQueue.put(('createDeterministicAddresses', 3, streamNumberForAddress, "unused deterministic address", self.dialog.ui.spinBoxNumberOfAddressesToMake.value( shared.addressGeneratorQueue.put(('createDeterministicAddresses', 3, streamNumberForAddress, "unused deterministic address", self.dialog.ui.spinBoxNumberOfAddressesToMake.value(
), self.dialog.ui.lineEditPassphrase.text().toUtf8(), self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) ), self.dialog.ui.lineEditPassphrase.text().toUtf8(), self.dialog.ui.checkBoxEighteenByteRipe.isChecked()))
else: else:
@ -2104,6 +2271,7 @@ class MyForm(QtGui.QMainWindow):
self.ui.labelFrom.setText('') self.ui.labelFrom.setText('')
else: else:
self.ui.labelFrom.setText(toAddressAtCurrentInboxRow) self.ui.labelFrom.setText(toAddressAtCurrentInboxRow)
self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(toAddressAtCurrentInboxRow)
self.ui.lineEditTo.setText(str(fromAddressAtCurrentInboxRow)) self.ui.lineEditTo.setText(str(fromAddressAtCurrentInboxRow))
self.ui.comboBoxSendFrom.setCurrentIndex(0) self.ui.comboBoxSendFrom.setCurrentIndex(0)
# self.ui.comboBoxSendFrom.setEditText(str(self.ui.tableWidgetInbox.item(currentInboxRow,0).text)) # self.ui.comboBoxSendFrom.setEditText(str(self.ui.tableWidgetInbox.item(currentInboxRow,0).text))
@ -2327,7 +2495,7 @@ class MyForm(QtGui.QMainWindow):
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 subsciptions twice. Perhaps rename the existing one if you want."))
continue continue
labelAtCurrentRow = self.ui.tableWidgetAddressBook.item(currentRow,0).text().toUtf8() labelAtCurrentRow = self.ui.tableWidgetAddressBook.item(currentRow,0).text().toUtf8()
self.addSubscription(labelAtCurrentRow, addressAtCurrentRow) self.addSubscription(addressAtCurrentRow, labelAtCurrentRow)
self.ui.tabWidget.setCurrentIndex(4) self.ui.tabWidget.setCurrentIndex(4)
def on_context_menuAddressBook(self, point): def on_context_menuAddressBook(self, point):
@ -2379,9 +2547,9 @@ class MyForm(QtGui.QMainWindow):
shared.sqlSubmitQueue.put('commit') shared.sqlSubmitQueue.put('commit')
shared.sqlLock.release() shared.sqlLock.release()
self.ui.tableWidgetSubscriptions.item( self.ui.tableWidgetSubscriptions.item(
currentRow, 0).setTextColor(QtGui.QColor(0, 0, 0)) currentRow, 0).setTextColor(QApplication.palette().text().color())
self.ui.tableWidgetSubscriptions.item( self.ui.tableWidgetSubscriptions.item(
currentRow, 1).setTextColor(QtGui.QColor(0, 0, 0)) currentRow, 1).setTextColor(QApplication.palette().text().color())
shared.reloadBroadcastSendersForWhichImWatching() shared.reloadBroadcastSendersForWhichImWatching()
def on_action_SubscriptionsDisable(self): def on_action_SubscriptionsDisable(self):
@ -2450,9 +2618,9 @@ class MyForm(QtGui.QMainWindow):
addressAtCurrentRow = self.ui.tableWidgetBlacklist.item( addressAtCurrentRow = self.ui.tableWidgetBlacklist.item(
currentRow, 1).text() currentRow, 1).text()
self.ui.tableWidgetBlacklist.item( self.ui.tableWidgetBlacklist.item(
currentRow, 0).setTextColor(QtGui.QColor(0, 0, 0)) currentRow, 0).setTextColor(QApplication.palette().text().color())
self.ui.tableWidgetBlacklist.item( self.ui.tableWidgetBlacklist.item(
currentRow, 1).setTextColor(QtGui.QColor(0, 0, 0)) currentRow, 1).setTextColor(QApplication.palette().text().color())
t = (str(addressAtCurrentRow),) t = (str(addressAtCurrentRow),)
shared.sqlLock.acquire() shared.sqlLock.acquire()
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black':
@ -2503,13 +2671,15 @@ class MyForm(QtGui.QMainWindow):
with open(shared.appdata + 'keys.dat', 'wb') as configfile: with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile) shared.config.write(configfile)
self.ui.tableWidgetYourIdentities.item( self.ui.tableWidgetYourIdentities.item(
currentRow, 0).setTextColor(QtGui.QColor(0, 0, 0)) currentRow, 0).setTextColor(QApplication.palette().text().color())
self.ui.tableWidgetYourIdentities.item( self.ui.tableWidgetYourIdentities.item(
currentRow, 1).setTextColor(QtGui.QColor(0, 0, 0)) currentRow, 1).setTextColor(QApplication.palette().text().color())
self.ui.tableWidgetYourIdentities.item( self.ui.tableWidgetYourIdentities.item(
currentRow, 2).setTextColor(QtGui.QColor(0, 0, 0)) currentRow, 2).setTextColor(QApplication.palette().text().color())
if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'): if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'):
self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177))
if shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'):
self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(216, 119, 0)) # orange
shared.reloadMyAddressHashes() shared.reloadMyAddressHashes()
def on_action_YourIdentitiesDisable(self): def on_action_YourIdentitiesDisable(self):
@ -2678,11 +2848,14 @@ class MyForm(QtGui.QMainWindow):
def writeNewAddressToTable(self, label, address, streamNumber): def writeNewAddressToTable(self, label, address, streamNumber):
self.ui.tableWidgetYourIdentities.setSortingEnabled(False) self.ui.tableWidgetYourIdentities.setSortingEnabled(False)
self.ui.tableWidgetYourIdentities.insertRow(0) self.ui.tableWidgetYourIdentities.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8'))
self.ui.tableWidgetYourIdentities.setItem( self.ui.tableWidgetYourIdentities.setItem(
0, 0, QtGui.QTableWidgetItem(unicode(label, 'utf-8'))) 0, 0, newItem)
newItem = QtGui.QTableWidgetItem(address) newItem = QtGui.QTableWidgetItem(address)
newItem.setFlags( newItem.setFlags(
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) 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) self.ui.tableWidgetYourIdentities.setItem(0, 1, newItem)
newItem = QtGui.QTableWidgetItem(streamNumber) newItem = QtGui.QTableWidgetItem(streamNumber)
newItem.setFlags( newItem.setFlags(
@ -2709,6 +2882,14 @@ class helpDialog(QtGui.QDialog):
self.ui.labelHelpURI.setOpenExternalLinks(True) self.ui.labelHelpURI.setOpenExternalLinks(True)
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
class connectDialog(QtGui.QDialog):
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_connectDialog()
self.ui.setupUi(self)
self.parent = parent
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
class aboutDialog(QtGui.QDialog): class aboutDialog(QtGui.QDialog):
@ -2729,7 +2910,6 @@ class regenerateAddressesDialog(QtGui.QDialog):
self.parent = parent self.parent = parent
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
class settingsDialog(QtGui.QDialog): class settingsDialog(QtGui.QDialog):
def __init__(self, parent): def __init__(self, parent):
@ -2763,6 +2943,8 @@ class settingsDialog(QtGui.QDialog):
shared.config.get('bitmessagesettings', 'port'))) shared.config.get('bitmessagesettings', 'port')))
self.ui.checkBoxAuthentication.setChecked(shared.config.getboolean( self.ui.checkBoxAuthentication.setChecked(shared.config.getboolean(
'bitmessagesettings', 'socksauthentication')) 'bitmessagesettings', 'socksauthentication'))
self.ui.checkBoxSocksListen.setChecked(shared.config.getboolean(
'bitmessagesettings', 'sockslisten'))
if str(shared.config.get('bitmessagesettings', 'socksproxytype')) == 'none': if str(shared.config.get('bitmessagesettings', 'socksproxytype')) == 'none':
self.ui.comboBoxProxyType.setCurrentIndex(0) self.ui.comboBoxProxyType.setCurrentIndex(0)
self.ui.lineEditSocksHostname.setEnabled(False) self.ui.lineEditSocksHostname.setEnabled(False)
@ -2770,6 +2952,7 @@ class settingsDialog(QtGui.QDialog):
self.ui.lineEditSocksUsername.setEnabled(False) self.ui.lineEditSocksUsername.setEnabled(False)
self.ui.lineEditSocksPassword.setEnabled(False) self.ui.lineEditSocksPassword.setEnabled(False)
self.ui.checkBoxAuthentication.setEnabled(False) self.ui.checkBoxAuthentication.setEnabled(False)
self.ui.checkBoxSocksListen.setEnabled(False)
elif str(shared.config.get('bitmessagesettings', 'socksproxytype')) == 'SOCKS4a': elif str(shared.config.get('bitmessagesettings', 'socksproxytype')) == 'SOCKS4a':
self.ui.comboBoxProxyType.setCurrentIndex(1) self.ui.comboBoxProxyType.setCurrentIndex(1)
self.ui.lineEditTCPPort.setEnabled(False) self.ui.lineEditTCPPort.setEnabled(False)
@ -2826,11 +3009,13 @@ class settingsDialog(QtGui.QDialog):
self.ui.lineEditSocksUsername.setEnabled(False) self.ui.lineEditSocksUsername.setEnabled(False)
self.ui.lineEditSocksPassword.setEnabled(False) self.ui.lineEditSocksPassword.setEnabled(False)
self.ui.checkBoxAuthentication.setEnabled(False) self.ui.checkBoxAuthentication.setEnabled(False)
self.ui.checkBoxSocksListen.setEnabled(False)
self.ui.lineEditTCPPort.setEnabled(True) self.ui.lineEditTCPPort.setEnabled(True)
elif comboBoxIndex == 1 or comboBoxIndex == 2: elif comboBoxIndex == 1 or comboBoxIndex == 2:
self.ui.lineEditSocksHostname.setEnabled(True) self.ui.lineEditSocksHostname.setEnabled(True)
self.ui.lineEditSocksPort.setEnabled(True) self.ui.lineEditSocksPort.setEnabled(True)
self.ui.checkBoxAuthentication.setEnabled(True) self.ui.checkBoxAuthentication.setEnabled(True)
self.ui.checkBoxSocksListen.setEnabled(True)
if self.ui.checkBoxAuthentication.isChecked(): if self.ui.checkBoxAuthentication.isChecked():
self.ui.lineEditSocksUsername.setEnabled(True) self.ui.lineEditSocksUsername.setEnabled(True)
self.ui.lineEditSocksPassword.setEnabled(True) self.ui.lineEditSocksPassword.setEnabled(True)
@ -2847,6 +3032,7 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
currentRow = parent.ui.tableWidgetYourIdentities.currentRow() currentRow = parent.ui.tableWidgetYourIdentities.currentRow()
addressAtCurrentRow = str( addressAtCurrentRow = str(
parent.ui.tableWidgetYourIdentities.item(currentRow, 1).text()) parent.ui.tableWidgetYourIdentities.item(currentRow, 1).text())
if not shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'):
if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'): if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'):
self.ui.radioButtonBehaviorMailingList.click() self.ui.radioButtonBehaviorMailingList.click()
else: else:
@ -2858,6 +3044,11 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
mailingListName = '' mailingListName = ''
self.ui.lineEditMailingListName.setText( self.ui.lineEditMailingListName.setText(
unicode(mailingListName, 'utf-8')) unicode(mailingListName, 'utf-8'))
else: # if addressAtCurrentRow is a chan address
self.ui.radioButtonBehaviorMailingList.setDisabled(True)
self.ui.lineEditMailingListName.setText(_translate(
"MainWindow", "This is a chan address. You cannot use it as a pseudo-mailing list."))
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
@ -2916,11 +3107,11 @@ class NewAddressDialog(QtGui.QDialog):
self.ui.groupBoxDeterministic.setHidden(True) self.ui.groupBoxDeterministic.setHidden(True)
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
class NewChanDialog(QtGui.QDialog): class newChanDialog(QtGui.QDialog):
def __init__(self, parent): def __init__(self, parent):
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.ui = Ui_NewChanDialog() self.ui = Ui_newChanDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
self.parent = parent self.parent = parent
self.ui.groupBoxCreateChan.setHidden(True) self.ui.groupBoxCreateChan.setHidden(True)
@ -3042,6 +3233,8 @@ def run():
myapp.appIndicatorInit(app) myapp.appIndicatorInit(app)
myapp.ubuntuMessagingMenuInit() myapp.ubuntuMessagingMenuInit()
myapp.notifierInit() myapp.notifierInit()
if shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
myapp.showConnectDialog() # ask the user if we may connect
if gevent is None: if gevent is None:
sys.exit(app.exec_()) sys.exit(app.exec_())
else: else:

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'bitmessageui.ui' # Form implementation generated from reading ui file 'bitmessageui.ui'
# #
# Created: Sat Jul 13 20:23:44 2013 # Created: Sun Jul 21 17:50:02 2013
# by: PyQt4 UI code generator 4.10.2 # by: PyQt4 UI code generator 4.10.2
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -453,9 +453,12 @@ class Ui_MainWindow(object):
self.actionRegenerateDeterministicAddresses.setObjectName(_fromUtf8("actionRegenerateDeterministicAddresses")) self.actionRegenerateDeterministicAddresses.setObjectName(_fromUtf8("actionRegenerateDeterministicAddresses"))
self.actionDeleteAllTrashedMessages = QtGui.QAction(MainWindow) self.actionDeleteAllTrashedMessages = QtGui.QAction(MainWindow)
self.actionDeleteAllTrashedMessages.setObjectName(_fromUtf8("actionDeleteAllTrashedMessages")) self.actionDeleteAllTrashedMessages.setObjectName(_fromUtf8("actionDeleteAllTrashedMessages"))
self.actionJoinChan = QtGui.QAction(MainWindow)
self.actionJoinChan.setObjectName(_fromUtf8("actionJoinChan"))
self.menuFile.addAction(self.actionManageKeys) self.menuFile.addAction(self.actionManageKeys)
self.menuFile.addAction(self.actionDeleteAllTrashedMessages) self.menuFile.addAction(self.actionDeleteAllTrashedMessages)
self.menuFile.addAction(self.actionRegenerateDeterministicAddresses) self.menuFile.addAction(self.actionRegenerateDeterministicAddresses)
self.menuFile.addAction(self.actionJoinChan)
self.menuFile.addAction(self.actionExit) self.menuFile.addAction(self.actionExit)
self.menuSettings.addAction(self.actionSettings) self.menuSettings.addAction(self.actionSettings)
self.menuHelp.addAction(self.actionHelp) self.menuHelp.addAction(self.actionHelp)
@ -599,5 +602,6 @@ class Ui_MainWindow(object):
self.actionSettings.setText(_translate("MainWindow", "Settings", None)) self.actionSettings.setText(_translate("MainWindow", "Settings", None))
self.actionRegenerateDeterministicAddresses.setText(_translate("MainWindow", "Regenerate deterministic addresses", None)) self.actionRegenerateDeterministicAddresses.setText(_translate("MainWindow", "Regenerate deterministic addresses", None))
self.actionDeleteAllTrashedMessages.setText(_translate("MainWindow", "Delete all trashed messages", None)) self.actionDeleteAllTrashedMessages.setText(_translate("MainWindow", "Delete all trashed messages", None))
self.actionJoinChan.setText(_translate("MainWindow", "Join / Create chan", None))
import bitmessage_icons_rc import bitmessage_icons_rc

View File

@ -14,7 +14,7 @@
<string>Bitmessage</string> <string>Bitmessage</string>
</property> </property>
<property name="windowIcon"> <property name="windowIcon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/can-icon-24px.png</normaloff>:/newPrefix/images/can-icon-24px.png</iconset> <normaloff>:/newPrefix/images/can-icon-24px.png</normaloff>:/newPrefix/images/can-icon-24px.png</iconset>
</property> </property>
<property name="tabShape"> <property name="tabShape">
@ -61,7 +61,7 @@
</property> </property>
<widget class="QWidget" name="inbox"> <widget class="QWidget" name="inbox">
<attribute name="icon"> <attribute name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/inbox.png</normaloff>:/newPrefix/images/inbox.png</iconset> <normaloff>:/newPrefix/images/inbox.png</normaloff>:/newPrefix/images/inbox.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
@ -188,7 +188,7 @@
</widget> </widget>
<widget class="QWidget" name="send"> <widget class="QWidget" name="send">
<attribute name="icon"> <attribute name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/send.png</normaloff>:/newPrefix/images/send.png</iconset> <normaloff>:/newPrefix/images/send.png</normaloff>:/newPrefix/images/send.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
@ -346,7 +346,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
<widget class="QWidget" name="sent"> <widget class="QWidget" name="sent">
<attribute name="icon"> <attribute name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/sent.png</normaloff>:/newPrefix/images/sent.png</iconset> <normaloff>:/newPrefix/images/sent.png</normaloff>:/newPrefix/images/sent.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
@ -466,7 +466,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
<widget class="QWidget" name="youridentities"> <widget class="QWidget" name="youridentities">
<attribute name="icon"> <attribute name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/identities.png</normaloff>:/newPrefix/images/identities.png</iconset> <normaloff>:/newPrefix/images/identities.png</normaloff>:/newPrefix/images/identities.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
@ -566,7 +566,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
<widget class="QWidget" name="subscriptions"> <widget class="QWidget" name="subscriptions">
<attribute name="icon"> <attribute name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/subscriptions.png</normaloff>:/newPrefix/images/subscriptions.png</iconset> <normaloff>:/newPrefix/images/subscriptions.png</normaloff>:/newPrefix/images/subscriptions.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
@ -651,7 +651,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
<widget class="QWidget" name="addressbook"> <widget class="QWidget" name="addressbook">
<attribute name="icon"> <attribute name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/addressbook.png</normaloff>:/newPrefix/images/addressbook.png</iconset> <normaloff>:/newPrefix/images/addressbook.png</normaloff>:/newPrefix/images/addressbook.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
@ -733,7 +733,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
<widget class="QWidget" name="blackwhitelist"> <widget class="QWidget" name="blackwhitelist">
<attribute name="icon"> <attribute name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/blacklist.png</normaloff>:/newPrefix/images/blacklist.png</iconset> <normaloff>:/newPrefix/images/blacklist.png</normaloff>:/newPrefix/images/blacklist.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
@ -825,7 +825,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
<widget class="QWidget" name="networkstatus"> <widget class="QWidget" name="networkstatus">
<attribute name="icon"> <attribute name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/networkstatus.png</normaloff>:/newPrefix/images/networkstatus.png</iconset> <normaloff>:/newPrefix/images/networkstatus.png</normaloff>:/newPrefix/images/networkstatus.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
@ -844,7 +844,7 @@ p, li { white-space: pre-wrap; }
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset> <iconset resource="bitmessage_icons.qrc">
<normaloff>:/newPrefix/images/redicon.png</normaloff>:/newPrefix/images/redicon.png</iconset> <normaloff>:/newPrefix/images/redicon.png</normaloff>:/newPrefix/images/redicon.png</iconset>
</property> </property>
<property name="flat"> <property name="flat">
@ -1021,6 +1021,7 @@ p, li { white-space: pre-wrap; }
<addaction name="actionManageKeys"/> <addaction name="actionManageKeys"/>
<addaction name="actionDeleteAllTrashedMessages"/> <addaction name="actionDeleteAllTrashedMessages"/>
<addaction name="actionRegenerateDeterministicAddresses"/> <addaction name="actionRegenerateDeterministicAddresses"/>
<addaction name="actionJoinChan"/>
<addaction name="actionExit"/> <addaction name="actionExit"/>
</widget> </widget>
<widget class="QMenu" name="menuSettings"> <widget class="QMenu" name="menuSettings">
@ -1094,6 +1095,11 @@ p, li { white-space: pre-wrap; }
<string>Delete all trashed messages</string> <string>Delete all trashed messages</string>
</property> </property>
</action> </action>
<action name="actionJoinChan">
<property name="text">
<string>Join / Create chan</string>
</property>
</action>
</widget> </widget>
<tabstops> <tabstops>
<tabstop>tabWidget</tabstop> <tabstop>tabWidget</tabstop>

View File

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'connect.ui'
#
# Created: Wed Jul 24 12:42:01 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_connectDialog(object):
def setupUi(self, connectDialog):
connectDialog.setObjectName(_fromUtf8("connectDialog"))
connectDialog.resize(400, 124)
self.gridLayout = QtGui.QGridLayout(connectDialog)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.label = QtGui.QLabel(connectDialog)
self.label.setObjectName(_fromUtf8("label"))
self.gridLayout.addWidget(self.label, 0, 0, 1, 2)
self.radioButtonConnectNow = QtGui.QRadioButton(connectDialog)
self.radioButtonConnectNow.setChecked(True)
self.radioButtonConnectNow.setObjectName(_fromUtf8("radioButtonConnectNow"))
self.gridLayout.addWidget(self.radioButtonConnectNow, 1, 0, 1, 2)
self.radioButtonConfigureNetwork = QtGui.QRadioButton(connectDialog)
self.radioButtonConfigureNetwork.setObjectName(_fromUtf8("radioButtonConfigureNetwork"))
self.gridLayout.addWidget(self.radioButtonConfigureNetwork, 2, 0, 1, 2)
spacerItem = QtGui.QSpacerItem(185, 24, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 3, 0, 1, 1)
self.buttonBox = QtGui.QDialogButtonBox(connectDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.gridLayout.addWidget(self.buttonBox, 3, 1, 1, 1)
self.retranslateUi(connectDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), connectDialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), connectDialog.reject)
QtCore.QMetaObject.connectSlotsByName(connectDialog)
def retranslateUi(self, connectDialog):
connectDialog.setWindowTitle(_translate("connectDialog", "Bitmessage", None))
self.label.setText(_translate("connectDialog", "Bitmessage won\'t connect to anyone until you let it. ", None))
self.radioButtonConnectNow.setText(_translate("connectDialog", "Connect now", None))
self.radioButtonConfigureNetwork.setText(_translate("connectDialog", "Let me configure special network settings first", None))

101
src/bitmessageqt/connect.ui Normal file
View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>connectDialog</class>
<widget class="QDialog" name="connectDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>124</height>
</rect>
</property>
<property name="windowTitle">
<string>Bitmessage</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Bitmessage won't connect to anyone until you let it. </string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QRadioButton" name="radioButtonConnectNow">
<property name="text">
<string>Connect now</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QRadioButton" name="radioButtonConfigureNetwork">
<property name="text">
<string>Let me configure special network settings first</string>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>185</width>
<height>24</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>connectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>connectDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'newchandialog.ui' # Form implementation generated from reading ui file 'newchandialog.ui'
# #
# Created: Tue Jun 25 17:03:01 2013 # Created: Mon Jul 22 01:05:35 2013
# by: PyQt4 UI code generator 4.10.2 # by: PyQt4 UI code generator 4.10.2
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -23,20 +23,36 @@ except AttributeError:
def _translate(context, text, disambig): def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig) return QtGui.QApplication.translate(context, text, disambig)
class Ui_NewChanDialog(object): class Ui_newChanDialog(object):
def setupUi(self, NewChanDialog): def setupUi(self, newChanDialog):
NewChanDialog.setObjectName(_fromUtf8("NewChanDialog")) newChanDialog.setObjectName(_fromUtf8("newChanDialog"))
NewChanDialog.resize(447, 441) newChanDialog.resize(530, 422)
self.formLayout = QtGui.QFormLayout(NewChanDialog) newChanDialog.setMinimumSize(QtCore.QSize(0, 0))
self.formLayout = QtGui.QFormLayout(newChanDialog)
self.formLayout.setObjectName(_fromUtf8("formLayout")) self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.radioButtonCreateChan = QtGui.QRadioButton(NewChanDialog) self.radioButtonCreateChan = QtGui.QRadioButton(newChanDialog)
self.radioButtonCreateChan.setObjectName(_fromUtf8("radioButtonCreateChan")) self.radioButtonCreateChan.setObjectName(_fromUtf8("radioButtonCreateChan"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.radioButtonCreateChan) self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.radioButtonCreateChan)
self.radioButtonJoinChan = QtGui.QRadioButton(NewChanDialog) self.radioButtonJoinChan = QtGui.QRadioButton(newChanDialog)
self.radioButtonJoinChan.setChecked(True) self.radioButtonJoinChan.setChecked(True)
self.radioButtonJoinChan.setObjectName(_fromUtf8("radioButtonJoinChan")) self.radioButtonJoinChan.setObjectName(_fromUtf8("radioButtonJoinChan"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.radioButtonJoinChan) self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.radioButtonJoinChan)
self.groupBoxJoinChan = QtGui.QGroupBox(NewChanDialog) self.groupBoxCreateChan = QtGui.QGroupBox(newChanDialog)
self.groupBoxCreateChan.setObjectName(_fromUtf8("groupBoxCreateChan"))
self.gridLayout = QtGui.QGridLayout(self.groupBoxCreateChan)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.label_4 = QtGui.QLabel(self.groupBoxCreateChan)
self.label_4.setWordWrap(True)
self.label_4.setObjectName(_fromUtf8("label_4"))
self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1)
self.label_5 = QtGui.QLabel(self.groupBoxCreateChan)
self.label_5.setObjectName(_fromUtf8("label_5"))
self.gridLayout.addWidget(self.label_5, 1, 0, 1, 1)
self.lineEditChanNameCreate = QtGui.QLineEdit(self.groupBoxCreateChan)
self.lineEditChanNameCreate.setObjectName(_fromUtf8("lineEditChanNameCreate"))
self.gridLayout.addWidget(self.lineEditChanNameCreate, 2, 0, 1, 1)
self.formLayout.setWidget(2, QtGui.QFormLayout.SpanningRole, self.groupBoxCreateChan)
self.groupBoxJoinChan = QtGui.QGroupBox(newChanDialog)
self.groupBoxJoinChan.setObjectName(_fromUtf8("groupBoxJoinChan")) self.groupBoxJoinChan.setObjectName(_fromUtf8("groupBoxJoinChan"))
self.gridLayout_2 = QtGui.QGridLayout(self.groupBoxJoinChan) self.gridLayout_2 = QtGui.QGridLayout(self.groupBoxJoinChan)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
@ -57,43 +73,30 @@ class Ui_NewChanDialog(object):
self.lineEditChanBitmessageAddress.setObjectName(_fromUtf8("lineEditChanBitmessageAddress")) self.lineEditChanBitmessageAddress.setObjectName(_fromUtf8("lineEditChanBitmessageAddress"))
self.gridLayout_2.addWidget(self.lineEditChanBitmessageAddress, 4, 0, 1, 1) self.gridLayout_2.addWidget(self.lineEditChanBitmessageAddress, 4, 0, 1, 1)
self.formLayout.setWidget(3, QtGui.QFormLayout.SpanningRole, self.groupBoxJoinChan) self.formLayout.setWidget(3, QtGui.QFormLayout.SpanningRole, self.groupBoxJoinChan)
self.groupBoxCreateChan = QtGui.QGroupBox(NewChanDialog) spacerItem = QtGui.QSpacerItem(389, 2, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.groupBoxCreateChan.setObjectName(_fromUtf8("groupBoxCreateChan")) self.formLayout.setItem(4, QtGui.QFormLayout.FieldRole, spacerItem)
self.gridLayout = QtGui.QGridLayout(self.groupBoxCreateChan) self.buttonBox = QtGui.QDialogButtonBox(newChanDialog)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.label_4 = QtGui.QLabel(self.groupBoxCreateChan)
self.label_4.setWordWrap(True)
self.label_4.setObjectName(_fromUtf8("label_4"))
self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1)
self.label_5 = QtGui.QLabel(self.groupBoxCreateChan)
self.label_5.setObjectName(_fromUtf8("label_5"))
self.gridLayout.addWidget(self.label_5, 1, 0, 1, 1)
self.lineEditChanNameCreate = QtGui.QLineEdit(self.groupBoxCreateChan)
self.lineEditChanNameCreate.setObjectName(_fromUtf8("lineEditChanNameCreate"))
self.gridLayout.addWidget(self.lineEditChanNameCreate, 2, 0, 1, 1)
self.formLayout.setWidget(2, QtGui.QFormLayout.SpanningRole, self.groupBoxCreateChan)
self.buttonBox = QtGui.QDialogButtonBox(NewChanDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox")) self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.buttonBox) self.formLayout.setWidget(5, QtGui.QFormLayout.FieldRole, self.buttonBox)
self.retranslateUi(NewChanDialog) self.retranslateUi(newChanDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), NewChanDialog.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), newChanDialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), NewChanDialog.reject) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), newChanDialog.reject)
QtCore.QObject.connect(self.radioButtonJoinChan, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.groupBoxJoinChan.setShown) QtCore.QObject.connect(self.radioButtonJoinChan, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.groupBoxJoinChan.setShown)
QtCore.QObject.connect(self.radioButtonCreateChan, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.groupBoxCreateChan.setShown) QtCore.QObject.connect(self.radioButtonCreateChan, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.groupBoxCreateChan.setShown)
QtCore.QMetaObject.connectSlotsByName(NewChanDialog) QtCore.QMetaObject.connectSlotsByName(newChanDialog)
def retranslateUi(self, NewChanDialog): def retranslateUi(self, newChanDialog):
NewChanDialog.setWindowTitle(_translate("NewChanDialog", "Dialog", None)) newChanDialog.setWindowTitle(_translate("newChanDialog", "Dialog", None))
self.radioButtonCreateChan.setText(_translate("NewChanDialog", "Create a new chan", None)) self.radioButtonCreateChan.setText(_translate("newChanDialog", "Create a new chan", None))
self.radioButtonJoinChan.setText(_translate("NewChanDialog", "Join a chan", None)) self.radioButtonJoinChan.setText(_translate("newChanDialog", "Join a chan", None))
self.groupBoxJoinChan.setTitle(_translate("NewChanDialog", "Join a chan", None)) self.groupBoxCreateChan.setTitle(_translate("newChanDialog", "Create a chan", None))
self.label.setText(_translate("NewChanDialog", "<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>", None)) self.label_4.setText(_translate("newChanDialog", "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.", None))
self.label_2.setText(_translate("NewChanDialog", "Chan name:", None)) self.label_5.setText(_translate("newChanDialog", "Chan name:", None))
self.label_3.setText(_translate("NewChanDialog", "Chan bitmessage address:", None)) self.groupBoxJoinChan.setTitle(_translate("newChanDialog", "Join a chan", None))
self.groupBoxCreateChan.setTitle(_translate("NewChanDialog", "Create a chan", None)) self.label.setText(_translate("newChanDialog", "<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>", None))
self.label_4.setText(_translate("NewChanDialog", "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.", None)) self.label_2.setText(_translate("newChanDialog", "Chan name:", None))
self.label_5.setText(_translate("NewChanDialog", "Chan name:", None)) self.label_3.setText(_translate("newChanDialog", "Chan bitmessage address:", None))

View File

@ -1,15 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>NewChanDialog</class> <class>newChanDialog</class>
<widget class="QDialog" name="NewChanDialog"> <widget class="QDialog" name="newChanDialog">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>447</width> <width>530</width>
<height>441</height> <height>422</height>
</rect> </rect>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Dialog</string>
</property> </property>
@ -31,45 +37,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="groupBoxJoinChan">
<property name="title">
<string>Join a chan</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;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).&lt;/p&gt;&lt;p&gt;Chans are experimental and are unmoderatable.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Chan name:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLineEdit" name="lineEditChanNameJoin"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Chan bitmessage address:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLineEdit" name="lineEditChanBitmessageAddress"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="groupBoxCreateChan"> <widget class="QGroupBox" name="groupBoxCreateChan">
<property name="title"> <property name="title">
@ -99,7 +66,59 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="groupBoxJoinChan">
<property name="title">
<string>Join a chan</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A chan exists when a group of people share the same decryption keys. The keys and bitmessage address used by a chan are generated from a human-friendly word or phrase (the chan name). To send a message to everyone in the chan, send a normal person-to-person message to the chan address.&lt;/p&gt;&lt;p&gt;Chans are experimental and completely unmoderatable.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Chan name:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLineEdit" name="lineEditChanNameJoin"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Chan bitmessage address:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLineEdit" name="lineEditChanBitmessageAddress"/>
</item>
</layout>
</widget>
</item>
<item row="4" column="1"> <item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>389</width>
<height>2</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -116,7 +135,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>NewChanDialog</receiver> <receiver>newChanDialog</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -132,7 +151,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>NewChanDialog</receiver> <receiver>newChanDialog</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -2,8 +2,8 @@
# Form implementation generated from reading ui file 'settings.ui' # Form implementation generated from reading ui file 'settings.ui'
# #
# Created: Mon Jun 10 11:31:56 2013 # Created: Fri Jul 12 12:37:53 2013
# by: PyQt4 UI code generator 4.9.4 # by: PyQt4 UI code generator 4.10.1
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try: try:
_fromUtf8 = QtCore.QString.fromUtf8 _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError: except AttributeError:
_fromUtf8 = lambda s: s def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_settingsDialog(object): class Ui_settingsDialog(object):
def setupUi(self, settingsDialog): def setupUi(self, settingsDialog):
@ -122,6 +131,9 @@ class Ui_settingsDialog(object):
self.lineEditSocksPassword.setEchoMode(QtGui.QLineEdit.Password) self.lineEditSocksPassword.setEchoMode(QtGui.QLineEdit.Password)
self.lineEditSocksPassword.setObjectName(_fromUtf8("lineEditSocksPassword")) self.lineEditSocksPassword.setObjectName(_fromUtf8("lineEditSocksPassword"))
self.gridLayout_2.addWidget(self.lineEditSocksPassword, 2, 5, 1, 1) self.gridLayout_2.addWidget(self.lineEditSocksPassword, 2, 5, 1, 1)
self.checkBoxSocksListen = QtGui.QCheckBox(self.groupBox_2)
self.checkBoxSocksListen.setObjectName(_fromUtf8("checkBoxSocksListen"))
self.gridLayout_2.addWidget(self.checkBoxSocksListen, 3, 1, 1, 4)
self.gridLayout_4.addWidget(self.groupBox_2, 1, 0, 1, 1) self.gridLayout_4.addWidget(self.groupBox_2, 1, 0, 1, 1)
spacerItem2 = QtGui.QSpacerItem(20, 70, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) spacerItem2 = QtGui.QSpacerItem(20, 70, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout_4.addItem(spacerItem2, 2, 0, 1, 1) self.gridLayout_4.addItem(spacerItem2, 2, 0, 1, 1)
@ -235,38 +247,40 @@ class Ui_settingsDialog(object):
settingsDialog.setTabOrder(self.lineEditSocksPort, self.checkBoxAuthentication) settingsDialog.setTabOrder(self.lineEditSocksPort, self.checkBoxAuthentication)
settingsDialog.setTabOrder(self.checkBoxAuthentication, self.lineEditSocksUsername) settingsDialog.setTabOrder(self.checkBoxAuthentication, self.lineEditSocksUsername)
settingsDialog.setTabOrder(self.lineEditSocksUsername, self.lineEditSocksPassword) settingsDialog.setTabOrder(self.lineEditSocksUsername, self.lineEditSocksPassword)
settingsDialog.setTabOrder(self.lineEditSocksPassword, self.buttonBox) settingsDialog.setTabOrder(self.lineEditSocksPassword, self.checkBoxSocksListen)
settingsDialog.setTabOrder(self.checkBoxSocksListen, self.buttonBox)
def retranslateUi(self, settingsDialog): def retranslateUi(self, settingsDialog):
settingsDialog.setWindowTitle(QtGui.QApplication.translate("settingsDialog", "Settings", None, QtGui.QApplication.UnicodeUTF8)) settingsDialog.setWindowTitle(_translate("settingsDialog", "Settings", None))
self.checkBoxStartOnLogon.setText(QtGui.QApplication.translate("settingsDialog", "Start Bitmessage on user login", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxStartOnLogon.setText(_translate("settingsDialog", "Start Bitmessage on user login", None))
self.checkBoxStartInTray.setText(QtGui.QApplication.translate("settingsDialog", "Start Bitmessage in the tray (don\'t show main window)", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxStartInTray.setText(_translate("settingsDialog", "Start Bitmessage in the tray (don\'t show main window)", None))
self.checkBoxMinimizeToTray.setText(QtGui.QApplication.translate("settingsDialog", "Minimize to tray", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxMinimizeToTray.setText(_translate("settingsDialog", "Minimize to tray", None))
self.checkBoxShowTrayNotifications.setText(QtGui.QApplication.translate("settingsDialog", "Show notification when message received", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxShowTrayNotifications.setText(_translate("settingsDialog", "Show notification when message received", None))
self.checkBoxPortableMode.setText(QtGui.QApplication.translate("settingsDialog", "Run in Portable Mode", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxPortableMode.setText(_translate("settingsDialog", "Run in Portable Mode", None))
self.label_7.setText(QtGui.QApplication.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, QtGui.QApplication.UnicodeUTF8)) self.label_7.setText(_translate("settingsDialog", "In Portable Mode, messages and config files are stored in the same directory as the program rather than the normal application-data folder. This makes it convenient to run Bitmessage from a USB thumb drive.", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabUserInterface), QtGui.QApplication.translate("settingsDialog", "User Interface", None, QtGui.QApplication.UnicodeUTF8)) self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabUserInterface), _translate("settingsDialog", "User Interface", None))
self.groupBox.setTitle(QtGui.QApplication.translate("settingsDialog", "Listening port", None, QtGui.QApplication.UnicodeUTF8)) self.groupBox.setTitle(_translate("settingsDialog", "Listening port", None))
self.label.setText(QtGui.QApplication.translate("settingsDialog", "Listen for connections on port:", None, QtGui.QApplication.UnicodeUTF8)) self.label.setText(_translate("settingsDialog", "Listen for connections on port:", None))
self.groupBox_2.setTitle(QtGui.QApplication.translate("settingsDialog", "Proxy server / Tor", None, QtGui.QApplication.UnicodeUTF8)) self.groupBox_2.setTitle(_translate("settingsDialog", "Proxy server / Tor", None))
self.label_2.setText(QtGui.QApplication.translate("settingsDialog", "Type:", None, QtGui.QApplication.UnicodeUTF8)) self.label_2.setText(_translate("settingsDialog", "Type:", None))
self.comboBoxProxyType.setItemText(0, QtGui.QApplication.translate("settingsDialog", "none", None, QtGui.QApplication.UnicodeUTF8)) self.comboBoxProxyType.setItemText(0, _translate("settingsDialog", "none", None))
self.comboBoxProxyType.setItemText(1, QtGui.QApplication.translate("settingsDialog", "SOCKS4a", None, QtGui.QApplication.UnicodeUTF8)) self.comboBoxProxyType.setItemText(1, _translate("settingsDialog", "SOCKS4a", None))
self.comboBoxProxyType.setItemText(2, QtGui.QApplication.translate("settingsDialog", "SOCKS5", None, QtGui.QApplication.UnicodeUTF8)) self.comboBoxProxyType.setItemText(2, _translate("settingsDialog", "SOCKS5", None))
self.label_3.setText(QtGui.QApplication.translate("settingsDialog", "Server hostname:", None, QtGui.QApplication.UnicodeUTF8)) self.label_3.setText(_translate("settingsDialog", "Server hostname:", None))
self.label_4.setText(QtGui.QApplication.translate("settingsDialog", "Port:", None, QtGui.QApplication.UnicodeUTF8)) self.label_4.setText(_translate("settingsDialog", "Port:", None))
self.checkBoxAuthentication.setText(QtGui.QApplication.translate("settingsDialog", "Authentication", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxAuthentication.setText(_translate("settingsDialog", "Authentication", None))
self.label_5.setText(QtGui.QApplication.translate("settingsDialog", "Username:", None, QtGui.QApplication.UnicodeUTF8)) self.label_5.setText(_translate("settingsDialog", "Username:", None))
self.label_6.setText(QtGui.QApplication.translate("settingsDialog", "Pass:", None, QtGui.QApplication.UnicodeUTF8)) self.label_6.setText(_translate("settingsDialog", "Pass:", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabNetworkSettings), QtGui.QApplication.translate("settingsDialog", "Network Settings", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxSocksListen.setText(_translate("settingsDialog", "Listen for incoming connections when using proxy", None))
self.label_8.setText(QtGui.QApplication.translate("settingsDialog", "When someone sends you a message, their computer must first complete some work. The difficulty of this work, by default, is 1. You may raise this default for new addresses you create by changing the values here. Any new addresses you create will require senders to meet the higher difficulty. There is one exception: if you add a friend or acquaintance to your address book, Bitmessage will automatically notify them when you next send a message that they need only complete the minimum amount of work: difficulty 1. ", None, QtGui.QApplication.UnicodeUTF8)) self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabNetworkSettings), _translate("settingsDialog", "Network Settings", None))
self.label_9.setText(QtGui.QApplication.translate("settingsDialog", "Total difficulty:", None, QtGui.QApplication.UnicodeUTF8)) self.label_8.setText(_translate("settingsDialog", "When someone sends you a message, their computer must first complete some work. The difficulty of this work, by default, is 1. You may raise this default for new addresses you create by changing the values here. Any new addresses you create will require senders to meet the higher difficulty. There is one exception: if you add a friend or acquaintance to your address book, Bitmessage will automatically notify them when you next send a message that they need only complete the minimum amount of work: difficulty 1. ", None))
self.label_11.setText(QtGui.QApplication.translate("settingsDialog", "Small message difficulty:", None, QtGui.QApplication.UnicodeUTF8)) self.label_9.setText(_translate("settingsDialog", "Total difficulty:", None))
self.label_12.setText(QtGui.QApplication.translate("settingsDialog", "The \'Small message difficulty\' mostly only affects the difficulty of sending small messages. Doubling this value makes it almost twice as difficult to send a small message but doesn\'t really affect large messages.", None, QtGui.QApplication.UnicodeUTF8)) self.label_11.setText(_translate("settingsDialog", "Small message difficulty:", None))
self.label_10.setText(QtGui.QApplication.translate("settingsDialog", "The \'Total difficulty\' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work.", None, QtGui.QApplication.UnicodeUTF8)) self.label_12.setText(_translate("settingsDialog", "The \'Small message difficulty\' mostly only affects the difficulty of sending small messages. Doubling this value makes it almost twice as difficult to send a small message but doesn\'t really affect large messages.", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tab), QtGui.QApplication.translate("settingsDialog", "Demanded difficulty", None, QtGui.QApplication.UnicodeUTF8)) self.label_10.setText(_translate("settingsDialog", "The \'Total difficulty\' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work.", None))
self.label_15.setText(QtGui.QApplication.translate("settingsDialog", "Here you may set the maximum amount of work you are willing to do to send a message to another person. Setting these values to 0 means that any value is acceptable.", None, QtGui.QApplication.UnicodeUTF8)) self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tab), _translate("settingsDialog", "Demanded difficulty", None))
self.label_13.setText(QtGui.QApplication.translate("settingsDialog", "Maximum acceptable total difficulty:", None, QtGui.QApplication.UnicodeUTF8)) self.label_15.setText(_translate("settingsDialog", "Here you may set the maximum amount of work you are willing to do to send a message to another person. Setting these values to 0 means that any value is acceptable.", None))
self.label_14.setText(QtGui.QApplication.translate("settingsDialog", "Maximum acceptable small message difficulty:", None, QtGui.QApplication.UnicodeUTF8)) self.label_13.setText(_translate("settingsDialog", "Maximum acceptable total difficulty:", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tab_2), QtGui.QApplication.translate("settingsDialog", "Max acceptable difficulty", None, QtGui.QApplication.UnicodeUTF8)) self.label_14.setText(_translate("settingsDialog", "Maximum acceptable small message difficulty:", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tab_2), _translate("settingsDialog", "Max acceptable difficulty", None))

View File

@ -247,6 +247,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1" colspan="4">
<widget class="QCheckBox" name="checkBoxSocksListen">
<property name="text">
<string>Listen for incoming connections when using proxy</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -508,6 +515,7 @@
<tabstop>checkBoxAuthentication</tabstop> <tabstop>checkBoxAuthentication</tabstop>
<tabstop>lineEditSocksUsername</tabstop> <tabstop>lineEditSocksUsername</tabstop>
<tabstop>lineEditSocksPassword</tabstop> <tabstop>lineEditSocksPassword</tabstop>
<tabstop>checkBoxSocksListen</tabstop>
<tabstop>buttonBox</tabstop> <tabstop>buttonBox</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>

View File

@ -21,7 +21,7 @@ if sys.platform == 'darwin':
setup_requires=['py2app'], setup_requires=['py2app'],
app=[mainscript], app=[mainscript],
options=dict(py2app=dict(argv_emulation=True, options=dict(py2app=dict(argv_emulation=True,
includes = ['PyQt4.QtCore','PyQt4.QtGui', 'sip'], includes = ['PyQt4.QtCore','PyQt4.QtGui', 'sip', 'sqlite3'],
packages = ['bitmessageqt'], packages = ['bitmessageqt'],
frameworks = ['/usr/local/opt/openssl/lib/libcrypto.dylib'], frameworks = ['/usr/local/opt/openssl/lib/libcrypto.dylib'],
iconfile='images/bitmessage.icns', iconfile='images/bitmessage.icns',

View File

@ -28,6 +28,8 @@ class addressGenerator(threading.Thread):
elif queueValue[0] == 'joinChan': elif queueValue[0] == 'joinChan':
command, chanAddress, label, deterministicPassphrase = queueValue command, chanAddress, label, deterministicPassphrase = queueValue
eighteenByteRipe = False eighteenByteRipe = False
addressVersionNumber = decodeAddress(chanAddress)[1]
streamNumber = decodeAddress(chanAddress)[2]
numberOfAddressesToMake = 1 numberOfAddressesToMake = 1
elif len(queueValue) == 7: elif len(queueValue) == 7:
command, addressVersionNumber, streamNumber, label, numberOfAddressesToMake, deterministicPassphrase, eighteenByteRipe = queueValue command, addressVersionNumber, streamNumber, label, numberOfAddressesToMake, deterministicPassphrase, eighteenByteRipe = queueValue
@ -35,7 +37,7 @@ class addressGenerator(threading.Thread):
command, addressVersionNumber, streamNumber, label, numberOfAddressesToMake, deterministicPassphrase, eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes = queueValue command, addressVersionNumber, streamNumber, label, numberOfAddressesToMake, deterministicPassphrase, eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes = queueValue
else: else:
sys.stderr.write( sys.stderr.write(
'Programming error: A structure with the wrong number of values was passed into the addressGeneratorQueue. Here is the queueValue: %s\n' % queueValue) 'Programming error: A structure with the wrong number of values was passed into the addressGeneratorQueue. Here is the queueValue: %s\n' % repr(queueValue))
if addressVersionNumber < 3 or addressVersionNumber > 3: if addressVersionNumber < 3 or addressVersionNumber > 3:
sys.stderr.write( sys.stderr.write(
'Program error: For some reason the address generator queue has been given a request to create at least one version %s address which it cannot do.\n' % addressVersionNumber) 'Program error: For some reason the address generator queue has been given a request to create at least one version %s address which it cannot do.\n' % addressVersionNumber)
@ -117,9 +119,8 @@ class addressGenerator(threading.Thread):
with open(shared.appdata + 'keys.dat', 'wb') as configfile: with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile) shared.config.write(configfile)
# It may be the case that this address is being generated # The API and the join and create Chan functionality
# as a result of a call to the API. Let us put the result # both need information back from the address generator.
# in the necessary queue.
shared.apiAddressGeneratorReturnQueue.put(address) shared.apiAddressGeneratorReturnQueue.put(address)
shared.UISignalQueue.put(( shared.UISignalQueue.put((
@ -128,7 +129,7 @@ class addressGenerator(threading.Thread):
label, address, streamNumber))) label, address, streamNumber)))
shared.reloadMyAddressHashes() shared.reloadMyAddressHashes()
shared.workerQueue.put(( shared.workerQueue.put((
'doPOWForMyV3Pubkey', ripe.digest())) 'sendOutOrStoreMyV3Pubkey', ripe.digest()))
elif command == 'createDeterministicAddresses' or command == 'getDeterministicAddress' or command == 'createChan' or command == 'joinChan': elif command == 'createDeterministicAddresses' or command == 'getDeterministicAddress' or command == 'createChan' or command == 'joinChan':
if len(deterministicPassphrase) == 0: if len(deterministicPassphrase) == 0:
@ -188,8 +189,7 @@ class addressGenerator(threading.Thread):
# If we are joining an existing chan, let us check to make sure it matches the provided Bitmessage address # If we are joining an existing chan, let us check to make sure it matches the provided Bitmessage address
if command == 'joinChan': if command == 'joinChan':
if address != chanAddress: if address != chanAddress:
#todo: show an error message in the UI shared.apiAddressGeneratorReturnQueue.put('chan name does not match address')
shared.apiAddressGeneratorReturnQueue.put('API Error 0018: Chan name does not match address.')
saveAddressToDisk = False saveAddressToDisk = False
if command == 'getDeterministicAddress': if command == 'getDeterministicAddress':
saveAddressToDisk = False saveAddressToDisk = False
@ -210,8 +210,13 @@ class addressGenerator(threading.Thread):
privEncryptionKeyWIF = arithmetic.changebase( privEncryptionKeyWIF = arithmetic.changebase(
privEncryptionKey + checksum, 256, 58) privEncryptionKey + checksum, 256, 58)
addressAlreadyExists = False
try: try:
shared.config.add_section(address) shared.config.add_section(address)
except:
print address, 'already exists. Not adding it again.'
addressAlreadyExists = True
if not addressAlreadyExists:
print 'label:', label print 'label:', label
shared.config.set(address, 'label', label) shared.config.set(address, 'label', label)
shared.config.set(address, 'enabled', 'true') shared.config.set(address, 'enabled', 'true')
@ -237,17 +242,13 @@ class addressGenerator(threading.Thread):
potentialPrivEncryptionKey.encode('hex')) potentialPrivEncryptionKey.encode('hex'))
shared.myAddressesByHash[ shared.myAddressesByHash[
ripe.digest()] = address ripe.digest()] = address
#todo: don't send out pubkey if dealing with a chan; save in pubkeys table instead.
shared.workerQueue.put(( shared.workerQueue.put((
'doPOWForMyV3Pubkey', ripe.digest())) 'sendOutOrStoreMyV3Pubkey', ripe.digest())) # If this is a chan address,
except: # the worker thread won't send out the pubkey over the network.
print address, 'already exists. Not adding it again.'
# Done generating addresses. # Done generating addresses.
if command == 'createDeterministicAddresses': if command == 'createDeterministicAddresses' or command == 'joinChan' or command == 'createChan':
# It may be the case that this address is being
# generated as a result of a call to the API. Let us
# put the result in the necessary queue.
shared.apiAddressGeneratorReturnQueue.put( shared.apiAddressGeneratorReturnQueue.put(
listOfNewAddressesToSendOutThroughTheAPI) listOfNewAddressesToSendOutThroughTheAPI)
shared.UISignalQueue.put(( shared.UISignalQueue.put((

View File

@ -7,7 +7,6 @@ import socket
import sys import sys
import tr import tr
#import bitmessagemain
from class_sendDataThread import * from class_sendDataThread import *
from class_receiveDataThread import * from class_receiveDataThread import *
@ -24,7 +23,8 @@ class outgoingSynSender(threading.Thread):
self.selfInitiatedConnections = selfInitiatedConnections self.selfInitiatedConnections = selfInitiatedConnections
def run(self): def run(self):
time.sleep(1) while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
time.sleep(2)
while True: while True:
while len(self.selfInitiatedConnections[self.streamNumber]) >= 8: # maximum number of outgoing connections = 8 while len(self.selfInitiatedConnections[self.streamNumber]) >= 8: # maximum number of outgoing connections = 8
time.sleep(10) time.sleep(10)

View File

@ -1412,33 +1412,38 @@ class receiveDataThread(threading.Thread):
if len(requestedHash) != 20: if len(requestedHash) != 20:
print 'The length of the requested hash is not 20 bytes. Something is wrong. Ignoring.' print 'The length of the requested hash is not 20 bytes. Something is wrong. Ignoring.'
return return
with shared.printLock:
print 'the hash requested in this getpubkey request is:', requestedHash.encode('hex') print 'the hash requested in this getpubkey request is:', requestedHash.encode('hex')
if requestedHash in shared.myAddressesByHash: # if this address hash is one of mine if requestedHash in shared.myAddressesByHash: # if this address hash is one of mine
if decodeAddress(shared.myAddressesByHash[requestedHash])[1] != requestedAddressVersionNumber: if decodeAddress(shared.myAddressesByHash[requestedHash])[1] != requestedAddressVersionNumber:
with shared.printLock: with shared.printLock:
sys.stderr.write( sys.stderr.write(
'(Within the recgetpubkey function) Someone requested one of my pubkeys but the requestedAddressVersionNumber doesn\'t match my actual address version number. That shouldn\'t have happened. Ignoring.\n') '(Within the recgetpubkey function) Someone requested one of my pubkeys but the requestedAddressVersionNumber doesn\'t match my actual address version number. They shouldn\'t have done that. Ignoring.\n')
return
if shared.safeConfigGetBoolean(shared.myAddressesByHash[requestedHash], 'chan'):
with shared.printLock:
print 'Ignoring getpubkey request because it is for one of my chan addresses. The other party should already have the pubkey.'
return return
try: try:
lastPubkeySendTime = int(shared.config.get( lastPubkeySendTime = int(shared.config.get(
shared.myAddressesByHash[requestedHash], 'lastpubkeysendtime')) shared.myAddressesByHash[requestedHash], 'lastpubkeysendtime'))
except: except:
lastPubkeySendTime = 0 lastPubkeySendTime = 0
if lastPubkeySendTime < time.time() - shared.lengthOfTimeToHoldOnToAllPubkeys: # If the last time we sent our pubkey was at least 28 days ago... if lastPubkeySendTime > time.time() - shared.lengthOfTimeToHoldOnToAllPubkeys: # If the last time we sent our pubkey was more recent than 28 days ago...
with shared.printLock:
print 'Found getpubkey-requested-hash in my list of EC hashes BUT we already sent it recently. Ignoring request. The lastPubkeySendTime is:', lastPubkeySendTime
return
with shared.printLock: with shared.printLock:
print 'Found getpubkey-requested-hash in my list of EC hashes. Telling Worker thread to do the POW for a pubkey message and send it out.' print 'Found getpubkey-requested-hash in my list of EC hashes. Telling Worker thread to do the POW for a pubkey message and send it out.'
if requestedAddressVersionNumber == 2: if requestedAddressVersionNumber == 2:
shared.workerQueue.put(( shared.workerQueue.put((
'doPOWForMyV2Pubkey', requestedHash)) 'doPOWForMyV2Pubkey', requestedHash))
elif requestedAddressVersionNumber == 3: elif requestedAddressVersionNumber == 3:
shared.workerQueue.put(( shared.workerQueue.put((
'doPOWForMyV3Pubkey', requestedHash)) 'sendOutOrStoreMyV3Pubkey', requestedHash))
else:
with shared.printLock:
print 'Found getpubkey-requested-hash in my list of EC hashes BUT we already sent it recently. Ignoring request. The lastPubkeySendTime is:', lastPubkeySendTime
else: else:
with shared.printLock: with shared.printLock:

View File

@ -3,6 +3,7 @@ import shared
import socket import socket
from class_sendDataThread import * from class_sendDataThread import *
from class_receiveDataThread import * from class_receiveDataThread import *
import helper_bootstrap
# Only one singleListener thread will ever exist. It creates the # Only one singleListener thread will ever exist. It creates the
# receiveDataThread and sendDataThread for each incoming connection. Note # receiveDataThread and sendDataThread for each incoming connection. Note
@ -21,11 +22,15 @@ class singleListener(threading.Thread):
self.selfInitiatedConnections = selfInitiatedConnections self.selfInitiatedConnections = selfInitiatedConnections
def run(self): def run(self):
# We don't want to accept incoming connections if the user is using a while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
# SOCKS proxy. If they eventually select proxy 'none' then this will time.sleep(1)
# start listening for connections. helper_bootstrap.dns()
while shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS': # We typically don't want to accept incoming connections if the user is using a
time.sleep(300) # SOCKS proxy, unless they have configured otherwise. If they eventually select
# proxy 'none' or configure SOCKS listening then this will start listening for
# connections.
while shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS' and not shared.config.getboolean('bitmessagesettings', 'sockslisten'):
time.sleep(5)
with shared.printLock: with shared.printLock:
print 'Listening for incoming connections.' print 'Listening for incoming connections.'
@ -40,10 +45,11 @@ class singleListener(threading.Thread):
sock.listen(2) sock.listen(2)
while True: while True:
# We don't want to accept incoming connections if the user is using # We typically don't want to accept incoming connections if the user is using a
# a SOCKS proxy. If the user eventually select proxy 'none' then # SOCKS proxy, unless they have configured otherwise. If they eventually select
# this will start listening for connections. # proxy 'none' or configure SOCKS listening then this will start listening for
while shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS': # connections.
while shared.config.get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS' and not shared.config.getboolean('bitmessagesettings', 'sockslisten'):
time.sleep(10) time.sleep(10)
while len(shared.connectedHostsList) > 220: while len(shared.connectedHostsList) > 220:
with shared.printLock: with shared.printLock:

View File

@ -72,8 +72,8 @@ class singleWorker(threading.Thread):
self.sendBroadcast() self.sendBroadcast()
elif command == 'doPOWForMyV2Pubkey': elif command == 'doPOWForMyV2Pubkey':
self.doPOWForMyV2Pubkey(data) self.doPOWForMyV2Pubkey(data)
elif command == 'doPOWForMyV3Pubkey': elif command == 'sendOutOrStoreMyV3Pubkey':
self.doPOWForMyV3Pubkey(data) self.sendOutOrStoreMyV3Pubkey(data)
"""elif command == 'newpubkey': """elif command == 'newpubkey':
toAddressVersion,toStreamNumber,toRipe = data toAddressVersion,toStreamNumber,toRipe = data
if toRipe in shared.neededPubkeys: if toRipe in shared.neededPubkeys:
@ -173,7 +173,11 @@ class singleWorker(threading.Thread):
with open(shared.appdata + 'keys.dat', 'wb') as configfile: with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile) shared.config.write(configfile)
def doPOWForMyV3Pubkey(self, hash): # This function also broadcasts out the pubkey message once it is done with the POW # If this isn't a chan address, this function assembles the pubkey data,
# does the necessary POW and sends it out. If it *is* a chan then it
# assembles the pubkey and stores is in the pubkey table so that we can
# send messages to "ourselves".
def sendOutOrStoreMyV3Pubkey(self, hash):
myAddress = shared.myAddressesByHash[hash] myAddress = shared.myAddressesByHash[hash]
status, addressVersionNumber, streamNumber, hash = decodeAddress( status, addressVersionNumber, streamNumber, hash = decodeAddress(
myAddress) myAddress)
@ -192,7 +196,7 @@ class singleWorker(threading.Thread):
except Exception as err: except Exception as err:
with shared.printLock: with shared.printLock:
sys.stderr.write( sys.stderr.write(
'Error within doPOWForMyV3Pubkey. Could not read the keys from the keys.dat file for a requested address. %s\n' % err) 'Error within sendOutOrStoreMyV3Pubkey. Could not read the keys from the keys.dat file for a requested address. %s\n' % err)
return return
@ -216,6 +220,7 @@ class singleWorker(threading.Thread):
payload += encodeVarint(len(signature)) payload += encodeVarint(len(signature))
payload += signature payload += signature
if not shared.safeConfigGetBoolean(myAddress, 'chan'):
# Do the POW for this pubkey message # Do the POW for this pubkey message
target = 2 ** 64 / ((len(payload) + shared.networkDefaultPayloadLengthExtraBytes + target = 2 ** 64 / ((len(payload) + shared.networkDefaultPayloadLengthExtraBytes +
8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) 8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte)
@ -225,14 +230,6 @@ class singleWorker(threading.Thread):
print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce
payload = pack('>Q', nonce) + payload payload = pack('>Q', nonce) + payload
"""t = (hash,payload,embeddedTime,'no')
shared.sqlLock.acquire()
shared.sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?)''')
shared.sqlSubmitQueue.put(t)
queryreturn = shared.sqlReturnQueue.get()
shared.sqlSubmitQueue.put('commit')
shared.sqlLock.release()"""
inventoryHash = calculateInventoryHash(payload) inventoryHash = calculateInventoryHash(payload)
objectType = 'pubkey' objectType = 'pubkey'
shared.inventory[inventoryHash] = ( shared.inventory[inventoryHash] = (
@ -244,6 +241,19 @@ class singleWorker(threading.Thread):
shared.broadcastToSendDataQueues(( shared.broadcastToSendDataQueues((
streamNumber, 'sendinv', inventoryHash)) streamNumber, 'sendinv', inventoryHash))
shared.UISignalQueue.put(('updateStatusBar', '')) shared.UISignalQueue.put(('updateStatusBar', ''))
# If this is a chan address then we won't send out the pubkey over the
# network but rather will only store it in our pubkeys table so that
# we can send messages to "ourselves".
if shared.safeConfigGetBoolean(myAddress, 'chan'):
payload = '\x00' * 8 + payload # Attach a fake nonce on the front
# just so that it is in the correct format.
t = (hash,payload,embeddedTime,'yes')
shared.sqlLock.acquire()
shared.sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?)''')
shared.sqlSubmitQueue.put(t)
shared.sqlReturnQueue.get()
shared.sqlSubmitQueue.put('commit')
shared.sqlLock.release()
shared.config.set( shared.config.set(
myAddress, 'lastpubkeysendtime', str(int(time.time()))) myAddress, 'lastpubkeysendtime', str(int(time.time())))
with open(shared.appdata + 'keys.dat', 'wb') as configfile: with open(shared.appdata + 'keys.dat', 'wb') as configfile:
@ -414,10 +424,10 @@ class singleWorker(threading.Thread):
# Update the status of the message in the 'sent' table to have # Update the status of the message in the 'sent' table to have
# a 'broadcastsent' status # a 'broadcastsent' status
shared.sqlLock.acquire() shared.sqlLock.acquire()
t = ('broadcastsent', int( t = (inventoryHash,'broadcastsent', int(
time.time()), fromaddress, subject, body, 'broadcastqueued') time.time()), fromaddress, subject, body, 'broadcastqueued')
shared.sqlSubmitQueue.put( shared.sqlSubmitQueue.put(
'UPDATE sent SET status=?, lastactiontime=? WHERE fromaddress=? AND subject=? AND message=? AND status=?') 'UPDATE sent SET msgid=?, status=?, lastactiontime=? WHERE fromaddress=? AND subject=? AND message=? AND status=?')
shared.sqlSubmitQueue.put(t) shared.sqlSubmitQueue.put(t)
queryreturn = shared.sqlReturnQueue.get() queryreturn = shared.sqlReturnQueue.get()
shared.sqlSubmitQueue.put('commit') shared.sqlSubmitQueue.put('commit')
@ -722,6 +732,11 @@ class singleWorker(threading.Thread):
subject + '\n' + 'Body:' + message subject + '\n' + 'Body:' + message
payload += encodeVarint(len(messageToTransmit)) payload += encodeVarint(len(messageToTransmit))
payload += messageToTransmit payload += messageToTransmit
if shared.safeConfigGetBoolean(toaddress, 'chan'):
with shared.printLock:
print 'Not bothering to generate ackdata because we are sending to a chan.'
fullAckPayload = ''
else:
fullAckPayload = self.generateFullAckMessage( fullAckPayload = self.generateFullAckMessage(
ackdata, toStreamNumber, embeddedTime) # The fullAckPayload is a normal msg protocol message with the proof of work already completed that the receiver of this message can easily send out. ackdata, toStreamNumber, embeddedTime) # The fullAckPayload is a normal msg protocol message with the proof of work already completed that the receiver of this message can easily send out.
payload += encodeVarint(len(fullAckPayload)) payload += encodeVarint(len(fullAckPayload))
@ -765,6 +780,11 @@ class singleWorker(threading.Thread):
objectType = 'msg' objectType = 'msg'
shared.inventory[inventoryHash] = ( shared.inventory[inventoryHash] = (
objectType, toStreamNumber, encryptedPayload, int(time.time())) objectType, toStreamNumber, encryptedPayload, int(time.time()))
if shared.safeConfigGetBoolean(toaddress, 'chan'):
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Sent on %1").arg(unicode(
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))))
else:
# not sending to a chan
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Waiting on acknowledgement. Sent on %1").arg(unicode( shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Waiting on acknowledgement. Sent on %1").arg(unicode(
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8'))))) strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))))
print 'Broadcasting inv for my msg(within sendmsg function):', inventoryHash.encode('hex') print 'Broadcasting inv for my msg(within sendmsg function):', inventoryHash.encode('hex')
@ -772,10 +792,14 @@ class singleWorker(threading.Thread):
streamNumber, 'sendinv', inventoryHash)) streamNumber, 'sendinv', inventoryHash))
# Update the status of the message in the 'sent' table to have a # Update the status of the message in the 'sent' table to have a
# 'msgsent' status # 'msgsent' status or 'msgsentnoackexpected' status.
if shared.safeConfigGetBoolean(toaddress, 'chan'):
newStatus = 'msgsentnoackexpected'
else:
newStatus = 'msgsent'
shared.sqlLock.acquire() shared.sqlLock.acquire()
t = (ackdata,) t = (inventoryHash,newStatus,ackdata,)
shared.sqlSubmitQueue.put('''UPDATE sent SET status='msgsent' WHERE ackdata=?''') shared.sqlSubmitQueue.put('''UPDATE sent SET msgid=?, status=? WHERE ackdata=?''')
shared.sqlSubmitQueue.put(t) shared.sqlSubmitQueue.put(t)
queryreturn = shared.sqlReturnQueue.get() queryreturn = shared.sqlReturnQueue.get()
shared.sqlSubmitQueue.put('commit') shared.sqlSubmitQueue.put('commit')

View File

@ -5,6 +5,7 @@ import time
import shutil # used for moving the messages.dat file import shutil # used for moving the messages.dat file
import sys import sys
import os import os
from debug import logger
# This thread exists because SQLITE3 is so un-threadsafe that we must # This thread exists because SQLITE3 is so un-threadsafe that we must
# submit queries to it and it puts results back in a different queue. They # submit queries to it and it puts results back in a different queue. They
@ -80,6 +81,7 @@ class sqlThread(threading.Thread):
shared.config.set('bitmessagesettings', 'socksauthentication', 'false') shared.config.set('bitmessagesettings', 'socksauthentication', 'false')
shared.config.set('bitmessagesettings', 'socksusername', '') shared.config.set('bitmessagesettings', 'socksusername', '')
shared.config.set('bitmessagesettings', 'sockspassword', '') shared.config.set('bitmessagesettings', 'sockspassword', '')
shared.config.set('bitmessagesettings', 'sockslisten', 'false')
shared.config.set('bitmessagesettings', 'keysencrypted', 'false') shared.config.set('bitmessagesettings', 'keysencrypted', 'false')
shared.config.set('bitmessagesettings', 'messagesencrypted', 'false') shared.config.set('bitmessagesettings', 'messagesencrypted', 'false')
with open(shared.appdata + 'keys.dat', 'wb') as configfile: with open(shared.appdata + 'keys.dat', 'wb') as configfile:
@ -185,6 +187,9 @@ class sqlThread(threading.Thread):
'''update sent set status='broadcastqueued' where status='broadcastpending' ''') '''update sent set status='broadcastqueued' where status='broadcastpending' ''')
self.conn.commit() self.conn.commit()
if not shared.config.has_option('bitmessagesettings', 'sockslisten'):
shared.config.set('bitmessagesettings', 'sockslisten', 'false')
try: try:
testpayload = '\x00\x00' testpayload = '\x00\x00'
t = ('1234', testpayload, '12345678', 'no') t = ('1234', testpayload, '12345678', 'no')

View File

@ -23,7 +23,8 @@ import shared
# TODO(xj9): Get from a config file. # TODO(xj9): Get from a config file.
log_level = 'DEBUG' log_level = 'DEBUG'
logging.config.dictConfig({ def configureLogging():
logging.config.dictConfig({
'version': 1, 'version': 1,
'formatters': { 'formatters': {
'default': { 'default': {
@ -64,7 +65,17 @@ logging.config.dictConfig({
'level': log_level, 'level': log_level,
'handlers': ['console'], 'handlers': ['console'],
}, },
}) })
# TODO (xj9): Get from a config file. # TODO (xj9): Get from a config file.
#logger = logging.getLogger('console_only') #logger = logging.getLogger('console_only')
configureLogging()
logger = logging.getLogger('both') logger = logging.getLogger('both')
def restartLoggingInUpdatedAppdataLocation():
global logger
for i in list(logger.handlers):
logger.removeHandler(i)
i.flush()
i.close()
configureLogging()
logger = logging.getLogger('both')

View File

@ -12,28 +12,25 @@ def knownNodes():
shared.knownNodes = pickle.load(pickleFile) shared.knownNodes = pickle.load(pickleFile)
pickleFile.close() pickleFile.close()
except: except:
defaultKnownNodes.createDefaultKnownNodes(shared.appdata) shared.knownNodes = defaultKnownNodes.createDefaultKnownNodes(shared.appdata)
pickleFile = open(shared.appdata + 'knownnodes.dat', 'rb')
shared.knownNodes = pickle.load(pickleFile)
pickleFile.close()
if shared.config.getint('bitmessagesettings', 'settingsversion') > 6: if shared.config.getint('bitmessagesettings', 'settingsversion') > 6:
print 'Bitmessage cannot read future versions of the keys file (keys.dat). Run the newer version of Bitmessage.' print 'Bitmessage cannot read future versions of the keys file (keys.dat). Run the newer version of Bitmessage.'
raise SystemExit raise SystemExit
def dns(): def dns():
# DNS bootstrap. This could be programmed to use the SOCKS proxy to do the # DNS bootstrap. This could be programmed to use the SOCKS proxy to do the
# DNS lookup some day but for now we will just rely on the entries in # DNS lookup some day but for now we will just rely on the entries in
# defaultKnownNodes.py. Hopefully either they are up to date or the user # defaultKnownNodes.py. Hopefully either they are up to date or the user
# has run Bitmessage recently without SOCKS turned on and received good # has run Bitmessage recently without SOCKS turned on and received good
# bootstrap nodes using that method. # bootstrap nodes using that method.
with shared.printLock:
if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none': if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none':
try: try:
for item in socket.getaddrinfo('bootstrap8080.bitmessage.org', 80): for item in socket.getaddrinfo('bootstrap8080.bitmessage.org', 80):
print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method' print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method'
shared.knownNodes[1][item[4][0]] = (8080, int(time.time())) shared.knownNodes[1][item[4][0]] = (8080, int(time.time()))
except: except:
print 'bootstrap8080.bitmessage.org DNS bootstraping failed.' print 'bootstrap8080.bitmessage.org DNS bootstrapping failed.'
try: try:
for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80): for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80):
print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method' print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method'

View File

@ -50,6 +50,8 @@ def loadConfig():
shared.config.set('bitmessagesettings', 'socksport', '9050') shared.config.set('bitmessagesettings', 'socksport', '9050')
shared.config.set( shared.config.set(
'bitmessagesettings', 'socksauthentication', 'false') 'bitmessagesettings', 'socksauthentication', 'false')
shared.config.set(
'bitmessagesettings', 'sockslisten', 'false')
shared.config.set('bitmessagesettings', 'socksusername', '') shared.config.set('bitmessagesettings', 'socksusername', '')
shared.config.set('bitmessagesettings', 'sockspassword', '') shared.config.set('bitmessagesettings', 'sockspassword', '')
shared.config.set('bitmessagesettings', 'keysencrypted', 'false') shared.config.set('bitmessagesettings', 'keysencrypted', 'false')
@ -64,6 +66,7 @@ def loadConfig():
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', '0') 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', '0')
shared.config.set( shared.config.set(
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', '0') 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', '0')
shared.config.set('bitmessagesettings', 'dontconnect', 'true')
if storeConfigFilesInSameDirectoryAsProgramByDefault: if storeConfigFilesInSameDirectoryAsProgramByDefault:
# Just use the same directory as the program and forget about # Just use the same directory as the program and forget about
@ -74,5 +77,7 @@ def loadConfig():
print 'Creating new config files in', shared.appdata print 'Creating new config files in', shared.appdata
if not os.path.exists(shared.appdata): if not os.path.exists(shared.appdata):
os.makedirs(shared.appdata) os.makedirs(shared.appdata)
if not sys.platform.startswith('win'):
os.umask(0o077)
with open(shared.appdata + 'keys.dat', 'wb') as configfile: with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile) shared.config.write(configfile)

View File

@ -107,8 +107,8 @@ def vacuum():
#takeInboxMessagesOutOfTrash() #takeInboxMessagesOutOfTrash()
#takeSentMessagesOutOfTrash() #takeSentMessagesOutOfTrash()
#markAllInboxMessagesAsUnread() #markAllInboxMessagesAsUnread()
#readInbox() readInbox()
readSent() #readSent()
#readPubkeys() #readPubkeys()
#readSubscriptions() #readSubscriptions()
#readInventory() #readInventory()

View File

@ -8,22 +8,26 @@ maximumAgeOfNodesThatIAdvertiseToOthers = 10800 # Equals three hours
useVeryEasyProofOfWorkForTesting = False # If you set this to True while on the normal network, you won't be able to send or sometimes receive messages. useVeryEasyProofOfWorkForTesting = False # If you set this to True while on the normal network, you won't be able to send or sometimes receive messages.
import threading # Libraries.
import sys
from addresses import *
import highlevelcrypto
import Queue
import pickle
import os
import time
import ConfigParser import ConfigParser
import socket import os
import pickle
import Queue
import random import random
import socket
import sys
import stat
import threading
import time
# Project imports.
from addresses import *
import highlevelcrypto import highlevelcrypto
import shared import shared
import helper_startup import helper_startup
config = ConfigParser.SafeConfigParser() config = ConfigParser.SafeConfigParser()
myECCryptorObjects = {} myECCryptorObjects = {}
MyECSubscriptionCryptorObjects = {} MyECSubscriptionCryptorObjects = {}
@ -118,8 +122,11 @@ def lookupAppdataFolder():
if "HOME" in environ: if "HOME" in environ:
dataFolder = path.join(os.environ["HOME"], "Library/Application Support/", APPNAME) + '/' dataFolder = path.join(os.environ["HOME"], "Library/Application Support/", APPNAME) + '/'
else: else:
logger.critical('Could not find home folder, please report this message and your ' stringToLog = 'Could not find home folder, please report this message and your OS X version to the BitMessage Github.'
'OS X version to the BitMessage Github.') if 'logger' in globals():
logger.critical(stringToLog)
else:
print stringToLog
sys.exit() sys.exit()
elif 'win32' in sys.platform or 'win64' in sys.platform: elif 'win32' in sys.platform or 'win64' in sys.platform:
@ -133,9 +140,14 @@ def lookupAppdataFolder():
# Migrate existing data to the proper location if this is an existing install # Migrate existing data to the proper location if this is an existing install
try: try:
logger.info("Moving data folder to %s" % (dataFolder))
move(path.join(environ["HOME"], ".%s" % APPNAME), dataFolder) move(path.join(environ["HOME"], ".%s" % APPNAME), dataFolder)
stringToLog = "Moving data folder to %s" % (dataFolder)
if 'logger' in globals():
logger.info(stringToLog)
else:
print stringToLog
except IOError: except IOError:
# Old directory may not exist.
pass pass
dataFolder = dataFolder + '/' dataFolder = dataFolder + '/'
return dataFolder return dataFolder
@ -183,21 +195,24 @@ def isAddressInMyAddressBookSubscriptionsListOrWhitelist(address):
def safeConfigGetBoolean(section,field): def safeConfigGetBoolean(section,field):
try: try:
return config.getboolean(section,field) return config.getboolean(section,field)
except: except Exception, err:
return False return False
def decodeWalletImportFormat(WIFstring): def decodeWalletImportFormat(WIFstring):
fullString = arithmetic.changebase(WIFstring,58,256) fullString = arithmetic.changebase(WIFstring,58,256)
privkey = fullString[:-4] privkey = fullString[:-4]
if fullString[-4:] != hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]: if fullString[-4:] != hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]:
sys.stderr.write('Major problem! When trying to decode one of your private keys, the checksum failed. Here is the PRIVATE key: %s\n' % str(WIFstring)) logger.error('Major problem! When trying to decode one of your private keys, the checksum '
'failed. Here is the PRIVATE key: %s\n' % str(WIFstring))
return "" return ""
else: else:
#checksum passed #checksum passed
if privkey[0] == '\x80': if privkey[0] == '\x80':
return privkey[1:] return privkey[1:]
else: else:
sys.stderr.write('Major problem! When trying to decode one of your private keys, the checksum passed but the key doesn\'t begin with hex 80. Here is the PRIVATE key: %s\n' % str(WIFstring)) logger.error('Major problem! When trying to decode one of your private keys, the '
'checksum passed but the key doesn\'t begin with hex 80. Here is the '
'PRIVATE key: %s\n' % str(WIFstring))
return "" return ""
@ -206,19 +221,32 @@ def reloadMyAddressHashes():
myECCryptorObjects.clear() myECCryptorObjects.clear()
myAddressesByHash.clear() myAddressesByHash.clear()
#myPrivateKeys.clear() #myPrivateKeys.clear()
keyfileSecure = checkSensitiveFilePermissions(appdata + 'keys.dat')
configSections = config.sections() configSections = config.sections()
hasEnabledKeys = False
for addressInKeysFile in configSections: for addressInKeysFile in configSections:
if addressInKeysFile <> 'bitmessagesettings': if addressInKeysFile <> 'bitmessagesettings':
isEnabled = config.getboolean(addressInKeysFile, 'enabled') isEnabled = config.getboolean(addressInKeysFile, 'enabled')
if isEnabled: if isEnabled:
hasEnabledKeys = True
status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile) status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile)
if addressVersionNumber == 2 or addressVersionNumber == 3: if addressVersionNumber == 2 or addressVersionNumber == 3:
privEncryptionKey = decodeWalletImportFormat(config.get(addressInKeysFile, 'privencryptionkey')).encode('hex') #returns a simple 32 bytes of information encoded in 64 Hex characters, or null if there was an error # 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')
if len(privEncryptionKey) == 64:#It is 32 bytes encoded as 64 hex characters if len(privEncryptionKey) == 64:#It is 32 bytes encoded as 64 hex characters
myECCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey) myECCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey)
myAddressesByHash[hash] = addressInKeysFile myAddressesByHash[hash] = addressInKeysFile
else: else:
sys.stderr.write('Error in reloadMyAddressHashes: Can\'t handle address versions other than 2 or 3.\n') logger.error('Error in reloadMyAddressHashes: Can\'t handle address '
'versions other than 2 or 3.\n')
if not keyfileSecure:
fixSensitiveFilePermissions(appdata + 'keys.dat', hasEnabledKeys)
def reloadBroadcastSendersForWhichImWatching(): def reloadBroadcastSendersForWhichImWatching():
logger.debug('reloading subscriptions...') logger.debug('reloading subscriptions...')
@ -269,6 +297,7 @@ def doCleanShutdown():
sqlSubmitQueue.put('exit') sqlSubmitQueue.put('exit')
sqlLock.release() sqlLock.release()
logger.info('Finished flushing inventory.') logger.info('Finished flushing inventory.')
# Wait long enough to guarantee that any running proof of work worker threads will check the # 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. # shutdown variable and exit. If the main thread closes before they do then they won't stop.
time.sleep(.25) time.sleep(.25)
@ -306,5 +335,40 @@ def fixPotentiallyInvalidUTF8Data(text):
output = 'Part of the message is corrupt. The message cannot be displayed the normal way.\n\n' + repr(text) output = 'Part of the message is corrupt. The message cannot be displayed the normal way.\n\n' + repr(text)
return output return output
# Checks sensitive file permissions for inappropriate umask during keys.dat creation.
# (Or unwise subsequent chmod.)
#
# Returns true iff file appears to have appropriate permissions.
def checkSensitiveFilePermissions(filename):
if sys.platform == 'win32':
# TODO: This might deserve extra checks by someone familiar with
# Windows systems.
return True
else:
present_permissions = os.stat(filename)[0]
disallowed_permissions = stat.S_IRWXG | stat.S_IRWXO
return present_permissions & disallowed_permissions == 0
# Fixes permissions on a sensitive file.
def fixSensitiveFilePermissions(filename, hasEnabledKeys):
if hasEnabledKeys:
logger.warning('Keyfile had insecure permissions, and there were enabled keys. '
'The truly paranoid should stop using them immediately.')
else:
logger.warning('Keyfile had insecure permissions, but there were no enabled keys.')
try:
present_permissions = os.stat(filename)[0]
disallowed_permissions = stat.S_IRWXG | stat.S_IRWXO
allowed_permissions = ((1<<32)-1) ^ disallowed_permissions
new_permissions = (
allowed_permissions & present_permissions)
os.chmod(filename, new_permissions)
logger.info('Keyfile permissions automatically fixed.')
except Exception, e:
logger.exception('Keyfile permissions could not be fixed.')
raise
helper_startup.loadConfig() helper_startup.loadConfig()
from debug import logger from debug import logger

View File

@ -0,0 +1,30 @@
SOURCES += ../addresses.py
SOURCES += ../bitmessagemain.py
SOURCES += ../class_addressGenerator.py
SOURCES += ../class_outgoingSynSender.py
SOURCES += ../class_receiveDataThread.py
SOURCES += ../class_sendDataThread.py
SOURCES += ../class_singleCleaner.py
SOURCES += ../class_singleListener.py
SOURCES += ../class_singleWorker.py
SOURCES += ../class_sqlThread.py
SOURCES += ../helper_bitcoin.py
SOURCES += ../helper_bootstrap.py
SOURCES += ../helper_generic.py
SOURCES += ../helper_inbox.py
SOURCES += ../helper_sent.py
SOURCES += ../helper_startup.py
SOURCES += ../shared.py
SOURCES += ../bitmessageqt/__init__.py
SOURCES += ../bitmessageqt/about.py
SOURCES += ../bitmessageqt/bitmessageui.py
SOURCES += ../bitmessageqt/help.py
SOURCES += ../bitmessageqt/iconglossary.py
SOURCES += ../bitmessageqt/newaddressdialog.py
SOURCES += ../bitmessageqt/newchandialog.py
SOURCES += ../bitmessageqt/newsubscriptiondialog.py
SOURCES += ../bitmessageqt/regenerateaddresses.py
SOURCES += ../bitmessageqt/settings.py
SOURCES += ../bitmessageqt/specialaddressbehavior.py
TRANSLATIONS = bitmessage_ru_RU.ts

Binary file not shown.

View File

@ -0,0 +1,1260 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="ru_RU">
<context>
<name>MainWindow</name>
<message>
<location filename="../bitmessageqt/__init__.py" line="68"/>
<source>One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. May we delete it now?</source>
<translation>Один из Ваших адресов, %1, является устаревшим адресом версии 1. Адреса версии 1 больше не поддерживаются. Хотите ли Вы удалить его сейчас?</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="136"/>
<source>Reply</source>
<translation>Ответить</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="138"/>
<source>Add sender to your Address Book</source>
<translation>Добавить отправителя в адресную книгу</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="239"/>
<source>Move to Trash</source>
<translation>Поместить в корзину</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="142"/>
<source>View HTML code as formatted text</source>
<translation>Просмотреть HTML код как отформатированный текст</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="144"/>
<source>Save message as...</source>
<translation>Сохранить сообщение как ...</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="505"/>
<source>New</source>
<translation>Новый адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="262"/>
<source>Enable</source>
<translation>Включить</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="264"/>
<source>Disable</source>
<translation>Выключить</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="260"/>
<source>Copy address to clipboard</source>
<translation>Скопировать адрес в буфер обмена</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="170"/>
<source>Special address behavior...</source>
<translation>Особое поведение адресов...</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="188"/>
<source>Send message to this address</source>
<translation>Отправить сообщение на этот адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="192"/>
<source>Subscribe to this address</source>
<translation>Подписаться на рассылку с этого адреса</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="194"/>
<source>Add New Address</source>
<translation>Добавить новый адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="258"/>
<source>Delete</source>
<translation>Удалить</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="241"/>
<source>Copy destination address to clipboard</source>
<translation>Скопировать адрес отправки в буфер обмена</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="243"/>
<source>Force send</source>
<translation>Форсировать отправку</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="532"/>
<source>Add new entry</source>
<translation>Добавить новую запись</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="466"/>
<source>Waiting on their encryption key. Will request it again soon.</source>
<translation>Ожидаем ключ шифрования от Вашего собеседника. Запрос будет повторен через некоторое время.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="469"/>
<source>Encryption key request queued.</source>
<translation>Запрос ключа шифрования поставлен в очередь.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="472"/>
<source>Queued.</source>
<translation>В очереди.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="475"/>
<source>Message sent. Waiting on acknowledgement. Sent at %1</source>
<translation>Сообщение отправлено. Ожидаем подтверждения. Отправлено в %1 </translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="478"/>
<source>Need to do work to send message. Work is queued.</source>
<translation>Нужно провести требуемые вычисления, чтобы отправить сообщение. Вычисления ожидают очереди.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="481"/>
<source>Acknowledgement of the message received %1</source>
<translation>Сообщение получено %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="484"/>
<source>Broadcast queued.</source>
<translation>Рассылка ожидает очереди.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="487"/>
<source>Broadcast on %1</source>
<translation>Рассылка на %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="490"/>
<source>Problem: The work demanded by the recipient is more difficult than you are willing to do. %1</source>
<translation>Проблема: Ваш получатель требует более сложных вычислений, чем максимум, указанный в Ваших настройках. %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="493"/>
<source>Problem: The recipient&apos;s encryption key is no good. Could not encrypt message. %1</source>
<translation>Проблема: ключ получателя неправильный. Невозможно зашифровать сообщение. %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="496"/>
<source>Forced difficulty override. Send should start soon.</source>
<translation>Форсирована смена сложности. Отправляем через некоторое время.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="499"/>
<source>Unknown status: %1 %2</source>
<translation>Неизвестный статус: %1 %2</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="553"/>
<source>Since startup on %1</source>
<translation>С начала работы %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1082"/>
<source>Not Connected</source>
<translation>Не соединено</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="710"/>
<source>Show Bitmessage</source>
<translation>Показать Bitmessage</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="494"/>
<source>Send</source>
<translation>Отправка</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="725"/>
<source>Subscribe</source>
<translation>Подписки</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="529"/>
<source>Address Book</source>
<translation>Адресная книга</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="554"/>
<source>Quit</source>
<translation>Выйти</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="931"/>
<source>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.</source>
<translation>Вы можете управлять Вашими ключами, отредактировав файл keys.dat, находящийся в той же папке, что и эта программа.
Создайте резервную копию этого файла перед тем как будете его редактировать.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="935"/>
<source>You may manage your keys by editing the keys.dat file stored in
%1
It is important that you back up this file.</source>
<translation>Вы можете управлять Вашими ключами, отредактировав файл keys.dat, находящийся в
%1
Создайте резервную копию этого файла перед тем как будете его редактировать.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="942"/>
<source>Open keys.dat?</source>
<translation>Открыть файл keys.dat?</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="939"/>
<source>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.)</source>
<translation>Вы можете управлять Вашими ключами, отредактировав файл keys.dat, находящийся в той же папке, что и эта программа.
Создайте резервную копию этого файла перед тем как будете его редактировать. Хотели бы Вы открыть этот файл сейчас?
(пожалуйста, закройте Bitmessage до того как Вы внесете в этот файл какие-либо изменения.)</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="942"/>
<source>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.)</source>
<translation>Вы можете управлять Вашими ключами, отредактировав файл keys.dat, находящийся в
%1
Создайте резервную копию этого файла перед тем как будете его редактировать. Хотели бы Вы открыть этот файл сейчас?
(пожалуйста, закройте Bitmessage до того как Вы внесете в этот файл какие-либо изменения.)</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="948"/>
<source>Delete trash?</source>
<translation>Очистить корзину?</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="948"/>
<source>Are you sure you want to delete all trashed messages?</source>
<translation>Вы уверены, что хотите очистить корзину?</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="959"/>
<source>bad passphrase</source>
<translation>Неподходящая секретная фраза</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="959"/>
<source>You must type your passphrase. If you don&apos;t have one then this is not the form for you.</source>
<translation>Вы должны ввести секретную фразу. Если Вы не хотите это делать, то Вы выбрали неправильную опцию.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1004"/>
<source>Processed %1 person-to-person messages.</source>
<translation>Обработано %1 сообщений.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1009"/>
<source>Processed %1 broadcast messages.</source>
<translation>Обработано %1 рассылок.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1014"/>
<source>Processed %1 public keys.</source>
<translation>Обработано %1 открытых ключей.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1058"/>
<source>Total Connections: %1</source>
<translation>Всего соединений: %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1077"/>
<source>Connection lost</source>
<translation>Соединение потеряно</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1115"/>
<source>Connected</source>
<translation>Соединено</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1161"/>
<source>Message trashed</source>
<translation>Сообщение удалено</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1295"/>
<source>Error: Bitmessage addresses start with BM- Please check %1</source>
<translation>Ошибка: Bitmessage адреса начинаются с BM- Пожалуйста, проверьте %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1298"/>
<source>Error: The address %1 is not typed or copied correctly. Please check it.</source>
<translation>Ошибка: адрес %1 внесен или скопирован неправильно. Пожалуйста, перепроверьте.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1301"/>
<source>Error: The address %1 contains invalid characters. Please check it.</source>
<translation>Ошибка: адрес %1 содержит запрещенные символы. Пожалуйста, перепроверьте.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1304"/>
<source>Error: The address version in %1 is too high. Either you need to upgrade your Bitmessage software or your acquaintance is being clever.</source>
<translation>Ошибка: версия адреса в %1 слишком новая. Либо Вам нужно обновить Bitmessage, либо Ваш собеседник дал неправильный адрес.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1307"/>
<source>Error: Some data encoded in the address %1 is too short. There might be something wrong with the software of your acquaintance.</source>
<translation>Ошибка: некоторые данные, закодированные в адресе %1, слишком короткие. Возможно, что-то не так с программой Вашего собеседника.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1310"/>
<source>Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance.</source>
<translation>Ошибка: некоторые данные, закодированные в адресе %1, слишком длинные. Возможно, что-то не так с программой Вашего собеседника.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1313"/>
<source>Error: Something is wrong with the address %1.</source>
<translation>Ошибка: что-то не так с адресом %1.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1381"/>
<source>Error: You must specify a From address. If you don&apos;t have one, go to the &apos;Your Identities&apos; tab.</source>
<translation>Вы должны указать адрес в поле &quot;От кого&quot;. Вы можете найти Ваш адрес во вкладе &quot;Ваши Адреса&quot;.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1325"/>
<source>Sending to your address</source>
<translation>Отправка на Ваш собственный адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1325"/>
<source>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.</source>
<translation>Ошибка: Один из адресов, на который Вы отправляете сообщение, %1, принадлежит Вам. К сожалению, Bitmessage не может отправлять сообщения самому себе. Попробуйте запустить второго клиента на другом компьютере или на виртуальной машине.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1331"/>
<source>Address version number</source>
<translation>Версия адреса</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1331"/>
<source>Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version.</source>
<translation>По поводу адреса %1: Bitmessage не поддерживаем адреса версии %2. Возможно, Вам нужно обновить клиент Bitmessage.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1335"/>
<source>Stream number</source>
<translation>Номер потока</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1335"/>
<source>Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version.</source>
<translation>По поводу адреса %1: Bitmessage не поддерживаем стрим номер %2. Возможно, Вам нужно обновить клиент Bitmessage.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1340"/>
<source>Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won&apos;t send until you connect.</source>
<translation>Внимание: Вы не подключены к сети. Bitmessage проделает необходимые вычисления, чтобы отправить сообщение, но не отправит его до тех пор, пока Вы не подсоединитесь к сети.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1377"/>
<source>Your &apos;To&apos; field is empty.</source>
<translation>Вы не заполнили поле &apos;Кому&apos;.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1432"/>
<source>Work is queued.</source>
<translation>Вычисления поставлены в очередь.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1454"/>
<source>Right click one or more entries in your address book and select &apos;Send message to this address&apos;.</source>
<translation>Нажмите правую кнопку мышки на каком-либо адресе и выберите &quot;Отправить сообщение на этот адрес&quot;.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1521"/>
<source>Work is queued. %1</source>
<translation>Вычисления поставлены в очередь. %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1588"/>
<source>New Message</source>
<translation>Новое сообщение</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1588"/>
<source>From </source>
<translation>От </translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2823"/>
<source>Address is valid.</source>
<translation>Адрес введен правильно.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2099"/>
<source>Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want.</source>
<translation>Ошибка: Вы не можете добавлять один и тот же адрес в Адресную Книгу несколько раз. Просто переименуйте существующий адрес.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1908"/>
<source>The address you entered was invalid. Ignoring it.</source>
<translation>Вы ввели неправильный адрес. Это адрес проигнорирован.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2269"/>
<source>Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want.</source>
<translation>Ошибка: Вы не можете добавлять один и тот же адрес в подписку несколько раз. Просто переименуйте существующую подписку.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1751"/>
<source>Restart</source>
<translation>Перезапустить</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1745"/>
<source>You must restart Bitmessage for the port number change to take effect.</source>
<translation>Вы должны перезапустить Bitmessage, чтобы смена номера порта имела эффект.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1751"/>
<source>Bitmessage will use your proxy from now on but you may want to manually restart Bitmessage now to close existing connections.</source>
<translation>Bitmessage будет использовать Ваш прокси в дальнейшем, тем не менее, мы рекомендуем перезапустить Bitmessage в ручную, чтобы закрыть уже существующие соединения.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1905"/>
<source>Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want.</source>
<translation>Ошибка: Вы не можете добавлять один и тот же адрес в список несколько раз. Просто переименуйте существующий адрес.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1961"/>
<source>Passphrase mismatch</source>
<translation>Секретная фраза не подходит</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1961"/>
<source>The passphrase you entered twice doesn&apos;t match. Try again.</source>
<translation>Вы ввели две разные секретные фразы. Пожалуйста, повторите заново.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1964"/>
<source>Choose a passphrase</source>
<translation>Придумайте секретную фразу</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1964"/>
<source>You really do need a passphrase.</source>
<translation>Вы действительно должны ввести секретную фразу.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1992"/>
<source>All done. Closing user interface...</source>
<translation>Программа завершена. Закрываем пользовательский интерфейс...</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2040"/>
<source>Address is gone</source>
<translation>Адрес утерян</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2040"/>
<source>Bitmessage cannot find your address %1. Perhaps you removed it?</source>
<translation>Bitmessage не может найти Ваш адрес %1. Возможно Вы удалили его?</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2044"/>
<source>Address disabled</source>
<translation>Адрес выключен</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2044"/>
<source>Error: The address from which you are trying to send is disabled. You&apos;ll have to enable it on the &apos;Your Identities&apos; tab before using it.</source>
<translation>Ошибка: адрес, с которого Вы пытаетесь отправить, выключен. Вам нужно будет включить этот адрес во вкладке &quot;Ваши адреса&quot;.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2096"/>
<source>Entry added to the Address Book. Edit the label to your liking.</source>
<translation>Запись добавлена в Адресную Книгу. Вы можете ее отредактировать.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2161"/>
<source>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.</source>
<translation>Удалено в корзину. Чтобы попасть в корзину, Вам нужно будет найти файл корзины на диске.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2135"/>
<source>Save As...</source>
<translation>Сохранить как ...</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2144"/>
<source>Write error.</source>
<translation>Ошибка записи.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2255"/>
<source>No addresses selected.</source>
<translation>Вы не выбрали адрес.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2687"/>
<source>Options have been disabled because they either aren&apos;t applicable or because they haven&apos;t yet been implemented for your operating system.</source>
<translation>Опции были отключены, потому что ли они либо не подходят, либо еще не выполнены под Вашу операционную систему.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2805"/>
<source>The address should start with &apos;&apos;BM-&apos;&apos;</source>
<translation>Адрес должен начинаться с &quot;BM-&quot;</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2808"/>
<source>The address is not typed or copied correctly (the checksum failed).</source>
<translation>Адрес введен или скопирован неверно (контрольная сумма не сходится).</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2811"/>
<source>The version number of this address is higher than this software can support. Please upgrade Bitmessage.</source>
<translation>Версия этого адреса более поздняя, чем Ваша программа. Пожалуйста, обновите программу Bitmessage.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2814"/>
<source>The address contains invalid characters.</source>
<translation>Адрес содержит запрещенные символы.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2817"/>
<source>Some data encoded in the address is too short.</source>
<translation>Данные, закодированные в адресе, слишком короткие.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2820"/>
<source>Some data encoded in the address is too long.</source>
<translation>Данные, закодированные в адресе, слишком длинные.</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2865"/>
<source>You are using TCP port %1. (This can be changed in the settings).</source>
<translation>Вы используете TCP порт %1 (Его можно поменять в настройках).</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="469"/>
<source>Bitmessage</source>
<translation>Bitmessage</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="497"/>
<source>To</source>
<translation>Кому</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="499"/>
<source>From</source>
<translation>От кого</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="501"/>
<source>Subject</source>
<translation>Тема</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="478"/>
<source>Received</source>
<translation>Получено</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="479"/>
<source>Inbox</source>
<translation>Входящие</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="480"/>
<source>Load from Address book</source>
<translation>Взять из адресной книги</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="481"/>
<source>Message:</source>
<translation>Сообщение:</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="482"/>
<source>Subject:</source>
<translation>Тема:</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="483"/>
<source>Send to one or more specific people</source>
<translation>Отправить одному или нескольким указанным получателям</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="484"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="489"/>
<source>To:</source>
<translation>Кому:</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="490"/>
<source>From:</source>
<translation>От:</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="491"/>
<source>Broadcast to everyone who is subscribed to your address</source>
<translation>Рассылка всем, кто подписался на Ваш адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="493"/>
<source>Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them.</source>
<translation>Пожалуйста, учитывайте, что рассылки шифруются лишь Вашим адресом. Любой человек, который знает Ваш адрес, сможет прочитать Вашу рассылку.</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="503"/>
<source>Status</source>
<translation>Статус</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="504"/>
<source>Sent</source>
<translation>Отправленные</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="508"/>
<source>Label (not shown to anyone)</source>
<translation>Название (не показывается никому)</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="537"/>
<source>Address</source>
<translation>Адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="512"/>
<source>Stream</source>
<translation>Поток</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="513"/>
<source>Your Identities</source>
<translation>Ваши Адреса</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="514"/>
<source>Here you can subscribe to &apos;broadcast messages&apos; that are sent by other users. Messages will appear in your Inbox. Addresses here override those on the Blacklist tab.</source>
<translation>Здесь Вы можете подписаться на рассылки от других пользователей. Все рассылки будут появляться у Вас во Входящих. Вы будете следить за всеми адресами, указанными здесь, даже если они в черном списке.</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="515"/>
<source>Add new Subscription</source>
<translation>Добавить новую подписку</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="518"/>
<source>Label</source>
<translation>Название</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="521"/>
<source>Subscriptions</source>
<translation>Подписки</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="522"/>
<source>The Address book is useful for adding names or labels to other people&apos;s Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the &apos;Add&apos; button, or from your inbox by right-clicking on a message.</source>
<translation>Адресная книга удобна для присвоения осмысленных имен Bitmessage адресам Ваших друзей. Вы можете добавлять новые записи с помощью кнопки &quot;Добавить новую запись&quot;, или же правым кликом мышки на сообщении.</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="535"/>
<source>Name or Label</source>
<translation>Название</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="530"/>
<source>Use a Blacklist (Allow all incoming messages except those on the Blacklist)</source>
<translation>Использовать черный список (Разрешить все входящие сообщения, кроме указанных в черном списке)</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="531"/>
<source>Use a Whitelist (Block all incoming messages except those on the Whitelist)</source>
<translation>Использовать белый список (блокировать все входящие сообщения, кроме указанных в белом списке)</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="538"/>
<source>Blacklist</source>
<translation>Черный список</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="540"/>
<source>Stream #</source>
<translation> потока</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="542"/>
<source>Connections</source>
<translation>Соединений</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="543"/>
<source>Total connections: 0</source>
<translation>Всего соединений: 0</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="544"/>
<source>Since startup at asdf:</source>
<translation>С начала работы программы в asdf:</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="545"/>
<source>Processed 0 person-to-person message.</source>
<translation>Обработано 0 сообщений.</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="546"/>
<source>Processed 0 public key.</source>
<translation>Обработано 0 открытых ключей.</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="547"/>
<source>Processed 0 broadcast.</source>
<translation>Обработано 0 рассылок.</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="548"/>
<source>Network Status</source>
<translation>Статус сети</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="549"/>
<source>File</source>
<translation>Файл</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="557"/>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="555"/>
<source>Help</source>
<translation>Помощь</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="552"/>
<source>Import keys</source>
<translation>Импортировать ключи</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="553"/>
<source>Manage keys</source>
<translation>Управлять ключами</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="556"/>
<source>About</source>
<translation>О программе</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="558"/>
<source>Regenerate deterministic addresses</source>
<translation>Сгенерировать заново все адреса</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="559"/>
<source>Delete all trashed messages</source>
<translation>Стереть все сообщения из корзины</translation>
</message>
</context>
<context>
<name>NewAddressDialog</name>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="173"/>
<source>Create new Address</source>
<translation>Создать новый адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="174"/>
<source>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 &quot;deterministic&quot; address.
The &apos;Random Number&apos; option is selected by default but deterministic addresses have several pros and cons:</source>
<translation>Здесь Вы сможете сгенерировать столько адресов сколько хотите. На самом деле, создание и выкидывание адресов даже поощряется. Вы можете сгенерировать адреса используя либо генератор случайных чисел либо придумав секретную фразу. Если Вы используете секретную фразу, то адреса будут называться &quot;детерминистическими&quot;. Генератор случайных чисел выбран по умолчанию, однако детерминистические адреса имеют следующие плюсы и минусы по сравнению с ними:</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="176"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Pros:&lt;br/&gt;&lt;/span&gt;You can recreate your addresses on any computer from memory. &lt;br/&gt;You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. &lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cons:&lt;br/&gt;&lt;/span&gt;You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. &lt;br/&gt;You must remember the address version number and the stream number along with your passphrase. &lt;br/&gt;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.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Плюсы:&lt;br/&gt;&lt;/span&gt;Вы сможете восстановить адрес по памяти на любом компьютере&lt;br/&gt;Вам не нужно беспокоиться о сохранении файла keys.dat, если Вы запомнили секретную фразу&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Минусы:&lt;br/&gt;&lt;/span&gt;Вы должны запомнить (или записать) секретную фразу, если Вы хотите когда-либо восстановить Ваш адрес на другом компьютере &lt;br/&gt;Вы должны также запомнить версию адреса и номер потока вместе с секретной фразой&lt;br/&gt;Если Вы выберите слишком короткую секретную фразу, кто-нибудь в интернете сможет подобрать ключ и, как следствие, читать и отправлять от Вашего имени сообщения.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="177"/>
<source>Use a random number generator to make an address</source>
<translation>Использовать генератор случайных чисел для создания адреса</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="178"/>
<source>Use a passphrase to make addresses</source>
<translation>Использовать секретную фразу для создания адресов</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="179"/>
<source>Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter</source>
<translation>Потратить несколько лишних минут, чтобы сделать адрес(а) короче на 1 или 2 символа</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="180"/>
<source>Make deterministic addresses</source>
<translation>Создать детерминистический адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="181"/>
<source>Address version number: 3</source>
<translation>Версия адреса: 3</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="182"/>
<source>In addition to your passphrase, you must remember these numbers:</source>
<translation>В дополнение к секретной фразе, Вам необходимо запомнить эти числа:</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="183"/>
<source>Passphrase</source>
<translation>Придумайте секретную фразу</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="184"/>
<source>Number of addresses to make based on your passphrase:</source>
<translation>Кол-во адресов, которые Вы хотите получить из секретной фразы:</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="185"/>
<source>Stream number: 1</source>
<translation>Номер потока: 1</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="186"/>
<source>Retype passphrase</source>
<translation>Повторите секретную фразу</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="187"/>
<source>Randomly generate address</source>
<translation>Сгенерировать случайный адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="188"/>
<source>Label (not shown to anyone except you)</source>
<translation>Название (не показывается никому кроме Вас)</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="189"/>
<source>Use the most available stream</source>
<translation>Использовать наиболее доступный поток</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="190"/>
<source> (best if this is the first of many addresses you will create)</source>
<translation> (выберите этот вариант, если это лишь первый из многих адресов, которые Вы планируете создать)</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="191"/>
<source>Use the same stream as an existing address</source>
<translation>Использовать тот же поток, что и указанный существующий адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="192"/>
<source>(saves you some bandwidth and processing power)</source>
<translation>(немного сэкономит Вам пропускную способность сети и вычислительную мощь)</translation>
</message>
</context>
<context>
<name>NewChanDialog</name>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="89"/>
<source>Dialog</source>
<translation>Новый chan</translation>
</message>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="90"/>
<source>Create a new chan</source>
<translation>Создать новый chan</translation>
</message>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="92"/>
<source>Join a chan</source>
<translation>Присоединиться к chan</translation>
</message>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="93"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;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).&lt;/p&gt;&lt;p&gt;Chans are experimental and are unmoderatable.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Chan - это набор ключей шифрования, которые известны некоторой группе людей. Ключи и Bitmessage-адрес используемый chan-ом генерируется из слова или фразы (имя chan-а).&lt;/p&gt;&lt;p&gt;Chan-ы - это экспериментальная новинка.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="98"/>
<source>Chan name:</source>
<translation>Имя chan:</translation>
</message>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="95"/>
<source>Chan bitmessage address:</source>
<translation>Bitmessage адрес chan:</translation>
</message>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="96"/>
<source>Create a chan</source>
<translation>Создать chan</translation>
</message>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="97"/>
<source>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.</source>
<translation>Введите имя Вашего chan-a. Если Вы выберете достаточно сложное имя для chan-а (например, сложную и необычную секретную фразу) и никто из Ваших друзей не опубликует эту фразу, то Вам chan будет надежно зашифрован.</translation>
</message>
</context>
<context>
<name>NewSubscriptionDialog</name>
<message>
<location filename="../bitmessageqt/newsubscriptiondialog.py" line="57"/>
<source>Add new entry</source>
<translation>Добавить новую запись</translation>
</message>
<message>
<location filename="../bitmessageqt/newsubscriptiondialog.py" line="58"/>
<source>Label</source>
<translation>Название</translation>
</message>
<message>
<location filename="../bitmessageqt/newsubscriptiondialog.py" line="59"/>
<source>Address</source>
<translation>Адрес</translation>
</message>
</context>
<context>
<name>SpecialAddressBehaviorDialog</name>
<message>
<location filename="../bitmessageqt/specialaddressbehavior.py" line="59"/>
<source>Special Address Behavior</source>
<translation>Особое поведение адреса</translation>
</message>
<message>
<location filename="../bitmessageqt/specialaddressbehavior.py" line="60"/>
<source>Behave as a normal address</source>
<translation>Вести себя как обычный адрес</translation>
</message>
<message>
<location filename="../bitmessageqt/specialaddressbehavior.py" line="61"/>
<source>Behave as a pseudo-mailing-list address</source>
<translation>Вести себя как адрес псевдо-рассылки</translation>
</message>
<message>
<location filename="../bitmessageqt/specialaddressbehavior.py" line="62"/>
<source>Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers (and thus will be public).</source>
<translation>Почта, полученная на адрес псевдо-рассылки, будет автоматически разослана всем подписчикам (и поэтому будет доступна общей публике).</translation>
</message>
<message>
<location filename="../bitmessageqt/specialaddressbehavior.py" line="63"/>
<source>Name of the pseudo-mailing-list:</source>
<translation>Имя псевдо-рассылки:</translation>
</message>
</context>
<context>
<name>aboutDialog</name>
<message>
<location filename="../bitmessageqt/about.py" line="57"/>
<source>About</source>
<translation>О программе</translation>
</message>
<message>
<location filename="../bitmessageqt/about.py" line="58"/>
<source>PyBitmessage</source>
<translation>PyBitmessage</translation>
</message>
<message>
<location filename="../bitmessageqt/about.py" line="59"/>
<source>version ?</source>
<translation>версия ?</translation>
</message>
<message utf8="true">
<location filename="../bitmessageqt/about.py" line="60"/>
<source>Copyright © 2013 Jonathan Warren</source>
<translation>Копирайт © 2013 Джонатан Уоррен</translation>
</message>
<message>
<location filename="../bitmessageqt/about.py" line="61"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Distributed under the MIT/X11 software license; see &lt;a href=&quot;http://www.opensource.org/licenses/mit-license.php&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.opensource.org/licenses/mit-license.php&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Программа распространяется в соответствии с лицензией MIT/X11; см. &lt;a href=&quot;http://www.opensource.org/licenses/mit-license.php&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.opensource.org/licenses/mit-license.php&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../bitmessageqt/about.py" line="62"/>
<source>This is Beta software.</source>
<translation>Это бета версия программы.</translation>
</message>
</context>
<context>
<name>helpDialog</name>
<message>
<location filename="../bitmessageqt/help.py" line="45"/>
<source>Help</source>
<translation>Помощь</translation>
</message>
<message>
<location filename="../bitmessageqt/help.py" line="46"/>
<source>&lt;a href=&quot;http://Bitmessage.org/wiki/PyBitmessage_Help&quot;&gt;http://Bitmessage.org/wiki/PyBitmessage_Help&lt;/a&gt;</source>
<translation>&lt;a href=&quot;http://Bitmessage.org/wiki/PyBitmessage_Help&quot;&gt;http://Bitmessage.org/wiki/PyBitmessage_Help&lt;/a&gt;</translation>
</message>
<message>
<location filename="../bitmessageqt/help.py" line="47"/>
<source>As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki:</source>
<translation>Bitmessage - общественный проект. Вы можете найти подсказки и советы на Wiki-страничке Bitmessage:</translation>
</message>
</context>
<context>
<name>iconGlossaryDialog</name>
<message>
<location filename="../bitmessageqt/iconglossary.py" line="82"/>
<source>Icon Glossary</source>
<translation>Описание значков</translation>
</message>
<message>
<location filename="../bitmessageqt/iconglossary.py" line="83"/>
<source>You have no connections with other peers. </source>
<translation>Нет соединения с другими участниками сети.</translation>
</message>
<message>
<location filename="../bitmessageqt/iconglossary.py" line="84"/>
<source>You have made at least one connection to a peer using an outgoing connection but you have not yet received any incoming connections. Your firewall or home router probably isn&apos;t configured to forward incoming TCP connections to your computer. Bitmessage will work just fine but it would help the Bitmessage network if you allowed for incoming connections and will help you be a better-connected node.</source>
<translation>На текущий момент Вы установили по-крайней мере одно исходящее соединение, но пока ни одного входящего. Ваш файрвол или маршрутизатор скорее всего не настроен на переброс входящих TCP соединений к Вашему компьютеру. Bitmessage будет прекрасно работать и без этого, но Вы могли бы помочь сети если бы разрешили и входящие соединения тоже. Это помогло бы Вам стать более важным узлом сети.</translation>
</message>
<message>
<location filename="../bitmessageqt/iconglossary.py" line="85"/>
<source>You are using TCP port ?. (This can be changed in the settings).</source>
<translation>Вы используете TCP порт ?. (Его можно поменять в настройках).</translation>
</message>
<message>
<location filename="../bitmessageqt/iconglossary.py" line="86"/>
<source>You do have connections with other peers and your firewall is correctly configured.</source>
<translation>Вы установили соединение с другими участниками сети и ваш файрвол настроен правильно.</translation>
</message>
</context>
<context>
<name>regenerateAddressesDialog</name>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="104"/>
<source>Regenerate Existing Addresses</source>
<translation>Сгенерировать заново существующие адреса</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="105"/>
<source>Regenerate existing addresses</source>
<translation>Сгенерировать заново существующие адреса</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="106"/>
<source>Passphrase</source>
<translation>Секретная фраза</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="107"/>
<source>Number of addresses to make based on your passphrase:</source>
<translation>Кол-во адресов, которые Вы хотите получить из Вашей секретной фразы:</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="108"/>
<source>Address version Number:</source>
<translation>Версия адреса:</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="109"/>
<source>3</source>
<translation>3</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="110"/>
<source>Stream number:</source>
<translation>Номер потока:</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="111"/>
<source>1</source>
<translation>1</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="112"/>
<source>Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter</source>
<translation>Потратить несколько лишних минут, чтобы сделать адрес(а) короче на 1 или 2 символа</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="113"/>
<source>You must check (or not check) this box just like you did (or didn&apos;t) when you made your addresses the first time.</source>
<translation>Вы должны кликнуть эту галочку (или не кликать) точно также как Вы сделали в самый первый раз, когда создавали Ваши адреса.</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="114"/>
<source>If you have previously made deterministic addresses but lost them due to an accident (like hard drive failure), you can regenerate them here. If you used the random number generator to make your addresses then this form will be of no use to you.</source>
<translation>Если Вы ранее делали детерминистические адреса, но случайно потеряли их, Вы можете их восстановить здесь. Если же Вы использовали генератор случайных чисел, чтобы создать Ваши адреса, то Вы не сможете их здесь восстановить.</translation>
</message>
</context>
<context>
<name>settingsDialog</name>
<message>
<location filename="../bitmessageqt/settings.py" line="241"/>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="242"/>
<source>Start Bitmessage on user login</source>
<translation>Запускать Bitmessage при входе в систему</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="243"/>
<source>Start Bitmessage in the tray (don&apos;t show main window)</source>
<translation>Запускать Bitmessage в свернутом виде (не показывать главное окно)</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="244"/>
<source>Minimize to tray</source>
<translation>Сворачивать в трей</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="245"/>
<source>Show notification when message received</source>
<translation>Показывать уведомления при получении новых сообщений</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="246"/>
<source>Run in Portable Mode</source>
<translation>Запустить в переносном режиме</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="247"/>
<source>In Portable Mode, messages and config files are stored in the same directory as the program rather than the normal application-data folder. This makes it convenient to run Bitmessage from a USB thumb drive.</source>
<translation>В переносном режиме, все сообщения и конфигурационные файлы сохраняются в той же самой папке что и сама программа. Это делает более удобным использование Bitmessage с USB-флэшки.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="248"/>
<source>User Interface</source>
<translation>Пользовательские</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="249"/>
<source>Listening port</source>
<translation>Порт прослушивания</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="250"/>
<source>Listen for connections on port:</source>
<translation>Прослушивать соединения на порту:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="251"/>
<source>Proxy server / Tor</source>
<translation>Прокси сервер / Tor</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="252"/>
<source>Type:</source>
<translation>Тип:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="253"/>
<source>none</source>
<translation>отсутствует</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="254"/>
<source>SOCKS4a</source>
<translation>SOCKS4a</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="255"/>
<source>SOCKS5</source>
<translation>SOCKS5</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="256"/>
<source>Server hostname:</source>
<translation>Адрес сервера:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="257"/>
<source>Port:</source>
<translation>Порт:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="258"/>
<source>Authentication</source>
<translation>Авторизация</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="259"/>
<source>Username:</source>
<translation>Имя пользователя:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="260"/>
<source>Pass:</source>
<translation>Прль:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="261"/>
<source>Network Settings</source>
<translation>Сетевые настройки</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="262"/>
<source>When someone sends you a message, their computer must first complete some work. The difficulty of this work, by default, is 1. You may raise this default for new addresses you create by changing the values here. Any new addresses you create will require senders to meet the higher difficulty. There is one exception: if you add a friend or acquaintance to your address book, Bitmessage will automatically notify them when you next send a message that they need only complete the minimum amount of work: difficulty 1. </source>
<translation>Когда кто-либо отправляет Вам сообщение, его компьютер должен сперва решить определенную вычислительную задачу. Сложность этой задачи по умолчанию равна 1. Вы можете повысить эту сложность для новых адресов, которые Вы создадите, здесь. Таким образом, любые новые адреса, которые Вы создадите, могут требовать от отправителей сложность большую чем 1. Однако, есть одно исключение: если Вы специально добавите Вашего собеседника в адресную книгу, то Bitmessage автоматически уведомит его о том, что для него минимальная сложность будет составлять всегда всего лишь 1.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="263"/>
<source>Total difficulty:</source>
<translation>Общая сложность:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="264"/>
<source>Small message difficulty:</source>
<translation>Сложность для маленьких сообщений:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="265"/>
<source>The &apos;Small message difficulty&apos; mostly only affects the difficulty of sending small messages. Doubling this value makes it almost twice as difficult to send a small message but doesn&apos;t really affect large messages.</source>
<translation>&quot;Сложность для маленьких сообщений&quot; влияет исключительно на небольшие сообщения. Увеличив это число в два раза, вы сделаете отправку маленьких сообщений в два раза сложнее, в то время как сложность отправки больших сообщений не изменится.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="266"/>
<source>The &apos;Total difficulty&apos; affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work.</source>
<translation>&quot;Общая сложность&quot; влияет на абсолютное количество вычислений, которые отправитель должен провести, чтобы отправить сообщение. Увеличив это число в два раза, вы увеличите в два раза объем требуемых вычислений.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="267"/>
<source>Demanded difficulty</source>
<translation>Требуемая сложность</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="268"/>
<source>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.</source>
<translation>Здесь Вы можете установить максимальную вычислительную работу, которую Вы согласны проделать, чтобы отправить сообщение другому пользователю. Ноль означает, чтобы любое значение допустимо.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="269"/>
<source>Maximum acceptable total difficulty:</source>
<translation>Макс допустимая общая сложность:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="270"/>
<source>Maximum acceptable small message difficulty:</source>
<translation>Макс допустимая сложность для маленький сообщений:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="271"/>
<source>Max acceptable difficulty</source>
<translation>Макс допустимая сложность</translation>
</message>
</context>
</TS>