From da7a60c60b539f019e2fb47dac47a1a7f0acc3fb Mon Sep 17 00:00:00 2001 From: tpltnt Date: Wed, 27 Mar 2013 09:29:39 +0100 Subject: [PATCH 01/25] unicode() wrapped around strftime --- bitmessagemain.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 762ee484..e2f2abb0 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -2418,7 +2418,7 @@ class singleCleaner(QThread): sqlSubmitQueue.put('''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=? WHERE toripe=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() - #self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),toripe,'Public key requested again. ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + #self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),toripe,'Public key requested again. ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) else:# status == sentmessage if int(time.time()) - lastactiontime > (maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (msgretrynumber))): print 'It has been a long time and we haven\'t heard an acknowledgement to our msg. Sending again.' @@ -2426,7 +2426,7 @@ class singleCleaner(QThread): sqlSubmitQueue.put('''UPDATE sent SET lastactiontime=?, msgretrynumber=?, status=? WHERE ackdata=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() - #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent again because the acknowledgement was never received. ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent again because the acknowledgement was never received. ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) workerQueue.put(('sendmessage',toaddress)) self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing work necessary to again attempt to deliver a message...") sqlLock.release() @@ -2634,7 +2634,7 @@ class singleWorker(QThread): print 'sending inv (within sendBroadcast function)' broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) - self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) #Update the status of the message in the 'sent' table to have a 'broadcastsent' status sqlLock.acquire() @@ -2696,7 +2696,7 @@ class singleWorker(QThread): print 'sending inv (within sendBroadcast function)' broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) - self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) #Update the status of the message in the 'sent' table to have a 'broadcastsent' status sqlLock.acquire() @@ -2887,7 +2887,7 @@ class singleWorker(QThread): inventoryHash = calculateInventoryHash(payload) objectType = 'msg' inventory[inventoryHash] = (objectType, toStreamNumber, payload, int(time.time())) - self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent. Waiting on acknowledgement. Sent on ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent. Waiting on acknowledgement. Sent on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) print 'sending inv (within sendmsg function)' broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) @@ -2938,7 +2938,7 @@ class singleWorker(QThread): broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Broacasting the public key request. This program will auto-retry if they are offline.') - self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),ripe,'Sending public key request. Waiting for reply. Requested at ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),ripe,'Sending public key request. Waiting for reply. Requested at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) def generateFullAckMessage(self,ackdata,toStreamNumber,embeddedTime): nonce = 0 @@ -3934,7 +3934,7 @@ class MyForm(QtGui.QMainWindow): newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidgetInbox.setItem(0,2,newItem) - newItem = myTableWidgetItem(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(received)))) + newItem = myTableWidgetItem(unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(received))))) newItem.setData(Qt.UserRole,QByteArray(msgid)) newItem.setData(33,int(received)) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) @@ -3986,17 +3986,17 @@ class MyForm(QtGui.QMainWindow): if status == 'findingpubkey': newItem = myTableWidgetItem('Waiting on their public key. Will request it again soon.') elif status == 'sentmessage': - newItem = myTableWidgetItem('Message sent. Waiting on acknowledgement. Sent at ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(lastactiontime))) + newItem = myTableWidgetItem('Message sent. Waiting on acknowledgement. Sent at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(lastactiontime)))) elif status == 'doingpow': newItem = myTableWidgetItem('Need to do work to send message. Work is queued.') elif status == 'ackreceived': - newItem = myTableWidgetItem('Acknowledgement of the message received ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime)))) + newItem = myTableWidgetItem('Acknowledgement of the message received ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))))) elif status == 'broadcastpending': newItem = myTableWidgetItem('Doing the work necessary to send broadcast...') elif status == 'broadcastsent': - newItem = myTableWidgetItem('Broadcast on ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime)))) + newItem = myTableWidgetItem('Broadcast on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))))) else: - newItem = myTableWidgetItem('Unknown status. ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime)))) + newItem = myTableWidgetItem('Unknown status. ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))))) newItem.setData(Qt.UserRole,QByteArray(ackdata)) newItem.setData(33,int(lastactiontime)) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) @@ -4056,7 +4056,7 @@ class MyForm(QtGui.QMainWindow): #self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png")) self.statusbar = self.statusBar() self.statusbar.insertPermanentWidget(0,self.ui.pushButtonStatusIcon) - self.ui.labelStartupTime.setText('Since startup on ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + self.ui.labelStartupTime.setText('Since startup on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) self.numberOfMessagesProcessed = 0 self.numberOfBroadcastsProcessed = 0 self.numberOfPubkeysProcessed = 0 @@ -4397,7 +4397,7 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) self.ui.tableWidgetSent.setItem(0,2,newItem) - newItem = myTableWidgetItem('Just pressed ''send'' '+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + newItem = myTableWidgetItem('Just pressed ''send'' ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) newItem.setData(Qt.UserRole,QByteArray(ackdata)) newItem.setData(33,int(time.time())) self.ui.tableWidgetSent.setItem(0,3,newItem) @@ -4454,7 +4454,7 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) self.ui.tableWidgetSent.setItem(0,2,newItem) - #newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + #newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) newItem = myTableWidgetItem('Work is queued.') newItem.setData(Qt.UserRole,QByteArray(ackdata)) newItem.setData(33,int(time.time())) @@ -4559,8 +4559,8 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) self.ui.tableWidgetSent.setItem(0,2,newItem) - #newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) - newItem = myTableWidgetItem('Work is queued. '+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + #newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + newItem = myTableWidgetItem('Work is queued. '+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) newItem.setData(Qt.UserRole,QByteArray(ackdata)) newItem.setData(33,int(time.time())) self.ui.tableWidgetSent.setItem(0,3,newItem) @@ -4625,7 +4625,7 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) self.ui.tableWidgetInbox.setItem(0,2,newItem) - newItem = myTableWidgetItem(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) + newItem = myTableWidgetItem(unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) newItem.setData(Qt.UserRole,QByteArray(inventoryHash)) newItem.setData(33,int(time.time())) self.ui.tableWidgetInbox.setItem(0,3,newItem) From 3842b2be38dc103b7e0efdb2028c8f0da9f72ba0 Mon Sep 17 00:00:00 2001 From: tpltnt Date: Wed, 27 Mar 2013 09:31:03 +0100 Subject: [PATCH 02/25] unicode() wrapped around strftime --- defaultKnownNodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaultKnownNodes.py b/defaultKnownNodes.py index 250877da..4362368a 100644 --- a/defaultKnownNodes.py +++ b/defaultKnownNodes.py @@ -48,7 +48,7 @@ def readDefaultKnownNodes(appdata): for stream, storedValue in knownNodes.items(): for host,value in storedValue.items(): port, storedtime = storedValue[host] - print host, '\t', port, '\t', strftime('%a, %d %b %Y %I:%M %p',localtime(storedtime)) + print host, '\t', port, '\t', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(storedtime))) if __name__ == "__main__": From c6d98da9bace8c52446f70e5fdd3d9f46704b25a Mon Sep 17 00:00:00 2001 From: tpltnt Date: Wed, 27 Mar 2013 09:34:13 +0100 Subject: [PATCH 03/25] fixes issue #75 --- messages.dat reader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/messages.dat reader.py b/messages.dat reader.py index 7958ecdb..41ce797a 100644 --- a/messages.dat reader.py +++ b/messages.dat reader.py @@ -59,7 +59,7 @@ def readPubkeys(): output = cur.fetchall() for row in output: hash, havecorrectnonce, transmitdata, time, usedpersonally = row - print 'Hash:', hash.encode('hex'), '\tHave correct nonce:', havecorrectnonce, '\tTime first broadcast:', strftime('%a, %d %b %Y %I:%M %p',localtime(time)), '\tUsed by me personally:', usedpersonally, '\tFull pubkey message:', transmitdata.encode('hex') + print 'Hash:', hash.encode('hex'), '\tHave correct nonce:', havecorrectnonce, '\tTime first broadcast:', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(time))), '\tUsed by me personally:', usedpersonally, '\tFull pubkey message:', transmitdata.encode('hex') def readInventory(): print 'Printing everything in inventory table:' @@ -69,7 +69,7 @@ def readInventory(): output = cur.fetchall() for row in output: hash, objecttype, streamnumber, payload, receivedtime = row - print 'Hash:', hash.encode('hex'), objecttype, streamnumber, '\t', payload.encode('hex'), '\t', strftime('%a, %d %b %Y %I:%M %p',localtime(receivedtime)) + print 'Hash:', hash.encode('hex'), objecttype, streamnumber, '\t', payload.encode('hex'), '\t', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(receivedtime))) def takeInboxMessagesOutOfTrash(): From ec4160c5a985d96a29e885d3a53db95b459075b3 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Mon, 1 Apr 2013 12:38:15 -0400 Subject: [PATCH 04/25] Fix bug introduced in last commit by tpltnt: exception when updating ackdata --- bitmessagemain.py | 57 +++++++++++++++++++++--------------------- messages.dat reader.py | 4 +-- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 3b87df29..92aef20f 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -1252,34 +1252,32 @@ class receiveDataThread(QThread): #We have received a getdata request from our peer def recgetdata(self, data): - value, lengthOfVarint = decodeVarint(data[:10]) - #print 'Number of items in getdata request:', value - try: - for i in xrange(value): - hash = data[lengthOfVarint+(i*32):32+lengthOfVarint+(i*32)] - printLock.acquire() - print 'received getdata request for item:', hash.encode('hex') - printLock.release() - #print 'inventory is', inventory - if hash in inventory: - objectType, streamNumber, payload, receivedTime = inventory[hash] + numberOfRequestedInventoryItems, lengthOfVarint = decodeVarint(data[:10]) + if len(data) < lengthOfVarint + (32 * numberOfRequestedInventoryItems): + print 'getdata message does not contain enough data. Ignoring.' + return + for i in xrange(numberOfRequestedInventoryItems): + hash = data[lengthOfVarint+(i*32):32+lengthOfVarint+(i*32)] + printLock.acquire() + print 'received getdata request for item:', hash.encode('hex') + printLock.release() + #print 'inventory is', inventory + if hash in inventory: + objectType, streamNumber, payload, receivedTime = inventory[hash] + self.sendData(objectType,payload) + else: + t = (hash,) + sqlLock.acquire() + sqlSubmitQueue.put('''select objecttype, payload from inventory where hash=?''') + sqlSubmitQueue.put(t) + queryreturn = sqlReturnQueue.get() + sqlLock.release() + if queryreturn <> []: + for row in queryreturn: + objectType, payload = row self.sendData(objectType,payload) else: - t = (hash,) - sqlLock.acquire() - sqlSubmitQueue.put('''select objecttype, payload from inventory where hash=?''') - sqlSubmitQueue.put(t) - queryreturn = sqlReturnQueue.get() - sqlLock.release() - if queryreturn <> []: - for row in queryreturn: - objectType, payload = row - self.sendData(objectType,payload) - else: - print 'Someone asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. That shouldn\'t have happened.' - - except: - pass #someone is probably trying to cause a program error by, for example, making a request for 10 items but only including the hashes for 5. + print 'Someone asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. That shouldn\'t have happened.' #Our peer has requested (in a getdata message) that we send an object. def sendData(self,objectType,payload): @@ -1343,7 +1341,7 @@ class receiveDataThread(QThread): if numberOfAddressesIncluded > 1000 or numberOfAddressesIncluded == 0: return - if self.payloadLength < lengthOfNumberOfAddresses + (34 * numberOfAddressesIncluded): + if len(data) < lengthOfNumberOfAddresses + (34 * numberOfAddressesIncluded): print 'addr message does not contain enough data. Ignoring.' return @@ -2298,7 +2296,7 @@ class singleWorker(QThread): print 'sending inv (within sendBroadcast function)' broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) - self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) #Update the status of the message in the 'sent' table to have a 'broadcastsent' status sqlLock.acquire() @@ -3903,7 +3901,8 @@ class MyForm(QtGui.QMainWindow): tableAckdata = self.ui.tableWidgetSent.item(i,3).data(Qt.UserRole).toPyObject() status,addressVersionNumber,streamNumber,ripe = decodeAddress(toAddress) if ackdata == tableAckdata: - self.ui.tableWidgetSent.item(i,3).setText(unicode(textToDisplay,'utf-8')) + #self.ui.tableWidgetSent.item(i,3).setText(unicode(textToDisplay,'utf-8')) + self.ui.tableWidgetSent.item(i,3).setText(textToDisplay) def rerenderInboxFromLabels(self): for i in range(self.ui.tableWidgetInbox.rowCount()): diff --git a/messages.dat reader.py b/messages.dat reader.py index 41ce797a..cb6ca7d0 100644 --- a/messages.dat reader.py +++ b/messages.dat reader.py @@ -90,10 +90,10 @@ def takeSentMessagesOutOfTrash(): #takeInboxMessagesOutOfTrash() #takeSentMessagesOutOfTrash() -readInbox() +#readInbox() #readSent() #readPubkeys() #readSubscriptions() -#readInventory() +readInventory() From 088d26c7a00bfdaaeb213541bfaaef3309f16162 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Mon, 1 Apr 2013 13:56:15 -0400 Subject: [PATCH 05/25] fix github issue 84 (receive msg while sorted display issue) --- bitmessagemain.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 92aef20f..e592626c 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -401,7 +401,7 @@ class receiveDataThread(QThread): POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(data[:8]+ hashlib.sha512(data[8:]).digest()).digest()).digest()[0:8]) #print 'POW:', POW #Notice that I have divided the averageProofOfWorkNonceTrialsPerByte by two. This makes the POW requirement easier. This gives us wiggle-room: if we decide that we want to make the POW easier, the change won't obsolete old clients because they already expect a lower POW. If we decide that the current work done by clients feels approperate then we can remove this division by 2 and make the requirement match what is actually done by a sending node. If we want to raise the POW requirement then old nodes will HAVE to upgrade no matter what. - return POW < 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * (averageProofOfWorkNonceTrialsPerByte/2)) + return POW <= 2**64 / ((len(data)+payloadLengthExtraBytes) * (averageProofOfWorkNonceTrialsPerByte/2)) def sendpong(self): print 'Sending pong' @@ -4217,6 +4217,7 @@ class MyForm(QtGui.QMainWindow): if fromLabel == '': fromLabel = fromAddress + self.ui.tableWidgetSent.setSortingEnabled(False) self.ui.tableWidgetSent.insertRow(0) if toLabel == '': newItem = QtGui.QTableWidgetItem(unicode(toAddress,'utf-8')) @@ -4239,6 +4240,7 @@ class MyForm(QtGui.QMainWindow): newItem.setData(33,int(time.time())) self.ui.tableWidgetSent.setItem(0,3,newItem) self.ui.textEditSentMessage.setPlainText(self.ui.tableWidgetSent.item(0,2).data(Qt.UserRole).toPyObject()) + self.ui.tableWidgetSent.setSortingEnabled(True) def displayNewInboxMessage(self,inventoryHash,toAddress,fromAddress,subject,message): '''print 'test signals displayNewInboxMessage' @@ -4278,7 +4280,7 @@ class MyForm(QtGui.QMainWindow): if toLabel == '': toLabel = toAddress - #msgid, toaddress, fromaddress, subject, received, message = row + self.ui.tableWidgetInbox.setSortingEnabled(False) newItem = QtGui.QTableWidgetItem(unicode(toLabel,'utf-8')) newItem.setData(Qt.UserRole,str(toAddress)) if safeConfigGetBoolean(str(toAddress),'mailinglist'): @@ -4303,15 +4305,14 @@ class MyForm(QtGui.QMainWindow): newItem.setData(Qt.UserRole,QByteArray(inventoryHash)) newItem.setData(33,int(time.time())) self.ui.tableWidgetInbox.setItem(0,3,newItem) - self.ui.tableWidgetInbox.setCurrentCell(0,0) - + #If we have received this message from either a broadcast address or from someone in our address book, display as HTML if decodeAddress(fromAddress)[3] in broadcastSendersForWhichImWatching or isAddressInMyAddressBook(fromAddress): self.ui.textEditInboxMessage.setText(self.ui.tableWidgetInbox.item(0,2).data(Qt.UserRole).toPyObject()) else: self.ui.textEditInboxMessage.setPlainText(self.ui.tableWidgetInbox.item(0,2).data(Qt.UserRole).toPyObject()) - + self.ui.tableWidgetInbox.setSortingEnabled(True) def click_pushButtonAddAddressBook(self): self.NewSubscriptionDialogInstance = NewSubscriptionDialog(self) @@ -4325,12 +4326,14 @@ class MyForm(QtGui.QMainWindow): queryreturn = sqlReturnQueue.get() 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()))) sqlLock.acquire() sqlSubmitQueue.put('''INSERT INTO addressbook VALUES (?,?)''') @@ -4356,12 +4359,14 @@ class MyForm(QtGui.QMainWindow): queryreturn = sqlReturnQueue.get() sqlLock.release() if queryreturn == []: + self.ui.tableWidgetSubscriptions.setSortingEnabled(False) self.ui.tableWidgetSubscriptions.insertRow(0) newItem = QtGui.QTableWidgetItem(unicode(self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8(),'utf-8')) self.ui.tableWidgetSubscriptions.setItem(0,0,newItem) newItem = QtGui.QTableWidgetItem(addBMIfNotPresent(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidgetSubscriptions.setItem(0,1,newItem) + self.ui.tableWidgetSubscriptions.setSortingEnabled(True) t = (str(self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8()),addBMIfNotPresent(str(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text())),True) sqlLock.acquire() sqlSubmitQueue.put('''INSERT INTO subscriptions VALUES (?,?,?)''') @@ -4520,12 +4525,14 @@ class MyForm(QtGui.QMainWindow): queryreturn = sqlReturnQueue.get() sqlLock.release() if queryreturn == []: + self.ui.tableWidgetBlacklist.setSortingEnabled(False) self.ui.tableWidgetBlacklist.insertRow(0) newItem = QtGui.QTableWidgetItem(unicode(self.NewBlacklistDialogInstance.ui.newsubscriptionlabel.text().toUtf8(),'utf-8')) self.ui.tableWidgetBlacklist.setItem(0,0,newItem) newItem = QtGui.QTableWidgetItem(addBMIfNotPresent(self.NewBlacklistDialogInstance.ui.lineEditSubscriptionAddress.text())) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidgetBlacklist.setItem(0,1,newItem) + self.ui.tableWidgetBlacklist.setSortingEnabled(True) t = (str(self.NewBlacklistDialogInstance.ui.newsubscriptionlabel.text().toUtf8()),addBMIfNotPresent(str(self.NewBlacklistDialogInstance.ui.lineEditSubscriptionAddress.text())),True) sqlLock.acquire() if config.get('bitmessagesettings', 'blackwhitelist') == 'black': @@ -4937,6 +4944,7 @@ class MyForm(QtGui.QMainWindow): self.rerenderSentToLabels() def writeNewAddressToTable(self,label,address,streamNumber): + self.ui.tableWidgetYourIdentities.setSortingEnabled(False) self.ui.tableWidgetYourIdentities.insertRow(0) self.ui.tableWidgetYourIdentities.setItem(0, 0, QtGui.QTableWidgetItem(unicode(label,'utf-8'))) newItem = QtGui.QTableWidgetItem(address) @@ -4945,6 +4953,7 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(streamNumber) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidgetYourIdentities.setItem(0, 2, newItem) + self.ui.tableWidgetYourIdentities.setSortingEnabled(True) self.rerenderComboBoxSendFrom() def updateStatusBar(self,data): From b535eac2d9676857a0c121b437f3957ea5786ae7 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Mon, 1 Apr 2013 15:11:46 -0400 Subject: [PATCH 06/25] try to resolve issue 94 --- bitmessagemain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index e592626c..9e79a7b5 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -3596,7 +3596,7 @@ class MyForm(QtGui.QMainWindow): newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidgetInbox.setItem(0,2,newItem) - newItem = myTableWidgetItem(unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(received))))) + newItem = myTableWidgetItem(unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(received)))),'utf-8') newItem.setData(Qt.UserRole,QByteArray(msgid)) newItem.setData(33,int(received)) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) From fa71fb132984d0ffb053f36a4d034e9109a5104f Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Mon, 1 Apr 2013 15:13:39 -0400 Subject: [PATCH 07/25] try to resolve issue 94 --- bitmessagemain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 9e79a7b5..bb5233c5 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -3596,7 +3596,7 @@ class MyForm(QtGui.QMainWindow): newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidgetInbox.setItem(0,2,newItem) - newItem = myTableWidgetItem(unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(received)))),'utf-8') + newItem = myTableWidgetItem(unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(received))),'utf-8')) newItem.setData(Qt.UserRole,QByteArray(msgid)) newItem.setData(33,int(received)) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) From 6fcca86fd54425f1b30cbe618f46cb52dda1662d Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Mon, 1 Apr 2013 15:36:22 -0400 Subject: [PATCH 08/25] Probably finalize Github issue 94 fix --- bitmessagemain.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index bb5233c5..75b80a0a 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -2058,7 +2058,6 @@ class singleCleaner(QThread): sqlSubmitQueue.put('''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=? WHERE toripe=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() - #self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),toripe,'Public key requested again. ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) else:# status == sentmessage if int(time.time()) - lastactiontime > (maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (msgretrynumber))): print 'It has been a long time and we haven\'t heard an acknowledgement to our msg. Sending again.' @@ -2066,7 +2065,6 @@ class singleCleaner(QThread): sqlSubmitQueue.put('''UPDATE sent SET lastactiontime=?, msgretrynumber=?, status=? WHERE ackdata=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() - #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent again because the acknowledgement was never received. ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) workerQueue.put(('sendmessage',toaddress)) self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing work necessary to again attempt to deliver a message...") sqlLock.release() @@ -2296,7 +2294,7 @@ class singleWorker(QThread): print 'sending inv (within sendBroadcast function)' broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) - self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent on '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) #Update the status of the message in the 'sent' table to have a 'broadcastsent' status sqlLock.acquire() @@ -2358,7 +2356,7 @@ class singleWorker(QThread): print 'sending inv (within sendBroadcast function)' broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) - self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) #Update the status of the message in the 'sent' table to have a 'broadcastsent' status sqlLock.acquire() @@ -2549,7 +2547,7 @@ class singleWorker(QThread): inventoryHash = calculateInventoryHash(payload) objectType = 'msg' inventory[inventoryHash] = (objectType, toStreamNumber, payload, int(time.time())) - self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent. Waiting on acknowledgement. Sent on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent. Waiting on acknowledgement. Sent on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) print 'sending inv (within sendmsg function)' broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) @@ -2600,7 +2598,7 @@ class singleWorker(QThread): broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Broacasting the public key request. This program will auto-retry if they are offline.') - self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),ripe,'Sending public key request. Waiting for reply. Requested at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + self.emit(SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"),ripe,'Sending public key request. Waiting for reply. Requested at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) def generateFullAckMessage(self,ackdata,toStreamNumber,embeddedTime): nonce = 0 @@ -3649,17 +3647,17 @@ class MyForm(QtGui.QMainWindow): if status == 'findingpubkey': newItem = myTableWidgetItem('Waiting on their public key. Will request it again soon.') elif status == 'sentmessage': - newItem = myTableWidgetItem('Message sent. Waiting on acknowledgement. Sent at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(lastactiontime)))) + newItem = myTableWidgetItem('Message sent. Waiting on acknowledgement. Sent at ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(lastactiontime)),'utf-8')) elif status == 'doingpow': newItem = myTableWidgetItem('Need to do work to send message. Work is queued.') elif status == 'ackreceived': - newItem = myTableWidgetItem('Acknowledgement of the message received ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))))) + newItem = myTableWidgetItem('Acknowledgement of the message received ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))),'utf-8')) elif status == 'broadcastpending': newItem = myTableWidgetItem('Doing the work necessary to send broadcast...') elif status == 'broadcastsent': - newItem = myTableWidgetItem('Broadcast on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))))) + newItem = myTableWidgetItem('Broadcast on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))),'utf-8')) else: - newItem = myTableWidgetItem('Unknown status. ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))))) + newItem = myTableWidgetItem('Unknown status. ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(lastactiontime))),'utf-8')) newItem.setData(Qt.UserRole,QByteArray(ackdata)) newItem.setData(33,int(lastactiontime)) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) @@ -3719,7 +3717,7 @@ class MyForm(QtGui.QMainWindow): #self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png")) self.statusbar = self.statusBar() self.statusbar.insertPermanentWidget(0,self.ui.pushButtonStatusIcon) - self.ui.labelStartupTime.setText('Since startup on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + self.ui.labelStartupTime.setText('Since startup on ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) self.numberOfMessagesProcessed = 0 self.numberOfBroadcastsProcessed = 0 self.numberOfPubkeysProcessed = 0 @@ -4071,7 +4069,7 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) self.ui.tableWidgetSent.setItem(0,2,newItem) - newItem = myTableWidgetItem('Just pressed ''send'' ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + newItem = myTableWidgetItem('Just pressed ''send'' ' + unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) newItem.setData(Qt.UserRole,QByteArray(ackdata)) newItem.setData(33,int(time.time())) self.ui.tableWidgetSent.setItem(0,3,newItem) @@ -4128,7 +4126,7 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) self.ui.tableWidgetSent.setItem(0,2,newItem) - #newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + #newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) newItem = myTableWidgetItem('Work is queued.') newItem.setData(Qt.UserRole,QByteArray(ackdata)) newItem.setData(33,int(time.time())) @@ -4234,8 +4232,8 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) self.ui.tableWidgetSent.setItem(0,2,newItem) - #newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) - newItem = myTableWidgetItem('Work is queued. '+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + #newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) + newItem = myTableWidgetItem('Work is queued. '+ unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) newItem.setData(Qt.UserRole,QByteArray(ackdata)) newItem.setData(33,int(time.time())) self.ui.tableWidgetSent.setItem(0,3,newItem) @@ -4301,7 +4299,7 @@ class MyForm(QtGui.QMainWindow): newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) self.ui.tableWidgetInbox.setItem(0,2,newItem) - newItem = myTableWidgetItem(unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))) + newItem = myTableWidgetItem(unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) newItem.setData(Qt.UserRole,QByteArray(inventoryHash)) newItem.setData(33,int(time.time())) self.ui.tableWidgetInbox.setItem(0,3,newItem) From fc30ac0b84e41772149c46ea626cdbea2576c358 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Mon, 1 Apr 2013 16:43:51 -0400 Subject: [PATCH 09/25] Pring out error no matter what the error is --- bitmessagemain.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 75b80a0a..2b30ea56 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -1245,10 +1245,10 @@ class receiveDataThread(QThread): try: self.sock.send(headerData + payload) except Exception, err: - if not 'Bad file descriptor' in err: - printLock.acquire() - sys.stderr.write('sock.send error: %s\n' % err) - printLock.release() + #if not 'Bad file descriptor' in err: + printLock.acquire() + sys.stderr.write('sock.send error: %s\n' % err) + printLock.release() #We have received a getdata request from our peer def recgetdata(self, data): From 234aa4dfec16e002a0418ebd6bea70a8494076eb Mon Sep 17 00:00:00 2001 From: delicatebits Date: Mon, 1 Apr 2013 19:29:30 -0400 Subject: [PATCH 10/25] Add context menu action to view message as richtext --- bitmessagemain.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bitmessagemain.py b/bitmessagemain.py index 2b30ea56..60dd894f 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -3426,9 +3426,12 @@ class MyForm(QtGui.QMainWindow): self.actionReply = self.ui.inboxContextMenuToolbar.addAction("Reply", self.on_action_InboxReply) self.actionAddSenderToAddressBook = self.ui.inboxContextMenuToolbar.addAction("Add sender to your Address Book", self.on_action_InboxAddSenderToAddressBook) self.actionTrashInboxMessage = self.ui.inboxContextMenuToolbar.addAction("Move to Trash", self.on_action_InboxTrash) + self.actionForceHtml = self.ui.inboxContextMenuToolbar.addAction("View as Richtext", self.on_action_InboxMsgForceHtml) self.ui.tableWidgetInbox.setContextMenuPolicy( QtCore.Qt.CustomContextMenu ) self.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'), self.on_context_menuInbox) self.popMenuInbox = QtGui.QMenu( self ) + self.popMenuInbox.addAction( self.actionForceHtml ) + self.popMenuInbox.addSeparator() self.popMenuInbox.addAction( self.actionReply ) self.popMenuInbox.addAction( self.actionAddSenderToAddressBook ) self.popMenuInbox.addSeparator() @@ -4637,6 +4640,16 @@ class MyForm(QtGui.QMainWindow): event.accept() raise SystemExit + def on_action_InboxMsgForceHtml(self): + lines = str(self.ui.textEditInboxMessage.toPlainText()).split('\n') + from_prefix = 'Message ostensibly from ' + for i in xrange(len(lines)): + if lines[i].find(from_prefix) != -1: + lines[i] = '

%s%s

' % (from_prefix,lines[i][24:-1]) + elif lines[i] == '------------------------------------------------------': + lines[i] = '
' + content = '\n'.join(lines) + self.ui.textEditInboxMessage.setHtml(QtCore.QString(content)) def on_action_InboxReply(self): currentInboxRow = self.ui.tableWidgetInbox.currentRow() From d94397443963a3dcad267cbb25dd2128c352bc6b Mon Sep 17 00:00:00 2001 From: delicatebits Date: Mon, 1 Apr 2013 20:52:22 -0400 Subject: [PATCH 11/25] Updated to catch exception --- bitmessagemain.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 60dd894f..f4cf3d57 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -4641,7 +4641,13 @@ class MyForm(QtGui.QMainWindow): raise SystemExit def on_action_InboxMsgForceHtml(self): - lines = str(self.ui.textEditInboxMessage.toPlainText()).split('\n') + # Updated to work with all characters. Previously, non-english characters caused errors. + try: + lines = str(self.ui.textEditInboxMessage.toPlainText()).split('\n') + except UnicodeEncodeError: + currentInboxRow = self.ui.tableWidgetInbox.currentRow() + self.ui.textEditInboxMessage.setHtml(self.ui.tableWidgetInbox.item(currentInboxRow,2).data(Qt.UserRole).toPyObject()) + return from_prefix = 'Message ostensibly from ' for i in xrange(len(lines)): if lines[i].find(from_prefix) != -1: @@ -4649,6 +4655,7 @@ class MyForm(QtGui.QMainWindow): elif lines[i] == '------------------------------------------------------': lines[i] = '
' content = '\n'.join(lines) + content = content.replace('\n\n', '

') self.ui.textEditInboxMessage.setHtml(QtCore.QString(content)) def on_action_InboxReply(self): From 7f9fda22846887d20cc4b7230971be9dd1e5d25e Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 2 Apr 2013 11:39:19 -0400 Subject: [PATCH 12/25] 12px font is good --- bitmessagemain.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index f4cf3d57..442acaec 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -3603,6 +3603,7 @@ class MyForm(QtGui.QMainWindow): newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidgetInbox.setItem(0,3,newItem) #self.ui.textEditInboxMessage.setPlainText(self.ui.tableWidgetInbox.item(0,2).data(Qt.UserRole).toPyObject()) + self.ui.tableWidgetInbox.sortItems(3,Qt.DescendingOrder) self.ui.tableWidgetInbox.keyPressEvent = self.tableWidgetInboxKeyPressEvent #Load Sent items from database @@ -3665,6 +3666,7 @@ class MyForm(QtGui.QMainWindow): newItem.setData(33,int(lastactiontime)) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidgetSent.setItem(0,3,newItem) + self.ui.tableWidgetSent.sortItems(3,Qt.DescendingOrder) #Initialize the address book sqlSubmitQueue.put('SELECT * FROM addressbook') @@ -4651,7 +4653,7 @@ class MyForm(QtGui.QMainWindow): from_prefix = 'Message ostensibly from ' for i in xrange(len(lines)): if lines[i].find(from_prefix) != -1: - lines[i] = '

%s%s

' % (from_prefix,lines[i][24:-1]) + lines[i] = '

%s%s

' % (from_prefix,lines[i][24:-1]) elif lines[i] == '------------------------------------------------------': lines[i] = '
' content = '\n'.join(lines) From 5f479ab05b62336a12c21f5282c8e1408e224aba Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 2 Apr 2013 12:23:34 -0400 Subject: [PATCH 13/25] use len(data) instead of self.payloadLength --- bitmessagemain.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 442acaec..033eb598 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -509,7 +509,7 @@ class receiveDataThread(QThread): if embeddedTime < (int(time.time())-maximumAgeOfAnObjectThatIAmWillingToAccept): print 'The embedded time in this broadcast message is too old. Ignoring message.' return - if self.payloadLength < 66: #todo: When version 1 addresses are completely abandoned, this should be changed to 180 + if len(data) < 180: print 'The payload length of this broadcast packet is unreasonably low. Someone is probably trying funny business. Ignoring message.' return inventoryLock.acquire() @@ -533,11 +533,11 @@ class receiveDataThread(QThread): self.processbroadcast(data)#When this function returns, we will have either successfully processed this broadcast because we are interested in it, ignored it because we aren't interested in it, or found problem with the broadcast that warranted ignoring it. # Let us now set lengthOfTimeWeShouldUseToProcessThisMessage. If we haven't used the specified amount of time, we shall sleep. These values are mostly the same values used for msg messages although broadcast messages are processed faster. - if self.payloadLength > 100000000: #Size is greater than 100 megabytes + if len(data) > 100000000: #Size is greater than 100 megabytes lengthOfTimeWeShouldUseToProcessThisMessage = 100 #seconds. - elif self.payloadLength > 10000000: #Between 100 and 10 megabytes + elif len(data) > 10000000: #Between 100 and 10 megabytes lengthOfTimeWeShouldUseToProcessThisMessage = 20 #seconds. - elif self.payloadLength > 1000000: #Between 10 and 1 megabyte + elif len(data) > 1000000: #Between 10 and 1 megabyte lengthOfTimeWeShouldUseToProcessThisMessage = 3 #seconds. else: #Less than 1 megabyte lengthOfTimeWeShouldUseToProcessThisMessage = .1 #seconds. @@ -714,11 +714,11 @@ class receiveDataThread(QThread): self.processmsg(readPosition,data) #When this function returns, we will have either successfully processed the message bound for us, ignored it because it isn't bound for us, or found problem with the message that warranted ignoring it. # Let us now set lengthOfTimeWeShouldUseToProcessThisMessage. If we haven't used the specified amount of time, we shall sleep. These values are based on test timings and you may change them at-will. - if self.payloadLength > 100000000: #Size is greater than 100 megabytes + if len(data) > 100000000: #Size is greater than 100 megabytes lengthOfTimeWeShouldUseToProcessThisMessage = 100 #seconds. Actual length of time it took my computer to decrypt and verify the signature of a 100 MB message: 3.7 seconds. - elif self.payloadLength > 10000000: #Between 100 and 10 megabytes + elif len(data) > 10000000: #Between 100 and 10 megabytes lengthOfTimeWeShouldUseToProcessThisMessage = 20 #seconds. Actual length of time it took my computer to decrypt and verify the signature of a 10 MB message: 0.53 seconds. Actual length of time it takes in practice when processing a real message: 1.44 seconds. - elif self.payloadLength > 1000000: #Between 10 and 1 megabyte + elif len(data) > 1000000: #Between 10 and 1 megabyte lengthOfTimeWeShouldUseToProcessThisMessage = 3 #seconds. Actual length of time it took my computer to decrypt and verify the signature of a 1 MB message: 0.18 seconds. Actual length of time it takes in practice when processing a real message: 0.30 seconds. else: #Less than 1 megabyte lengthOfTimeWeShouldUseToProcessThisMessage = .6 #seconds. Actual length of time it took my computer to decrypt and verify the signature of a 100 KB message: 0.15 seconds. Actual length of time it takes in practice when processing a real message: 0.25 seconds. @@ -1072,8 +1072,8 @@ class receiveDataThread(QThread): printLock.release() return if addressVersion == 2: - if self.payloadLength < 146: #sanity check. This is the minimum possible length. - print 'payloadLength less than 146. Sanity check failed.' + if len(data) < 146: #sanity check. This is the minimum possible length. + print '(within processpubkey) payloadLength less than 146. Sanity check failed.' return bitfieldBehaviors = data[readPosition:readPosition+4] readPosition += 4 @@ -1521,7 +1521,7 @@ class receiveDataThread(QThread): #We have received a version message def recversion(self,data): - if self.payloadLength < 83: + if len(data) < 83: #This version message is unreasonably short. Forget it. return elif not self.verackSent: From df2b996b88298f55ad4f3c05028d571a5d02a4c1 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 2 Apr 2013 12:31:14 -0400 Subject: [PATCH 14/25] Msg designation reserved for person-to-person messages --- bitmessagemain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 033eb598..aa7987e2 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -3426,7 +3426,7 @@ class MyForm(QtGui.QMainWindow): self.actionReply = self.ui.inboxContextMenuToolbar.addAction("Reply", self.on_action_InboxReply) self.actionAddSenderToAddressBook = self.ui.inboxContextMenuToolbar.addAction("Add sender to your Address Book", self.on_action_InboxAddSenderToAddressBook) self.actionTrashInboxMessage = self.ui.inboxContextMenuToolbar.addAction("Move to Trash", self.on_action_InboxTrash) - self.actionForceHtml = self.ui.inboxContextMenuToolbar.addAction("View as Richtext", self.on_action_InboxMsgForceHtml) + self.actionForceHtml = self.ui.inboxContextMenuToolbar.addAction("View as Richtext", self.on_action_InboxMessageForceHtml) self.ui.tableWidgetInbox.setContextMenuPolicy( QtCore.Qt.CustomContextMenu ) self.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'), self.on_context_menuInbox) self.popMenuInbox = QtGui.QMenu( self ) @@ -4642,7 +4642,7 @@ class MyForm(QtGui.QMainWindow): event.accept() raise SystemExit - def on_action_InboxMsgForceHtml(self): + def on_action_InboxMessageForceHtml(self): # Updated to work with all characters. Previously, non-english characters caused errors. try: lines = str(self.ui.textEditInboxMessage.toPlainText()).split('\n') From 89b23c0cd5559a318c0e4908e186e736dfdcbb44 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 2 Apr 2013 12:42:27 -0400 Subject: [PATCH 15/25] added embeddedTime fuzzing to pubkey and getpubkey message assembly --- bitmessagemain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index aa7987e2..bf4c8bd6 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -2182,7 +2182,7 @@ class singleWorker(QThread): myAddress = addressInKeysFile break - embeddedTime = int(time.time())+random.randrange(-300, 300) #the current time plus or minus five minutes + embeddedTime = int(time.time()+random.randrange(-300, 300)) #the current time plus or minus five minutes payload = pack('>I',(embeddedTime)) payload += encodeVarint(addressVersionNumber) #Address version number payload += encodeVarint(streamNumber) @@ -2567,7 +2567,7 @@ class singleWorker(QThread): def requestPubKey(self,addressVersionNumber,streamNumber,ripe): - payload = pack('>I',int(time.time())) + payload = pack('>I',(int(time.time())+random.randrange(-300, 300)))#the current time plus or minus five minutes. payload += encodeVarint(addressVersionNumber) payload += encodeVarint(streamNumber) payload += ripe From ba4858de254b1fa326ad61bffa38be98de0ceddf Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 2 Apr 2013 13:01:41 -0400 Subject: [PATCH 16/25] no unicode encoding needed when setting text; it is already unicode --- bitmessagemain.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index bf4c8bd6..b7d434fb 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -2471,7 +2471,11 @@ class singleWorker(QThread): sqlSubmitQueue.put((toRipe,)) queryreturn = sqlReturnQueue.get() sqlLock.release() - + if queryreturn == []: + printLock.acquire() + sys.stderr.write('(within sendMsg) The needed pubkey was not found. This should never happen. Aborting send.\n') + printLock.release() + return for row in queryreturn: pubkeyPayload, = row @@ -3896,7 +3900,8 @@ class MyForm(QtGui.QMainWindow): toAddress = str(self.ui.tableWidgetSent.item(i,0).data(Qt.UserRole).toPyObject()) status,addressVersionNumber,streamNumber,ripe = decodeAddress(toAddress) if ripe == toRipe: - self.ui.tableWidgetSent.item(i,3).setText(unicode(textToDisplay,'utf-8')) + #self.ui.tableWidgetSent.item(i,3).setText(unicode(textToDisplay,'utf-8')) + self.ui.tableWidgetSent.item(i,3).setText(textToDisplay,'utf-8') def updateSentItemStatusByAckdata(self,ackdata,textToDisplay): for i in range(self.ui.tableWidgetSent.rowCount()): From ccae1fcb8aeaed9cf39978a56324dc2b8cf57a08 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 2 Apr 2013 13:11:15 -0400 Subject: [PATCH 17/25] no unicode encoding needed when setting text; it is already unicode --- bitmessagemain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index b7d434fb..4d97bf0d 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -3901,7 +3901,7 @@ class MyForm(QtGui.QMainWindow): status,addressVersionNumber,streamNumber,ripe = decodeAddress(toAddress) if ripe == toRipe: #self.ui.tableWidgetSent.item(i,3).setText(unicode(textToDisplay,'utf-8')) - self.ui.tableWidgetSent.item(i,3).setText(textToDisplay,'utf-8') + self.ui.tableWidgetSent.item(i,3).setText(textToDisplay) def updateSentItemStatusByAckdata(self,ackdata,textToDisplay): for i in range(self.ui.tableWidgetSent.rowCount()): From 2ea7b52d185d2910809283745d571a42061937dd Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 2 Apr 2013 16:36:48 -0400 Subject: [PATCH 18/25] move isAckDataValid to its own function --- bitmessagemain.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 4d97bf0d..8b1d9968 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -959,20 +959,7 @@ class receiveDataThread(QThread): self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,'[Broadcast subscribers]',fromAddress,subject,message,ackdata) workerQueue.put(('sendbroadcast',(fromAddress,subject,message))) - #Now let's consider sending the acknowledgement. We'll need to make sure that our client will properly process the ackData; if the packet is malformed, we could clear out self.data and an attacker could use that behavior to determine that we were capable of decoding this message. - ackDataValidThusFar = True - if len(ackData) < 24: - print 'The length of ackData is unreasonably short. Not sending ackData.' - ackDataValidThusFar = False - elif ackData[0:4] != '\xe9\xbe\xb4\xd9': - print 'Ackdata magic bytes were wrong. Not sending ackData.' - ackDataValidThusFar = False - if ackDataValidThusFar: - ackDataPayloadLength, = unpack('>L',ackData[16:20]) - if len(ackData)-24 != ackDataPayloadLength: - print 'ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.' - ackDataValidThusFar = False - if ackDataValidThusFar: + if self.isAckDataValid(ackData): print 'ackData is valid. Will process it.' self.ackDataThatWeHaveYetToSend.append(ackData) #When we have processed all data, the processData function will pop the ackData out and process it as if it is a message received from our peer. #Display timing data @@ -986,6 +973,21 @@ class receiveDataThread(QThread): print 'Average time for all message decryption successes since startup:', sum / len(successfullyDecryptMessageTimings) printLock.release() + def isAckDataValid(self,ackData): + if len(ackData) < 24: + print 'The length of ackData is unreasonably short. Not sending ackData.' + return False + if ackData[0:4] != '\xe9\xbe\xb4\xd9': + print 'Ackdata magic bytes were wrong. Not sending ackData.' + return False + ackDataPayloadLength, = unpack('>L',ackData[16:24]) + if len(ackData)-24 != ackDataPayloadLength: + print 'ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.' + return False + if ackData[4:16] != 'getpubkey\x00\x00\x00' and ackData[4:16] != 'pubkey\x00\x00\x00\x00\x00\x00' and ackData[4:16] != 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00' and ackData[4:16] != 'broadcast\x00\x00\x00' : + return False + return True + def addMailingListNameToSubject(self,subject,mailingListName): subject = subject.strip() if subject[:3] == 'Re:' or subject[:3] == 'RE:': @@ -1159,7 +1161,7 @@ class receiveDataThread(QThread): print 'We have already received this getpubkey request (it is stored on disk in the SQL inventory). Ignoring it.' inventoryLock.release() return - self.objectsOfWhichThisRemoteNodeIsAlreadyAware[inventoryHash] = 0 + objectType = 'getpubkey' inventory[inventoryHash] = (objectType, self.streamNumber, data, embeddedTime) inventoryLock.release() @@ -2091,7 +2093,7 @@ class singleWorker(QThread): sqlSubmitQueue.put((toripe,)) queryreturn = sqlReturnQueue.get() sqlLock.release() - if queryreturn != '': #If we have the pubkey then send the message otherwise put the hash in the neededPubkeys data structure so that we will pay attention to it if it comes over the wire. + if queryreturn != []: #If we have the pubkey then send the message otherwise put the hash in the neededPubkeys data structure so that we will pay attention to it if it comes over the wire. self.sendMsg(toripe) else: neededPubkeys[toripe] = 0 From 10c6934b8ed024e430e605df0027dab65dbb6679 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 2 Apr 2013 18:00:43 -0400 Subject: [PATCH 19/25] move isAckDataValid to its own function --- bitmessagemain.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 8b1d9968..92f88e01 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -980,7 +980,7 @@ class receiveDataThread(QThread): if ackData[0:4] != '\xe9\xbe\xb4\xd9': print 'Ackdata magic bytes were wrong. Not sending ackData.' return False - ackDataPayloadLength, = unpack('>L',ackData[16:24]) + ackDataPayloadLength, = unpack('>L',ackData[16:20]) if len(ackData)-24 != ackDataPayloadLength: print 'ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.' return False @@ -4626,7 +4626,7 @@ class MyForm(QtGui.QMainWindow): printLock.acquire() print 'Closing. Flushing inventory in memory out to disk...' printLock.release() - self.statusBar().showMessage('Flushing inventory in memory out to disk.') + self.statusBar().showMessage('Flushing inventory in memory out to disk. This may take several minutes...') flushInventory() #This one last useless query will guarantee that the previous query committed before we close the program. @@ -4672,7 +4672,6 @@ class MyForm(QtGui.QMainWindow): toAddressAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item(currentInboxRow,0).data(Qt.UserRole).toPyObject()) fromAddressAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item(currentInboxRow,1).data(Qt.UserRole).toPyObject()) - if toAddressAtCurrentInboxRow == '[Broadcast subscribers]': self.ui.labelFrom.setText('') else: From 396df086ffbccecfd1fe2a7f48837ded3a3622e5 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Wed, 3 Apr 2013 12:59:43 -0400 Subject: [PATCH 20/25] refactor sendData function --- bitmessagemain.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 92f88e01..5738ccdb 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -1287,37 +1287,30 @@ class receiveDataThread(QThread): print 'sending pubkey' headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData += 'pubkey\x00\x00\x00\x00\x00\x00' - headerData += pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. + headerData += pack('>L',len(payload)) #payload length. headerData += hashlib.sha512(payload).digest()[:4] self.sock.send(headerData + payload) - elif objectType == 'getpubkey': + elif objectType == 'getpubkey' or objectType == 'pubkeyrequest': print 'sending getpubkey' headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData += 'getpubkey\x00\x00\x00' - headerData += pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. + headerData += pack('>L',len(payload)) #payload length. headerData += hashlib.sha512(payload).digest()[:4] self.sock.send(headerData + payload) elif objectType == 'msg': print 'sending msg' headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData += 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00' - headerData += pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. + headerData += pack('>L',len(payload)) #payload length. headerData += hashlib.sha512(payload).digest()[:4] self.sock.send(headerData + payload) elif objectType == 'broadcast': print 'sending broadcast' headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. headerData += 'broadcast\x00\x00\x00' - headerData += pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. + headerData += pack('>L',len(payload)) #payload length. headerData += hashlib.sha512(payload).digest()[:4] self.sock.send(headerData + payload) - elif objectType == 'getpubkey' or objectType == 'pubkeyrequest': - print 'sending getpubkey' - headerData = '\xe9\xbe\xb4\xd9' #magic bits, slighly different from Bitcoin's magic bits. - headerData += 'getpubkey\x00\x00\x00' #version command - headerData += pack('>L',len(payload)) #payload length - headerData += hashlib.sha512(payload).digest()[0:4] - self.sock.send(headerData + payload) else: sys.stderr.write('Error: sendData has been asked to send a strange objectType: %s\n' % str(objectType)) From 58175b90e730d6a19aefeaa29409370e7c6e1b2e Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Thu, 4 Apr 2013 12:32:25 -0400 Subject: [PATCH 21/25] UTC time in pseudo-mailing-list broadcasts --- bitmessagemain.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 5738ccdb..c082b037 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -46,7 +46,7 @@ import pickle import random import sqlite3 import threading #used for the locks, not for the threads -from time import strftime, localtime +from time import strftime, localtime, gmtime import os import shutil #used for moving the messages.dat file import string @@ -944,8 +944,8 @@ class receiveDataThread(QThread): #Let us send out this message as a broadcast subject = self.addMailingListNameToSubject(subject,mailingListName) #Let us now send this message out as a broadcast - message = 'Message ostensibly from ' + fromAddress + ':\n\n' + body - fromAddress = toAddress #The fromAddress for the broadcast is the toAddress (my address) for the msg message we are currently processing. + message = strftime("%a, %Y-%m-%d %H:%M:%S UTC",gmtime()) + ' Message ostensibly from ' + fromAddress + ':\n\n' + body + fromAddress = toAddress #The fromAddress for the broadcast that we are about to send is the toAddress (my address) for the msg message we are currently processing. ackdata = OpenSSL.rand(32) #We don't actually need the ackdata for acknowledgement since this is a broadcast message but we can use it to update the user interface when the POW is done generating. toAddress = '[Broadcast subscribers]' ripe = '' @@ -4643,20 +4643,16 @@ class MyForm(QtGui.QMainWindow): raise SystemExit def on_action_InboxMessageForceHtml(self): - # Updated to work with all characters. Previously, non-english characters caused errors. - try: - lines = str(self.ui.textEditInboxMessage.toPlainText()).split('\n') - except UnicodeEncodeError: - currentInboxRow = self.ui.tableWidgetInbox.currentRow() - self.ui.textEditInboxMessage.setHtml(self.ui.tableWidgetInbox.item(currentInboxRow,2).data(Qt.UserRole).toPyObject()) - return - from_prefix = 'Message ostensibly from ' + currentInboxRow = self.ui.tableWidgetInbox.currentRow() + lines = self.ui.tableWidgetInbox.item(currentInboxRow,2).data(Qt.UserRole).toPyObject().split('\n') for i in xrange(len(lines)): - if lines[i].find(from_prefix) != -1: - lines[i] = '

%s%s

' % (from_prefix,lines[i][24:-1]) + if lines[i].contains('Message ostensibly from '): + lines[i] = '

%s

' % (lines[i]) elif lines[i] == '------------------------------------------------------': lines[i] = '
' - content = '\n'.join(lines) + content = '' + for i in xrange(len(lines)): + content += lines[i] + '
' content = content.replace('\n\n', '

') self.ui.textEditInboxMessage.setHtml(QtCore.QString(content)) From b204de9949a01c72724f5a4659213f92a8acd673 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Thu, 4 Apr 2013 12:43:45 -0400 Subject: [PATCH 22/25] strip addresses before use rather than saying invalid characters --- addresses.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/addresses.py b/addresses.py index b29748aa..d3423503 100644 --- a/addresses.py +++ b/addresses.py @@ -122,14 +122,8 @@ def encodeAddress(version,stream,ripe): def decodeAddress(address): #returns (status, address version number, stream number, data (almost certainly a ripe hash)) - """#check for the BM- at the front of the address. If it isn't there, this address might be for a different version of Bitmessage - if address[:3] != 'BM-': - status = 'missingbm' - return status,0,0,0 - #take off the BM- - integer = decodeBase58(address[3:])""" + address = str(address).strip() - #changed Bitmessage to accept addresses that lack the "BM-" prefix. if address[:3] == 'BM-': integer = decodeBase58(address[3:]) else: @@ -189,6 +183,7 @@ def decodeAddress(address): return status,addressVersionNumber,streamNumber,'\x00\x00'+data[bytesUsedByVersionNumber+bytesUsedByStreamNumber:-4] def addBMIfNotPresent(address): + address = str(address).strip() if address[:3] != 'BM-': return 'BM-'+address else: From feb6061ccabf7ba63ccecdd7a13a43aacf454e68 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Thu, 4 Apr 2013 13:39:11 -0400 Subject: [PATCH 23/25] smarter commits Vastly improves disk performance --- bitmessagemain.py | 151 +++++++++++++------------------------------ defaultKnownNodes.py | 6 +- 2 files changed, 47 insertions(+), 110 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index c082b037..48a7adae 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -623,6 +623,7 @@ class receiveDataThread(QThread): sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() workerQueue.put(('newpubkey',(sendersAddressVersion,sendersStream,ripe.digest()))) #This will check to see whether we happen to be awaiting this pubkey in order to send a message. If we are, it will do the POW and send it. @@ -654,6 +655,7 @@ class receiveDataThread(QThread): sqlSubmitQueue.put('''INSERT INTO inbox VALUES (?,?,?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) @@ -749,6 +751,7 @@ class receiveDataThread(QThread): sqlSubmitQueue.put('UPDATE sent SET status=? WHERE ackdata=?') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),encryptedData[readPosition:],'Acknowledgement of the message received just now.') return @@ -850,6 +853,7 @@ class receiveDataThread(QThread): sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() workerQueue.put(('newpubkey',(sendersAddressVersionNumber,sendersStreamNumber,ripe.digest()))) #This will check to see whether we happen to be awaiting this pubkey in order to send a message. If we are, it will do the POW and send it. blockMessage = False #Gets set to True if the user shouldn't see the message according to black or white lists. @@ -923,6 +927,7 @@ class receiveDataThread(QThread): sqlSubmitQueue.put('''INSERT INTO inbox VALUES (?,?,?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) @@ -954,6 +959,7 @@ class receiveDataThread(QThread): sqlSubmitQueue.put('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,'[Broadcast subscribers]',fromAddress,subject,message,ackdata) @@ -1112,6 +1118,7 @@ class receiveDataThread(QThread): sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() printLock.acquire() printLock.release() @@ -1123,6 +1130,7 @@ class receiveDataThread(QThread): sqlSubmitQueue.put('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() printLock.acquire() printLock.release() @@ -1770,6 +1778,7 @@ def flushInventory(): sqlSubmitQueue.put(t) sqlReturnQueue.get() del inventory[hash] + sqlSubmitQueue.put('commit') sqlLock.release() def isInSqlInventory(hash): @@ -1974,13 +1983,16 @@ class sqlThread(QThread): while True: item = sqlSubmitQueue.get() - parameters = sqlSubmitQueue.get() - #print 'item', item - #print 'parameters', parameters - self.cur.execute(item, parameters) - sqlReturnQueue.put(self.cur.fetchall()) - sqlSubmitQueue.task_done() - self.conn.commit() + if item == 'commit': + self.conn.commit() + else: + parameters = sqlSubmitQueue.get() + #print 'item', item + #print 'parameters', parameters + self.cur.execute(item, parameters) + sqlReturnQueue.put(self.cur.fetchall()) + #sqlSubmitQueue.task_done() + '''The singleCleaner class is a timer-driven thread that cleans data structures to free memory, resends messages when a remote node doesn't respond, and sends pong messages to keep connections alive if the network isn't busy. @@ -2009,12 +2021,13 @@ class singleCleaner(QThread): self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing housekeeping (Flushing inventory in memory to disk...)") for hash, storedValue in inventory.items(): objectType, streamNumber, payload, receivedTime = storedValue - if int(time.time())- 600 > receivedTime: + if int(time.time())- 3600 > receivedTime: t = (hash,objectType,streamNumber,payload,receivedTime) sqlSubmitQueue.put('''INSERT INTO inventory VALUES (?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() del inventory[hash] + sqlSubmitQueue.put('commit') self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"") sqlLock.release() broadcastToSendDataQueues((0, 'pong', 'no data')) #commands the sendData threads to send out a pong message if they haven't sent anything else in the last five minutes. The socket timeout-time is 10 minutes. @@ -2033,6 +2046,7 @@ class singleCleaner(QThread): sqlSubmitQueue.put('''DELETE FROM pubkeys WHERE timeI',(int(time.time()))) - payload += encodeVarint(1) #broadcast version - payload += encodeVarint(addressVersionNumber) - payload += encodeVarint(streamNumber) - payload += ripe - payload += encodeVarint(len(nString)) - payload += nString - payload += encodeVarint(len(eString)) - payload += eString - payload += messageToTransmit - signature = rsa.sign(messageToTransmit,myPrivatekey,'SHA-512') - #print 'signature', signature.encode('hex') - payload += signature - - #print 'nString', repr(nString) - #print 'eString', repr(eString) - - nonce = 0 - trialValue = 99999999999999999999 - target = 2**64 / ((len(payload)+payloadLengthExtraBytes+8) * averageProofOfWorkNonceTrialsPerByte) - print '(For broadcast message) Doing proof of work...' - initialHash = hashlib.sha512(payload).digest() - while trialValue > target: - nonce += 1 - trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) - print '(For broadcast message) Found proof of work', trialValue, 'Nonce:', nonce - - payload = pack('>Q',nonce) + payload - - inventoryHash = calculateInventoryHash(payload) - objectType = 'broadcast' - inventory[inventoryHash] = (objectType, streamNumber, payload, int(time.time())) - print 'sending inv (within sendBroadcast function)' - broadcastToSendDataQueues((streamNumber, 'sendinv', inventoryHash)) - - self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Broadcast sent at '+unicode(strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')) - - #Update the status of the message in the 'sent' table to have a 'broadcastsent' status - sqlLock.acquire() - t = ('broadcastsent',int(time.time()),fromaddress, subject, body,'broadcastpending') - sqlSubmitQueue.put('UPDATE sent SET status=?, lastactiontime=? WHERE fromaddress=? AND subject=? AND message=? AND status=?') - sqlSubmitQueue.put(t) - queryreturn = sqlReturnQueue.get() - sqlLock.release()""" else: printLock.acquire() print 'In the singleWorker thread, the sendBroadcast function doesn\'t understand the address version' @@ -2371,6 +2326,7 @@ class singleWorker(QThread): sqlSubmitQueue.put('UPDATE sent SET status=? WHERE status=? AND toripe=?') sqlSubmitQueue.put(t) queryreturn = sqlReturnQueue.get() + sqlSubmitQueue.put('commit') t = ('doingpow',toRipe) sqlSubmitQueue.put('SELECT toaddress, fromaddress, subject, message, ackdata FROM sent WHERE status=? AND toripe=?') @@ -2488,41 +2444,6 @@ class singleWorker(QThread): readPosition += 64 encrypted = highlevelcrypto.encrypt(payload,"04"+pubEncryptionKeyBase256.encode('hex')) - """elif toAddressVersionNumber == 1: - sqlLock.acquire() - sqlSubmitQueue.put('SELECT transmitdata FROM pubkeys WHERE hash=?') - sqlSubmitQueue.put((toRipe,)) - queryreturn = sqlReturnQueue.get() - sqlLock.release() - - for row in queryreturn: - pubkeyPayload, = row - - readPosition = 8 #to bypass the nonce - behaviorBitfield = pubkeyPayload[8:12] - readPosition += 4 #to bypass the bitfield of behaviors - addressVersion, addressVersionLength = decodeVarint(pubkeyPayload[readPosition:readPosition+10]) - readPosition += addressVersionLength - streamNumber, streamNumberLength = decodeVarint(pubkeyPayload[readPosition:readPosition+10]) - readPosition += streamNumberLength - nLength, nLengthLength = decodeVarint(pubkeyPayload[readPosition:readPosition+10]) - readPosition += nLengthLength - n = convertStringToInt(pubkeyPayload[readPosition:readPosition+nLength]) - readPosition += nLength - eLength, eLengthLength = decodeVarint(pubkeyPayload[readPosition:readPosition+10]) - readPosition += eLengthLength - e = convertStringToInt(pubkeyPayload[readPosition:readPosition+eLength]) - receiversPubkey = rsa.PublicKey(n,e) - - infile = cStringIO.StringIO(payload) - outfile = cStringIO.StringIO() - #print 'Encrypting using public key:', receiversPubkey - encrypt_bigfile(infile,outfile,receiversPubkey) - - encrypted = outfile.getvalue() - infile.close() - outfile.close()""" - nonce = 0 trialValue = 99999999999999999999 @@ -2561,7 +2482,7 @@ class singleWorker(QThread): sqlSubmitQueue.put('''UPDATE pubkeys SET usedpersonally='yes' WHERE hash=?''') sqlSubmitQueue.put(t) queryreturn = sqlReturnQueue.get() - + sqlSubmitQueue.put('commit') sqlLock.release() @@ -3032,6 +2953,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): sqlSubmitQueue.put('''UPDATE inbox SET folder='trash' WHERE msgid=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() apiSignalQueue.put(('updateStatusBar','Per API: Trashed message (assuming message existed). UI not updated.')) return 'Trashed message (assuming message existed). UI not updated. To double check, run getAllInboxMessages to see that the message disappeared, or restart Bitmessage and look in the normal Bitmessage GUI.' @@ -3092,6 +3014,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): sqlSubmitQueue.put('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() toLabel = '' @@ -3152,6 +3075,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): sqlSubmitQueue.put('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() toLabel = '[Broadcast subscribers]' @@ -4030,6 +3954,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() @@ -4104,6 +4029,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?)''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() workerQueue.put(('sendbroadcast',(fromAddress,subject,message))) @@ -4342,6 +4268,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''INSERT INTO addressbook VALUES (?,?)''') sqlSubmitQueue.put(t) queryreturn = sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.rerenderInboxFromLabels() else: @@ -4375,6 +4302,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''INSERT INTO subscriptions VALUES (?,?,?)''') sqlSubmitQueue.put(t) queryreturn = sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.rerenderInboxFromLabels() self.reloadBroadcastSendersForWhichImWatching() @@ -4544,6 +4472,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''INSERT INTO whitelist VALUES (?,?,?)''') sqlSubmitQueue.put(t) queryreturn = sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() else: self.statusBar().showMessage('Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want.') @@ -4702,6 +4631,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''INSERT INTO addressbook VALUES (?,?)''') sqlSubmitQueue.put(t) queryreturn = sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.ui.tabWidget.setCurrentIndex(5) self.ui.tableWidgetAddressBook.setCurrentCell(0,0) @@ -4720,6 +4650,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''UPDATE inbox SET folder='trash' WHERE msgid=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.ui.textEditInboxMessage.setText("") self.ui.tableWidgetInbox.removeRow(currentRow) @@ -4735,6 +4666,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''UPDATE sent SET folder='trash' WHERE ackdata=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.ui.textEditSentMessage.setPlainText("") self.ui.tableWidgetSent.removeRow(currentRow) @@ -4757,6 +4689,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''DELETE FROM addressbook WHERE label=? AND address=?''') sqlSubmitQueue.put(t) queryreturn = sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.ui.tableWidgetAddressBook.removeRow(currentRow) self.rerenderInboxFromLabels() @@ -4792,6 +4725,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''DELETE FROM subscriptions WHERE label=? AND address=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.ui.tableWidgetSubscriptions.removeRow(currentRow) self.rerenderInboxFromLabels() @@ -4822,6 +4756,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''DELETE FROM whitelist WHERE label=? AND address=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.ui.tableWidgetBlacklist.removeRow(currentRow) def on_action_BlacklistClipboard(self): @@ -4846,6 +4781,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''UPDATE whitelist SET enabled=1 WHERE address=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() def on_action_BlacklistDisable(self): currentRow = self.ui.tableWidgetBlacklist.currentRow() @@ -4862,6 +4798,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''UPDATE whitelist SET enabled=0 WHERE address=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() #Group of functions for the Your Identities dialog box @@ -4941,6 +4878,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''UPDATE addressbook set label=? WHERE address=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.rerenderInboxFromLabels() self.rerenderSentToLabels() @@ -4954,6 +4892,7 @@ class MyForm(QtGui.QMainWindow): sqlSubmitQueue.put('''UPDATE subscriptions set label=? WHERE address=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() + sqlSubmitQueue.put('commit') sqlLock.release() self.rerenderInboxFromLabels() self.rerenderSentToLabels() diff --git a/defaultKnownNodes.py b/defaultKnownNodes.py index 352b18b8..23570662 100644 --- a/defaultKnownNodes.py +++ b/defaultKnownNodes.py @@ -9,12 +9,10 @@ from time import strftime, localtime def createDefaultKnownNodes(appdata): ############## Stream 1 ################ stream1 = {} - - stream1['80.69.173.220'] = (443,int(time.time())) - stream1['109.95.105.15'] = (8443,int(time.time())) + + stream1['84.48.88.42'] = (8444,int(time.time())) stream1['66.65.120.151'] = (8080,int(time.time())) stream1['76.180.233.38'] = (8444,int(time.time())) - stream1['84.48.88.42'] = (8444,int(time.time())) stream1['74.132.73.137'] = (8444,int(time.time())) stream1['60.242.109.18'] = (8444,int(time.time())) From c7efc06e835abadf96614abb86e5a4ec0d1240f7 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Thu, 4 Apr 2013 14:53:39 -0400 Subject: [PATCH 24/25] added knownNodesLock --- bitmessagemain.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 48a7adae..19cdf678 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -148,7 +148,9 @@ class outgoingSynSender(QThread): printLock.release() PORT, timeLastSeen = knownNodes[self.streamNumber][HOST] if (int(time.time())-timeLastSeen) > 172800 and len(knownNodes[self.streamNumber]) > 1000: # for nodes older than 48 hours old if we have more than 1000 hosts in our list, delete from the knownNodes data-structure. + knownNodesLock.acquire() del knownNodes[self.streamNumber][HOST] + knownNodesLock.release() print 'deleting ', HOST, 'from knownNodes because it is more than 48 hours old and we could not connect to it.' except socks.Socks5AuthError, err: self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"SOCKS5 Authentication problem: "+str(err)) @@ -169,7 +171,9 @@ class outgoingSynSender(QThread): printLock.release() PORT, timeLastSeen = knownNodes[self.streamNumber][HOST] if (int(time.time())-timeLastSeen) > 172800 and len(knownNodes[self.streamNumber]) > 1000: # for nodes older than 48 hours old if we have more than 1000 hosts in our list, delete from the knownNodes data-structure. + knownNodesLock.acquire() del knownNodes[self.streamNumber][HOST] + knownNodesLock.release() print 'deleting ', HOST, 'from knownNodes because it is more than 48 hours old and we could not connect to it.' except Exception, err: print 'An exception has occurred in the outgoingSynSender thread that was not caught by other exception types:', err @@ -323,7 +327,9 @@ class receiveDataThread(QThread): #print 'message checksum is correct' #The time we've last seen this node is obviously right now since we just received valid data from it. So update the knownNodes list so that other peers can be made aware of its existance. if self.initiatedConnection: #The remote port is only something we should share with others if it is the remote node's incoming port (rather than some random operating-system-assigned outgoing port). + knownNodesLock.acquire() knownNodes[self.streamNumber][self.HOST] = (self.PORT,int(time.time())) + knownNodesLock.release() if self.payloadLength <= 180000000: #If the size of the message is greater than 180MB, ignore it. (I get memory errors when processing messages much larger than this though it is concievable that this value will have to be lowered if some systems are less tolarant of large messages.) remoteCommand = self.data[4:16] printLock.acquire() @@ -1402,10 +1408,14 @@ class receiveDataThread(QThread): continue timeSomeoneElseReceivedMessageFromThisNode, = unpack('>I',data[lengthOfNumberOfAddresses+(34*i):4+lengthOfNumberOfAddresses+(34*i)]) #This is the 'time' value in the received addr message. if recaddrStream not in knownNodes: #knownNodes is a dictionary of dictionaries with one outer dictionary for each stream. If the outer stream dictionary doesn't exist yet then we must make it. + knownNodesLock.acquire() knownNodes[recaddrStream] = {} + knownNodesLock.release() if hostFromAddrMessage not in knownNodes[recaddrStream]: if len(knownNodes[recaddrStream]) < 20000 and timeSomeoneElseReceivedMessageFromThisNode > (int(time.time())-10800) and timeSomeoneElseReceivedMessageFromThisNode < (int(time.time()) + 10800): #If we have more than 20000 nodes in our list already then just forget about adding more. Also, make sure that the time that someone else received a message from this node is within three hours from now. + knownNodesLock.acquire() knownNodes[recaddrStream][hostFromAddrMessage] = (recaddrPort, timeSomeoneElseReceivedMessageFromThisNode) + knownNodesLock.release() print 'added new node', hostFromAddrMessage, 'to knownNodes in stream', recaddrStream needToWriteKnownNodesToDisk = True hostDetails = (timeSomeoneElseReceivedMessageFromThisNode, recaddrStream, recaddrServices, hostFromAddrMessage, recaddrPort) @@ -1413,12 +1423,16 @@ class receiveDataThread(QThread): else: PORT, timeLastReceivedMessageFromThisNode = knownNodes[recaddrStream][hostFromAddrMessage]#PORT in this case is either the port we used to connect to the remote node, or the port that was specified by someone else in a past addr message. if (timeLastReceivedMessageFromThisNode < timeSomeoneElseReceivedMessageFromThisNode) and (timeSomeoneElseReceivedMessageFromThisNode < int(time.time())): + knownNodesLock.acquire() knownNodes[recaddrStream][hostFromAddrMessage] = (PORT, timeSomeoneElseReceivedMessageFromThisNode) + knownNodesLock.release() if PORT != recaddrPort: print 'Strange occurance: The port specified in an addr message', str(recaddrPort),'does not match the port',str(PORT),'that this program (or some other peer) used to connect to it',str(hostFromAddrMessage),'. Perhaps they changed their port or are using a strange NAT configuration.' if needToWriteKnownNodesToDisk: #Runs if any nodes were new to us. Also, share those nodes with our peers. output = open(appdata + 'knownnodes.dat', 'wb') + knownNodesLock.acquire() pickle.dump(knownNodes, output) + knownNodesLock.release() output.close() self.broadcastaddr(listOfAddressDetailsToBroadcastToPeers) printLock.acquire() @@ -1560,9 +1574,11 @@ class receiveDataThread(QThread): printLock.release() return + knownNodesLock.acquire() knownNodes[self.streamNumber][self.HOST] = (self.remoteNodeIncomingPort, int(time.time())) output = open(appdata + 'knownnodes.dat', 'wb') pickle.dump(knownNodes, output) + knownNodesLock.release() output.close() self.sendverack() @@ -4395,9 +4411,11 @@ class MyForm(QtGui.QMainWindow): with open('keys.dat', 'wb') as configfile: config.write(configfile) #Write the knownnodes.dat file to disk in the new location + knownNodesLock.acquire() output = open('knownnodes.dat', 'wb') pickle.dump(knownNodes, output) output.close() + knownNodesLock.release() os.remove(appdata + 'keys.dat') os.remove(appdata + 'knownnodes.dat') appdata = '' @@ -4412,9 +4430,11 @@ class MyForm(QtGui.QMainWindow): with open(appdata + 'keys.dat', 'wb') as configfile: config.write(configfile) #Write the knownnodes.dat file to disk in the new location + knownNodesLock.acquire() output = open(appdata + 'knownnodes.dat', 'wb') pickle.dump(knownNodes, output) output.close() + knownNodesLock.release() os.remove('keys.dat') os.remove('knownnodes.dat') QMessageBox.about(self, "Restart", "Bitmessage has moved most of your config files to the application data directory but you must restart Bitmessage to move the last file (the file which holds messages).") @@ -4548,7 +4568,7 @@ class MyForm(QtGui.QMainWindow): printLock.acquire() print 'Closing. Flushing inventory in memory out to disk...' printLock.release() - self.statusBar().showMessage('Flushing inventory in memory out to disk. This may take several minutes...') + self.statusBar().showMessage('Flushing inventory in memory out to disk. This should normally only take a second...') flushInventory() #This one last useless query will guarantee that the previous query committed before we close the program. @@ -4559,9 +4579,11 @@ class MyForm(QtGui.QMainWindow): sqlLock.release() self.statusBar().showMessage('Saving the knownNodes list of peers to disk...') + knownNodesLock.acquire() output = open(appdata + 'knownnodes.dat', 'wb') pickle.dump(knownNodes, output) output.close() + knownNodesLock.release() self.trayIcon.hide() printLock.acquire() @@ -4945,6 +4967,7 @@ sqlSubmitQueue = Queue.Queue() #SQLITE3 is so thread-unsafe that they won't even sqlReturnQueue = Queue.Queue() sqlLock = threading.Lock() printLock = threading.Lock() +knownNodesLock = threading.Lock() ackdataForWhichImWatching = {} broadcastSendersForWhichImWatching = {} statusIconColor = 'red' @@ -5054,6 +5077,7 @@ if __name__ == "__main__": try: + #We shouldn't have to use the knownNodesLock because this had better be the only thread accessing knownNodes right now. pickleFile = open(appdata + 'knownnodes.dat', 'rb') knownNodes = pickle.load(pickleFile) pickleFile.close() From af87503ec729915fa2503ab6374f9648d52314a9 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Fri, 5 Apr 2013 17:54:38 -0400 Subject: [PATCH 25/25] Support select multiple items in inbox and Sent box --- bitmessagemain.py | 18 +++++++++--------- bitmessageui.py | 6 +++--- bitmessageui.ui | 4 ++-- messages.dat reader.py | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/bitmessagemain.py b/bitmessagemain.py index 19cdf678..b23adbb6 100755 --- a/bitmessagemain.py +++ b/bitmessagemain.py @@ -4663,36 +4663,36 @@ class MyForm(QtGui.QMainWindow): #Send item on the Inbox tab to trash def on_action_InboxTrash(self): - currentRow = self.ui.tableWidgetInbox.currentRow() - if currentRow >= 0: + while self.ui.tableWidgetInbox.selectedIndexes() != []: + currentRow = self.ui.tableWidgetInbox.selectedIndexes()[0].row() inventoryHashToTrash = str(self.ui.tableWidgetInbox.item(currentRow,3).data(Qt.UserRole).toPyObject()) t = (inventoryHashToTrash,) sqlLock.acquire() - #sqlSubmitQueue.put('''delete from inbox where msgid=?''') sqlSubmitQueue.put('''UPDATE inbox SET folder='trash' WHERE msgid=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() - sqlSubmitQueue.put('commit') sqlLock.release() self.ui.textEditInboxMessage.setText("") self.ui.tableWidgetInbox.removeRow(currentRow) - self.statusBar().showMessage('Moved item to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back.') + self.statusBar().showMessage('Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back.') + sqlSubmitQueue.put('commit') #Send item on the Sent tab to trash def on_action_SentTrash(self): - currentRow = self.ui.tableWidgetSent.currentRow() - if currentRow >= 0: + #currentRow = self.ui.tableWidgetSent.currentRow() + while self.ui.tableWidgetSent.selectedIndexes() != []: + currentRow = self.ui.tableWidgetSent.selectedIndexes()[0].row() ackdataToTrash = str(self.ui.tableWidgetSent.item(currentRow,3).data(Qt.UserRole).toPyObject()) t = (ackdataToTrash,) sqlLock.acquire() sqlSubmitQueue.put('''UPDATE sent SET folder='trash' WHERE ackdata=?''') sqlSubmitQueue.put(t) sqlReturnQueue.get() - sqlSubmitQueue.put('commit') sqlLock.release() self.ui.textEditSentMessage.setPlainText("") self.ui.tableWidgetSent.removeRow(currentRow) - self.statusBar().showMessage('Moved item to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back.') + self.statusBar().showMessage('Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back.') + sqlSubmitQueue.put('commit') def on_action_SentClipboard(self): currentRow = self.ui.tableWidgetSent.currentRow() addressAtCurrentRow = str(self.ui.tableWidgetSent.item(currentRow,0).data(Qt.UserRole).toPyObject()) diff --git a/bitmessageui.py b/bitmessageui.py index 026dbbda..c1c62d37 100644 --- a/bitmessageui.py +++ b/bitmessageui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'bitmessageui.ui' # -# Created: Wed Mar 27 17:23:59 2013 +# Created: Fri Apr 05 17:47:21 2013 # by: PyQt4 UI code generator 4.9.4 # # WARNING! All changes made in this file will be lost! @@ -47,7 +47,7 @@ class Ui_MainWindow(object): self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2")) self.tableWidgetInbox = QtGui.QTableWidget(self.inbox) self.tableWidgetInbox.setAlternatingRowColors(True) - self.tableWidgetInbox.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) + self.tableWidgetInbox.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.tableWidgetInbox.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.tableWidgetInbox.setWordWrap(False) self.tableWidgetInbox.setObjectName(_fromUtf8("tableWidgetInbox")) @@ -144,7 +144,7 @@ class Ui_MainWindow(object): self.tableWidgetSent = QtGui.QTableWidget(self.sent) self.tableWidgetSent.setDragDropMode(QtGui.QAbstractItemView.DragDrop) self.tableWidgetSent.setAlternatingRowColors(True) - self.tableWidgetSent.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) + self.tableWidgetSent.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.tableWidgetSent.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.tableWidgetSent.setWordWrap(False) self.tableWidgetSent.setObjectName(_fromUtf8("tableWidgetSent")) diff --git a/bitmessageui.ui b/bitmessageui.ui index cf7467ad..0e2e19aa 100644 --- a/bitmessageui.ui +++ b/bitmessageui.ui @@ -74,7 +74,7 @@ true - QAbstractItemView::SingleSelection + QAbstractItemView::ExtendedSelection QAbstractItemView::SelectRows @@ -319,7 +319,7 @@ p, li { white-space: pre-wrap; } true - QAbstractItemView::SingleSelection + QAbstractItemView::ExtendedSelection QAbstractItemView::SelectRows diff --git a/messages.dat reader.py b/messages.dat reader.py index cb6ca7d0..7843863e 100644 --- a/messages.dat reader.py +++ b/messages.dat reader.py @@ -88,12 +88,12 @@ def takeSentMessagesOutOfTrash(): conn.commit() print 'done' -#takeInboxMessagesOutOfTrash() +takeInboxMessagesOutOfTrash() #takeSentMessagesOutOfTrash() #readInbox() #readSent() #readPubkeys() #readSubscriptions() -readInventory() +#readInventory()