From d036ca18edd278f55473fcd49b014ba9479f850e Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Mon, 22 Jul 2013 01:10:22 -0400 Subject: [PATCH] Completed chan integration in the GUI --- src/bitmessageqt/__init__.py | 215 ++++++++++++++++++++---------- src/bitmessageqt/bitmessageui.py | 6 +- src/bitmessageqt/bitmessageui.ui | 26 ++-- src/bitmessageqt/newchandialog.py | 85 ++++++------ src/bitmessageqt/newchandialog.ui | 109 ++++++++------- src/class_addressGenerator.py | 31 ++--- src/class_outgoingSynSender.py | 1 - src/class_receiveDataThread.py | 33 +++-- src/class_singleWorker.py | 96 ++++++++----- src/message_data_reader.py | 4 +- src/shared.py | 4 +- 11 files changed, 374 insertions(+), 236 deletions(-) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 46bac1f3..dc12fcf8 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -17,6 +17,7 @@ from bitmessageui import * from newaddressdialog import * from newsubscriptiondialog import * from regenerateaddresses import * +from newchandialog import * from specialaddressbehavior import * from settings import * from about import * @@ -53,6 +54,7 @@ def _translate(context, text): class MyForm(QtGui.QMainWindow): str_broadcast_subscribers = '[Broadcast subscribers]' + str_chan = '[chan]' def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) @@ -105,6 +107,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( @@ -293,6 +297,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'): @@ -594,6 +600,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.") @@ -709,6 +718,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( @@ -1032,6 +1043,57 @@ 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()), 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 + self.addEntryToAddressBook(createdAddress, self.str_chan + ' ' + 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 openKeysFile(self): if 'linux' in sys.platform: subprocess.call(["xdg-open", shared.appdata + 'keys.dat']) @@ -1379,12 +1441,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: @@ -1517,6 +1578,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() @@ -1633,6 +1704,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) @@ -1672,45 +1745,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): @@ -1747,7 +1822,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 @@ -1990,6 +2065,8 @@ 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') @@ -2023,12 +2100,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: @@ -2040,11 +2111,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: @@ -2121,6 +2187,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)) @@ -2344,7 +2411,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): @@ -2527,6 +2594,8 @@ class MyForm(QtGui.QMainWindow): currentRow, 2).setTextColor(QtGui.QColor(0, 0, 0)) 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): @@ -2695,11 +2764,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( @@ -2746,7 +2818,6 @@ class regenerateAddressesDialog(QtGui.QDialog): self.parent = parent QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) - class settingsDialog(QtGui.QDialog): def __init__(self, parent): @@ -2869,17 +2940,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)) @@ -2938,11 +3015,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) diff --git a/src/bitmessageqt/bitmessageui.py b/src/bitmessageqt/bitmessageui.py index 1d04e5f1..4efecb97 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: Sat Jul 13 20:23:44 2013 +# Created: Sun Jul 21 17:50:02 2013 # by: PyQt4 UI code generator 4.10.2 # # WARNING! All changes made in this file will be lost! @@ -453,9 +453,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) @@ -599,5 +602,6 @@ class Ui_MainWindow(object): self.actionSettings.setText(_translate("MainWindow", "Settings", None)) self.actionRegenerateDeterministicAddresses.setText(_translate("MainWindow", "Regenerate deterministic addresses", None)) self.actionDeleteAllTrashedMessages.setText(_translate("MainWindow", "Delete all trashed messages", None)) + self.actionJoinChan.setText(_translate("MainWindow", "Join / Create chan", None)) import bitmessage_icons_rc diff --git a/src/bitmessageqt/bitmessageui.ui b/src/bitmessageqt/bitmessageui.ui index 6c18cbe0..d4478fc8 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 @@ -346,7 +346,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/sent.png:/newPrefix/images/sent.png @@ -466,7 +466,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/identities.png:/newPrefix/images/identities.png @@ -566,7 +566,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/subscriptions.png:/newPrefix/images/subscriptions.png @@ -651,7 +651,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/addressbook.png:/newPrefix/images/addressbook.png @@ -733,7 +733,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/blacklist.png:/newPrefix/images/blacklist.png @@ -825,7 +825,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/networkstatus.png:/newPrefix/images/networkstatus.png @@ -844,7 +844,7 @@ p, li { white-space: pre-wrap; } - + :/newPrefix/images/redicon.png:/newPrefix/images/redicon.png @@ -1021,6 +1021,7 @@ p, li { white-space: pre-wrap; } + @@ -1094,6 +1095,11 @@ p, li { white-space: pre-wrap; } Delete all trashed messages + + + Join / Create chan + + tabWidget 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/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..5c21d72c 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 * 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_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/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 557b332d..aead1f8a 100644 --- a/src/shared.py +++ b/src/shared.py @@ -195,8 +195,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)