diff --git a/Makefile b/Makefile index b9a85ff7..72a86ba2 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ APP=pybitmessage VERSION=0.3.4 RELEASE=1 ARCH_TYPE=`uname -m` +PREFIX?=/usr/local all: debug: @@ -9,37 +10,42 @@ source: tar -cvzf ../${APP}_${VERSION}.orig.tar.gz ../${APP}-${VERSION} --exclude-vcs install: mkdir -p ${DESTDIR}/usr - mkdir -p ${DESTDIR}/usr/bin - mkdir -m 755 -p ${DESTDIR}/usr/share - mkdir -m 755 -p ${DESTDIR}/usr/share/man - mkdir -m 755 -p ${DESTDIR}/usr/share/man/man1 - install -m 644 man/${APP}.1.gz ${DESTDIR}/usr/share/man/man1 - mkdir -m 755 -p ${DESTDIR}/usr/share/${APP} - mkdir -m 755 -p ${DESTDIR}/usr/share/applications - mkdir -m 755 -p ${DESTDIR}/usr/share/pixmaps - mkdir -m 755 -p ${DESTDIR}/usr/share/icons - mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor - mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor/scalable - mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor/scalable/apps - mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor/24x24 - mkdir -m 755 -p ${DESTDIR}/usr/share/icons/hicolor/24x24/apps - install -m 644 desktop/${APP}.desktop ${DESTDIR}/usr/share/applications/${APP}.desktop - install -m 644 desktop/icon24.png ${DESTDIR}/usr/share/icons/hicolor/24x24/apps/${APP}.png - cp -rf src/* ${DESTDIR}/usr/share/${APP} - echo '#!/bin/sh' > ${DESTDIR}/usr/bin/${APP} - echo 'cd /usr/share/pybitmessage' >> ${DESTDIR}/usr/bin/${APP} - echo 'LD_LIBRARY_PATH="/opt/openssl-compat-bitcoin/lib/" exec python2 bitmessagemain.py' >> ${DESTDIR}/usr/bin/${APP} - chmod +x ${DESTDIR}/usr/bin/${APP} + mkdir -p ${DESTDIR}${PREFIX} + mkdir -p ${DESTDIR}${PREFIX}/bin + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/man + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/man/man1 + install -m 644 man/${APP}.1.gz ${DESTDIR}${PREFIX}/share/man/man1 + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/${APP} + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/applications + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/pixmaps + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor/scalable + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor/scalable/apps + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor/24x24 + mkdir -m 755 -p ${DESTDIR}${PREFIX}/share/icons/hicolor/24x24/apps + install -m 644 desktop/${APP}.desktop ${DESTDIR}${PREFIX}/share/applications/${APP}.desktop + install -m 644 desktop/icon24.png ${DESTDIR}${PREFIX}/share/icons/hicolor/24x24/apps/${APP}.png + cp -rf src/* ${DESTDIR}${PREFIX}/share/${APP} + echo '#!/bin/sh' > ${DESTDIR}${PREFIX}/bin/${APP} + echo 'if [ -d /usr/local/share/${APP} ]; then' >> ${DESTDIR}${PREFIX}/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: - rm -f /usr/share/man/man1/${APP}.1.gz - rm -rf /usr/share/${APP} - rm -f /usr/bin/${APP} - rm -f /usr/share/applications/${APP}.desktop - rm -f /usr/share/icons/hicolor/scalable/apps/${APP}.svg - /usr/share/pixmaps/${APP}.svg + rm -f ${PREFIX}/share/man/man1/${APP}.1.gz + rm -rf ${PREFIX}/share/${APP} + rm -f ${PREFIX}/bin/${APP} + rm -f ${PREFIX}/share/applications/${APP}.desktop + rm -f ${PREFIX}/share/icons/hicolor/scalable/apps/${APP}.svg + rm -f ${PREFIX}/share/pixmaps/${APP}.svg clean: rm -f ${APP} \#* \.#* gnuplot* *.png debian/*.substvars debian/*.log rm -fr deb.* debian/${APP} rpmpackage/${ARCH_TYPE} rm -f ../${APP}*.deb ../${APP}*.changes ../${APP}*.asc ../${APP}*.dsc rm -f rpmpackage/*.src.rpm archpackage/*.gz archpackage/*.xz - rm -f puppypackage/*.gz puppypackage/*.pet slackpackage/*.txz + rm -f puppypackage/*.gz puppypackage/*.pet slackpackage/*.txz diff --git a/archpackage/PKGBUILD b/archpackage/PKGBUILD index 79ee8ded..e36c1a11 100644 --- a/archpackage/PKGBUILD +++ b/archpackage/PKGBUILD @@ -7,7 +7,7 @@ arch=('i686' 'x86_64') url="https://github.com/Bitmessage/PyBitmessage" license=('MIT') groups=() -depends=('python2' 'qt4' 'python2-pyqt4' 'sqlite' 'openssl') +depends=('python2' 'qt4' 'python2-pyqt4' 'sqlite' 'openssl' 'gst123') makedepends=() optdepends=('python2-gevent') provides=() @@ -27,5 +27,5 @@ build() { } package() { cd "$srcdir/$pkgname-$pkgver" - make DESTDIR="$pkgdir/" install + make DESTDIR="$pkgdir/" PREFIX="/usr" install } diff --git a/debian/control b/debian/control index 01bd7d8c..5e016a1c 100644 --- a/debian/control +++ b/debian/control @@ -4,12 +4,12 @@ Maintainer: Bob Mottram (4096 bits) Build-Depends: debhelper (>= 9.0.0) Standards-Version: 3.9.4 Homepage: https://github.com/Bitmessage/PyBitmessage -Vcs-Git: https://github.com/fuzzgun/fin.git +Vcs-Git: https://github.com/Bitmessage/PyBitmessage.git Package: pybitmessage Section: mail 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 Description: Send encrypted messages Bitmessage is a P2P communications protocol used to send encrypted diff --git a/debian/rules b/debian/rules index 233679ca..5b29d243 100644 --- a/debian/rules +++ b/debian/rules @@ -1,6 +1,7 @@ #!/usr/bin/make -f APP=pybitmessage +PREFIX=/usr build: build-stamp make build-arch: build-stamp @@ -20,7 +21,7 @@ install: build clean dh_testroot dh_prep dh_installdirs - ${MAKE} install -B DESTDIR=${CURDIR}/debian/${APP} + ${MAKE} install -B DESTDIR=${CURDIR}/debian/${APP} PREFIX=/usr binary-indep: build install dh_testdir dh_testroot diff --git a/ebuildpackage/pybitmessage-0.3.4-1.ebuild b/ebuildpackage/pybitmessage-0.3.4-1.ebuild index 20f056e4..01eddc4f 100755 --- a/ebuildpackage/pybitmessage-0.3.4-1.ebuild +++ b/ebuildpackage/pybitmessage-0.3.4-1.ebuild @@ -1,22 +1,32 @@ # $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." HOMEPAGE="https://github.com/Bitmessage/PyBitmessage" -SRC_URI="${PN}/${P}.tar.gz" +EGIT_REPO_URI="https://github.com/Bitmessage/PyBitmessage.git" LICENSE="MIT" SLOT="0" KEYWORDS="x86" -RDEPEND="dev-libs/popt" -DEPEND="${RDEPEND}" +DEPEND="dev-libs/popt + ${PYTHON_DEPS}" +RDEPEND="${DEPEND} + dev-libs/openssl + dev-python/PyQt4[]" src_configure() { econf --with-popt } +src_compile() { :; } + src_install() { - emake DESTDIR="${D}" install + emake DESTDIR="${D}" PREFIX="/usr" install # Install README and (Debian) changelog dodoc README.md debian/changelog } diff --git a/generate.sh b/generate.sh index 8909cf2f..173e3c79 100755 --- a/generate.sh +++ b/generate.sh @@ -4,4 +4,4 @@ rm -f Makefile rpmpackage/*.spec -packagemonkey -n "PyBitmessage" --version "0.3.4" --dir "." -l "mit" -e "Bob Mottram (4096 bits) " --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) " --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" diff --git a/puppy.sh b/puppy.sh index dd54ecc9..efe1d7da 100755 --- a/puppy.sh +++ b/puppy.sh @@ -27,7 +27,7 @@ mkdir -p ${PROJECTDIR} # Build the project make clean make -make install -B DESTDIR=${PROJECTDIR} +make install -B DESTDIR=${PROJECTDIR} PREFIX=/usr # Alter the desktop file categories sed -i "s/Categories=Office;Email;/Categories=Internet;mailnews;/g" ${PROJECTDIR}/usr/share/applications/${APP}.desktop diff --git a/puppypackage/pybitmessage-0.3.4.pet.specs b/puppypackage/pybitmessage-0.3.4.pet.specs index e346d0c9..aac180a9 100644 --- a/puppypackage/pybitmessage-0.3.4.pet.specs +++ b/puppypackage/pybitmessage-0.3.4.pet.specs @@ -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| diff --git a/rpmpackage/pybitmessage.spec b/rpmpackage/pybitmessage.spec index 27485d73..9c12661a 100644 --- a/rpmpackage/pybitmessage.spec +++ b/rpmpackage/pybitmessage.spec @@ -8,7 +8,7 @@ Packager: Bob Mottram (4096 bits) Source0: http://yourdomainname.com/src/%{name}_%{version}.orig.tar.gz Group: Office/Email -Requires: python, PyQt4, openssl-compat-bitcoin-libs +Requires: python, PyQt4, openssl-compat-bitcoin-libs, gst123 %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/apps # Make install but to the RPM BUILDROOT directory -make install -B DESTDIR=%{buildroot} +make install -B DESTDIR=%{buildroot} PREFIX=/usr %files %doc README.md LICENSE diff --git a/slack.sh b/slack.sh index cc71e1f3..5d826e0b 100755 --- a/slack.sh +++ b/slack.sh @@ -28,7 +28,7 @@ mkdir -p ${PROJECTDIR} # Build the project make clean 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 mkdir ${PROJECTDIR}/install diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 15acf545..9f87e80e 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -9,7 +9,7 @@ # The software version variable is now held in shared.py -#import ctypes +# import ctypes try: from gevent import monkey monkey.patch_all() @@ -36,7 +36,7 @@ import helper_bootstrap import sys 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 "Your version: {0}.{1}.{2}".format(*sys.version_info) sys.exit(0) @@ -56,8 +56,6 @@ def connectToStream(streamNumber): # This is one of several classes that constitute the API # This class was written by Vaibhav Bhatia. Modified by Jonathan Warren (Atheros). # http://code.activestate.com/recipes/501148-xmlrpc-serverclient-which-does-cookie-handling-and/ - - class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): def do_POST(self): @@ -342,7 +340,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): msgid, toAddress, fromAddress, subject, received, message, encodingtype = row subject = shared.fixPotentiallyInvalidUTF8Data(subject) message = shared.fixPotentiallyInvalidUTF8Data(message) - data += json.dumps({'msgid':msgid.encode('hex'),'toAddress':toAddress,'fromAddress':fromAddress,'subject':subject.encode('base64'),'message':message.encode('base64'),'encodingType':encodingtype,'receivedTime':received},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 += ']}' return data elif method == 'getAllSentMessages': @@ -358,7 +356,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): message = shared.fixPotentiallyInvalidUTF8Data(message) if len(data) > 25: data += ',' - data += json.dumps({'msgid':msgid.encode('hex'),'toAddress':toAddress,'fromAddress':fromAddress,'subject':subject.encode('base64'),'message':message.encode('base64'),'encodingType':encodingtype,'lastActionTime':lastactiontime,'status':status,'ackData':ackdata.encode('hex')},indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':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 += ']}' return data elif method == 'getInboxMessagesByAddress': @@ -373,12 +371,12 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): shared.sqlLock.release() data = '{"inboxMessages":[' for row in queryreturn: - msgid, toAddress, fromAddress, subject, received, message, encodingtype= row + msgid, toAddress, fromAddress, subject, received, message, encodingtype = row subject = shared.fixPotentiallyInvalidUTF8Data(subject) message = shared.fixPotentiallyInvalidUTF8Data(message) if len(data) > 25: data += ',' - data += json.dumps({'msgid':msgid.encode('hex'),'toAddress':toAddress,'fromAddress':fromAddress,'subject':subject.encode('base64'),'message':message.encode('base64'),'encodingType':encodingtype,'receivedTime':received},indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'receivedTime':received}, indent=4, separators=(',', ': ')) data += ']}' return data elif method == 'getSentMessageById': @@ -396,7 +394,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row subject = shared.fixPotentiallyInvalidUTF8Data(subject) message = shared.fixPotentiallyInvalidUTF8Data(message) - data += json.dumps({'msgid':msgid.encode('hex'),'toAddress':toAddress,'fromAddress':fromAddress,'subject':subject.encode('base64'),'message':message.encode('base64'),'encodingType':encodingtype,'lastActionTime':lastactiontime,'status':status,'ackData':ackdata.encode('hex')},indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':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 += ']}' return data elif method == 'getSentMessagesByAddress': @@ -416,7 +414,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): message = shared.fixPotentiallyInvalidUTF8Data(message) if len(data) > 25: data += ',' - data += json.dumps({'msgid':msgid.encode('hex'),'toAddress':toAddress,'fromAddress':fromAddress,'subject':subject.encode('base64'),'message':message.encode('base64'),'encodingType':encodingtype,'lastActionTime':lastactiontime,'status':status,'ackData':ackdata.encode('hex')},indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':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 += ']}' return data elif method == 'getSentMessageByAckData': @@ -434,7 +432,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row subject = shared.fixPotentiallyInvalidUTF8Data(subject) message = shared.fixPotentiallyInvalidUTF8Data(message) - data += json.dumps({'msgid':msgid.encode('hex'),'toAddress':toAddress,'fromAddress':fromAddress,'subject':subject.encode('base64'),'message':message.encode('base64'),'encodingType':encodingtype,'lastActionTime':lastactiontime,'status':status,'ackData':ackdata.encode('hex')},indent=4, separators=(',', ': ')) + data += json.dumps({'msgid':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 += ']}' return data elif (method == 'trashMessage') or (method == 'trashInboxMessage'): @@ -454,7 +452,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): shared.sqlReturnQueue.get() shared.sqlSubmitQueue.put('commit') 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).' elif method == 'sendMessage': if len(params) == 0: @@ -513,7 +511,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): return 'API Error 0014: Your fromAddress is disabled. Cannot send.' ackdata = OpenSSL.rand(32) - + t = ('', toAddress, toRipe, fromAddress, subject, message, ackdata, int( time.time()), 'msgqueued', 1, 1, 'sent', 2) helper_sent.insert(t) @@ -577,7 +575,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): toAddress = '[Broadcast subscribers]' ripe = '' - + t = ('', toAddress, ripe, fromAddress, subject, message, ackdata, int( time.time()), 'broadcastqueued', 1, 1, 'sent', 2) helper_sent.insert(t) @@ -719,7 +717,6 @@ if __name__ == "__main__": # signal.signal(signal.SIGINT, signal.SIG_DFL) helper_bootstrap.knownNodes() - helper_bootstrap.dns() # Start the address generation thread addressGeneratorThread = addressGenerator() addressGeneratorThread.daemon = True # close the main program even if there are threads left @@ -757,13 +754,6 @@ if __name__ == "__main__": singleAPIThread = singleAPI() singleAPIThread.daemon = True # close the main program even if there are threads left 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) @@ -783,6 +773,7 @@ if __name__ == "__main__": import bitmessageqt bitmessageqt.run() else: + shared.config.remove_option('bitmessagesettings', 'dontconnect') with shared.printLock: print 'Running as a daemon. You can use Ctrl+C to exit.' diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 1a7dbc42..c5d1192c 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -18,11 +18,13 @@ from namecoin import namecoinConnection, ensureNamecoinOptions from newaddressdialog import * from newsubscriptiondialog import * from regenerateaddresses import * +from newchandialog import * from specialaddressbehavior import * from settings import * from about import * from help import * from iconglossary import * +from connect import * import sys from time import strftime, localtime, gmtime import time @@ -32,11 +34,14 @@ import pickle import platform import debug from debug import logger +import subprocess + try: from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * + except Exception as err: print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download it from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\' (without quotes).' print 'Error message:', err @@ -53,7 +58,16 @@ def _translate(context, text): 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_chan = '[chan]' def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) @@ -106,6 +120,8 @@ class MyForm(QtGui.QMainWindow): "triggered()"), self.click_actionDeleteAllTrashedMessages) QtCore.QObject.connect(self.ui.actionRegenerateDeterministicAddresses, QtCore.SIGNAL( "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( "clicked()"), self.click_NewAddressDialog) QtCore.QObject.connect(self.ui.comboBoxSendFrom, QtCore.SIGNAL( @@ -296,6 +312,8 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(addressInKeysFile) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + if shared.safeConfigGetBoolean(addressInKeysFile, 'chan'): + newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange if not isEnabled: newItem.setTextColor(QtGui.QColor(128, 128, 128)) if shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist'): @@ -410,6 +428,8 @@ class MyForm(QtGui.QMainWindow): self.rerenderComboBoxSendFrom() + + # Show or hide the application window after clicking an item within the # tray icon or, on Windows, the try icon itself. def appIndicatorShowOrHideWindow(self): @@ -597,6 +617,9 @@ class MyForm(QtGui.QMainWindow): elif status == 'msgsent': statusText = _translate("MainWindow", "Message sent. Waiting on acknowledgement. Sent at %1").arg( 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': statusText = _translate( "MainWindow", "Need to do work to send message. Work is queued.") @@ -712,6 +735,8 @@ class MyForm(QtGui.QMainWindow): newItem.setData(Qt.UserRole, str(toAddress)) if shared.safeConfigGetBoolean(toAddress, 'mailinglist'): 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) if fromLabel == '': newItem = QtGui.QTableWidgetItem( @@ -957,6 +982,57 @@ class MyForm(QtGui.QMainWindow): # update the menu entries 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 def notifierInit(self): global withMessagingMenu @@ -964,8 +1040,11 @@ class MyForm(QtGui.QMainWindow): Notify.init('pybitmessage') # shows a notification - def notifierShow(self, title, subtitle): + def notifierShow(self, title, subtitle, fromCategory, label): global withMessagingMenu + + self.playSound(fromCategory, label); + if withMessagingMenu: n = Notify.Notification.new( title, subtitle, 'notification-message-email') @@ -1035,6 +1114,68 @@ class MyForm(QtGui.QMainWindow): ), self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(), self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked())) 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): if 'linux' in sys.platform: subprocess.call(["xdg-open", shared.appdata + 'keys.dat']) @@ -1138,7 +1279,8 @@ class MyForm(QtGui.QMainWindow): # if the connection is lost then show a notification if self.connected: self.notifierShow('Bitmessage', unicode(_translate( - "MainWindow", "Connection lost").toUtf8(),'utf-8')) + "MainWindow", "Connection lost").toUtf8(),'utf-8'), + self.SOUND_DISCONNECTED, None) self.connected = False if self.actionStatus is not None: @@ -1155,7 +1297,8 @@ class MyForm(QtGui.QMainWindow): # if a new connection has been established then show a notification if not self.connected: self.notifierShow('Bitmessage', unicode(_translate( - "MainWindow", "Connected").toUtf8(),'utf-8')) + "MainWindow", "Connected").toUtf8(),'utf-8'), + self.SOUND_CONNECTED, None) self.connected = True if self.actionStatus is not None: @@ -1171,7 +1314,8 @@ class MyForm(QtGui.QMainWindow): shared.statusIconColor = 'green' if not self.connected: self.notifierShow('Bitmessage', unicode(_translate( - "MainWindow", "Connected").toUtf8(),'utf-8')) + "MainWindow", "Connected").toUtf8(),'utf-8'), + self.SOUND_CONNECTION_GREEN, None) self.connected = True if self.actionStatus is not None: @@ -1278,7 +1422,7 @@ class MyForm(QtGui.QMainWindow): self.ui.tableWidgetInbox.item(i, 0).setTextColor(QtGui.QColor(137, 04, 177)) else: self.ui.tableWidgetInbox.item( - i, 0).setTextColor(QtGui.QColor(0, 0, 0)) + i, 0).setTextColor(QApplication.palette().text().color()) def rerenderSentFromLabels(self): for i in range(self.ui.tableWidgetSent.rowCount()): @@ -1382,12 +1526,11 @@ class MyForm(QtGui.QMainWindow): toAddress = addBMIfNotPresent(toAddress) try: shared.config.get(toAddress, 'enabled') - # The toAddress is one owned by me. We cannot send - # messages to ourselves without significant changes - # to the codebase. - 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)) - continue + # The toAddress is one owned by me. + if not shared.safeConfigGetBoolean(toAddress, 'chan'): + 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)) + continue except: pass if addressVersionNumber > 3 or addressVersionNumber <= 1: @@ -1531,6 +1674,16 @@ class MyForm(QtGui.QMainWindow): def redrawLabelFrom(self, index): self.ui.labelFrom.setText( self.ui.comboBoxSendFrom.itemData(index).toPyObject()) + self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(self.ui.comboBoxSendFrom.itemData(index).toPyObject()) + + def setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(self, address): + # 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): self.ui.comboBoxSendFrom.clear() @@ -1647,6 +1800,8 @@ class MyForm(QtGui.QMainWindow): newItem.setData(Qt.UserRole, str(toAddress)) if shared.safeConfigGetBoolean(str(toAddress), 'mailinglist'): 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.setItem(0, 0, newItem) @@ -1654,12 +1809,12 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(fromAddress, 'utf-8')) newItem.setToolTip(unicode(fromAddress, 'utf-8')) if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'): - self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(fromAddress, 'utf-8')) + self.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: newItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8')) newItem.setToolTip(unicode(unicode(fromLabel, 'utf-8'))) if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'): - self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(fromLabel, 'utf-8')) + self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(fromLabel, 'utf-8'), self.SOUND_KNOWN, unicode(fromLabel, 'utf-8')) newItem.setData(Qt.UserRole, str(fromAddress)) newItem.setFont(font) self.ui.tableWidgetInbox.setItem(0, 1, newItem) @@ -1686,45 +1841,47 @@ class MyForm(QtGui.QMainWindow): # First we must check to see if the address is already in the # address book. The user cannot add it again or else it will # cause problems when updating and deleting the entry. - shared.sqlLock.acquire() - t = (addBMIfNotPresent(str( - self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())),) - shared.sqlSubmitQueue.put( - '''select * from addressbook where address=?''') - shared.sqlSubmitQueue.put(t) - queryreturn = shared.sqlReturnQueue.get() - shared.sqlLock.release() - if queryreturn == []: - self.ui.tableWidgetAddressBook.setSortingEnabled(False) - self.ui.tableWidgetAddressBook.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode( - self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8(), 'utf-8')) - self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) - newItem = QtGui.QTableWidgetItem(addBMIfNotPresent( - self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())) - newItem.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.ui.tableWidgetAddressBook.setItem(0, 1, newItem) - self.ui.tableWidgetAddressBook.setSortingEnabled(True) - t = (str(self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8()), addBMIfNotPresent( - str(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text()))) - shared.sqlLock.acquire() - shared.sqlSubmitQueue.put( - '''INSERT INTO addressbook VALUES (?,?)''') - shared.sqlSubmitQueue.put(t) - queryreturn = shared.sqlReturnQueue.get() - shared.sqlSubmitQueue.put('commit') - shared.sqlLock.release() - self.rerenderInboxFromLabels() - self.rerenderSentToLabels() - else: - self.statusBar().showMessage(_translate( - "MainWindow", "Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want.")) + 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 addSubscription(self, label, address): + def addEntryToAddressBook(self,address,label): + shared.sqlLock.acquire() + t = (address,) + shared.sqlSubmitQueue.put( + '''select * from addressbook where address=?''') + shared.sqlSubmitQueue.put(t) + queryreturn = shared.sqlReturnQueue.get() + shared.sqlLock.release() + if queryreturn == []: + self.ui.tableWidgetAddressBook.setSortingEnabled(False) + self.ui.tableWidgetAddressBook.insertRow(0) + newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) + self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) + newItem = QtGui.QTableWidgetItem(address) + newItem.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + self.ui.tableWidgetAddressBook.setItem(0, 1, newItem) + self.ui.tableWidgetAddressBook.setSortingEnabled(True) + t = (str(label), address) + shared.sqlLock.acquire() + shared.sqlSubmitQueue.put( + '''INSERT INTO addressbook VALUES (?,?)''') + shared.sqlSubmitQueue.put(t) + queryreturn = shared.sqlReturnQueue.get() + shared.sqlSubmitQueue.put('commit') + shared.sqlLock.release() + self.rerenderInboxFromLabels() + self.rerenderSentToLabels() + else: + self.statusBar().showMessage(_translate( + "MainWindow", "Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want.")) + + def addSubscription(self, address, label): address = addBMIfNotPresent(address) #This should be handled outside of this function, for error displaying and such, but it must also be checked here. if shared.isAddressInMySubscriptionsList(address): @@ -1761,7 +1918,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.")) return label = self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8() - self.addSubscription(label, address) + self.addSubscription(address, label) def loadBlackWhiteList(self): # Initialize the Blacklist or Whitelist table @@ -1816,14 +1973,15 @@ class MyForm(QtGui.QMainWindow): shared.config.set('bitmessagesettings', 'startintray', str( self.settingsDialogInstance.ui.checkBoxStartInTray.isChecked())) if int(shared.config.get('bitmessagesettings', 'port')) != int(self.settingsDialogInstance.ui.lineEditTCPPort.text()): - QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate( - "MainWindow", "You must restart Bitmessage for the port number change to take effect.")) + if not shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'): + QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate( + "MainWindow", "You must restart Bitmessage for the port number change to take effect.")) shared.config.set('bitmessagesettings', 'port', str( self.settingsDialogInstance.ui.lineEditTCPPort.text())) if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none' and str(self.settingsDialogInstance.ui.comboBoxProxyType.currentText())[0:5] == 'SOCKS': if shared.statusIconColor != 'red': 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': self.statusBar().showMessage('') shared.config.set('bitmessagesettings', 'socksproxytype', str( @@ -2016,13 +2174,16 @@ class MyForm(QtGui.QMainWindow): currentRow = self.ui.tableWidgetYourIdentities.currentRow() addressAtCurrentRow = str( self.ui.tableWidgetYourIdentities.item(currentRow, 1).text()) + if shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'): + return if self.dialog.ui.radioButtonBehaveNormalAddress.isChecked(): shared.config.set(str( addressAtCurrentRow), 'mailinglist', 'false') # Set the color to either black or grey if shared.config.getboolean(addressAtCurrentRow, 'enabled'): self.ui.tableWidgetYourIdentities.item( - currentRow, 1).setTextColor(QtGui.QColor(0, 0, 0)) + currentRow, 1).setTextColor(QApplication.palette() + .text().color()) else: self.ui.tableWidgetYourIdentities.item( currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) @@ -2049,12 +2210,6 @@ class MyForm(QtGui.QMainWindow): # address.' streamNumberForAddress = addressStream( 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( self.dialog.ui.newaddresslabel.text().toUtf8()), 1, "", self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) else: @@ -2066,11 +2221,6 @@ class MyForm(QtGui.QMainWindow): "MainWindow", "Choose a passphrase"), _translate("MainWindow", "You really do need a passphrase.")) else: 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( ), self.dialog.ui.lineEditPassphrase.text().toUtf8(), self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) else: @@ -2147,6 +2297,7 @@ class MyForm(QtGui.QMainWindow): self.ui.labelFrom.setText('') else: self.ui.labelFrom.setText(toAddressAtCurrentInboxRow) + self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(toAddressAtCurrentInboxRow) self.ui.lineEditTo.setText(str(fromAddressAtCurrentInboxRow)) self.ui.comboBoxSendFrom.setCurrentIndex(0) # self.ui.comboBoxSendFrom.setEditText(str(self.ui.tableWidgetInbox.item(currentInboxRow,0).text)) @@ -2370,7 +2521,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.")) continue labelAtCurrentRow = self.ui.tableWidgetAddressBook.item(currentRow,0).text().toUtf8() - self.addSubscription(labelAtCurrentRow, addressAtCurrentRow) + self.addSubscription(addressAtCurrentRow, labelAtCurrentRow) self.ui.tabWidget.setCurrentIndex(4) def on_context_menuAddressBook(self, point): @@ -2422,9 +2573,9 @@ class MyForm(QtGui.QMainWindow): shared.sqlSubmitQueue.put('commit') shared.sqlLock.release() self.ui.tableWidgetSubscriptions.item( - currentRow, 0).setTextColor(QtGui.QColor(0, 0, 0)) + currentRow, 0).setTextColor(QApplication.palette().text().color()) self.ui.tableWidgetSubscriptions.item( - currentRow, 1).setTextColor(QtGui.QColor(0, 0, 0)) + currentRow, 1).setTextColor(QApplication.palette().text().color()) shared.reloadBroadcastSendersForWhichImWatching() def on_action_SubscriptionsDisable(self): @@ -2493,9 +2644,9 @@ class MyForm(QtGui.QMainWindow): addressAtCurrentRow = self.ui.tableWidgetBlacklist.item( currentRow, 1).text() self.ui.tableWidgetBlacklist.item( - currentRow, 0).setTextColor(QtGui.QColor(0, 0, 0)) + currentRow, 0).setTextColor(QApplication.palette().text().color()) self.ui.tableWidgetBlacklist.item( - currentRow, 1).setTextColor(QtGui.QColor(0, 0, 0)) + currentRow, 1).setTextColor(QApplication.palette().text().color()) t = (str(addressAtCurrentRow),) shared.sqlLock.acquire() if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': @@ -2546,13 +2697,15 @@ class MyForm(QtGui.QMainWindow): with open(shared.appdata + 'keys.dat', 'wb') as configfile: shared.config.write(configfile) self.ui.tableWidgetYourIdentities.item( - currentRow, 0).setTextColor(QtGui.QColor(0, 0, 0)) + currentRow, 0).setTextColor(QApplication.palette().text().color()) self.ui.tableWidgetYourIdentities.item( - currentRow, 1).setTextColor(QtGui.QColor(0, 0, 0)) + currentRow, 1).setTextColor(QApplication.palette().text().color()) self.ui.tableWidgetYourIdentities.item( - currentRow, 2).setTextColor(QtGui.QColor(0, 0, 0)) + currentRow, 2).setTextColor(QApplication.palette().text().color()) if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'): 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() def on_action_YourIdentitiesDisable(self): @@ -2721,11 +2874,14 @@ class MyForm(QtGui.QMainWindow): def writeNewAddressToTable(self, label, address, streamNumber): self.ui.tableWidgetYourIdentities.setSortingEnabled(False) self.ui.tableWidgetYourIdentities.insertRow(0) + newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) self.ui.tableWidgetYourIdentities.setItem( - 0, 0, QtGui.QTableWidgetItem(unicode(label, 'utf-8'))) + 0, 0, newItem) newItem = QtGui.QTableWidgetItem(address) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + if shared.safeConfigGetBoolean(address, 'chan'): + newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange self.ui.tableWidgetYourIdentities.setItem(0, 1, newItem) newItem = QtGui.QTableWidgetItem(streamNumber) newItem.setFlags( @@ -2751,7 +2907,15 @@ class helpDialog(QtGui.QDialog): self.parent = parent self.ui.labelHelpURI.setOpenExternalLinks(True) 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): @@ -2772,7 +2936,6 @@ class regenerateAddressesDialog(QtGui.QDialog): self.parent = parent QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) - class settingsDialog(QtGui.QDialog): def __init__(self, parent): @@ -2963,17 +3126,23 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog): currentRow = parent.ui.tableWidgetYourIdentities.currentRow() addressAtCurrentRow = str( parent.ui.tableWidgetYourIdentities.item(currentRow, 1).text()) - if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'): - self.ui.radioButtonBehaviorMailingList.click() - else: - self.ui.radioButtonBehaveNormalAddress.click() - try: - mailingListName = shared.config.get( - addressAtCurrentRow, 'mailinglistname') - except: - mailingListName = '' - self.ui.lineEditMailingListName.setText( - unicode(mailingListName, 'utf-8')) + if not shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'): + if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'): + self.ui.radioButtonBehaviorMailingList.click() + else: + self.ui.radioButtonBehaveNormalAddress.click() + try: + mailingListName = shared.config.get( + addressAtCurrentRow, 'mailinglistname') + except: + mailingListName = '' + self.ui.lineEditMailingListName.setText( + 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)) @@ -3032,11 +3201,11 @@ class NewAddressDialog(QtGui.QDialog): self.ui.groupBoxDeterministic.setHidden(True) QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) -class NewChanDialog(QtGui.QDialog): +class newChanDialog(QtGui.QDialog): def __init__(self, parent): QtGui.QWidget.__init__(self, parent) - self.ui = Ui_NewChanDialog() + self.ui = Ui_newChanDialog() self.ui.setupUi(self) self.parent = parent self.ui.groupBoxCreateChan.setHidden(True) @@ -3158,6 +3327,8 @@ def run(): myapp.appIndicatorInit(app) myapp.ubuntuMessagingMenuInit() myapp.notifierInit() + if shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'): + myapp.showConnectDialog() # ask the user if we may connect if gevent is None: sys.exit(app.exec_()) else: diff --git a/src/bitmessageqt/bitmessageui.py b/src/bitmessageqt/bitmessageui.py index bcf310bb..8edf5053 100644 --- a/src/bitmessageqt/bitmessageui.py +++ b/src/bitmessageqt/bitmessageui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'bitmessageui.ui' # -# Created: Wed Jul 17 18:15:14 2013 +# Created: Sat Jul 27 08:23:55 2013 # by: PyQt4 UI code generator 4.9.3 # # WARNING! All changes made in this file will be lost! @@ -450,9 +450,12 @@ class Ui_MainWindow(object): self.actionRegenerateDeterministicAddresses.setObjectName(_fromUtf8("actionRegenerateDeterministicAddresses")) self.actionDeleteAllTrashedMessages = QtGui.QAction(MainWindow) self.actionDeleteAllTrashedMessages.setObjectName(_fromUtf8("actionDeleteAllTrashedMessages")) + self.actionJoinChan = QtGui.QAction(MainWindow) + self.actionJoinChan.setObjectName(_fromUtf8("actionJoinChan")) self.menuFile.addAction(self.actionManageKeys) self.menuFile.addAction(self.actionDeleteAllTrashedMessages) self.menuFile.addAction(self.actionRegenerateDeterministicAddresses) + self.menuFile.addAction(self.actionJoinChan) self.menuFile.addAction(self.actionExit) self.menuSettings.addAction(self.actionSettings) self.menuHelp.addAction(self.actionHelp) @@ -597,5 +600,6 @@ class Ui_MainWindow(object): self.actionSettings.setText(QtGui.QApplication.translate("MainWindow", "Settings", None, QtGui.QApplication.UnicodeUTF8)) self.actionRegenerateDeterministicAddresses.setText(QtGui.QApplication.translate("MainWindow", "Regenerate deterministic addresses", None, QtGui.QApplication.UnicodeUTF8)) self.actionDeleteAllTrashedMessages.setText(QtGui.QApplication.translate("MainWindow", "Delete all trashed messages", None, QtGui.QApplication.UnicodeUTF8)) + self.actionJoinChan.setText(QtGui.QApplication.translate("MainWindow", "Join / Create chan", None, QtGui.QApplication.UnicodeUTF8)) import bitmessage_icons_rc diff --git a/src/bitmessageqt/bitmessageui.ui b/src/bitmessageqt/bitmessageui.ui index 04cc3d9b..65656a9a 100644 --- a/src/bitmessageqt/bitmessageui.ui +++ b/src/bitmessageqt/bitmessageui.ui @@ -14,7 +14,7 @@ Bitmessage - + :/newPrefix/images/can-icon-24px.png:/newPrefix/images/can-icon-24px.png @@ -61,7 +61,7 @@ - + :/newPrefix/images/inbox.png:/newPrefix/images/inbox.png @@ -188,7 +188,7 @@ - + :/newPrefix/images/send.png:/newPrefix/images/send.png @@ -358,7 +358,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/sent.png:/newPrefix/images/sent.png @@ -478,7 +478,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/identities.png:/newPrefix/images/identities.png @@ -578,7 +578,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/subscriptions.png:/newPrefix/images/subscriptions.png @@ -663,7 +663,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/addressbook.png:/newPrefix/images/addressbook.png @@ -745,7 +745,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/blacklist.png:/newPrefix/images/blacklist.png @@ -837,7 +837,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/networkstatus.png:/newPrefix/images/networkstatus.png @@ -856,7 +856,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/redicon.png:/newPrefix/images/redicon.png @@ -1033,6 +1033,7 @@ p, li { white-space: pre-wrap; } + @@ -1106,6 +1107,11 @@ p, li { white-space: pre-wrap; } Delete all trashed messages + + + Join / Create chan + + tabWidget diff --git a/src/bitmessageqt/connect.py b/src/bitmessageqt/connect.py new file mode 100644 index 00000000..1e224afb --- /dev/null +++ b/src/bitmessageqt/connect.py @@ -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)) + diff --git a/src/bitmessageqt/connect.ui b/src/bitmessageqt/connect.ui new file mode 100644 index 00000000..74173860 --- /dev/null +++ b/src/bitmessageqt/connect.ui @@ -0,0 +1,101 @@ + + + connectDialog + + + + 0 + 0 + 400 + 124 + + + + Bitmessage + + + + + + Bitmessage won't connect to anyone until you let it. + + + + + + + Connect now + + + true + + + + + + + Let me configure special network settings first + + + + + + + Qt::Horizontal + + + + 185 + 24 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + connectDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + connectDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/bitmessageqt/newchandialog.py b/src/bitmessageqt/newchandialog.py index 5c5e11f2..43235bfa 100644 --- a/src/bitmessageqt/newchandialog.py +++ b/src/bitmessageqt/newchandialog.py @@ -2,7 +2,7 @@ # 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 # # WARNING! All changes made in this file will be lost! @@ -23,20 +23,36 @@ except AttributeError: def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig) -class Ui_NewChanDialog(object): - def setupUi(self, NewChanDialog): - NewChanDialog.setObjectName(_fromUtf8("NewChanDialog")) - NewChanDialog.resize(447, 441) - self.formLayout = QtGui.QFormLayout(NewChanDialog) +class Ui_newChanDialog(object): + def setupUi(self, newChanDialog): + newChanDialog.setObjectName(_fromUtf8("newChanDialog")) + newChanDialog.resize(530, 422) + newChanDialog.setMinimumSize(QtCore.QSize(0, 0)) + self.formLayout = QtGui.QFormLayout(newChanDialog) self.formLayout.setObjectName(_fromUtf8("formLayout")) - self.radioButtonCreateChan = QtGui.QRadioButton(NewChanDialog) + self.radioButtonCreateChan = QtGui.QRadioButton(newChanDialog) self.radioButtonCreateChan.setObjectName(_fromUtf8("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.setObjectName(_fromUtf8("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.gridLayout_2 = QtGui.QGridLayout(self.groupBoxJoinChan) self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) @@ -57,43 +73,30 @@ class Ui_NewChanDialog(object): self.lineEditChanBitmessageAddress.setObjectName(_fromUtf8("lineEditChanBitmessageAddress")) self.gridLayout_2.addWidget(self.lineEditChanBitmessageAddress, 4, 0, 1, 1) self.formLayout.setWidget(3, QtGui.QFormLayout.SpanningRole, self.groupBoxJoinChan) - 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.buttonBox = QtGui.QDialogButtonBox(NewChanDialog) + spacerItem = QtGui.QSpacerItem(389, 2, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout.setItem(4, QtGui.QFormLayout.FieldRole, spacerItem) + self.buttonBox = QtGui.QDialogButtonBox(newChanDialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) 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) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), NewChanDialog.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), NewChanDialog.reject) + self.retranslateUi(newChanDialog) + 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.radioButtonJoinChan, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.groupBoxJoinChan.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): - NewChanDialog.setWindowTitle(_translate("NewChanDialog", "Dialog", None)) - self.radioButtonCreateChan.setText(_translate("NewChanDialog", "Create a new chan", None)) - self.radioButtonJoinChan.setText(_translate("NewChanDialog", "Join a chan", None)) - self.groupBoxJoinChan.setTitle(_translate("NewChanDialog", "Join a chan", None)) - self.label.setText(_translate("NewChanDialog", "

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

Chans are experimental and are unmoderatable.

", None)) - self.label_2.setText(_translate("NewChanDialog", "Chan name:", None)) - self.label_3.setText(_translate("NewChanDialog", "Chan bitmessage address:", None)) - self.groupBoxCreateChan.setTitle(_translate("NewChanDialog", "Create a chan", 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_5.setText(_translate("NewChanDialog", "Chan name:", None)) + def retranslateUi(self, newChanDialog): + newChanDialog.setWindowTitle(_translate("newChanDialog", "Dialog", None)) + self.radioButtonCreateChan.setText(_translate("newChanDialog", "Create a new chan", None)) + self.radioButtonJoinChan.setText(_translate("newChanDialog", "Join a chan", None)) + self.groupBoxCreateChan.setTitle(_translate("newChanDialog", "Create a chan", 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_5.setText(_translate("newChanDialog", "Chan name:", None)) + self.groupBoxJoinChan.setTitle(_translate("newChanDialog", "Join a chan", None)) + self.label.setText(_translate("newChanDialog", "

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.

Chans are experimental and completely unmoderatable.

", None)) + self.label_2.setText(_translate("newChanDialog", "Chan name:", None)) + self.label_3.setText(_translate("newChanDialog", "Chan bitmessage address:", None)) diff --git a/src/bitmessageqt/newchandialog.ui b/src/bitmessageqt/newchandialog.ui index 2e6e4657..3713c6a3 100644 --- a/src/bitmessageqt/newchandialog.ui +++ b/src/bitmessageqt/newchandialog.ui @@ -1,15 +1,21 @@ - NewChanDialog - + newChanDialog + 0 0 - 447 - 441 + 530 + 422 + + + 0 + 0 + + Dialog @@ -31,45 +37,6 @@ - - - - Join a chan - - - - - - <html><head/><body><p>A chan is a set of encryption keys that is shared by a group of people. The keys and bitmessage address used by a chan is generated from a human-friendly word or phrase (the chan name).</p><p>Chans are experimental and are unmoderatable.</p></body></html> - - - true - - - - - - - Chan name: - - - - - - - - - - Chan bitmessage address: - - - - - - - - - @@ -99,7 +66,59 @@ + + + + Join a chan + + + + + + <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> + + + true + + + + + + + Chan name: + + + + + + + + + + Chan bitmessage address: + + + + + + + + + + + + Qt::Vertical + + + + 389 + 2 + + + + + Qt::Horizontal @@ -116,7 +135,7 @@ buttonBox accepted() - NewChanDialog + newChanDialog accept() @@ -132,7 +151,7 @@ buttonBox rejected() - NewChanDialog + newChanDialog reject() diff --git a/src/build_osx.py b/src/build_osx.py index aac551b9..ff33f6c1 100644 --- a/src/build_osx.py +++ b/src/build_osx.py @@ -21,7 +21,7 @@ if sys.platform == 'darwin': setup_requires=['py2app'], app=[mainscript], options=dict(py2app=dict(argv_emulation=True, - includes = ['PyQt4.QtCore','PyQt4.QtGui', 'sip'], + includes = ['PyQt4.QtCore','PyQt4.QtGui', 'sip', 'sqlite3'], packages = ['bitmessageqt'], frameworks = ['/usr/local/opt/openssl/lib/libcrypto.dylib'], iconfile='images/bitmessage.icns', diff --git a/src/class_addressGenerator.py b/src/class_addressGenerator.py index 08c7773e..54582541 100644 --- a/src/class_addressGenerator.py +++ b/src/class_addressGenerator.py @@ -28,6 +28,8 @@ class addressGenerator(threading.Thread): elif queueValue[0] == 'joinChan': command, chanAddress, label, deterministicPassphrase = queueValue eighteenByteRipe = False + addressVersionNumber = decodeAddress(chanAddress)[1] + streamNumber = decodeAddress(chanAddress)[2] numberOfAddressesToMake = 1 elif len(queueValue) == 7: 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 else: sys.stderr.write( - 'Programming error: A structure with the wrong number of values was passed into the addressGeneratorQueue. Here is the queueValue: %s\n' % 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: 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) @@ -117,9 +119,8 @@ class addressGenerator(threading.Thread): with open(shared.appdata + 'keys.dat', 'wb') as configfile: shared.config.write(configfile) - # 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. + # The API and the join and create Chan functionality + # both need information back from the address generator. shared.apiAddressGeneratorReturnQueue.put(address) shared.UISignalQueue.put(( @@ -128,7 +129,7 @@ class addressGenerator(threading.Thread): label, address, streamNumber))) shared.reloadMyAddressHashes() shared.workerQueue.put(( - 'doPOWForMyV3Pubkey', ripe.digest())) + 'sendOutOrStoreMyV3Pubkey', ripe.digest())) elif command == 'createDeterministicAddresses' or command == 'getDeterministicAddress' or command == 'createChan' or command == 'joinChan': 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 command == 'joinChan': if address != chanAddress: - #todo: show an error message in the UI - shared.apiAddressGeneratorReturnQueue.put('API Error 0018: Chan name does not match address.') + shared.apiAddressGeneratorReturnQueue.put('chan name does not match address') saveAddressToDisk = False if command == 'getDeterministicAddress': saveAddressToDisk = False @@ -210,8 +210,13 @@ class addressGenerator(threading.Thread): privEncryptionKeyWIF = arithmetic.changebase( privEncryptionKey + checksum, 256, 58) + addressAlreadyExists = False try: shared.config.add_section(address) + except: + print address, 'already exists. Not adding it again.' + addressAlreadyExists = True + if not addressAlreadyExists: print 'label:', label shared.config.set(address, 'label', label) shared.config.set(address, 'enabled', 'true') @@ -237,17 +242,13 @@ class addressGenerator(threading.Thread): potentialPrivEncryptionKey.encode('hex')) shared.myAddressesByHash[ ripe.digest()] = address - #todo: don't send out pubkey if dealing with a chan; save in pubkeys table instead. shared.workerQueue.put(( - 'doPOWForMyV3Pubkey', ripe.digest())) - except: - print address, 'already exists. Not adding it again.' + 'sendOutOrStoreMyV3Pubkey', ripe.digest())) # If this is a chan address, + # the worker thread won't send out the pubkey over the network. + # Done generating addresses. - if command == 'createDeterministicAddresses': - # 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. + if command == 'createDeterministicAddresses' or command == 'joinChan' or command == 'createChan': shared.apiAddressGeneratorReturnQueue.put( listOfNewAddressesToSendOutThroughTheAPI) shared.UISignalQueue.put(( diff --git a/src/class_outgoingSynSender.py b/src/class_outgoingSynSender.py index 2c4766f4..ac0b11ac 100644 --- a/src/class_outgoingSynSender.py +++ b/src/class_outgoingSynSender.py @@ -7,7 +7,6 @@ import socket import sys import tr -#import bitmessagemain from class_sendDataThread import * from class_receiveDataThread import * @@ -24,7 +23,8 @@ class outgoingSynSender(threading.Thread): self.selfInitiatedConnections = selfInitiatedConnections def run(self): - time.sleep(1) + while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'): + time.sleep(2) while True: while len(self.selfInitiatedConnections[self.streamNumber]) >= 8: # maximum number of outgoing connections = 8 time.sleep(10) diff --git a/src/class_receiveDataThread.py b/src/class_receiveDataThread.py index e73f3d2b..2693b293 100644 --- a/src/class_receiveDataThread.py +++ b/src/class_receiveDataThread.py @@ -1412,34 +1412,39 @@ class receiveDataThread(threading.Thread): if len(requestedHash) != 20: print 'The length of the requested hash is not 20 bytes. Something is wrong. Ignoring.' return - print 'the hash requested in this getpubkey request is:', requestedHash.encode('hex') + with shared.printLock: + 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 decodeAddress(shared.myAddressesByHash[requestedHash])[1] != requestedAddressVersionNumber: with shared.printLock: 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 try: lastPubkeySendTime = int(shared.config.get( shared.myAddressesByHash[requestedHash], 'lastpubkeysendtime')) except: lastPubkeySendTime = 0 - if lastPubkeySendTime < time.time() - shared.lengthOfTimeToHoldOnToAllPubkeys: # If the last time we sent our pubkey was at least 28 days ago... - 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.' - - if requestedAddressVersionNumber == 2: - shared.workerQueue.put(( - 'doPOWForMyV2Pubkey', requestedHash)) - elif requestedAddressVersionNumber == 3: - shared.workerQueue.put(( - 'doPOWForMyV3Pubkey', requestedHash)) - else: + 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: + 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: + shared.workerQueue.put(( + 'doPOWForMyV2Pubkey', requestedHash)) + elif requestedAddressVersionNumber == 3: + shared.workerQueue.put(( + 'sendOutOrStoreMyV3Pubkey', requestedHash)) + + else: with shared.printLock: print 'This getpubkey request is not for any of my keys.' diff --git a/src/class_singleListener.py b/src/class_singleListener.py index d6b46643..3890447a 100644 --- a/src/class_singleListener.py +++ b/src/class_singleListener.py @@ -3,6 +3,7 @@ import shared import socket from class_sendDataThread import * from class_receiveDataThread import * +import helper_bootstrap # Only one singleListener thread will ever exist. It creates the # receiveDataThread and sendDataThread for each incoming connection. Note @@ -21,12 +22,15 @@ class singleListener(threading.Thread): self.selfInitiatedConnections = selfInitiatedConnections def run(self): + while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'): + time.sleep(1) + helper_bootstrap.dns() # We typically don't want to accept incoming connections if the user is using a # 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(300) + time.sleep(5) with shared.printLock: print 'Listening for incoming connections.' diff --git a/src/class_singleWorker.py b/src/class_singleWorker.py index 56b7be6e..2ba34eeb 100644 --- a/src/class_singleWorker.py +++ b/src/class_singleWorker.py @@ -72,8 +72,8 @@ class singleWorker(threading.Thread): self.sendBroadcast() elif command == 'doPOWForMyV2Pubkey': self.doPOWForMyV2Pubkey(data) - elif command == 'doPOWForMyV3Pubkey': - self.doPOWForMyV3Pubkey(data) + elif command == 'sendOutOrStoreMyV3Pubkey': + self.sendOutOrStoreMyV3Pubkey(data) """elif command == 'newpubkey': toAddressVersion,toStreamNumber,toRipe = data if toRipe in shared.neededPubkeys: @@ -173,7 +173,11 @@ class singleWorker(threading.Thread): with open(shared.appdata + 'keys.dat', 'wb') as 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] status, addressVersionNumber, streamNumber, hash = decodeAddress( myAddress) @@ -192,7 +196,7 @@ class singleWorker(threading.Thread): except Exception as err: with shared.printLock: 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 @@ -216,34 +220,40 @@ class singleWorker(threading.Thread): payload += encodeVarint(len(signature)) payload += signature - # Do the POW for this pubkey message - target = 2 ** 64 / ((len(payload) + shared.networkDefaultPayloadLengthExtraBytes + - 8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) - print '(For pubkey message) Doing proof of work...' - initialHash = hashlib.sha512(payload).digest() - trialValue, nonce = proofofwork.run(target, initialHash) - print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce + if not shared.safeConfigGetBoolean(myAddress, 'chan'): + # Do the POW for this pubkey message + target = 2 ** 64 / ((len(payload) + shared.networkDefaultPayloadLengthExtraBytes + + 8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte) + print '(For pubkey message) Doing proof of work...' + initialHash = hashlib.sha512(payload).digest() + trialValue, nonce = proofofwork.run(target, initialHash) + print '(For pubkey message) Found proof of work', trialValue, 'Nonce:', nonce - 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()""" + payload = pack('>Q', nonce) + payload + inventoryHash = calculateInventoryHash(payload) + objectType = 'pubkey' + shared.inventory[inventoryHash] = ( + objectType, streamNumber, payload, embeddedTime) - inventoryHash = calculateInventoryHash(payload) - objectType = 'pubkey' - shared.inventory[inventoryHash] = ( - objectType, streamNumber, payload, embeddedTime) + with shared.printLock: + print 'broadcasting inv with hash:', inventoryHash.encode('hex') - with shared.printLock: - print 'broadcasting inv with hash:', inventoryHash.encode('hex') - - shared.broadcastToSendDataQueues(( - streamNumber, 'sendinv', inventoryHash)) - shared.UISignalQueue.put(('updateStatusBar', '')) + shared.broadcastToSendDataQueues(( + streamNumber, 'sendinv', inventoryHash)) + 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( myAddress, 'lastpubkeysendtime', str(int(time.time()))) with open(shared.appdata + 'keys.dat', 'wb') as configfile: @@ -722,8 +732,13 @@ class singleWorker(threading.Thread): subject + '\n' + 'Body:' + message payload += encodeVarint(len(messageToTransmit)) payload += messageToTransmit - 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. + 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( + 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 += fullAckPayload signature = highlevelcrypto.sign(payload, privSigningKeyHex) @@ -765,17 +780,26 @@ class singleWorker(threading.Thread): objectType = 'msg' shared.inventory[inventoryHash] = ( objectType, toStreamNumber, encryptedPayload, int(time.time())) - 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'))))) + 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( + strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8'))))) print 'Broadcasting inv for my msg(within sendmsg function):', inventoryHash.encode('hex') shared.broadcastToSendDataQueues(( streamNumber, 'sendinv', inventoryHash)) # 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() - t = (inventoryHash,ackdata,) - shared.sqlSubmitQueue.put('''UPDATE sent SET msgid=?, status='msgsent' WHERE ackdata=?''') + t = (inventoryHash,newStatus,ackdata,) + shared.sqlSubmitQueue.put('''UPDATE sent SET msgid=?, status=? WHERE ackdata=?''') shared.sqlSubmitQueue.put(t) queryreturn = shared.sqlReturnQueue.get() shared.sqlSubmitQueue.put('commit') diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index f1a428d2..e07850e4 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -186,6 +186,9 @@ class sqlThread(threading.Thread): self.cur.execute( '''update sent set status='broadcastqueued' where status='broadcastpending' ''') self.conn.commit() + + if not shared.config.has_option('bitmessagesettings', 'sockslisten'): + shared.config.set('bitmessagesettings', 'sockslisten', 'false') try: testpayload = '\x00\x00' diff --git a/src/helper_bootstrap.py b/src/helper_bootstrap.py index c3d5c1fd..e0056342 100644 --- a/src/helper_bootstrap.py +++ b/src/helper_bootstrap.py @@ -12,14 +12,10 @@ def knownNodes(): shared.knownNodes = pickle.load(pickleFile) pickleFile.close() except: - defaultKnownNodes.createDefaultKnownNodes(shared.appdata) - pickleFile = open(shared.appdata + 'knownnodes.dat', 'rb') - shared.knownNodes = pickle.load(pickleFile) - pickleFile.close() + shared.knownNodes = defaultKnownNodes.createDefaultKnownNodes(shared.appdata) 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.' raise SystemExit - def dns(): # DNS bootstrap. This could be programmed to use the SOCKS proxy to do the @@ -27,19 +23,20 @@ def dns(): # defaultKnownNodes.py. Hopefully either they are up to date or the user # has run Bitmessage recently without SOCKS turned on and received good # bootstrap nodes using that method. - if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none': - try: - for item in socket.getaddrinfo('bootstrap8080.bitmessage.org', 80): - print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method' - shared.knownNodes[1][item[4][0]] = (8080, int(time.time())) - except: - print 'bootstrap8080.bitmessage.org DNS bootstrapping failed.' - try: - for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80): - print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method' - shared.knownNodes[1][item[4][0]] = (8444, int(time.time())) - except: - print 'bootstrap8444.bitmessage.org DNS bootstrapping failed.' - else: - print 'DNS bootstrap skipped because SOCKS is used.' - + with shared.printLock: + if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none': + try: + for item in socket.getaddrinfo('bootstrap8080.bitmessage.org', 80): + print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method' + shared.knownNodes[1][item[4][0]] = (8080, int(time.time())) + except: + print 'bootstrap8080.bitmessage.org DNS bootstrapping failed.' + try: + for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80): + print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method' + shared.knownNodes[1][item[4][0]] = (8444, int(time.time())) + except: + print 'bootstrap8444.bitmessage.org DNS bootstrapping failed.' + else: + print 'DNS bootstrap skipped because SOCKS is used.' + diff --git a/src/helper_startup.py b/src/helper_startup.py index 86395be6..256dbcaa 100644 --- a/src/helper_startup.py +++ b/src/helper_startup.py @@ -68,6 +68,7 @@ def loadConfig(): 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', '0') shared.config.set( 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', '0') + shared.config.set('bitmessagesettings', 'dontconnect', 'true') ensureNamecoinOptions() if storeConfigFilesInSameDirectoryAsProgramByDefault: @@ -83,9 +84,3 @@ def loadConfig(): os.umask(0o077) with open(shared.appdata + 'keys.dat', 'wb') as configfile: shared.config.write(configfile) - - # Initialize settings that may be missing due to upgrades and could - # cause errors if missing. - if not shared.config.has_option('bitmessagesettings', 'sockslisten'): - shared.config.set('bitmessagesettings', 'sockslisten', 'false') - diff --git a/src/message_data_reader.py b/src/message_data_reader.py index 90f4bedc..c600935d 100644 --- a/src/message_data_reader.py +++ b/src/message_data_reader.py @@ -107,8 +107,8 @@ def vacuum(): #takeInboxMessagesOutOfTrash() #takeSentMessagesOutOfTrash() #markAllInboxMessagesAsUnread() -#readInbox() -readSent() +readInbox() +#readSent() #readPubkeys() #readSubscriptions() #readInventory() diff --git a/src/shared.py b/src/shared.py index 98e540d7..d24e450f 100644 --- a/src/shared.py +++ b/src/shared.py @@ -200,8 +200,8 @@ def isAddressInMyAddressBookSubscriptionsListOrWhitelist(address): def safeConfigGetBoolean(section,field): try: return config.getboolean(section,field) - except: - return False + except Exception, err: + return False def decodeWalletImportFormat(WIFstring): fullString = arithmetic.changebase(WIFstring,58,256)