From eb9339052da0f59746f21849d01cfbb55ec45929 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 21 May 2013 14:10:48 -0400 Subject: [PATCH 1/2] adjust tab order --- src/bitmessagemain.py | 2 +- src/bitmessageui.py | 26 +++++++++++++++++++++++++- src/bitmessageui.ui | 27 +++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 9bb61177..35d64144 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -216,7 +216,7 @@ class singleListener(threading.Thread): #The following code will, unfortunately, block an incoming connection if someone else on the same LAN is already connected because the two computers will share the same external IP. This is here to prevent connection flooding. while HOST in shared.connectedHostsList: shared.printLock.acquire() - print 'incoming connection is from a host in shared.connectedHostsList (we are already connected to it). Ignoring it.' + print 'We are already connected to', HOST+'. Ignoring connection.' shared.printLock.release() a.close() a,(HOST,PORT) = sock.accept() diff --git a/src/bitmessageui.py b/src/bitmessageui.py index a7c85206..ca2d8b0b 100644 --- a/src/bitmessageui.py +++ b/src/bitmessageui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'bitmessageui.ui' # -# Created: Mon Apr 22 16:34:47 2013 +# Created: Tue May 21 14:09:58 2013 # by: PyQt4 UI code generator 4.9.4 # # WARNING! All changes made in this file will be lost! @@ -428,6 +428,30 @@ class Ui_MainWindow(object): QtCore.QObject.connect(self.radioButtonSpecific, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.labelSendBroadcastWarning.hide) QtCore.QObject.connect(self.radioButtonBroadcast, QtCore.SIGNAL(_fromUtf8("clicked()")), self.labelSendBroadcastWarning.show) QtCore.QMetaObject.connectSlotsByName(MainWindow) + MainWindow.setTabOrder(self.tabWidget, self.tableWidgetInbox) + MainWindow.setTabOrder(self.tableWidgetInbox, self.textEditInboxMessage) + MainWindow.setTabOrder(self.textEditInboxMessage, self.radioButtonSpecific) + MainWindow.setTabOrder(self.radioButtonSpecific, self.radioButtonBroadcast) + MainWindow.setTabOrder(self.radioButtonBroadcast, self.comboBoxSendFrom) + MainWindow.setTabOrder(self.comboBoxSendFrom, self.lineEditTo) + MainWindow.setTabOrder(self.lineEditTo, self.pushButtonLoadFromAddressBook) + MainWindow.setTabOrder(self.pushButtonLoadFromAddressBook, self.lineEditSubject) + MainWindow.setTabOrder(self.lineEditSubject, self.textEditMessage) + MainWindow.setTabOrder(self.textEditMessage, self.pushButtonSend) + MainWindow.setTabOrder(self.pushButtonSend, self.tableWidgetSent) + MainWindow.setTabOrder(self.tableWidgetSent, self.textEditSentMessage) + MainWindow.setTabOrder(self.textEditSentMessage, self.pushButtonNewAddress) + MainWindow.setTabOrder(self.pushButtonNewAddress, self.tableWidgetYourIdentities) + MainWindow.setTabOrder(self.tableWidgetYourIdentities, self.pushButtonAddSubscription) + MainWindow.setTabOrder(self.pushButtonAddSubscription, self.tableWidgetSubscriptions) + MainWindow.setTabOrder(self.tableWidgetSubscriptions, self.pushButtonAddAddressBook) + MainWindow.setTabOrder(self.pushButtonAddAddressBook, self.tableWidgetAddressBook) + MainWindow.setTabOrder(self.tableWidgetAddressBook, self.radioButtonBlacklist) + MainWindow.setTabOrder(self.radioButtonBlacklist, self.radioButtonWhitelist) + MainWindow.setTabOrder(self.radioButtonWhitelist, self.pushButtonAddBlacklist) + MainWindow.setTabOrder(self.pushButtonAddBlacklist, self.tableWidgetBlacklist) + MainWindow.setTabOrder(self.tableWidgetBlacklist, self.tableWidgetConnectionCount) + MainWindow.setTabOrder(self.tableWidgetConnectionCount, self.pushButtonStatusIcon) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "Bitmessage", None, QtGui.QApplication.UnicodeUTF8)) diff --git a/src/bitmessageui.ui b/src/bitmessageui.ui index cef8cd69..8487b673 100644 --- a/src/bitmessageui.ui +++ b/src/bitmessageui.ui @@ -1003,6 +1003,33 @@ p, li { white-space: pre-wrap; } + + tabWidget + tableWidgetInbox + textEditInboxMessage + radioButtonSpecific + radioButtonBroadcast + comboBoxSendFrom + lineEditTo + pushButtonLoadFromAddressBook + lineEditSubject + textEditMessage + pushButtonSend + tableWidgetSent + textEditSentMessage + pushButtonNewAddress + tableWidgetYourIdentities + pushButtonAddSubscription + tableWidgetSubscriptions + pushButtonAddAddressBook + tableWidgetAddressBook + radioButtonBlacklist + radioButtonWhitelist + pushButtonAddBlacklist + tableWidgetBlacklist + tableWidgetConnectionCount + pushButtonStatusIcon + From 4705c4f78ac22420729bc87faa65b6ce66f3992f Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Wed, 22 May 2013 22:01:35 -0400 Subject: [PATCH 2/2] New tray icon, also use existing local-IP rejection function for received addr messages also --- src/bitmessagemain.py | 33 ++++++++++++++-------------- src/images/can-icon-24px-green.png | Bin 885 -> 4326 bytes src/images/can-icon-24px-red.png | Bin 867 -> 4325 bytes src/images/can-icon-24px-yellow.png | Bin 872 -> 4315 bytes 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 35d64144..e8d82521 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -1667,10 +1667,7 @@ class receiveDataThread(threading.Thread): if data[28+lengthOfNumberOfAddresses+(34*i)] == '\x7F': print 'Ignoring IP address in loopback range:', hostFromAddrMessage continue - if data[28+lengthOfNumberOfAddresses+(34*i)] == '\x0A': - print 'Ignoring IP address in private range:', hostFromAddrMessage - continue - if data[28+lengthOfNumberOfAddresses+(34*i):30+lengthOfNumberOfAddresses+(34*i)] == '\xC0A8': + if isHostInPrivateIPRange(hostFromAddrMessage): print 'Ignoring IP address in private range:', hostFromAddrMessage continue timeSomeoneElseReceivedMessageFromThisNode, = unpack('>I',data[lengthOfNumberOfAddresses+(34*i):4+lengthOfNumberOfAddresses+(34*i)]) #This is the 'time' value in the received addr message. @@ -1836,21 +1833,21 @@ class receiveDataThread(threading.Thread): for i in range(500): random.seed() HOST, = random.sample(shared.knownNodes[self.streamNumber], 1) - if self.isHostInPrivateIPRange(HOST): + if isHostInPrivateIPRange(HOST): continue addrsInMyStream[HOST] = shared.knownNodes[self.streamNumber][HOST] if len(shared.knownNodes[self.streamNumber*2]) > 0: for i in range(250): random.seed() HOST, = random.sample(shared.knownNodes[self.streamNumber*2], 1) - if self.isHostInPrivateIPRange(HOST): + if isHostInPrivateIPRange(HOST): continue addrsInChildStreamLeft[HOST] = shared.knownNodes[self.streamNumber*2][HOST] if len(shared.knownNodes[(self.streamNumber*2)+1]) > 0: for i in range(250): random.seed() HOST, = random.sample(shared.knownNodes[(self.streamNumber*2)+1], 1) - if self.isHostInPrivateIPRange(HOST): + if isHostInPrivateIPRange(HOST): continue addrsInChildStreamRight[HOST] = shared.knownNodes[(self.streamNumber*2)+1][HOST] shared.knownNodesLock.release() @@ -1992,16 +1989,7 @@ class receiveDataThread(threading.Thread): if self.verackReceived == True: self.connectionFullyEstablished() - def isHostInPrivateIPRange(self,host): - if host[:3] == '10.': - return True - if host[:4] == '172.': - if host[6] == '.': - if int(host[4:6]) >= 16 and int(host[4:6]) <= 31: - return True - if host[:8] == '192.168.': - return True - return False + #Every connection to a peer has a sendDataThread (and also a receiveDataThread). class sendDataThread(threading.Thread): @@ -2294,6 +2282,17 @@ def assembleVersionMessage(remoteHost,remotePort,myStreamNumber): datatosend = datatosend + hashlib.sha512(payload).digest()[0:4] return datatosend + payload +def isHostInPrivateIPRange(host): + if host[:3] == '10.': + return True + if host[:4] == '172.': + if host[6] == '.': + if int(host[4:6]) >= 16 and int(host[4:6]) <= 31: + return True + if host[:8] == '192.168.': + return True + return False + #This thread exists because SQLITE3 is so un-threadsafe that we must submit queries to it and it puts results back in a different queue. They won't let us just use locks. class sqlThread(threading.Thread): def __init__(self): diff --git a/src/images/can-icon-24px-green.png b/src/images/can-icon-24px-green.png index 5e7e52ec5db725d3838086b0be80bc465e8c18b0..247bebc7ef1b3df4dc2e443ca361139ecb988ef9 100644 GIT binary patch literal 4326 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 JPDHLkV1ge!T~`1A delta 849 zcmV-X1FrnrA?OB>B!2{RLP=Bz2nYy#2xN!=000SaNLh0L01ejw01ejxLMWSf0000P zbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$Sq{eVTB@2wPhzLUJ)Ph}F4u91_f(}t&B_-luipUf# z;30CU0n4B?Gqq4WsN*u5GxI$iTxXomaipHx`z-(8^SrzZF*E+BiNPdyc6N%osL-1X z&H+GRd=^DdU0hPmPq`WjVgec&=ow;0Jdsyp;{-Cf6jSGul8!iii-fJJj}CNS1(4_? z4gk?0t`;S2*MC_5d+oL+7#sYUC$aQ8a6{ZH?%>?m*lhcXC*TBs2D@S;mKwK`3(x_# zRd~GKvuTmpY*xBi(F|aBVDTja7>9*UM=uH8`-+NOCsNatG5<#-b0w&DnPz6aX0K&H`4}aoEvVg@f_X7s)-KIFed|j8C z{c2_Dbq{`g{ZM1GS?@73)EYI^Dpj!ZZMxK~()EtjTlvP+lp%o1LN%dh!8|i#v1AA& zmT9#S2@w(D0q+12hCHHZ@b#|(91cghM?i6&{+MOiWdv~Pt*PmvWoFh88yB-r5J*nn zE-}gy6My&5`UX}zBPLBriNWHVkgu<-Td-OyMn`{tl6_T}&LyN~eeoAs8(knSjD%`?pxkP=5q0jDIeCKp}y~t*_FkK^8 z;|0(c8~VW%-`d&`DVHox+OAAZTUNGl8qDPz{(pc4+T|Aj08lG$D4FjXjm9v4fLw#Y z;dZ$O05B1%bZG}i)}pi%PU?dalWfB;m$Md^UdhhsDv!!!!pH4qO;3aP26=+ry_bhJE44pFIU3yvPI1|WGA z*-9x30=k!1^H3oM;Q38|w2rohOh{bDAPtcufrYscE8Q-rs