Merge remote-tracking branch 'upstream/master'
Conflicts: src/proofofwork.py
This commit is contained in:
commit
9d7bec58d1
4
COPYING
4
COPYING
|
@ -1,5 +1,5 @@
|
||||||
Copyright (c) 2012-2014 Jonathan Warren
|
Copyright (c) 2012-2015 Jonathan Warren
|
||||||
Copyright (c) 2013-2014 The Bitmessage Developers
|
Copyright (c) 2013-2015 The Bitmessage Developers
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
11
INSTALL.md
11
INSTALL.md
|
@ -4,10 +4,10 @@ For an up-to-date version of these instructions, please visit the
|
||||||
[Bitmessage Wiki](https://bitmessage.org/wiki/Compiling_instructions).
|
[Bitmessage Wiki](https://bitmessage.org/wiki/Compiling_instructions).
|
||||||
|
|
||||||
PyBitmessage can be run either straight from source or from an installed
|
PyBitmessage can be run either straight from source or from an installed
|
||||||
packaged.
|
package.
|
||||||
|
|
||||||
##Dependencies
|
##Dependencies
|
||||||
Before running PyBitmessage, make sure you have all the needed dependencies
|
Before running PyBitmessage, make sure you have all the necessary dependencies
|
||||||
installed on your system.
|
installed on your system.
|
||||||
|
|
||||||
Here's a list of dependencies needed for PyBitmessage
|
Here's a list of dependencies needed for PyBitmessage
|
||||||
|
@ -42,7 +42,7 @@ cd PyBitmessage/ && python src/bitmessagemain.py
|
||||||
That's it! *Honestly*!
|
That's it! *Honestly*!
|
||||||
|
|
||||||
####Windows
|
####Windows
|
||||||
In Windows you can download an executable for Bitmessage
|
On Windows you can download an executable for Bitmessage
|
||||||
[here](https://bitmessage.org/download/windows/Bitmessage.exe).
|
[here](https://bitmessage.org/download/windows/Bitmessage.exe).
|
||||||
|
|
||||||
However, if you would like to run PyBitmessage via Python in Windows, you can
|
However, if you would like to run PyBitmessage via Python in Windows, you can
|
||||||
|
@ -52,13 +52,12 @@ information on how to do so.
|
||||||
####OS X
|
####OS X
|
||||||
First off, install Homebrew.
|
First off, install Homebrew.
|
||||||
```
|
```
|
||||||
ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
|
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, install the required dependencies
|
Now, install the required dependencies
|
||||||
```
|
```
|
||||||
brew install python pyqt
|
brew install git python pyqt
|
||||||
brew install git
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Download and run PyBitmessage:
|
Download and run PyBitmessage:
|
||||||
|
|
4
osx.sh
4
osx.sh
|
@ -1,9 +1,9 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# OS X Build script wrapper around the py2app script.
|
# OS X Build script wrapper around the py2app script.
|
||||||
# These build can only be generated on OS X.
|
# This build can only be generated on OS X.
|
||||||
# Requires all build dependencies for Bitmessage
|
# Requires all build dependencies for Bitmessage
|
||||||
# Especially important is openssl installed through brew
|
# Especially important is OpenSSL installed through brew
|
||||||
|
|
||||||
export ARCHFLAGS="-arch i386 -arch x86_64"
|
export ARCHFLAGS="-arch i386 -arch x86_64"
|
||||||
|
|
||||||
|
|
67
src/api.py
67
src/api.py
|
@ -637,14 +637,22 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
elif len(params) == 4:
|
elif len(params) == 4:
|
||||||
toAddress, fromAddress, subject, message = params
|
toAddress, fromAddress, subject, message = params
|
||||||
encodingType = 2
|
encodingType = 2
|
||||||
|
TTL = 4*24*60*60
|
||||||
elif len(params) == 5:
|
elif len(params) == 5:
|
||||||
toAddress, fromAddress, subject, message, encodingType = params
|
toAddress, fromAddress, subject, message, encodingType = params
|
||||||
|
TTL = 4*24*60*60
|
||||||
|
elif len(params) == 6:
|
||||||
|
toAddress, fromAddress, subject, message, encodingType, TTL = params
|
||||||
if encodingType != 2:
|
if encodingType != 2:
|
||||||
raise APIError(6, 'The encoding type must be 2 because that is the only one this program currently supports.')
|
raise APIError(6, 'The encoding type must be 2 because that is the only one this program currently supports.')
|
||||||
subject = self._decode(subject, "base64")
|
subject = self._decode(subject, "base64")
|
||||||
message = self._decode(message, "base64")
|
message = self._decode(message, "base64")
|
||||||
if len(subject + message) > (2 ** 18 - 500):
|
if len(subject + message) > (2 ** 18 - 500):
|
||||||
raise APIError(27, 'Message is too long.')
|
raise APIError(27, 'Message is too long.')
|
||||||
|
if TTL < 60*60:
|
||||||
|
TTL = 60*60
|
||||||
|
if TTL > 28*24*60*60:
|
||||||
|
TTL = 28*24*60*60
|
||||||
toAddress = addBMIfNotPresent(toAddress)
|
toAddress = addBMIfNotPresent(toAddress)
|
||||||
fromAddress = addBMIfNotPresent(fromAddress)
|
fromAddress = addBMIfNotPresent(fromAddress)
|
||||||
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(toAddress)
|
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(toAddress)
|
||||||
|
@ -659,8 +667,21 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
|
|
||||||
ackdata = OpenSSL.rand(32)
|
ackdata = OpenSSL.rand(32)
|
||||||
|
|
||||||
t = ('', toAddress, toRipe, fromAddress, subject, message, ackdata, int(
|
t = ('',
|
||||||
time.time()), 'msgqueued', 1, 1, 'sent', 2)
|
toAddress,
|
||||||
|
toRipe,
|
||||||
|
fromAddress,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
ackdata,
|
||||||
|
int(time.time()), # sentTime (this won't change)
|
||||||
|
int(time.time()), # lastActionTime
|
||||||
|
0,
|
||||||
|
'msgqueued',
|
||||||
|
0,
|
||||||
|
'sent',
|
||||||
|
2,
|
||||||
|
TTL)
|
||||||
helper_sent.insert(t)
|
helper_sent.insert(t)
|
||||||
|
|
||||||
toLabel = ''
|
toLabel = ''
|
||||||
|
@ -682,14 +703,22 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if len(params) == 3:
|
if len(params) == 3:
|
||||||
fromAddress, subject, message = params
|
fromAddress, subject, message = params
|
||||||
encodingType = 2
|
encodingType = 2
|
||||||
|
TTL = 4*24*60*60
|
||||||
elif len(params) == 4:
|
elif len(params) == 4:
|
||||||
fromAddress, subject, message, encodingType = params
|
fromAddress, subject, message, encodingType = params
|
||||||
|
TTL = 4*24*60*60
|
||||||
|
elif len(params) == 5:
|
||||||
|
fromAddress, subject, message, encodingType, TTL = params
|
||||||
if encodingType != 2:
|
if encodingType != 2:
|
||||||
raise APIError(6, 'The encoding type must be 2 because that is the only one this program currently supports.')
|
raise APIError(6, 'The encoding type must be 2 because that is the only one this program currently supports.')
|
||||||
subject = self._decode(subject, "base64")
|
subject = self._decode(subject, "base64")
|
||||||
message = self._decode(message, "base64")
|
message = self._decode(message, "base64")
|
||||||
if len(subject + message) > (2 ** 18 - 500):
|
if len(subject + message) > (2 ** 18 - 500):
|
||||||
raise APIError(27, 'Message is too long.')
|
raise APIError(27, 'Message is too long.')
|
||||||
|
if TTL < 60*60:
|
||||||
|
TTL = 60*60
|
||||||
|
if TTL > 28*24*60*60:
|
||||||
|
TTL = 28*24*60*60
|
||||||
fromAddress = addBMIfNotPresent(fromAddress)
|
fromAddress = addBMIfNotPresent(fromAddress)
|
||||||
self._verifyAddress(fromAddress)
|
self._verifyAddress(fromAddress)
|
||||||
try:
|
try:
|
||||||
|
@ -701,9 +730,21 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
toAddress = '[Broadcast subscribers]'
|
toAddress = '[Broadcast subscribers]'
|
||||||
ripe = ''
|
ripe = ''
|
||||||
|
|
||||||
|
t = ('',
|
||||||
t = ('', toAddress, ripe, fromAddress, subject, message, ackdata, int(
|
toAddress,
|
||||||
time.time()), 'broadcastqueued', 1, 1, 'sent', 2)
|
ripe,
|
||||||
|
fromAddress,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
ackdata,
|
||||||
|
int(time.time()), # sentTime (this doesn't change)
|
||||||
|
int(time.time()), # lastActionTime
|
||||||
|
0,
|
||||||
|
'broadcastqueued',
|
||||||
|
0,
|
||||||
|
'sent',
|
||||||
|
2,
|
||||||
|
TTL)
|
||||||
helper_sent.insert(t)
|
helper_sent.insert(t)
|
||||||
|
|
||||||
toLabel = '[Broadcast subscribers]'
|
toLabel = '[Broadcast subscribers]'
|
||||||
|
@ -940,22 +981,6 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
data += json.dumps({'data':payload.encode('hex')}, indent=4, separators=(',', ': '))
|
data += json.dumps({'data':payload.encode('hex')}, indent=4, separators=(',', ': '))
|
||||||
data += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
elif method == 'getPubkeyByHash':
|
|
||||||
# Method will eventually be used by a particular Android app to
|
|
||||||
# retrieve pubkeys. Please do not yet add this to the api docs.
|
|
||||||
if len(params) != 1:
|
|
||||||
raise APIError(0, 'I need 1 parameter!')
|
|
||||||
requestedHash, = params
|
|
||||||
if len(requestedHash) != 40:
|
|
||||||
raise APIError(19, 'The length of hash should be 20 bytes (encoded in hex thus 40 characters).')
|
|
||||||
requestedHash = self._decode(requestedHash, "hex")
|
|
||||||
queryreturn = sqlQuery('''SELECT transmitdata FROM pubkeys WHERE hash = ? ; ''', requestedHash)
|
|
||||||
data = '{"pubkey":['
|
|
||||||
for row in queryreturn:
|
|
||||||
transmitdata, = row
|
|
||||||
data += json.dumps({'data':transmitdata.encode('hex')}, indent=4, separators=(',', ': '))
|
|
||||||
data += ']}'
|
|
||||||
return data
|
|
||||||
elif method == 'clientStatus':
|
elif method == 'clientStatus':
|
||||||
if len(shared.connectedHostsList) == 0:
|
if len(shared.connectedHostsList) == 0:
|
||||||
networkStatus = 'notConnected'
|
networkStatus = 'notConnected'
|
||||||
|
|
|
@ -760,7 +760,7 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
|
||||||
exit_label="Continue")
|
exit_label="Continue")
|
||||||
ackdata = OpenSSL.rand(32)
|
ackdata = OpenSSL.rand(32)
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
"INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
||||||
"",
|
"",
|
||||||
addr,
|
addr,
|
||||||
ripe,
|
ripe,
|
||||||
|
@ -768,12 +768,14 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
|
||||||
subject,
|
subject,
|
||||||
body,
|
body,
|
||||||
ackdata,
|
ackdata,
|
||||||
int(time.time()),
|
int(time.time()), # sentTime (this will never change)
|
||||||
|
int(time.time()), # lastActionTime
|
||||||
|
0, # sleepTill time. This will get set when the POW gets done.
|
||||||
"msgqueued",
|
"msgqueued",
|
||||||
1,
|
0, # retryNumber
|
||||||
1,
|
|
||||||
"sent",
|
"sent",
|
||||||
2)
|
2, # encodingType
|
||||||
|
shared.config.getint('bitmessagesettings', 'ttl'))
|
||||||
shared.workerQueue.put(("sendmessage", addr))
|
shared.workerQueue.put(("sendmessage", addr))
|
||||||
else: # Broadcast
|
else: # Broadcast
|
||||||
if recv == "":
|
if recv == "":
|
||||||
|
@ -785,7 +787,7 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
|
||||||
recv = BROADCAST_STR
|
recv = BROADCAST_STR
|
||||||
ripe = ""
|
ripe = ""
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
"INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
||||||
"",
|
"",
|
||||||
recv,
|
recv,
|
||||||
ripe,
|
ripe,
|
||||||
|
@ -793,12 +795,14 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
|
||||||
subject,
|
subject,
|
||||||
body,
|
body,
|
||||||
ackdata,
|
ackdata,
|
||||||
int(time.time()),
|
int(time.time()), # sentTime (this will never change)
|
||||||
|
int(time.time()), # lastActionTime
|
||||||
|
0, # sleepTill time. This will get set when the POW gets done.
|
||||||
"broadcastqueued",
|
"broadcastqueued",
|
||||||
1,
|
0, # retryNumber
|
||||||
1,
|
"sent", # folder
|
||||||
"sent",
|
2, # encodingType
|
||||||
2)
|
shared.config.getint('bitmessagesettings', 'ttl'))
|
||||||
shared.workerQueue.put(('sendbroadcast', ''))
|
shared.workerQueue.put(('sendbroadcast', ''))
|
||||||
|
|
||||||
def loadInbox():
|
def loadInbox():
|
||||||
|
|
|
@ -20,6 +20,8 @@ import socket
|
||||||
import ctypes
|
import ctypes
|
||||||
from struct import pack
|
from struct import pack
|
||||||
import sys
|
import sys
|
||||||
|
from subprocess import call
|
||||||
|
import time
|
||||||
|
|
||||||
from SimpleXMLRPCServer import SimpleXMLRPCServer
|
from SimpleXMLRPCServer import SimpleXMLRPCServer
|
||||||
from api import MySimpleXMLRPCRequestHandler
|
from api import MySimpleXMLRPCRequestHandler
|
||||||
|
@ -30,16 +32,12 @@ from helper_sql import sqlQuery
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
# Classes
|
# Classes
|
||||||
#from helper_sql import *
|
|
||||||
#from class_sqlThread import *
|
|
||||||
from class_sqlThread import sqlThread
|
from class_sqlThread import sqlThread
|
||||||
from class_singleCleaner import singleCleaner
|
from class_singleCleaner import singleCleaner
|
||||||
#from class_singleWorker import *
|
|
||||||
from class_objectProcessor import objectProcessor
|
from class_objectProcessor import objectProcessor
|
||||||
from class_outgoingSynSender import outgoingSynSender
|
from class_outgoingSynSender import outgoingSynSender
|
||||||
from class_singleListener import singleListener
|
from class_singleListener import singleListener
|
||||||
from class_singleWorker import singleWorker
|
from class_singleWorker import singleWorker
|
||||||
#from class_addressGenerator import *
|
|
||||||
from class_addressGenerator import addressGenerator
|
from class_addressGenerator import addressGenerator
|
||||||
from debug import logger
|
from debug import logger
|
||||||
|
|
||||||
|
@ -47,9 +45,6 @@ from debug import logger
|
||||||
import helper_bootstrap
|
import helper_bootstrap
|
||||||
import helper_generic
|
import helper_generic
|
||||||
|
|
||||||
from subprocess import call
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def connectToStream(streamNumber):
|
def connectToStream(streamNumber):
|
||||||
shared.streamsInWhichIAmParticipating[streamNumber] = 'no data'
|
shared.streamsInWhichIAmParticipating[streamNumber] = 'no data'
|
||||||
|
|
|
@ -212,6 +212,8 @@ class MyForm(QtGui.QMainWindow):
|
||||||
"clicked()"), self.click_pushButtonAddSubscription)
|
"clicked()"), self.click_pushButtonAddSubscription)
|
||||||
QtCore.QObject.connect(self.ui.pushButtonAddBlacklist, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.ui.pushButtonAddBlacklist, QtCore.SIGNAL(
|
||||||
"clicked()"), self.click_pushButtonAddBlacklist)
|
"clicked()"), self.click_pushButtonAddBlacklist)
|
||||||
|
QtCore.QObject.connect(self.ui.pushButtonTTL, QtCore.SIGNAL(
|
||||||
|
"clicked()"), self.click_pushButtonTTL)
|
||||||
QtCore.QObject.connect(self.ui.pushButtonSend, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.ui.pushButtonSend, QtCore.SIGNAL(
|
||||||
"clicked()"), self.click_pushButtonSend)
|
"clicked()"), self.click_pushButtonSend)
|
||||||
QtCore.QObject.connect(self.ui.pushButtonLoadFromAddressBook,
|
QtCore.QObject.connect(self.ui.pushButtonLoadFromAddressBook,
|
||||||
|
@ -608,7 +610,7 @@ class MyForm(QtGui.QMainWindow):
|
||||||
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
||||||
"updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
|
"updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
|
||||||
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
||||||
"updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash)
|
"updateSentItemStatusByToAddress(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByToAddress)
|
||||||
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
||||||
"updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata)
|
"updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata)
|
||||||
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
||||||
|
@ -648,6 +650,18 @@ class MyForm(QtGui.QMainWindow):
|
||||||
|
|
||||||
self.rerenderComboBoxSendFrom()
|
self.rerenderComboBoxSendFrom()
|
||||||
|
|
||||||
|
# Put the TTL slider in the correct spot
|
||||||
|
TTL = shared.config.getint('bitmessagesettings', 'ttl')
|
||||||
|
if TTL < 3600: # an hour
|
||||||
|
TTL = 3600
|
||||||
|
elif TTL > 28*24*60*60: # 28 days
|
||||||
|
TTL = 28*24*60*60
|
||||||
|
self.ui.horizontalSliderTTL.setSliderPosition((TTL - 3600) ** (1/3.199))
|
||||||
|
self.updateHumanFriendlyTTLDescription(TTL)
|
||||||
|
|
||||||
|
QtCore.QObject.connect(self.ui.horizontalSliderTTL, QtCore.SIGNAL(
|
||||||
|
"valueChanged(int)"), self.updateTTL)
|
||||||
|
|
||||||
# Check to see whether we can connect to namecoin. Hide the 'Fetch Namecoin ID' button if we can't.
|
# Check to see whether we can connect to namecoin. Hide the 'Fetch Namecoin ID' button if we can't.
|
||||||
try:
|
try:
|
||||||
options = {}
|
options = {}
|
||||||
|
@ -663,6 +677,22 @@ class MyForm(QtGui.QMainWindow):
|
||||||
print 'There was a problem testing for a Namecoin daemon. Hiding the Fetch Namecoin ID button'
|
print 'There was a problem testing for a Namecoin daemon. Hiding the Fetch Namecoin ID button'
|
||||||
self.ui.pushButtonFetchNamecoinID.hide()
|
self.ui.pushButtonFetchNamecoinID.hide()
|
||||||
|
|
||||||
|
def updateTTL(self, sliderPosition):
|
||||||
|
TTL = int(sliderPosition ** 3.199 + 3600)
|
||||||
|
self.updateHumanFriendlyTTLDescription(TTL)
|
||||||
|
shared.config.set('bitmessagesettings', 'ttl', str(TTL))
|
||||||
|
shared.writeKeysFile()
|
||||||
|
|
||||||
|
def updateHumanFriendlyTTLDescription(self, TTL):
|
||||||
|
numberOfHours = int(round(TTL / (60*60)))
|
||||||
|
if numberOfHours < 48:
|
||||||
|
if numberOfHours == 1:
|
||||||
|
self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "1 hour"))
|
||||||
|
else:
|
||||||
|
self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%1 hours").arg(numberOfHours))
|
||||||
|
else:
|
||||||
|
numberOfDays = int(round(TTL / (24*60*60)))
|
||||||
|
self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%1 days").arg(numberOfDays))
|
||||||
|
|
||||||
# Show or hide the application window after clicking an item within the
|
# Show or hide the application window after clicking an item within the
|
||||||
# tray icon or, on Windows, the try icon itself.
|
# tray icon or, on Windows, the try icon itself.
|
||||||
|
@ -999,10 +1029,9 @@ class MyForm(QtGui.QMainWindow):
|
||||||
# create application indicator
|
# create application indicator
|
||||||
def appIndicatorInit(self, app):
|
def appIndicatorInit(self, app):
|
||||||
self.initTrayIcon("can-icon-24px-red.png", app)
|
self.initTrayIcon("can-icon-24px-red.png", app)
|
||||||
if sys.platform[0:3] == 'win':
|
traySignal = "activated(QSystemTrayIcon::ActivationReason)"
|
||||||
traySignal = "activated(QSystemTrayIcon::ActivationReason)"
|
QtCore.QObject.connect(self.tray, QtCore.SIGNAL(
|
||||||
QtCore.QObject.connect(self.tray, QtCore.SIGNAL(
|
traySignal), self.__icon_activated)
|
||||||
traySignal), self.__icon_activated)
|
|
||||||
|
|
||||||
m = QMenu()
|
m = QMenu()
|
||||||
|
|
||||||
|
@ -1450,18 +1479,16 @@ class MyForm(QtGui.QMainWindow):
|
||||||
self.init_blacklist_popup_menu(False)
|
self.init_blacklist_popup_menu(False)
|
||||||
if event.type() == QtCore.QEvent.WindowStateChange:
|
if event.type() == QtCore.QEvent.WindowStateChange:
|
||||||
if self.windowState() & QtCore.Qt.WindowMinimized:
|
if self.windowState() & QtCore.Qt.WindowMinimized:
|
||||||
self.actionShow.setChecked(False)
|
if shared.config.getboolean('bitmessagesettings', 'minimizetotray') and not 'darwin' in sys.platform:
|
||||||
if shared.config.getboolean('bitmessagesettings', 'minimizetotray') and not 'darwin' in sys.platform:
|
|
||||||
if event.type() == QtCore.QEvent.WindowStateChange:
|
|
||||||
if self.windowState() & QtCore.Qt.WindowMinimized:
|
|
||||||
self.appIndicatorHide()
|
self.appIndicatorHide()
|
||||||
if 'win32' in sys.platform or 'win64' in sys.platform:
|
if 'win32' in sys.platform or 'win64' in sys.platform:
|
||||||
self.setWindowFlags(Qt.ToolTip)
|
self.setWindowFlags(Qt.ToolTip)
|
||||||
elif event.oldState() & QtCore.Qt.WindowMinimized:
|
elif event.oldState() & QtCore.Qt.WindowMinimized:
|
||||||
# The window state has just been changed to
|
# The window state has just been changed to
|
||||||
# Normal/Maximised/FullScreen
|
# Normal/Maximised/FullScreen
|
||||||
pass
|
pass
|
||||||
# QtGui.QWidget.changeEvent(self, event)
|
# QtGui.QWidget.changeEvent(self, event)
|
||||||
|
|
||||||
|
|
||||||
def __icon_activated(self, reason):
|
def __icon_activated(self, reason):
|
||||||
if reason == QtGui.QSystemTrayIcon.Trigger:
|
if reason == QtGui.QSystemTrayIcon.Trigger:
|
||||||
|
@ -1667,13 +1694,11 @@ class MyForm(QtGui.QMainWindow):
|
||||||
cnt, = row
|
cnt, = row
|
||||||
return int(cnt)
|
return int(cnt)
|
||||||
|
|
||||||
def updateSentItemStatusByHash(self, toRipe, textToDisplay):
|
def updateSentItemStatusByToAddress(self, toAddress, textToDisplay):
|
||||||
for i in range(self.ui.tableWidgetSent.rowCount()):
|
for i in range(self.ui.tableWidgetSent.rowCount()):
|
||||||
toAddress = str(self.ui.tableWidgetSent.item(
|
rowAddress = str(self.ui.tableWidgetSent.item(
|
||||||
i, 0).data(Qt.UserRole).toPyObject())
|
i, 0).data(Qt.UserRole).toPyObject())
|
||||||
status, addressVersionNumber, streamNumber, ripe = decodeAddress(
|
if toAddress == rowAddress:
|
||||||
toAddress)
|
|
||||||
if ripe == toRipe:
|
|
||||||
self.ui.tableWidgetSent.item(i, 3).setToolTip(textToDisplay)
|
self.ui.tableWidgetSent.item(i, 3).setToolTip(textToDisplay)
|
||||||
try:
|
try:
|
||||||
newlinePosition = textToDisplay.indexOf('\n')
|
newlinePosition = textToDisplay.indexOf('\n')
|
||||||
|
@ -1871,6 +1896,13 @@ class MyForm(QtGui.QMainWindow):
|
||||||
newItem.setTextColor(QtGui.QColor(128, 128, 128))
|
newItem.setTextColor(QtGui.QColor(128, 128, 128))
|
||||||
self.ui.tableWidgetBlacklist.setItem(0, 1, newItem)
|
self.ui.tableWidgetBlacklist.setItem(0, 1, newItem)
|
||||||
|
|
||||||
|
def click_pushButtonTTL(self):
|
||||||
|
QtGui.QMessageBox.information(self, 'Time To Live', _translate(
|
||||||
|
"MainWindow", "The TTL, or Time-To-Live is the length of time that the network will hold the message. \
|
||||||
|
The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it \
|
||||||
|
will resend the message automatically. The longer the Time-To-Live, the \
|
||||||
|
more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate."), QMessageBox.Ok)
|
||||||
|
|
||||||
def click_pushButtonSend(self):
|
def click_pushButtonSend(self):
|
||||||
self.statusBar().showMessage('')
|
self.statusBar().showMessage('')
|
||||||
toAddresses = str(self.ui.lineEditTo.text())
|
toAddresses = str(self.ui.lineEditTo.text())
|
||||||
|
@ -1946,7 +1978,7 @@ class MyForm(QtGui.QMainWindow):
|
||||||
ackdata = OpenSSL.rand(32)
|
ackdata = OpenSSL.rand(32)
|
||||||
t = ()
|
t = ()
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)''',
|
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
|
||||||
'',
|
'',
|
||||||
toAddress,
|
toAddress,
|
||||||
ripe,
|
ripe,
|
||||||
|
@ -1954,12 +1986,15 @@ class MyForm(QtGui.QMainWindow):
|
||||||
subject,
|
subject,
|
||||||
message,
|
message,
|
||||||
ackdata,
|
ackdata,
|
||||||
int(time.time()),
|
int(time.time()), # sentTime (this will never change)
|
||||||
|
int(time.time()), # lastActionTime
|
||||||
|
0, # sleepTill time. This will get set when the POW gets done.
|
||||||
'msgqueued',
|
'msgqueued',
|
||||||
1,
|
0, # retryNumber
|
||||||
1,
|
'sent', # folder
|
||||||
'sent',
|
2, # encodingtype
|
||||||
2)
|
shared.config.getint('bitmessagesettings', 'ttl')
|
||||||
|
)
|
||||||
|
|
||||||
toLabel = ''
|
toLabel = ''
|
||||||
queryreturn = sqlQuery('''select label from addressbook where address=?''',
|
queryreturn = sqlQuery('''select label from addressbook where address=?''',
|
||||||
|
@ -1994,10 +2029,24 @@ class MyForm(QtGui.QMainWindow):
|
||||||
ackdata = OpenSSL.rand(32)
|
ackdata = OpenSSL.rand(32)
|
||||||
toAddress = self.str_broadcast_subscribers
|
toAddress = self.str_broadcast_subscribers
|
||||||
ripe = ''
|
ripe = ''
|
||||||
t = ('', toAddress, ripe, fromAddress, subject, message, ackdata, int(
|
t = ('', # msgid. We don't know what this will be until the POW is done.
|
||||||
time.time()), 'broadcastqueued', 1, 1, 'sent', 2)
|
toAddress,
|
||||||
|
ripe,
|
||||||
|
fromAddress,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
ackdata,
|
||||||
|
int(time.time()), # sentTime (this will never change)
|
||||||
|
int(time.time()), # lastActionTime
|
||||||
|
0, # sleepTill time. This will get set when the POW gets done.
|
||||||
|
'broadcastqueued',
|
||||||
|
0, # retryNumber
|
||||||
|
'sent', # folder
|
||||||
|
2, # encoding type
|
||||||
|
shared.config.getint('bitmessagesettings', 'ttl')
|
||||||
|
)
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)''', *t)
|
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', *t)
|
||||||
|
|
||||||
toLabel = self.str_broadcast_subscribers
|
toLabel = self.str_broadcast_subscribers
|
||||||
|
|
||||||
|
@ -2424,13 +2473,6 @@ class MyForm(QtGui.QMainWindow):
|
||||||
self.settingsDialogInstance.ui.lineEditDays.text())))
|
self.settingsDialogInstance.ui.lineEditDays.text())))
|
||||||
shared.config.set('bitmessagesettings', 'stopresendingafterxmonths', str(float(
|
shared.config.set('bitmessagesettings', 'stopresendingafterxmonths', str(float(
|
||||||
self.settingsDialogInstance.ui.lineEditMonths.text())))
|
self.settingsDialogInstance.ui.lineEditMonths.text())))
|
||||||
#end
|
|
||||||
|
|
||||||
# if str(self.settingsDialogInstance.ui.comboBoxMaxCores.currentText()) == 'All':
|
|
||||||
# shared.config.set('bitmessagesettings', 'maxcores', '99999')
|
|
||||||
# else:
|
|
||||||
# shared.config.set('bitmessagesettings', 'maxcores',
|
|
||||||
# str(self.settingsDialogInstance.ui.comboBoxMaxCores.currentText()))
|
|
||||||
|
|
||||||
shared.writeKeysFile()
|
shared.writeKeysFile()
|
||||||
|
|
||||||
|
@ -3449,9 +3491,6 @@ class settingsDialog(QtGui.QDialog):
|
||||||
self.ui.checkBoxStartOnLogon.setDisabled(True)
|
self.ui.checkBoxStartOnLogon.setDisabled(True)
|
||||||
self.ui.checkBoxStartOnLogon.setText(_translate(
|
self.ui.checkBoxStartOnLogon.setText(_translate(
|
||||||
"MainWindow", "Start-on-login not yet supported on your OS."))
|
"MainWindow", "Start-on-login not yet supported on your OS."))
|
||||||
self.ui.checkBoxMinimizeToTray.setDisabled(True)
|
|
||||||
self.ui.checkBoxMinimizeToTray.setText(_translate(
|
|
||||||
"MainWindow", "Minimize-to-tray not yet supported on your OS."))
|
|
||||||
# On the Network settings tab:
|
# On the Network settings tab:
|
||||||
self.ui.lineEditTCPPort.setText(str(
|
self.ui.lineEditTCPPort.setText(str(
|
||||||
shared.config.get('bitmessagesettings', 'port')))
|
shared.config.get('bitmessagesettings', 'port')))
|
||||||
|
@ -3762,8 +3801,6 @@ class NewAddressDialog(QtGui.QDialog):
|
||||||
# the 'Your Identities' tab.
|
# the 'Your Identities' tab.
|
||||||
while self.parent.ui.tableWidgetYourIdentities.item(row - 1, 1):
|
while self.parent.ui.tableWidgetYourIdentities.item(row - 1, 1):
|
||||||
self.ui.radioButtonExisting.click()
|
self.ui.radioButtonExisting.click()
|
||||||
# print
|
|
||||||
# self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text()
|
|
||||||
self.ui.comboBoxExisting.addItem(
|
self.ui.comboBoxExisting.addItem(
|
||||||
self.parent.ui.tableWidgetYourIdentities.item(row - 1, 1).text())
|
self.parent.ui.tableWidgetYourIdentities.item(row - 1, 1).text())
|
||||||
row += 1
|
row += 1
|
||||||
|
@ -3815,10 +3852,10 @@ class UISignaler(QThread):
|
||||||
"writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), label, address, str(streamNumber))
|
"writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), label, address, str(streamNumber))
|
||||||
elif command == 'updateStatusBar':
|
elif command == 'updateStatusBar':
|
||||||
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"), data)
|
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"), data)
|
||||||
elif command == 'updateSentItemStatusByHash':
|
elif command == 'updateSentItemStatusByToAddress':
|
||||||
hash, message = data
|
toAddress, message = data
|
||||||
self.emit(SIGNAL(
|
self.emit(SIGNAL(
|
||||||
"updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), hash, message)
|
"updateSentItemStatusByToAddress(PyQt_PyObject,PyQt_PyObject)"), toAddress, message)
|
||||||
elif command == 'updateSentItemStatusByAckdata':
|
elif command == 'updateSentItemStatusByAckdata':
|
||||||
ackData, message = data
|
ackData, message = data
|
||||||
self.emit(SIGNAL(
|
self.emit(SIGNAL(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'bitmessageui.ui'
|
# Form implementation generated from reading ui file 'bitmessageui.ui'
|
||||||
#
|
#
|
||||||
# Created: Mon Jan 05 16:21:20 2015
|
# Created: Sun Mar 08 22:07:43 2015
|
||||||
# by: PyQt4 UI code generator 4.10.3
|
# by: PyQt4 UI code generator 4.10.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -115,56 +115,46 @@ class Ui_MainWindow(object):
|
||||||
self.pushButtonLoadFromAddressBook.setFont(font)
|
self.pushButtonLoadFromAddressBook.setFont(font)
|
||||||
self.pushButtonLoadFromAddressBook.setObjectName(_fromUtf8("pushButtonLoadFromAddressBook"))
|
self.pushButtonLoadFromAddressBook.setObjectName(_fromUtf8("pushButtonLoadFromAddressBook"))
|
||||||
self.gridLayout_2.addWidget(self.pushButtonLoadFromAddressBook, 3, 2, 1, 1)
|
self.gridLayout_2.addWidget(self.pushButtonLoadFromAddressBook, 3, 2, 1, 1)
|
||||||
self.pushButtonFetchNamecoinID = QtGui.QPushButton(self.send)
|
self.label_3 = QtGui.QLabel(self.send)
|
||||||
font = QtGui.QFont()
|
self.label_3.setObjectName(_fromUtf8("label_3"))
|
||||||
font.setPointSize(7)
|
self.gridLayout_2.addWidget(self.label_3, 4, 0, 1, 1)
|
||||||
self.pushButtonFetchNamecoinID.setFont(font)
|
self.pushButtonSend = QtGui.QPushButton(self.send)
|
||||||
self.pushButtonFetchNamecoinID.setObjectName(_fromUtf8("pushButtonFetchNamecoinID"))
|
self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend"))
|
||||||
self.gridLayout_2.addWidget(self.pushButtonFetchNamecoinID, 3, 3, 1, 1)
|
self.gridLayout_2.addWidget(self.pushButtonSend, 7, 8, 1, 1)
|
||||||
self.label_4 = QtGui.QLabel(self.send)
|
self.horizontalSliderTTL = QtGui.QSlider(self.send)
|
||||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
self.horizontalSliderTTL.setMinimumSize(QtCore.QSize(35, 0))
|
||||||
self.gridLayout_2.addWidget(self.label_4, 5, 0, 1, 1)
|
self.horizontalSliderTTL.setMaximumSize(QtCore.QSize(70, 16777215))
|
||||||
|
self.horizontalSliderTTL.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.horizontalSliderTTL.setInvertedAppearance(False)
|
||||||
|
self.horizontalSliderTTL.setInvertedControls(False)
|
||||||
|
self.horizontalSliderTTL.setObjectName(_fromUtf8("horizontalSliderTTL"))
|
||||||
|
self.gridLayout_2.addWidget(self.horizontalSliderTTL, 7, 6, 1, 1)
|
||||||
|
spacerItem = QtGui.QSpacerItem(20, 297, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||||
|
self.gridLayout_2.addItem(spacerItem, 6, 0, 1, 1)
|
||||||
self.comboBoxSendFrom = QtGui.QComboBox(self.send)
|
self.comboBoxSendFrom = QtGui.QComboBox(self.send)
|
||||||
self.comboBoxSendFrom.setMinimumSize(QtCore.QSize(300, 0))
|
self.comboBoxSendFrom.setMinimumSize(QtCore.QSize(300, 0))
|
||||||
self.comboBoxSendFrom.setObjectName(_fromUtf8("comboBoxSendFrom"))
|
self.comboBoxSendFrom.setObjectName(_fromUtf8("comboBoxSendFrom"))
|
||||||
self.gridLayout_2.addWidget(self.comboBoxSendFrom, 2, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.comboBoxSendFrom, 2, 1, 1, 1)
|
||||||
self.label_3 = QtGui.QLabel(self.send)
|
self.labelHumanFriendlyTTLDescription = QtGui.QLabel(self.send)
|
||||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
|
||||||
self.gridLayout_2.addWidget(self.label_3, 4, 0, 1, 1)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
self.labelFrom = QtGui.QLabel(self.send)
|
sizePolicy.setVerticalStretch(0)
|
||||||
self.labelFrom.setText(_fromUtf8(""))
|
sizePolicy.setHeightForWidth(self.labelHumanFriendlyTTLDescription.sizePolicy().hasHeightForWidth())
|
||||||
self.labelFrom.setObjectName(_fromUtf8("labelFrom"))
|
self.labelHumanFriendlyTTLDescription.setSizePolicy(sizePolicy)
|
||||||
self.gridLayout_2.addWidget(self.labelFrom, 2, 2, 1, 3)
|
self.labelHumanFriendlyTTLDescription.setMinimumSize(QtCore.QSize(45, 0))
|
||||||
|
self.labelHumanFriendlyTTLDescription.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||||
|
self.labelHumanFriendlyTTLDescription.setObjectName(_fromUtf8("labelHumanFriendlyTTLDescription"))
|
||||||
|
self.gridLayout_2.addWidget(self.labelHumanFriendlyTTLDescription, 7, 7, 1, 1)
|
||||||
|
self.label_4 = QtGui.QLabel(self.send)
|
||||||
|
self.label_4.setObjectName(_fromUtf8("label_4"))
|
||||||
|
self.gridLayout_2.addWidget(self.label_4, 5, 0, 1, 1)
|
||||||
|
self.label = QtGui.QLabel(self.send)
|
||||||
|
self.label.setObjectName(_fromUtf8("label"))
|
||||||
|
self.gridLayout_2.addWidget(self.label, 3, 0, 1, 1)
|
||||||
self.radioButtonSpecific = QtGui.QRadioButton(self.send)
|
self.radioButtonSpecific = QtGui.QRadioButton(self.send)
|
||||||
self.radioButtonSpecific.setChecked(True)
|
self.radioButtonSpecific.setChecked(True)
|
||||||
self.radioButtonSpecific.setObjectName(_fromUtf8("radioButtonSpecific"))
|
self.radioButtonSpecific.setObjectName(_fromUtf8("radioButtonSpecific"))
|
||||||
self.gridLayout_2.addWidget(self.radioButtonSpecific, 0, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.radioButtonSpecific, 0, 1, 1, 1)
|
||||||
self.lineEditTo = QtGui.QLineEdit(self.send)
|
|
||||||
self.lineEditTo.setObjectName(_fromUtf8("lineEditTo"))
|
|
||||||
self.gridLayout_2.addWidget(self.lineEditTo, 3, 1, 1, 1)
|
|
||||||
self.textEditMessage = QtGui.QTextEdit(self.send)
|
|
||||||
self.textEditMessage.setObjectName(_fromUtf8("textEditMessage"))
|
|
||||||
self.gridLayout_2.addWidget(self.textEditMessage, 5, 1, 2, 5)
|
|
||||||
self.label = QtGui.QLabel(self.send)
|
|
||||||
self.label.setObjectName(_fromUtf8("label"))
|
|
||||||
self.gridLayout_2.addWidget(self.label, 3, 0, 1, 1)
|
|
||||||
self.label_2 = QtGui.QLabel(self.send)
|
|
||||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
|
||||||
self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
|
|
||||||
spacerItem = QtGui.QSpacerItem(20, 297, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
|
||||||
self.gridLayout_2.addItem(spacerItem, 6, 0, 1, 1)
|
|
||||||
self.radioButtonBroadcast = QtGui.QRadioButton(self.send)
|
|
||||||
self.radioButtonBroadcast.setObjectName(_fromUtf8("radioButtonBroadcast"))
|
|
||||||
self.gridLayout_2.addWidget(self.radioButtonBroadcast, 1, 1, 1, 3)
|
|
||||||
self.lineEditSubject = QtGui.QLineEdit(self.send)
|
|
||||||
self.lineEditSubject.setText(_fromUtf8(""))
|
|
||||||
self.lineEditSubject.setObjectName(_fromUtf8("lineEditSubject"))
|
|
||||||
self.gridLayout_2.addWidget(self.lineEditSubject, 4, 1, 1, 5)
|
|
||||||
spacerItem1 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
|
||||||
self.gridLayout_2.addItem(spacerItem1, 3, 4, 1, 1)
|
|
||||||
self.pushButtonSend = QtGui.QPushButton(self.send)
|
|
||||||
self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend"))
|
|
||||||
self.gridLayout_2.addWidget(self.pushButtonSend, 7, 5, 1, 1)
|
|
||||||
self.labelSendBroadcastWarning = QtGui.QLabel(self.send)
|
self.labelSendBroadcastWarning = QtGui.QLabel(self.send)
|
||||||
self.labelSendBroadcastWarning.setEnabled(True)
|
self.labelSendBroadcastWarning.setEnabled(True)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Preferred)
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Preferred)
|
||||||
|
@ -175,6 +165,56 @@ class Ui_MainWindow(object):
|
||||||
self.labelSendBroadcastWarning.setIndent(-1)
|
self.labelSendBroadcastWarning.setIndent(-1)
|
||||||
self.labelSendBroadcastWarning.setObjectName(_fromUtf8("labelSendBroadcastWarning"))
|
self.labelSendBroadcastWarning.setObjectName(_fromUtf8("labelSendBroadcastWarning"))
|
||||||
self.gridLayout_2.addWidget(self.labelSendBroadcastWarning, 7, 1, 1, 4)
|
self.gridLayout_2.addWidget(self.labelSendBroadcastWarning, 7, 1, 1, 4)
|
||||||
|
self.radioButtonBroadcast = QtGui.QRadioButton(self.send)
|
||||||
|
self.radioButtonBroadcast.setObjectName(_fromUtf8("radioButtonBroadcast"))
|
||||||
|
self.gridLayout_2.addWidget(self.radioButtonBroadcast, 1, 1, 1, 2)
|
||||||
|
self.pushButtonTTL = QtGui.QPushButton(self.send)
|
||||||
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.pushButtonTTL.sizePolicy().hasHeightForWidth())
|
||||||
|
self.pushButtonTTL.setSizePolicy(sizePolicy)
|
||||||
|
self.pushButtonTTL.setMaximumSize(QtCore.QSize(32, 16777215))
|
||||||
|
palette = QtGui.QPalette()
|
||||||
|
brush = QtGui.QBrush(QtGui.QColor(0, 0, 255))
|
||||||
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
|
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
|
||||||
|
brush = QtGui.QBrush(QtGui.QColor(0, 0, 255))
|
||||||
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
|
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
|
||||||
|
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
|
||||||
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
|
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
|
||||||
|
self.pushButtonTTL.setPalette(palette)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setUnderline(True)
|
||||||
|
self.pushButtonTTL.setFont(font)
|
||||||
|
self.pushButtonTTL.setFlat(True)
|
||||||
|
self.pushButtonTTL.setObjectName(_fromUtf8("pushButtonTTL"))
|
||||||
|
self.gridLayout_2.addWidget(self.pushButtonTTL, 7, 5, 1, 1)
|
||||||
|
self.label_2 = QtGui.QLabel(self.send)
|
||||||
|
self.label_2.setObjectName(_fromUtf8("label_2"))
|
||||||
|
self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
|
||||||
|
self.lineEditTo = QtGui.QLineEdit(self.send)
|
||||||
|
self.lineEditTo.setObjectName(_fromUtf8("lineEditTo"))
|
||||||
|
self.gridLayout_2.addWidget(self.lineEditTo, 3, 1, 1, 1)
|
||||||
|
self.textEditMessage = QtGui.QTextEdit(self.send)
|
||||||
|
self.textEditMessage.setObjectName(_fromUtf8("textEditMessage"))
|
||||||
|
self.gridLayout_2.addWidget(self.textEditMessage, 5, 1, 2, 8)
|
||||||
|
self.pushButtonFetchNamecoinID = QtGui.QPushButton(self.send)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(7)
|
||||||
|
self.pushButtonFetchNamecoinID.setFont(font)
|
||||||
|
self.pushButtonFetchNamecoinID.setObjectName(_fromUtf8("pushButtonFetchNamecoinID"))
|
||||||
|
self.gridLayout_2.addWidget(self.pushButtonFetchNamecoinID, 3, 3, 1, 1)
|
||||||
|
self.labelFrom = QtGui.QLabel(self.send)
|
||||||
|
self.labelFrom.setText(_fromUtf8(""))
|
||||||
|
self.labelFrom.setObjectName(_fromUtf8("labelFrom"))
|
||||||
|
self.gridLayout_2.addWidget(self.labelFrom, 2, 2, 1, 7)
|
||||||
|
self.lineEditSubject = QtGui.QLineEdit(self.send)
|
||||||
|
self.lineEditSubject.setText(_fromUtf8(""))
|
||||||
|
self.lineEditSubject.setObjectName(_fromUtf8("lineEditSubject"))
|
||||||
|
self.gridLayout_2.addWidget(self.lineEditSubject, 4, 1, 1, 8)
|
||||||
icon2 = QtGui.QIcon()
|
icon2 = QtGui.QIcon()
|
||||||
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/send.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/send.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
self.tabWidget.addTab(self.send, icon2, _fromUtf8(""))
|
self.tabWidget.addTab(self.send, icon2, _fromUtf8(""))
|
||||||
|
@ -239,8 +279,8 @@ class Ui_MainWindow(object):
|
||||||
self.pushButtonNewAddress = QtGui.QPushButton(self.youridentities)
|
self.pushButtonNewAddress = QtGui.QPushButton(self.youridentities)
|
||||||
self.pushButtonNewAddress.setObjectName(_fromUtf8("pushButtonNewAddress"))
|
self.pushButtonNewAddress.setObjectName(_fromUtf8("pushButtonNewAddress"))
|
||||||
self.gridLayout_3.addWidget(self.pushButtonNewAddress, 0, 0, 1, 1)
|
self.gridLayout_3.addWidget(self.pushButtonNewAddress, 0, 0, 1, 1)
|
||||||
spacerItem2 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
spacerItem1 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
self.gridLayout_3.addItem(spacerItem2, 0, 1, 1, 1)
|
self.gridLayout_3.addItem(spacerItem1, 0, 1, 1, 1)
|
||||||
self.tableWidgetYourIdentities = QtGui.QTableWidget(self.youridentities)
|
self.tableWidgetYourIdentities = QtGui.QTableWidget(self.youridentities)
|
||||||
self.tableWidgetYourIdentities.setFrameShadow(QtGui.QFrame.Sunken)
|
self.tableWidgetYourIdentities.setFrameShadow(QtGui.QFrame.Sunken)
|
||||||
self.tableWidgetYourIdentities.setLineWidth(1)
|
self.tableWidgetYourIdentities.setLineWidth(1)
|
||||||
|
@ -283,8 +323,8 @@ class Ui_MainWindow(object):
|
||||||
self.pushButtonAddSubscription = QtGui.QPushButton(self.subscriptions)
|
self.pushButtonAddSubscription = QtGui.QPushButton(self.subscriptions)
|
||||||
self.pushButtonAddSubscription.setObjectName(_fromUtf8("pushButtonAddSubscription"))
|
self.pushButtonAddSubscription.setObjectName(_fromUtf8("pushButtonAddSubscription"))
|
||||||
self.gridLayout_4.addWidget(self.pushButtonAddSubscription, 1, 0, 1, 1)
|
self.gridLayout_4.addWidget(self.pushButtonAddSubscription, 1, 0, 1, 1)
|
||||||
spacerItem3 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
spacerItem2 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
self.gridLayout_4.addItem(spacerItem3, 1, 1, 1, 1)
|
self.gridLayout_4.addItem(spacerItem2, 1, 1, 1, 1)
|
||||||
self.tableWidgetSubscriptions = QtGui.QTableWidget(self.subscriptions)
|
self.tableWidgetSubscriptions = QtGui.QTableWidget(self.subscriptions)
|
||||||
self.tableWidgetSubscriptions.setAlternatingRowColors(True)
|
self.tableWidgetSubscriptions.setAlternatingRowColors(True)
|
||||||
self.tableWidgetSubscriptions.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
|
self.tableWidgetSubscriptions.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
|
||||||
|
@ -317,8 +357,8 @@ class Ui_MainWindow(object):
|
||||||
self.pushButtonAddAddressBook = QtGui.QPushButton(self.addressbook)
|
self.pushButtonAddAddressBook = QtGui.QPushButton(self.addressbook)
|
||||||
self.pushButtonAddAddressBook.setObjectName(_fromUtf8("pushButtonAddAddressBook"))
|
self.pushButtonAddAddressBook.setObjectName(_fromUtf8("pushButtonAddAddressBook"))
|
||||||
self.gridLayout_5.addWidget(self.pushButtonAddAddressBook, 1, 0, 1, 1)
|
self.gridLayout_5.addWidget(self.pushButtonAddAddressBook, 1, 0, 1, 1)
|
||||||
spacerItem4 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
spacerItem3 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
self.gridLayout_5.addItem(spacerItem4, 1, 1, 1, 1)
|
self.gridLayout_5.addItem(spacerItem3, 1, 1, 1, 1)
|
||||||
self.tableWidgetAddressBook = QtGui.QTableWidget(self.addressbook)
|
self.tableWidgetAddressBook = QtGui.QTableWidget(self.addressbook)
|
||||||
self.tableWidgetAddressBook.setAlternatingRowColors(True)
|
self.tableWidgetAddressBook.setAlternatingRowColors(True)
|
||||||
self.tableWidgetAddressBook.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
|
self.tableWidgetAddressBook.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
|
||||||
|
@ -353,8 +393,8 @@ class Ui_MainWindow(object):
|
||||||
self.pushButtonAddBlacklist = QtGui.QPushButton(self.blackwhitelist)
|
self.pushButtonAddBlacklist = QtGui.QPushButton(self.blackwhitelist)
|
||||||
self.pushButtonAddBlacklist.setObjectName(_fromUtf8("pushButtonAddBlacklist"))
|
self.pushButtonAddBlacklist.setObjectName(_fromUtf8("pushButtonAddBlacklist"))
|
||||||
self.gridLayout_6.addWidget(self.pushButtonAddBlacklist, 2, 0, 1, 1)
|
self.gridLayout_6.addWidget(self.pushButtonAddBlacklist, 2, 0, 1, 1)
|
||||||
spacerItem5 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
spacerItem4 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
self.gridLayout_6.addItem(spacerItem5, 2, 1, 1, 1)
|
self.gridLayout_6.addItem(spacerItem4, 2, 1, 1, 1)
|
||||||
self.tableWidgetBlacklist = QtGui.QTableWidget(self.blackwhitelist)
|
self.tableWidgetBlacklist = QtGui.QTableWidget(self.blackwhitelist)
|
||||||
self.tableWidgetBlacklist.setAlternatingRowColors(True)
|
self.tableWidgetBlacklist.setAlternatingRowColors(True)
|
||||||
self.tableWidgetBlacklist.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
|
self.tableWidgetBlacklist.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
|
||||||
|
@ -556,20 +596,22 @@ class Ui_MainWindow(object):
|
||||||
item.setText(_translate("MainWindow", "Received", None))
|
item.setText(_translate("MainWindow", "Received", None))
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.inbox), _translate("MainWindow", "Inbox", None))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.inbox), _translate("MainWindow", "Inbox", None))
|
||||||
self.pushButtonLoadFromAddressBook.setText(_translate("MainWindow", "Load from Address book", None))
|
self.pushButtonLoadFromAddressBook.setText(_translate("MainWindow", "Load from Address book", None))
|
||||||
self.pushButtonFetchNamecoinID.setText(_translate("MainWindow", "Fetch Namecoin ID", None))
|
|
||||||
self.label_4.setText(_translate("MainWindow", "Message:", None))
|
|
||||||
self.label_3.setText(_translate("MainWindow", "Subject:", None))
|
self.label_3.setText(_translate("MainWindow", "Subject:", None))
|
||||||
|
self.pushButtonSend.setText(_translate("MainWindow", "Send", None))
|
||||||
|
self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "X days", None))
|
||||||
|
self.label_4.setText(_translate("MainWindow", "Message:", None))
|
||||||
|
self.label.setText(_translate("MainWindow", "To:", None))
|
||||||
self.radioButtonSpecific.setText(_translate("MainWindow", "Send to one or more specific people", None))
|
self.radioButtonSpecific.setText(_translate("MainWindow", "Send to one or more specific people", None))
|
||||||
|
self.labelSendBroadcastWarning.setText(_translate("MainWindow", "Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them.", None))
|
||||||
|
self.radioButtonBroadcast.setText(_translate("MainWindow", "Broadcast to everyone who is subscribed to your address", None))
|
||||||
|
self.pushButtonTTL.setText(_translate("MainWindow", "TTL:", None))
|
||||||
|
self.label_2.setText(_translate("MainWindow", "From:", None))
|
||||||
self.textEditMessage.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
self.textEditMessage.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||||
"p, li { white-space: pre-wrap; }\n"
|
"p, li { white-space: pre-wrap; }\n"
|
||||||
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
||||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>", None))
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>", None))
|
||||||
self.label.setText(_translate("MainWindow", "To:", None))
|
self.pushButtonFetchNamecoinID.setText(_translate("MainWindow", "Fetch Namecoin ID", None))
|
||||||
self.label_2.setText(_translate("MainWindow", "From:", None))
|
|
||||||
self.radioButtonBroadcast.setText(_translate("MainWindow", "Broadcast to everyone who is subscribed to your address", None))
|
|
||||||
self.pushButtonSend.setText(_translate("MainWindow", "Send", None))
|
|
||||||
self.labelSendBroadcastWarning.setText(_translate("MainWindow", "Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them.", None))
|
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None))
|
||||||
self.sentSearchLineEdit.setPlaceholderText(_translate("MainWindow", "Search", None))
|
self.sentSearchLineEdit.setPlaceholderText(_translate("MainWindow", "Search", None))
|
||||||
self.sentSearchOptionCB.setItemText(0, _translate("MainWindow", "All", None))
|
self.sentSearchOptionCB.setItemText(0, _translate("MainWindow", "All", None))
|
||||||
|
|
|
@ -216,35 +216,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="3">
|
|
||||||
<widget class="QPushButton" name="pushButtonFetchNamecoinID">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>7</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Fetch Namecoin ID</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Message:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QComboBox" name="comboBoxSendFrom">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>300</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -252,48 +223,35 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2" colspan="3">
|
<item row="7" column="8">
|
||||||
<widget class="QLabel" name="labelFrom">
|
<widget class="QPushButton" name="pushButtonSend">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string>Send</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="7" column="6">
|
||||||
<widget class="QRadioButton" name="radioButtonSpecific">
|
<widget class="QSlider" name="horizontalSliderTTL">
|
||||||
<property name="text">
|
<property name="minimumSize">
|
||||||
<string>Send to one or more specific people</string>
|
<size>
|
||||||
|
<width>35</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="maximumSize">
|
||||||
<bool>true</bool>
|
<size>
|
||||||
|
<width>70</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="orientation">
|
||||||
</item>
|
<enum>Qt::Horizontal</enum>
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="lineEditTo"/>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1" rowspan="2" colspan="5">
|
|
||||||
<widget class="QTextEdit" name="textEditMessage">
|
|
||||||
<property name="html">
|
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
|
||||||
p, li { white-space: pre-wrap; }
|
|
||||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;">
|
|
||||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="invertedAppearance">
|
||||||
</item>
|
<bool>false</bool>
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>To:</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="invertedControls">
|
||||||
</item>
|
<bool>false</bool>
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>From:</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -310,37 +268,62 @@ p, li { white-space: pre-wrap; }
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" colspan="3">
|
<item row="2" column="1">
|
||||||
<widget class="QRadioButton" name="radioButtonBroadcast">
|
<widget class="QComboBox" name="comboBoxSendFrom">
|
||||||
<property name="text">
|
<property name="minimumSize">
|
||||||
<string>Broadcast to everyone who is subscribed to your address</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1" colspan="5">
|
|
||||||
<widget class="QLineEdit" name="lineEditSubject">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="4">
|
|
||||||
<spacer name="horizontalSpacer_6">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>300</width>
|
||||||
<height>20</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="5">
|
<item row="7" column="7">
|
||||||
<widget class="QPushButton" name="pushButtonSend">
|
<widget class="QLabel" name="labelHumanFriendlyTTLDescription">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>45</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>45</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Send</string>
|
<string>X days</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Message:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>To:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QRadioButton" name="radioButtonSpecific">
|
||||||
|
<property name="text">
|
||||||
|
<string>Send to one or more specific people</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -363,6 +346,124 @@ p, li { white-space: pre-wrap; }
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="1" colspan="2">
|
||||||
|
<widget class="QRadioButton" name="radioButtonBroadcast">
|
||||||
|
<property name="text">
|
||||||
|
<string>Broadcast to everyone who is subscribed to your address</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="5">
|
||||||
|
<widget class="QPushButton" name="pushButtonTTL">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="ButtonText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="ButtonText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="ButtonText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>120</red>
|
||||||
|
<green>120</green>
|
||||||
|
<blue>120</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<underline>true</underline>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>TTL:</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>From:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditTo"/>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1" rowspan="2" colspan="8">
|
||||||
|
<widget class="QTextEdit" name="textEditMessage">
|
||||||
|
<property name="html">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="3">
|
||||||
|
<widget class="QPushButton" name="pushButtonFetchNamecoinID">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>7</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Fetch Namecoin ID</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2" colspan="7">
|
||||||
|
<widget class="QLabel" name="labelFrom">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1" colspan="8">
|
||||||
|
<widget class="QLineEdit" name="lineEditSubject">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="sent">
|
<widget class="QWidget" name="sent">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'help.ui'
|
# Form implementation generated from reading ui file 'help.ui'
|
||||||
#
|
#
|
||||||
# Created: Mon Mar 11 11:20:54 2013
|
# Created: Wed Jan 14 22:42:39 2015
|
||||||
# by: PyQt4 UI code generator 4.9.4
|
# by: PyQt4 UI code generator 4.9.4
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -43,6 +43,6 @@ class Ui_helpDialog(object):
|
||||||
|
|
||||||
def retranslateUi(self, helpDialog):
|
def retranslateUi(self, helpDialog):
|
||||||
helpDialog.setWindowTitle(QtGui.QApplication.translate("helpDialog", "Help", None, QtGui.QApplication.UnicodeUTF8))
|
helpDialog.setWindowTitle(QtGui.QApplication.translate("helpDialog", "Help", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.labelHelpURI.setText(QtGui.QApplication.translate("helpDialog", "<a href=\"http://Bitmessage.org/wiki/PyBitmessage_Help\">http://Bitmessage.org/wiki/PyBitmessage_Help</a>", None, QtGui.QApplication.UnicodeUTF8))
|
self.labelHelpURI.setText(QtGui.QApplication.translate("helpDialog", "<a href=\"https://bitmessage.org/wiki/PyBitmessage_Help\">https://bitmessage.org/wiki/PyBitmessage_Help</a>", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label.setText(QtGui.QApplication.translate("helpDialog", "As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki:", None, QtGui.QApplication.UnicodeUTF8))
|
self.label.setText(QtGui.QApplication.translate("helpDialog", "As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki:", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>335</width>
|
<width>405</width>
|
||||||
<height>96</height>
|
<height>104</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="labelHelpURI">
|
<widget class="QLabel" name="labelHelpURI">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><a href="http://Bitmessage.org/wiki/PyBitmessage_Help">http://Bitmessage.org/wiki/PyBitmessage_Help</a></string>
|
<string><a href="https://bitmessage.org/wiki/PyBitmessage_Help">https://bitmessage.org/wiki/PyBitmessage_Help</a></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="openExternalLinks">
|
<property name="openExternalLinks">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|
|
@ -201,7 +201,7 @@ class objectProcessor(threading.Thread):
|
||||||
ripe = ripeHasher.digest()
|
ripe = ripeHasher.digest()
|
||||||
|
|
||||||
|
|
||||||
logger.info('within recpubkey, addressVersion: %s, streamNumber: %s \n\
|
logger.debug('within recpubkey, addressVersion: %s, streamNumber: %s \n\
|
||||||
ripe %s\n\
|
ripe %s\n\
|
||||||
publicSigningKey in hex: %s\n\
|
publicSigningKey in hex: %s\n\
|
||||||
publicEncryptionKey in hex: %s' % (addressVersion,
|
publicEncryptionKey in hex: %s' % (addressVersion,
|
||||||
|
@ -212,17 +212,19 @@ class objectProcessor(threading.Thread):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
queryreturn = sqlQuery(
|
|
||||||
'''SELECT usedpersonally FROM pubkeys WHERE hash=? AND addressversion=? AND usedpersonally='yes' ''', ripe, addressVersion)
|
|
||||||
|
|
||||||
|
address = encodeAddress(addressVersion, streamNumber, ripe)
|
||||||
|
|
||||||
|
queryreturn = sqlQuery(
|
||||||
|
'''SELECT usedpersonally FROM pubkeys WHERE address=? AND usedpersonally='yes' ''', address)
|
||||||
if queryreturn != []: # if this pubkey is already in our database and if we have used it personally:
|
if queryreturn != []: # if this pubkey is already in our database and if we have used it personally:
|
||||||
logger.info('We HAVE used this pubkey personally. Updating time.')
|
logger.info('We HAVE used this pubkey personally. Updating time.')
|
||||||
t = (ripe, addressVersion, dataToStore, int(time.time()), 'yes')
|
t = (address, addressVersion, dataToStore, int(time.time()), 'yes')
|
||||||
else:
|
else:
|
||||||
logger.info('We have NOT used this pubkey personally. Inserting in database.')
|
logger.info('We have NOT used this pubkey personally. Inserting in database.')
|
||||||
t = (ripe, addressVersion, dataToStore, int(time.time()), 'no')
|
t = (address, addressVersion, dataToStore, int(time.time()), 'no')
|
||||||
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
||||||
self.possibleNewPubkey(ripe = ripe)
|
self.possibleNewPubkey(address)
|
||||||
if addressVersion == 3:
|
if addressVersion == 3:
|
||||||
if len(data) < 170: # sanity check.
|
if len(data) < 170: # sanity check.
|
||||||
logger.warning('(within processpubkey) payloadLength less than 170. Sanity check failed.')
|
logger.warning('(within processpubkey) payloadLength less than 170. Sanity check failed.')
|
||||||
|
@ -258,7 +260,7 @@ class objectProcessor(threading.Thread):
|
||||||
ripe = ripeHasher.digest()
|
ripe = ripeHasher.digest()
|
||||||
|
|
||||||
|
|
||||||
logger.info('within recpubkey, addressVersion: %s, streamNumber: %s \n\
|
logger.debug('within recpubkey, addressVersion: %s, streamNumber: %s \n\
|
||||||
ripe %s\n\
|
ripe %s\n\
|
||||||
publicSigningKey in hex: %s\n\
|
publicSigningKey in hex: %s\n\
|
||||||
publicEncryptionKey in hex: %s' % (addressVersion,
|
publicEncryptionKey in hex: %s' % (addressVersion,
|
||||||
|
@ -269,16 +271,16 @@ class objectProcessor(threading.Thread):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
address = encodeAddress(addressVersion, streamNumber, ripe)
|
||||||
queryreturn = sqlQuery('''SELECT usedpersonally FROM pubkeys WHERE hash=? AND addressversion=? AND usedpersonally='yes' ''', ripe, addressVersion)
|
queryreturn = sqlQuery('''SELECT usedpersonally FROM pubkeys WHERE address=? AND usedpersonally='yes' ''', address)
|
||||||
if queryreturn != []: # if this pubkey is already in our database and if we have used it personally:
|
if queryreturn != []: # if this pubkey is already in our database and if we have used it personally:
|
||||||
logger.info('We HAVE used this pubkey personally. Updating time.')
|
logger.info('We HAVE used this pubkey personally. Updating time.')
|
||||||
t = (ripe, addressVersion, dataToStore, int(time.time()), 'yes')
|
t = (address, addressVersion, dataToStore, int(time.time()), 'yes')
|
||||||
else:
|
else:
|
||||||
logger.info('We have NOT used this pubkey personally. Inserting in database.')
|
logger.info('We have NOT used this pubkey personally. Inserting in database.')
|
||||||
t = (ripe, addressVersion, dataToStore, int(time.time()), 'no')
|
t = (address, addressVersion, dataToStore, int(time.time()), 'no')
|
||||||
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
||||||
self.possibleNewPubkey(ripe = ripe)
|
self.possibleNewPubkey(address)
|
||||||
|
|
||||||
if addressVersion == 4:
|
if addressVersion == 4:
|
||||||
if len(data) < 350: # sanity check.
|
if len(data) < 350: # sanity check.
|
||||||
|
@ -296,7 +298,7 @@ class objectProcessor(threading.Thread):
|
||||||
# At this point we know that we have been waiting on this pubkey.
|
# At this point we know that we have been waiting on this pubkey.
|
||||||
# This function will command the workerThread to start work on
|
# This function will command the workerThread to start work on
|
||||||
# the messages that require it.
|
# the messages that require it.
|
||||||
self.possibleNewPubkey(address=toAddress)
|
self.possibleNewPubkey(toAddress)
|
||||||
|
|
||||||
# Display timing data
|
# Display timing data
|
||||||
timeRequiredToProcessPubkey = time.time(
|
timeRequiredToProcessPubkey = time.time(
|
||||||
|
@ -325,8 +327,10 @@ class objectProcessor(threading.Thread):
|
||||||
if data[-32:] in shared.ackdataForWhichImWatching:
|
if data[-32:] in shared.ackdataForWhichImWatching:
|
||||||
logger.info('This msg IS an acknowledgement bound for me.')
|
logger.info('This msg IS an acknowledgement bound for me.')
|
||||||
del shared.ackdataForWhichImWatching[data[-32:]]
|
del shared.ackdataForWhichImWatching[data[-32:]]
|
||||||
sqlExecute('UPDATE sent SET status=? WHERE ackdata=?',
|
sqlExecute('UPDATE sent SET status=?, lastactiontime=? WHERE ackdata=?',
|
||||||
'ackreceived', data[-32:])
|
'ackreceived',
|
||||||
|
int(time.time()),
|
||||||
|
data[-32:])
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (data[-32:], tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(l10n.formatTimestamp()))))
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (data[-32:], tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(l10n.formatTimestamp()))))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -427,6 +431,7 @@ class objectProcessor(threading.Thread):
|
||||||
logger.debug('As a matter of intellectual curiosity, here is the Bitcoin address associated with the keys owned by the other person: %s ..and here is the testnet address: %s. The other person must take their private signing key from Bitmessage and import it into Bitcoin (or a service like Blockchain.info) for it to be of any use. Do not use this unless you know what you are doing.' %
|
logger.debug('As a matter of intellectual curiosity, here is the Bitcoin address associated with the keys owned by the other person: %s ..and here is the testnet address: %s. The other person must take their private signing key from Bitmessage and import it into Bitcoin (or a service like Blockchain.info) for it to be of any use. Do not use this unless you know what you are doing.' %
|
||||||
(helper_bitcoin.calculateBitcoinAddressFromPubkey(pubSigningKey), helper_bitcoin.calculateTestnetAddressFromPubkey(pubSigningKey))
|
(helper_bitcoin.calculateBitcoinAddressFromPubkey(pubSigningKey), helper_bitcoin.calculateTestnetAddressFromPubkey(pubSigningKey))
|
||||||
)
|
)
|
||||||
|
sigHash = hashlib.sha512(hashlib.sha512(signature).digest()).digest()[32:] # Used to detect and ignore duplicate messages in our inbox
|
||||||
|
|
||||||
# calculate the fromRipe.
|
# calculate the fromRipe.
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
|
@ -440,7 +445,7 @@ class objectProcessor(threading.Thread):
|
||||||
# person.
|
# person.
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
|
'''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
|
||||||
ripe.digest(),
|
fromAddress,
|
||||||
sendersAddressVersionNumber,
|
sendersAddressVersionNumber,
|
||||||
decryptedData[:endOfThePublicKeyPosition],
|
decryptedData[:endOfThePublicKeyPosition],
|
||||||
int(time.time()),
|
int(time.time()),
|
||||||
|
@ -449,10 +454,7 @@ class objectProcessor(threading.Thread):
|
||||||
# Check to see whether we happen to be awaiting this
|
# 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
|
# pubkey in order to send a message. If we are, it will do the POW
|
||||||
# and send it.
|
# and send it.
|
||||||
if sendersAddressVersionNumber <= 3:
|
self.possibleNewPubkey(fromAddress)
|
||||||
self.possibleNewPubkey(ripe=ripe.digest())
|
|
||||||
elif sendersAddressVersionNumber >= 4:
|
|
||||||
self.possibleNewPubkey(address = fromAddress)
|
|
||||||
|
|
||||||
# If this message is bound for one of my version 3 addresses (or
|
# If this message is bound for one of my version 3 addresses (or
|
||||||
# higher), then we must check to make sure it meets our demanded
|
# higher), then we must check to make sure it meets our demanded
|
||||||
|
@ -503,13 +505,13 @@ class objectProcessor(threading.Thread):
|
||||||
body = 'Unknown encoding type.\n\n' + repr(message)
|
body = 'Unknown encoding type.\n\n' + repr(message)
|
||||||
subject = ''
|
subject = ''
|
||||||
# Let us make sure that we haven't already received this message
|
# Let us make sure that we haven't already received this message
|
||||||
if helper_inbox.isMessageAlreadyInInbox(toAddress, fromAddress, subject, body, messageEncodingType):
|
if helper_inbox.isMessageAlreadyInInbox(sigHash):
|
||||||
logger.info('This msg is already in our inbox. Ignoring it.')
|
logger.info('This msg is already in our inbox. Ignoring it.')
|
||||||
blockMessage = True
|
blockMessage = True
|
||||||
if not blockMessage:
|
if not blockMessage:
|
||||||
if messageEncodingType != 0:
|
if messageEncodingType != 0:
|
||||||
t = (inventoryHash, toAddress, fromAddress, subject, int(
|
t = (inventoryHash, toAddress, fromAddress, subject, int(
|
||||||
time.time()), body, 'inbox', messageEncodingType, 0)
|
time.time()), body, 'inbox', messageEncodingType, 0, sigHash)
|
||||||
helper_inbox.insert(t)
|
helper_inbox.insert(t)
|
||||||
|
|
||||||
shared.UISignalQueue.put(('displayNewInboxMessage', (
|
shared.UISignalQueue.put(('displayNewInboxMessage', (
|
||||||
|
@ -547,8 +549,25 @@ class objectProcessor(threading.Thread):
|
||||||
toAddress = '[Broadcast subscribers]'
|
toAddress = '[Broadcast subscribers]'
|
||||||
ripe = ''
|
ripe = ''
|
||||||
|
|
||||||
t = ('', toAddress, ripe, fromAddress, subject, message, ackdataForBroadcast, int(
|
# We really should have a discussion about how to
|
||||||
time.time()), 'broadcastqueued', 1, 1, 'sent', 2)
|
# set the TTL for mailing list broadcasts. This is obviously
|
||||||
|
# hard-coded.
|
||||||
|
TTL = 2*7*24*60*60 # 2 weeks
|
||||||
|
t = ('',
|
||||||
|
toAddress,
|
||||||
|
ripe,
|
||||||
|
fromAddress,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
ackdataForBroadcast,
|
||||||
|
int(time.time()), # sentTime (this doesn't change)
|
||||||
|
int(time.time()), # lastActionTime
|
||||||
|
0,
|
||||||
|
'broadcastqueued',
|
||||||
|
0,
|
||||||
|
'sent',
|
||||||
|
2,
|
||||||
|
TTL)
|
||||||
helper_sent.insert(t)
|
helper_sent.insert(t)
|
||||||
|
|
||||||
shared.UISignalQueue.put(('displayNewSentMessage', (
|
shared.UISignalQueue.put(('displayNewSentMessage', (
|
||||||
|
@ -701,6 +720,7 @@ class objectProcessor(threading.Thread):
|
||||||
logger.debug('ECDSA verify failed')
|
logger.debug('ECDSA verify failed')
|
||||||
return
|
return
|
||||||
logger.debug('ECDSA verify passed')
|
logger.debug('ECDSA verify passed')
|
||||||
|
sigHash = hashlib.sha512(hashlib.sha512(signature).digest()).digest()[32:] # Used to detect and ignore duplicate messages in our inbox
|
||||||
|
|
||||||
fromAddress = encodeAddress(
|
fromAddress = encodeAddress(
|
||||||
sendersAddressVersion, sendersStream, calculatedRipe)
|
sendersAddressVersion, sendersStream, calculatedRipe)
|
||||||
|
@ -708,7 +728,7 @@ class objectProcessor(threading.Thread):
|
||||||
|
|
||||||
# Let's store the public key in case we want to reply to this person.
|
# Let's store the public key in case we want to reply to this person.
|
||||||
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
|
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
|
||||||
calculatedRipe,
|
fromAddress,
|
||||||
sendersAddressVersion,
|
sendersAddressVersion,
|
||||||
decryptedData[:endOfPubkeyPosition],
|
decryptedData[:endOfPubkeyPosition],
|
||||||
int(time.time()),
|
int(time.time()),
|
||||||
|
@ -717,10 +737,7 @@ class objectProcessor(threading.Thread):
|
||||||
# Check to see whether we happen to be awaiting this
|
# 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
|
# pubkey in order to send a message. If we are, it will do the POW
|
||||||
# and send it.
|
# and send it.
|
||||||
if broadcastVersion == 4:
|
self.possibleNewPubkey(fromAddress)
|
||||||
self.possibleNewPubkey(ripe=calculatedRipe)
|
|
||||||
elif broadcastVersion == 5:
|
|
||||||
self.possibleNewPubkey(address=fromAddress)
|
|
||||||
|
|
||||||
fromAddress = encodeAddress(
|
fromAddress = encodeAddress(
|
||||||
sendersAddressVersion, sendersStream, calculatedRipe)
|
sendersAddressVersion, sendersStream, calculatedRipe)
|
||||||
|
@ -735,63 +752,65 @@ class objectProcessor(threading.Thread):
|
||||||
subject = ''
|
subject = ''
|
||||||
elif messageEncodingType == 0:
|
elif messageEncodingType == 0:
|
||||||
logger.info('messageEncodingType == 0. Doing nothing with the message.')
|
logger.info('messageEncodingType == 0. Doing nothing with the message.')
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
body = 'Unknown encoding type.\n\n' + repr(message)
|
body = 'Unknown encoding type.\n\n' + repr(message)
|
||||||
subject = ''
|
subject = ''
|
||||||
|
|
||||||
toAddress = '[Broadcast subscribers]'
|
toAddress = '[Broadcast subscribers]'
|
||||||
if messageEncodingType != 0:
|
if helper_inbox.isMessageAlreadyInInbox(sigHash):
|
||||||
if helper_inbox.isMessageAlreadyInInbox(toAddress, fromAddress, subject, body, messageEncodingType):
|
logger.info('This broadcast is already in our inbox. Ignoring it.')
|
||||||
logger.info('This broadcast is already in our inbox. Ignoring it.')
|
return
|
||||||
else:
|
t = (inventoryHash, toAddress, fromAddress, subject, int(
|
||||||
t = (inventoryHash, toAddress, fromAddress, subject, int(
|
time.time()), body, 'inbox', messageEncodingType, 0, sigHash)
|
||||||
time.time()), body, 'inbox', messageEncodingType, 0)
|
helper_inbox.insert(t)
|
||||||
helper_inbox.insert(t)
|
|
||||||
|
|
||||||
shared.UISignalQueue.put(('displayNewInboxMessage', (
|
shared.UISignalQueue.put(('displayNewInboxMessage', (
|
||||||
inventoryHash, toAddress, fromAddress, subject, body)))
|
inventoryHash, toAddress, fromAddress, subject, body)))
|
||||||
|
|
||||||
# If we are behaving as an API then we might need to run an
|
# If we are behaving as an API then we might need to run an
|
||||||
# outside command to let some program know that a new message
|
# outside command to let some program know that a new message
|
||||||
# has arrived.
|
# has arrived.
|
||||||
if shared.safeConfigGetBoolean('bitmessagesettings', 'apienabled'):
|
if shared.safeConfigGetBoolean('bitmessagesettings', 'apienabled'):
|
||||||
try:
|
try:
|
||||||
apiNotifyPath = shared.config.get(
|
apiNotifyPath = shared.config.get(
|
||||||
'bitmessagesettings', 'apinotifypath')
|
'bitmessagesettings', 'apinotifypath')
|
||||||
except:
|
except:
|
||||||
apiNotifyPath = ''
|
apiNotifyPath = ''
|
||||||
if apiNotifyPath != '':
|
if apiNotifyPath != '':
|
||||||
call([apiNotifyPath, "newBroadcast"])
|
call([apiNotifyPath, "newBroadcast"])
|
||||||
|
|
||||||
# Display timing data
|
# Display timing data
|
||||||
logger.info('Time spent processing this interesting broadcast: %s' % (time.time() - messageProcessingStartTime,))
|
logger.info('Time spent processing this interesting broadcast: %s' % (time.time() - messageProcessingStartTime,))
|
||||||
|
|
||||||
|
|
||||||
def possibleNewPubkey(self, ripe=None, address=None):
|
def possibleNewPubkey(self, address):
|
||||||
"""
|
"""
|
||||||
We have inserted a pubkey into our pubkey table which we received from a
|
We have inserted a pubkey into our pubkey table which we received from a
|
||||||
pubkey, msg, or broadcast message. It might be one that we have been
|
pubkey, msg, or broadcast message. It might be one that we have been
|
||||||
waiting for. Let's check.
|
waiting for. Let's check.
|
||||||
"""
|
"""
|
||||||
# For address versions <= 3, we wait on a key with the correct ripe hash
|
|
||||||
if ripe != None:
|
# For address versions <= 3, we wait on a key with the correct address version,
|
||||||
if ripe in shared.neededPubkeys:
|
# stream number, and RIPE hash.
|
||||||
del shared.neededPubkeys[ripe]
|
status, addressVersion, streamNumber, ripe = decodeAddress(address)
|
||||||
self.sendMessages(ripe)
|
if addressVersion <=3:
|
||||||
|
if address in shared.neededPubkeys:
|
||||||
|
del shared.neededPubkeys[address]
|
||||||
|
self.sendMessages(address)
|
||||||
else:
|
else:
|
||||||
logger.debug('We don\'t need this pub key. We didn\'t ask for it. Pubkey hash: %s' % ripe.encode('hex'))
|
logger.debug('We don\'t need this pub key. We didn\'t ask for it. For address: %s' % address)
|
||||||
# For address versions >= 4, we wait on a pubkey with the correct tag.
|
# For address versions >= 4, we wait on a pubkey with the correct tag.
|
||||||
# Let us create the tag from the address and see if we were waiting
|
# Let us create the tag from the address and see if we were waiting
|
||||||
# for it.
|
# for it.
|
||||||
elif address != None:
|
elif addressVersion >= 4:
|
||||||
status, addressVersion, streamNumber, ripe = decodeAddress(address)
|
|
||||||
tag = hashlib.sha512(hashlib.sha512(encodeVarint(
|
tag = hashlib.sha512(hashlib.sha512(encodeVarint(
|
||||||
addressVersion) + encodeVarint(streamNumber) + ripe).digest()).digest()[32:]
|
addressVersion) + encodeVarint(streamNumber) + ripe).digest()).digest()[32:]
|
||||||
if tag in shared.neededPubkeys:
|
if tag in shared.neededPubkeys:
|
||||||
del shared.neededPubkeys[tag]
|
del shared.neededPubkeys[tag]
|
||||||
self.sendMessages(ripe)
|
self.sendMessages(address)
|
||||||
|
|
||||||
def sendMessages(self, ripe):
|
def sendMessages(self, address):
|
||||||
"""
|
"""
|
||||||
This function is called by the possibleNewPubkey function when
|
This function is called by the possibleNewPubkey function when
|
||||||
that function sees that we now have the necessary pubkey
|
that function sees that we now have the necessary pubkey
|
||||||
|
@ -799,8 +818,8 @@ class objectProcessor(threading.Thread):
|
||||||
"""
|
"""
|
||||||
logger.info('We have been awaiting the arrival of this pubkey.')
|
logger.info('We have been awaiting the arrival of this pubkey.')
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET status='doingmsgpow' WHERE toripe=? AND (status='awaitingpubkey' or status='doingpubkeypow') and folder='sent' ''',
|
'''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='awaitingpubkey' or status='doingpubkeypow') AND folder='sent' ''',
|
||||||
ripe)
|
address)
|
||||||
shared.workerQueue.put(('sendmessage', ''))
|
shared.workerQueue.put(('sendmessage', ''))
|
||||||
|
|
||||||
def ackDataHasAVaildHeader(self, ackData):
|
def ackDataHasAVaildHeader(self, ackData):
|
||||||
|
|
|
@ -16,11 +16,7 @@ import traceback
|
||||||
#import highlevelcrypto
|
#import highlevelcrypto
|
||||||
from addresses import *
|
from addresses import *
|
||||||
from helper_generic import addDataPadding, isHostInPrivateIPRange
|
from helper_generic import addDataPadding, isHostInPrivateIPRange
|
||||||
#import helper_bitcoin
|
from helper_sql import sqlQuery
|
||||||
#import helper_inbox
|
|
||||||
#import helper_sent
|
|
||||||
from helper_sql import *
|
|
||||||
#import tr
|
|
||||||
from debug import logger
|
from debug import logger
|
||||||
|
|
||||||
# This thread is created either by the synSenderThread(for outgoing
|
# This thread is created either by the synSenderThread(for outgoing
|
||||||
|
@ -151,9 +147,8 @@ class receiveDataThread(threading.Thread):
|
||||||
# just received valid data from it. So update the knownNodes list so
|
# just received valid data from it. So update the knownNodes list so
|
||||||
# that other peers can be made aware of its existance.
|
# that other peers can be made aware of its existance.
|
||||||
if self.initiatedConnection and self.connectionIsOrWasFullyEstablished: # 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).
|
if self.initiatedConnection and self.connectionIsOrWasFullyEstablished: # 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).
|
||||||
shared.knownNodesLock.acquire()
|
with shared.knownNodesLock:
|
||||||
shared.knownNodes[self.streamNumber][self.peer] = int(time.time())
|
shared.knownNodes[self.streamNumber][self.peer] = int(time.time())
|
||||||
shared.knownNodesLock.release()
|
|
||||||
|
|
||||||
#Strip the nulls
|
#Strip the nulls
|
||||||
command = command.rstrip('\x00')
|
command = command.rstrip('\x00')
|
||||||
|
@ -479,7 +474,7 @@ class receiveDataThread(threading.Thread):
|
||||||
payload, = row
|
payload, = row
|
||||||
self.sendObject(payload)
|
self.sendObject(payload)
|
||||||
else:
|
else:
|
||||||
logger.warning('%s asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. We probably cleaned it out after advertising it but before they got around to asking for it.' % self.peer)
|
logger.warning('%s asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. We probably cleaned it out after advertising it but before they got around to asking for it.' % (self.peer,))
|
||||||
|
|
||||||
# Our peer has requested (in a getdata message) that we send an object.
|
# Our peer has requested (in a getdata message) that we send an object.
|
||||||
def sendObject(self, payload):
|
def sendObject(self, payload):
|
||||||
|
@ -488,35 +483,33 @@ class receiveDataThread(threading.Thread):
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('object',payload)))
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('object',payload)))
|
||||||
|
|
||||||
|
|
||||||
def _checkIPv4Address(self, host, hostFromAddrMessage):
|
def _checkIPv4Address(self, host, hostStandardFormat):
|
||||||
# print 'hostFromAddrMessage', hostFromAddrMessage
|
# print 'hostStandardFormat', hostStandardFormat
|
||||||
if host[0] == '\x7F':
|
if host[0] == '\x7F':
|
||||||
print 'Ignoring IP address in loopback range:', hostFromAddrMessage
|
print 'Ignoring IP address in loopback range:', hostStandardFormat
|
||||||
return False
|
return False
|
||||||
if host[0] == '\x0A':
|
if host[0] == '\x0A':
|
||||||
print 'Ignoring IP address in private range:', hostFromAddrMessage
|
print 'Ignoring IP address in private range:', hostStandardFormat
|
||||||
return False
|
return False
|
||||||
if host[0:2] == '\xC0\xA8':
|
if host[0:2] == '\xC0\xA8':
|
||||||
print 'Ignoring IP address in private range:', hostFromAddrMessage
|
print 'Ignoring IP address in private range:', hostStandardFormat
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _checkIPv6Address(self, host, hostFromAddrMessage):
|
def _checkIPv6Address(self, host, hostStandardFormat):
|
||||||
if host == ('\x00' * 15) + '\x01':
|
if host == ('\x00' * 15) + '\x01':
|
||||||
print 'Ignoring loopback address:', hostFromAddrMessage
|
print 'Ignoring loopback address:', hostStandardFormat
|
||||||
return False
|
return False
|
||||||
if host[0] == '\xFE' and (ord(host[1]) & 0xc0) == 0x80:
|
if host[0] == '\xFE' and (ord(host[1]) & 0xc0) == 0x80:
|
||||||
print 'Ignoring local address:', hostFromAddrMessage
|
print 'Ignoring local address:', hostStandardFormat
|
||||||
return False
|
return False
|
||||||
if (ord(host[0]) & 0xfe) == 0xfc:
|
if (ord(host[0]) & 0xfe) == 0xfc:
|
||||||
print 'Ignoring unique local address:', hostFromAddrMessage
|
print 'Ignoring unique local address:', hostStandardFormat
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# We have received an addr message.
|
# We have received an addr message.
|
||||||
def recaddr(self, data):
|
def recaddr(self, data):
|
||||||
#listOfAddressDetailsToBroadcastToPeers = []
|
|
||||||
numberOfAddressesIncluded = 0
|
|
||||||
numberOfAddressesIncluded, lengthOfNumberOfAddresses = decodeVarint(
|
numberOfAddressesIncluded, lengthOfNumberOfAddresses = decodeVarint(
|
||||||
data[:10])
|
data[:10])
|
||||||
|
|
||||||
|
@ -531,91 +524,56 @@ class receiveDataThread(threading.Thread):
|
||||||
return
|
return
|
||||||
|
|
||||||
for i in range(0, numberOfAddressesIncluded):
|
for i in range(0, numberOfAddressesIncluded):
|
||||||
try:
|
fullHost = data[20 + lengthOfNumberOfAddresses + (38 * i):36 + lengthOfNumberOfAddresses + (38 * i)]
|
||||||
fullHost = data[20 + lengthOfNumberOfAddresses + (38 * i):36 + lengthOfNumberOfAddresses + (38 * i)]
|
recaddrStream, = unpack('>I', data[8 + lengthOfNumberOfAddresses + (
|
||||||
except Exception as err:
|
38 * i):12 + lengthOfNumberOfAddresses + (38 * i)])
|
||||||
with shared.printLock:
|
|
||||||
sys.stderr.write(
|
|
||||||
'ERROR TRYING TO UNPACK recaddr (recaddrHost). Message: %s\n' % str(err))
|
|
||||||
break # giving up on unpacking any more. We should still be connected however.
|
|
||||||
|
|
||||||
try:
|
|
||||||
recaddrStream, = unpack('>I', data[8 + lengthOfNumberOfAddresses + (
|
|
||||||
38 * i):12 + lengthOfNumberOfAddresses + (38 * i)])
|
|
||||||
except Exception as err:
|
|
||||||
with shared.printLock:
|
|
||||||
sys.stderr.write(
|
|
||||||
'ERROR TRYING TO UNPACK recaddr (recaddrStream). Message: %s\n' % str(err))
|
|
||||||
break # giving up on unpacking any more. We should still be connected however.
|
|
||||||
if recaddrStream == 0:
|
if recaddrStream == 0:
|
||||||
continue
|
continue
|
||||||
if recaddrStream != self.streamNumber and recaddrStream != (self.streamNumber * 2) and recaddrStream != ((self.streamNumber * 2) + 1): # if the embedded stream number is not in my stream or either of my child streams then ignore it. Someone might be trying funny business.
|
if recaddrStream != self.streamNumber and recaddrStream != (self.streamNumber * 2) and recaddrStream != ((self.streamNumber * 2) + 1): # if the embedded stream number is not in my stream or either of my child streams then ignore it. Someone might be trying funny business.
|
||||||
continue
|
continue
|
||||||
try:
|
recaddrServices, = unpack('>Q', data[12 + lengthOfNumberOfAddresses + (
|
||||||
recaddrServices, = unpack('>Q', data[12 + lengthOfNumberOfAddresses + (
|
38 * i):20 + lengthOfNumberOfAddresses + (38 * i)])
|
||||||
38 * i):20 + lengthOfNumberOfAddresses + (38 * i)])
|
recaddrPort, = unpack('>H', data[36 + lengthOfNumberOfAddresses + (
|
||||||
except Exception as err:
|
38 * i):38 + lengthOfNumberOfAddresses + (38 * i)])
|
||||||
with shared.printLock:
|
|
||||||
sys.stderr.write(
|
|
||||||
'ERROR TRYING TO UNPACK recaddr (recaddrServices). Message: %s\n' % str(err))
|
|
||||||
break # giving up on unpacking any more. We should still be connected however.
|
|
||||||
|
|
||||||
try:
|
|
||||||
recaddrPort, = unpack('>H', data[36 + lengthOfNumberOfAddresses + (
|
|
||||||
38 * i):38 + lengthOfNumberOfAddresses + (38 * i)])
|
|
||||||
except Exception as err:
|
|
||||||
with shared.printLock:
|
|
||||||
sys.stderr.write(
|
|
||||||
'ERROR TRYING TO UNPACK recaddr (recaddrPort). Message: %s\n' % str(err))
|
|
||||||
break # giving up on unpacking any more. We should still be connected however.
|
|
||||||
# print 'Within recaddr(): IP', recaddrIP, ', Port',
|
|
||||||
# recaddrPort, ', i', i
|
|
||||||
if fullHost[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF':
|
if fullHost[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF':
|
||||||
ipv4Host = fullHost[12:]
|
ipv4Host = fullHost[12:]
|
||||||
hostFromAddrMessage = socket.inet_ntop(socket.AF_INET, ipv4Host)
|
hostStandardFormat = socket.inet_ntop(socket.AF_INET, ipv4Host)
|
||||||
if not self._checkIPv4Address(ipv4Host, hostFromAddrMessage):
|
if not self._checkIPv4Address(ipv4Host, hostStandardFormat):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
hostFromAddrMessage = socket.inet_ntop(socket.AF_INET6, fullHost)
|
hostStandardFormat = socket.inet_ntop(socket.AF_INET6, fullHost)
|
||||||
if hostFromAddrMessage == "":
|
if hostStandardFormat == "":
|
||||||
# This can happen on Windows systems which are not 64-bit compatible
|
# This can happen on Windows systems which are not 64-bit compatible
|
||||||
# so let us drop the IPv6 address.
|
# so let us drop the IPv6 address.
|
||||||
continue
|
continue
|
||||||
if not self._checkIPv6Address(fullHost, hostFromAddrMessage):
|
if not self._checkIPv6Address(fullHost, hostStandardFormat):
|
||||||
continue
|
continue
|
||||||
timeSomeoneElseReceivedMessageFromThisNode, = unpack('>Q', data[lengthOfNumberOfAddresses + (
|
timeSomeoneElseReceivedMessageFromThisNode, = unpack('>Q', data[lengthOfNumberOfAddresses + (
|
||||||
38 * i):8 + lengthOfNumberOfAddresses + (38 * i)]) # This is the 'time' value in the received addr message. 64-bit.
|
38 * i):8 + lengthOfNumberOfAddresses + (38 * i)]) # This is the 'time' value in the received addr message. 64-bit.
|
||||||
if recaddrStream not in shared.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.
|
if recaddrStream not in shared.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.
|
||||||
shared.knownNodesLock.acquire()
|
with shared.knownNodesLock:
|
||||||
shared.knownNodes[recaddrStream] = {}
|
shared.knownNodes[recaddrStream] = {}
|
||||||
shared.knownNodesLock.release()
|
peerFromAddrMessage = shared.Peer(hostStandardFormat, recaddrPort)
|
||||||
peerFromAddrMessage = shared.Peer(hostFromAddrMessage, recaddrPort)
|
|
||||||
if peerFromAddrMessage not in shared.knownNodes[recaddrStream]:
|
if peerFromAddrMessage not in shared.knownNodes[recaddrStream]:
|
||||||
if len(shared.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.
|
if len(shared.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.
|
||||||
shared.knownNodesLock.acquire()
|
with shared.knownNodesLock:
|
||||||
shared.knownNodes[recaddrStream][peerFromAddrMessage] = (
|
shared.knownNodes[recaddrStream][peerFromAddrMessage] = timeSomeoneElseReceivedMessageFromThisNode
|
||||||
timeSomeoneElseReceivedMessageFromThisNode)
|
|
||||||
shared.knownNodesLock.release()
|
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'added new node', peerFromAddrMessage, 'to knownNodes in stream', recaddrStream
|
print 'added new node', peerFromAddrMessage, 'to knownNodes in stream', recaddrStream
|
||||||
|
|
||||||
shared.needToWriteKnownNodesToDisk = True
|
shared.needToWriteKnownNodesToDisk = True
|
||||||
hostDetails = (
|
hostDetails = (
|
||||||
timeSomeoneElseReceivedMessageFromThisNode,
|
timeSomeoneElseReceivedMessageFromThisNode,
|
||||||
recaddrStream, recaddrServices, hostFromAddrMessage, recaddrPort)
|
recaddrStream, recaddrServices, hostStandardFormat, recaddrPort)
|
||||||
#listOfAddressDetailsToBroadcastToPeers.append(hostDetails)
|
|
||||||
shared.broadcastToSendDataQueues((
|
shared.broadcastToSendDataQueues((
|
||||||
self.streamNumber, 'advertisepeer', hostDetails))
|
self.streamNumber, 'advertisepeer', hostDetails))
|
||||||
else:
|
else:
|
||||||
timeLastReceivedMessageFromThisNode = shared.knownNodes[recaddrStream][
|
timeLastReceivedMessageFromThisNode = shared.knownNodes[recaddrStream][
|
||||||
peerFromAddrMessage] # 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.
|
peerFromAddrMessage]
|
||||||
if (timeLastReceivedMessageFromThisNode < timeSomeoneElseReceivedMessageFromThisNode) and (timeSomeoneElseReceivedMessageFromThisNode < int(time.time())):
|
if (timeLastReceivedMessageFromThisNode < timeSomeoneElseReceivedMessageFromThisNode) and (timeSomeoneElseReceivedMessageFromThisNode < int(time.time())+900): # 900 seconds for wiggle-room in case other nodes' clocks aren't quite right.
|
||||||
shared.knownNodesLock.acquire()
|
with shared.knownNodesLock:
|
||||||
shared.knownNodes[recaddrStream][peerFromAddrMessage] = timeSomeoneElseReceivedMessageFromThisNode
|
shared.knownNodes[recaddrStream][peerFromAddrMessage] = timeSomeoneElseReceivedMessageFromThisNode
|
||||||
shared.knownNodesLock.release()
|
|
||||||
|
|
||||||
#if listOfAddressDetailsToBroadcastToPeers != []:
|
|
||||||
# self.broadcastaddr(listOfAddressDetailsToBroadcastToPeers)
|
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'knownNodes currently has', len(shared.knownNodes[self.streamNumber]), 'nodes for this stream.'
|
print 'knownNodes currently has', len(shared.knownNodes[self.streamNumber]), 'nodes for this stream.'
|
||||||
|
|
||||||
|
@ -633,31 +591,30 @@ class receiveDataThread(threading.Thread):
|
||||||
# We are going to share a maximum number of 1000 addrs with our peer.
|
# We are going to share a maximum number of 1000 addrs with our peer.
|
||||||
# 500 from this stream, 250 from the left child stream, and 250 from
|
# 500 from this stream, 250 from the left child stream, and 250 from
|
||||||
# the right child stream.
|
# the right child stream.
|
||||||
shared.knownNodesLock.acquire()
|
with shared.knownNodesLock:
|
||||||
if len(shared.knownNodes[self.streamNumber]) > 0:
|
if len(shared.knownNodes[self.streamNumber]) > 0:
|
||||||
for i in range(500):
|
for i in range(500):
|
||||||
peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
|
peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
|
||||||
if isHostInPrivateIPRange(peer.host):
|
if isHostInPrivateIPRange(peer.host):
|
||||||
continue
|
continue
|
||||||
addrsInMyStream[peer] = shared.knownNodes[
|
addrsInMyStream[peer] = shared.knownNodes[
|
||||||
self.streamNumber][peer]
|
self.streamNumber][peer]
|
||||||
if len(shared.knownNodes[self.streamNumber * 2]) > 0:
|
if len(shared.knownNodes[self.streamNumber * 2]) > 0:
|
||||||
for i in range(250):
|
for i in range(250):
|
||||||
peer, = random.sample(shared.knownNodes[
|
peer, = random.sample(shared.knownNodes[
|
||||||
self.streamNumber * 2], 1)
|
self.streamNumber * 2], 1)
|
||||||
if isHostInPrivateIPRange(peer.host):
|
if isHostInPrivateIPRange(peer.host):
|
||||||
continue
|
continue
|
||||||
addrsInChildStreamLeft[peer] = shared.knownNodes[
|
addrsInChildStreamLeft[peer] = shared.knownNodes[
|
||||||
self.streamNumber * 2][peer]
|
self.streamNumber * 2][peer]
|
||||||
if len(shared.knownNodes[(self.streamNumber * 2) + 1]) > 0:
|
if len(shared.knownNodes[(self.streamNumber * 2) + 1]) > 0:
|
||||||
for i in range(250):
|
for i in range(250):
|
||||||
peer, = random.sample(shared.knownNodes[
|
peer, = random.sample(shared.knownNodes[
|
||||||
(self.streamNumber * 2) + 1], 1)
|
(self.streamNumber * 2) + 1], 1)
|
||||||
if isHostInPrivateIPRange(peer.host):
|
if isHostInPrivateIPRange(peer.host):
|
||||||
continue
|
continue
|
||||||
addrsInChildStreamRight[peer] = shared.knownNodes[
|
addrsInChildStreamRight[peer] = shared.knownNodes[
|
||||||
(self.streamNumber * 2) + 1][peer]
|
(self.streamNumber * 2) + 1][peer]
|
||||||
shared.knownNodesLock.release()
|
|
||||||
numberOfAddressesInAddrMessage = 0
|
numberOfAddressesInAddrMessage = 0
|
||||||
payload = ''
|
payload = ''
|
||||||
# print 'addrsInMyStream.items()', addrsInMyStream.items()
|
# print 'addrsInMyStream.items()', addrsInMyStream.items()
|
||||||
|
@ -771,10 +728,9 @@ class receiveDataThread(threading.Thread):
|
||||||
# in this version message. Let us inform the sendDataThread.
|
# in this version message. Let us inform the sendDataThread.
|
||||||
self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))
|
self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))
|
||||||
|
|
||||||
shared.knownNodesLock.acquire()
|
with shared.knownNodesLock:
|
||||||
shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
|
shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
|
||||||
shared.needToWriteKnownNodesToDisk = True
|
shared.needToWriteKnownNodesToDisk = True
|
||||||
shared.knownNodesLock.release()
|
|
||||||
|
|
||||||
self.sendverack()
|
self.sendverack()
|
||||||
if self.initiatedConnection == False:
|
if self.initiatedConnection == False:
|
||||||
|
|
|
@ -76,23 +76,23 @@ class singleCleaner(threading.Thread):
|
||||||
'''DELETE FROM pubkeys WHERE time<? AND usedpersonally='no' ''',
|
'''DELETE FROM pubkeys WHERE time<? AND usedpersonally='no' ''',
|
||||||
int(time.time()) - shared.lengthOfTimeToHoldOnToAllPubkeys)
|
int(time.time()) - shared.lengthOfTimeToHoldOnToAllPubkeys)
|
||||||
|
|
||||||
|
# Let us resend getpubkey objects if we have not yet heard a pubkey, and also msg objects if we have not yet heard an acknowledgement
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''select toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, pubkeyretrynumber, msgretrynumber FROM sent WHERE ((status='awaitingpubkey' OR status='msgsent') AND folder='sent' AND lastactiontime>?) ''',
|
'''select toaddress, ackdata, status FROM sent WHERE ((status='awaitingpubkey' OR status='msgsent') AND folder='sent' AND sleeptill<? AND senttime>?) ''',
|
||||||
int(time.time()) - shared.maximumLengthOfTimeToBotherResendingMessages) # If the message's folder='trash' then we'll ignore it.
|
int(time.time()),
|
||||||
|
int(time.time()) - shared.maximumLengthOfTimeToBotherResendingMessages)
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
if len(row) < 5:
|
if len(row) < 2:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
'Something went wrong in the singleCleaner thread: a query did not return the requested fields. ' + repr(row))
|
'Something went wrong in the singleCleaner thread: a query did not return the requested fields. ' + repr(row))
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
break
|
break
|
||||||
toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, pubkeyretrynumber, msgretrynumber = row
|
toAddress, ackData, status = row
|
||||||
if status == 'awaitingpubkey':
|
if status == 'awaitingpubkey':
|
||||||
if (int(time.time()) - lastactiontime) > (shared.maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (pubkeyretrynumber))):
|
resendPubkeyRequest(toAddress)
|
||||||
resendPubkey(pubkeyretrynumber,toripe)
|
elif status == 'msgsent':
|
||||||
else: # status == msgsent
|
resendMsg(ackData)
|
||||||
if (int(time.time()) - lastactiontime) > (shared.maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (msgretrynumber))):
|
|
||||||
resendMsg(msgretrynumber,ackdata)
|
|
||||||
|
|
||||||
# Let's also clear and reload shared.inventorySets to keep it from
|
# Let's also clear and reload shared.inventorySets to keep it from
|
||||||
# taking up an unnecessary amount of memory.
|
# taking up an unnecessary amount of memory.
|
||||||
|
@ -126,32 +126,26 @@ class singleCleaner(threading.Thread):
|
||||||
time.sleep(300)
|
time.sleep(300)
|
||||||
|
|
||||||
|
|
||||||
def resendPubkey(pubkeyretrynumber,toripe):
|
def resendPubkeyRequest(address):
|
||||||
print 'It has been a long time and we haven\'t heard a response to our getpubkey request. Sending again.'
|
logger.debug('It has been a long time and we haven\'t heard a response to our getpubkey request. Sending again.')
|
||||||
try:
|
try:
|
||||||
del shared.neededPubkeys[
|
del shared.neededPubkeys[
|
||||||
toripe] # We need to take this entry out of the shared.neededPubkeys structure because the shared.workerQueue checks to see whether the entry is already present and will not do the POW and send the message because it assumes that it has already done it recently.
|
address] # We need to take this entry out of the shared.neededPubkeys structure because the shared.workerQueue checks to see whether the entry is already present and will not do the POW and send the message because it assumes that it has already done it recently.
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
shared.UISignalQueue.put((
|
shared.UISignalQueue.put((
|
||||||
'updateStatusBar', 'Doing work necessary to again attempt to request a public key...'))
|
'updateStatusBar', 'Doing work necessary to again attempt to request a public key...'))
|
||||||
t = ()
|
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=?, status='msgqueued' WHERE toripe=?''',
|
'''UPDATE sent SET status='msgqueued' WHERE toaddress=?''',
|
||||||
int(time.time()),
|
address)
|
||||||
pubkeyretrynumber + 1,
|
|
||||||
toripe)
|
|
||||||
shared.workerQueue.put(('sendmessage', ''))
|
shared.workerQueue.put(('sendmessage', ''))
|
||||||
|
|
||||||
def resendMsg(msgretrynumber,ackdata):
|
def resendMsg(ackdata):
|
||||||
print 'It has been a long time and we haven\'t heard an acknowledgement to our msg. Sending again.'
|
logger.debug('It has been a long time and we haven\'t heard an acknowledgement to our msg. Sending again.')
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET lastactiontime=?, msgretrynumber=?, status=? WHERE ackdata=?''',
|
'''UPDATE sent SET status='msgqueued' WHERE ackdata=?''',
|
||||||
int(time.time()),
|
ackdata)
|
||||||
msgretrynumber + 1,
|
|
||||||
'msgqueued',
|
|
||||||
ackdata)
|
|
||||||
shared.workerQueue.put(('sendmessage', ''))
|
shared.workerQueue.put(('sendmessage', ''))
|
||||||
shared.UISignalQueue.put((
|
shared.UISignalQueue.put((
|
||||||
'updateStatusBar', 'Doing work necessary to again attempt to deliver a message...'))
|
'updateStatusBar', 'Doing work necessary to again attempt to deliver a message...'))
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
import shared
|
import shared
|
||||||
import time
|
import time
|
||||||
|
@ -26,13 +28,15 @@ class singleWorker(threading.Thread):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
|
# Initialize the neededPubkeys dictionary.
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT DISTINCT toaddress FROM sent WHERE (status='awaitingpubkey' AND folder='sent')''')
|
'''SELECT DISTINCT toaddress FROM sent WHERE (status='awaitingpubkey' AND folder='sent')''')
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
toAddress, = row
|
toAddress, = row
|
||||||
toStatus, toAddressVersionNumber, toStreamNumber, toRipe = decodeAddress(toAddress)
|
toStatus, toAddressVersionNumber, toStreamNumber, toRipe = decodeAddress(toAddress)
|
||||||
if toAddressVersionNumber <= 3 :
|
if toAddressVersionNumber <= 3 :
|
||||||
shared.neededPubkeys[toRipe] = 0
|
shared.neededPubkeys[toAddress] = 0
|
||||||
elif toAddressVersionNumber >= 4:
|
elif toAddressVersionNumber >= 4:
|
||||||
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(encodeVarint(
|
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(encodeVarint(
|
||||||
toAddressVersionNumber) + encodeVarint(toStreamNumber) + toRipe).digest()).digest()
|
toAddressVersionNumber) + encodeVarint(toStreamNumber) + toRipe).digest()).digest()
|
||||||
|
@ -48,15 +52,15 @@ class singleWorker(threading.Thread):
|
||||||
print 'Watching for ackdata', ackdata.encode('hex')
|
print 'Watching for ackdata', ackdata.encode('hex')
|
||||||
shared.ackdataForWhichImWatching[ackdata] = 0
|
shared.ackdataForWhichImWatching[ackdata] = 0
|
||||||
|
|
||||||
|
time.sleep(
|
||||||
|
10) # give some time for the GUI to start before we start on existing POW tasks.
|
||||||
|
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT DISTINCT toaddress FROM sent WHERE (status='doingpubkeypow' AND folder='sent')''')
|
'''SELECT DISTINCT toaddress FROM sent WHERE (status='doingpubkeypow' AND folder='sent')''')
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
toaddress, = row
|
toaddress, = row
|
||||||
self.requestPubKey(toaddress)
|
self.requestPubKey(toaddress)
|
||||||
|
|
||||||
time.sleep(
|
|
||||||
10) # give some time for the GUI to start before we start on existing POW tasks.
|
|
||||||
|
|
||||||
self.sendMsg()
|
self.sendMsg()
|
||||||
# just in case there are any pending tasks for msg
|
# just in case there are any pending tasks for msg
|
||||||
# messages that have yet to be sent.
|
# messages that have yet to be sent.
|
||||||
|
@ -349,9 +353,9 @@ class singleWorker(threading.Thread):
|
||||||
|
|
||||||
def sendBroadcast(self):
|
def sendBroadcast(self):
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT fromaddress, subject, message, ackdata FROM sent WHERE status=? and folder='sent' ''', 'broadcastqueued')
|
'''SELECT fromaddress, subject, message, ackdata, ttl FROM sent WHERE status=? and folder='sent' ''', 'broadcastqueued')
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
fromaddress, subject, body, ackdata = row
|
fromaddress, subject, body, ackdata, TTL = row
|
||||||
status, addressVersionNumber, streamNumber, ripe = decodeAddress(
|
status, addressVersionNumber, streamNumber, ripe = decodeAddress(
|
||||||
fromaddress)
|
fromaddress)
|
||||||
if addressVersionNumber <= 1:
|
if addressVersionNumber <= 1:
|
||||||
|
@ -381,7 +385,11 @@ class singleWorker(threading.Thread):
|
||||||
pubEncryptionKey = highlevelcrypto.privToPub(
|
pubEncryptionKey = highlevelcrypto.privToPub(
|
||||||
privEncryptionKeyHex).decode('hex')
|
privEncryptionKeyHex).decode('hex')
|
||||||
|
|
||||||
TTL = int(28 * 24 * 60 * 60 + random.randrange(-300, 300))# 28 days from now plus or minus five minutes
|
if TTL > 28 * 24 * 60 * 60:
|
||||||
|
TTL = 28 * 24 * 60 * 60
|
||||||
|
if TTL < 60*60:
|
||||||
|
TTL = 60*60
|
||||||
|
TTL = int(TTL + random.randrange(-300, 300))# add some randomness to the TTL
|
||||||
embeddedTime = int(time.time() + TTL)
|
embeddedTime = int(time.time() + TTL)
|
||||||
payload = pack('>Q', embeddedTime)
|
payload = pack('>Q', embeddedTime)
|
||||||
payload += '\x00\x00\x00\x03' # object type: broadcast
|
payload += '\x00\x00\x00\x03' # object type: broadcast
|
||||||
|
@ -477,12 +485,12 @@ class singleWorker(threading.Thread):
|
||||||
|
|
||||||
# Select just one msg that needs work.
|
# Select just one msg that needs work.
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT toaddress, toripe, fromaddress, subject, message, ackdata, status FROM sent WHERE (status='msgqueued' or status='doingmsgpow' or status='forcepow') and folder='sent' LIMIT 1''')
|
'''SELECT toaddress, fromaddress, subject, message, ackdata, status, ttl, retrynumber FROM sent WHERE (status='msgqueued' or status='doingmsgpow' or status='forcepow') and folder='sent' LIMIT 1''')
|
||||||
if len(queryreturn) == 0: # if there is no work to do then
|
if len(queryreturn) == 0: # if there is no work to do then
|
||||||
break # break out of this sendMsg loop and
|
break # break out of this sendMsg loop and
|
||||||
# wait for something to get put in the shared.workerQueue.
|
# wait for something to get put in the shared.workerQueue.
|
||||||
row = queryreturn[0]
|
row = queryreturn[0]
|
||||||
toaddress, toripe, fromaddress, subject, message, ackdata, status = row
|
toaddress, fromaddress, subject, message, ackdata, status, TTL, retryNumber = row
|
||||||
toStatus, toAddressVersionNumber, toStreamNumber, toRipe = decodeAddress(
|
toStatus, toAddressVersionNumber, toStreamNumber, toRipe = decodeAddress(
|
||||||
toaddress)
|
toaddress)
|
||||||
fromStatus, fromAddressVersionNumber, fromStreamNumber, fromRipe = decodeAddress(
|
fromStatus, fromAddressVersionNumber, fromStreamNumber, fromRipe = decodeAddress(
|
||||||
|
@ -494,38 +502,45 @@ class singleWorker(threading.Thread):
|
||||||
# because the user could not have overridden the message about the POW being
|
# because the user could not have overridden the message about the POW being
|
||||||
# too difficult without knowing the required difficulty.
|
# too difficult without knowing the required difficulty.
|
||||||
pass
|
pass
|
||||||
|
elif status == 'doingmsgpow':
|
||||||
|
# We wouldn't have set the status to doingmsgpow if we didn't already have the pubkey
|
||||||
|
# so let's assume that we have it.
|
||||||
|
pass
|
||||||
# If we are sending a message to ourselves or a chan then we won't need an entry in the pubkeys table; we can calculate the needed pubkey using the private keys in our keys.dat file.
|
# If we are sending a message to ourselves or a chan then we won't need an entry in the pubkeys table; we can calculate the needed pubkey using the private keys in our keys.dat file.
|
||||||
elif shared.config.has_section(toaddress):
|
elif shared.config.has_section(toaddress):
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND status='msgqueued' ''',
|
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND status='msgqueued' ''',
|
||||||
toaddress)
|
toaddress)
|
||||||
status='doingmsgpow'
|
status='doingmsgpow'
|
||||||
else:
|
elif status == 'msgqueued':
|
||||||
# Let's see if we already have the pubkey in our pubkeys table
|
# Let's see if we already have the pubkey in our pubkeys table
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT hash FROM pubkeys WHERE hash=? AND addressversion=?''', toRipe, toAddressVersionNumber)
|
'''SELECT address FROM pubkeys WHERE address=?''', toaddress)
|
||||||
if queryreturn != []: # If we have the needed pubkey in the pubkey table already,
|
if queryreturn != []: # If we have the needed pubkey in the pubkey table already,
|
||||||
# set the status of this msg to doingmsgpow
|
# set the status of this msg to doingmsgpow
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND status='msgqueued' ''',
|
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND status='msgqueued' ''',
|
||||||
toaddress)
|
toaddress)
|
||||||
status = 'doingmsgpow'
|
status = 'doingmsgpow'
|
||||||
# mark the pubkey as 'usedpersonally' so that we don't delete it later
|
# mark the pubkey as 'usedpersonally' so that we don't delete it later. If the pubkey version
|
||||||
|
# is >= 4 then usedpersonally will already be set to yes because we'll only ever have
|
||||||
|
# usedpersonally v4 pubkeys in the pubkeys table.
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE pubkeys SET usedpersonally='yes' WHERE hash=? and addressversion=?''',
|
'''UPDATE pubkeys SET usedpersonally='yes' WHERE address=?''',
|
||||||
toRipe,
|
toaddress)
|
||||||
toAddressVersionNumber)
|
|
||||||
else: # We don't have the needed pubkey in the pubkeys table already.
|
else: # We don't have the needed pubkey in the pubkeys table already.
|
||||||
if toAddressVersionNumber <= 3:
|
if toAddressVersionNumber <= 3:
|
||||||
toTag = ''
|
toTag = ''
|
||||||
else:
|
else:
|
||||||
toTag = hashlib.sha512(hashlib.sha512(encodeVarint(toAddressVersionNumber)+encodeVarint(toStreamNumber)+toRipe).digest()).digest()[32:]
|
toTag = hashlib.sha512(hashlib.sha512(encodeVarint(toAddressVersionNumber)+encodeVarint(toStreamNumber)+toRipe).digest()).digest()[32:]
|
||||||
if toRipe in shared.neededPubkeys or toTag in shared.neededPubkeys:
|
if toaddress in shared.neededPubkeys or toTag in shared.neededPubkeys:
|
||||||
# We already sent a request for the pubkey
|
# We already sent a request for the pubkey
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET status='awaitingpubkey' WHERE toaddress=? AND status='msgqueued' ''', toaddress)
|
'''UPDATE sent SET status='awaitingpubkey', sleeptill=? WHERE toaddress=? AND status='msgqueued' ''',
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByHash', (
|
int(time.time()) + 2.5*24*60*60,
|
||||||
toRipe, tr.translateText("MainWindow",'Encryption key was requested earlier.'))))
|
toaddress)
|
||||||
|
shared.UISignalQueue.put(('updateSentItemStatusByToAddress', (
|
||||||
|
toaddress, tr.translateText("MainWindow",'Encryption key was requested earlier.'))))
|
||||||
continue #on with the next msg on which we can do some work
|
continue #on with the next msg on which we can do some work
|
||||||
else:
|
else:
|
||||||
# We have not yet sent a request for the pubkey
|
# We have not yet sent a request for the pubkey
|
||||||
|
@ -552,13 +567,13 @@ class singleWorker(threading.Thread):
|
||||||
if shared.decryptAndCheckPubkeyPayload(payload, toaddress) == 'successful':
|
if shared.decryptAndCheckPubkeyPayload(payload, toaddress) == 'successful':
|
||||||
needToRequestPubkey = False
|
needToRequestPubkey = False
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''',
|
'''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''',
|
||||||
toaddress)
|
toaddress)
|
||||||
del shared.neededPubkeys[tag]
|
del shared.neededPubkeys[tag]
|
||||||
continue # We'll start back at the beginning, pick up this msg, mark the pubkey as 'usedpersonally', and then send the msg.
|
break
|
||||||
#else: # There was something wrong with this pubkey object even
|
#else: # There was something wrong with this pubkey object even
|
||||||
# though it had the correct tag- almost certainly because
|
# though it had the correct tag- almost certainly because
|
||||||
# of malicious behavior or a badly programmed client. If
|
# of malicious behavior or a badly programmed client. If
|
||||||
# there are any other pubkeys in our inventory with the correct
|
# there are any other pubkeys in our inventory with the correct
|
||||||
# tag then we'll try to decrypt those.
|
# tag then we'll try to decrypt those.
|
||||||
|
|
||||||
|
@ -570,21 +585,27 @@ class singleWorker(threading.Thread):
|
||||||
if shared.decryptAndCheckPubkeyPayload(payload, toaddress) == 'successful': #if valid, this function also puts it in the pubkeys table.
|
if shared.decryptAndCheckPubkeyPayload(payload, toaddress) == 'successful': #if valid, this function also puts it in the pubkeys table.
|
||||||
needToRequestPubkey = False
|
needToRequestPubkey = False
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''',
|
'''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''',
|
||||||
toaddress)
|
toaddress)
|
||||||
del shared.neededPubkeys[tag]
|
del shared.neededPubkeys[tag]
|
||||||
continue # We'll start back at the beginning, pick up this msg, mark the pubkey as 'usedpersonally', and then send the msg.
|
break
|
||||||
if needToRequestPubkey:
|
if needToRequestPubkey:
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET status='doingpubkeypow' WHERE toaddress=? AND status='msgqueued' ''',
|
'''UPDATE sent SET status='doingpubkeypow' WHERE toaddress=? AND status='msgqueued' ''',
|
||||||
toaddress)
|
toaddress)
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByHash', (
|
shared.UISignalQueue.put(('updateSentItemStatusByToAddress', (
|
||||||
toRipe, tr.translateText("MainWindow",'Sending a request for the recipient\'s encryption key.'))))
|
toaddress, tr.translateText("MainWindow",'Sending a request for the recipient\'s encryption key.'))))
|
||||||
self.requestPubKey(toaddress)
|
self.requestPubKey(toaddress)
|
||||||
continue #on with the next msg on which we can do some work
|
continue #on with the next msg on which we can do some work
|
||||||
|
|
||||||
# At this point we know that we have the necessary pubkey in the pubkeys table.
|
# At this point we know that we have the necessary pubkey in the pubkeys table.
|
||||||
TTL = int(28 * 24 * 60 * 60 + random.randrange(-300, 300))# 28 days from now plus or minus five minutes
|
|
||||||
|
if retryNumber == 0:
|
||||||
|
if TTL > 28 * 24 * 60 * 60:
|
||||||
|
TTL = 28 * 24 * 60 * 60
|
||||||
|
else:
|
||||||
|
TTL = 28 * 24 * 60 * 60
|
||||||
|
TTL = int(TTL + random.randrange(-300, 300))# add some randomness to the TTL
|
||||||
embeddedTime = int(time.time() + TTL)
|
embeddedTime = int(time.time() + TTL)
|
||||||
|
|
||||||
if not shared.config.has_section(toaddress): # if we aren't sending this to ourselves or a chan
|
if not shared.config.has_section(toaddress): # if we aren't sending this to ourselves or a chan
|
||||||
|
@ -598,9 +619,8 @@ class singleWorker(threading.Thread):
|
||||||
# the required proof of work difficulty is too hard then we'll
|
# the required proof of work difficulty is too hard then we'll
|
||||||
# abort.
|
# abort.
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'SELECT transmitdata FROM pubkeys WHERE hash=? and addressversion=?',
|
'SELECT transmitdata FROM pubkeys WHERE address=?',
|
||||||
toRipe,
|
toaddress)
|
||||||
toAddressVersionNumber)
|
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
pubkeyPayload, = row
|
pubkeyPayload, = row
|
||||||
|
|
||||||
|
@ -750,7 +770,7 @@ class singleWorker(threading.Thread):
|
||||||
fullAckPayload = ''
|
fullAckPayload = ''
|
||||||
else:
|
else:
|
||||||
fullAckPayload = self.generateFullAckMessage(
|
fullAckPayload = self.generateFullAckMessage(
|
||||||
ackdata, toStreamNumber) # The fullAckPayload is a normal msg protocol message with the proof of work already completed that the receiver of this message can easily send out.
|
ackdata, toStreamNumber, TTL) # The fullAckPayload is a normal msg protocol message with the proof of work already completed that the receiver of this message can easily send out.
|
||||||
payload += encodeVarint(len(fullAckPayload))
|
payload += encodeVarint(len(fullAckPayload))
|
||||||
payload += fullAckPayload
|
payload += fullAckPayload
|
||||||
dataToSign = pack('>Q', embeddedTime) + '\x00\x00\x00\x02' + encodeVarint(1) + encodeVarint(toStreamNumber) + payload
|
dataToSign = pack('>Q', embeddedTime) + '\x00\x00\x00\x02' + encodeVarint(1) + encodeVarint(toStreamNumber) + payload
|
||||||
|
@ -807,20 +827,29 @@ class singleWorker(threading.Thread):
|
||||||
shared.broadcastToSendDataQueues((
|
shared.broadcastToSendDataQueues((
|
||||||
toStreamNumber, 'advertiseobject', inventoryHash))
|
toStreamNumber, 'advertiseobject', inventoryHash))
|
||||||
|
|
||||||
# Update the status of the message in the 'sent' table to have a
|
# Update the sent message in the sent table with the necessary information.
|
||||||
# 'msgsent' or 'msgsentnoackexpected' status.
|
|
||||||
if shared.config.has_section(toaddress):
|
if shared.config.has_section(toaddress):
|
||||||
newStatus = 'msgsentnoackexpected'
|
newStatus = 'msgsentnoackexpected'
|
||||||
else:
|
else:
|
||||||
newStatus = 'msgsent'
|
newStatus = 'msgsent'
|
||||||
sqlExecute('''UPDATE sent SET msgid=?, status=? WHERE ackdata=?''',
|
if retryNumber == 0:
|
||||||
inventoryHash,newStatus,ackdata)
|
sleepTill = int(time.time()) + TTL
|
||||||
|
else:
|
||||||
|
sleepTill = int(time.time()) + 28*24*60*60 * 2**retryNumber
|
||||||
|
sqlExecute('''UPDATE sent SET msgid=?, status=?, retrynumber=?, sleeptill=?, lastactiontime=? WHERE ackdata=?''',
|
||||||
|
inventoryHash,
|
||||||
|
newStatus,
|
||||||
|
retryNumber+1,
|
||||||
|
sleepTill,
|
||||||
|
int(time.time()),
|
||||||
|
ackdata)
|
||||||
|
|
||||||
# If we are sending to ourselves or a chan, let's put the message in
|
# If we are sending to ourselves or a chan, let's put the message in
|
||||||
# our own inbox.
|
# our own inbox.
|
||||||
if shared.config.has_section(toaddress):
|
if shared.config.has_section(toaddress):
|
||||||
|
sigHash = hashlib.sha512(hashlib.sha512(signature).digest()).digest()[32:] # Used to detect and ignore duplicate messages in our inbox
|
||||||
t = (inventoryHash, toaddress, fromaddress, subject, int(
|
t = (inventoryHash, toaddress, fromaddress, subject, int(
|
||||||
time.time()), message, 'inbox', 2, 0)
|
time.time()), message, 'inbox', 2, 0, sigHash)
|
||||||
helper_inbox.insert(t)
|
helper_inbox.insert(t)
|
||||||
|
|
||||||
shared.UISignalQueue.put(('displayNewInboxMessage', (
|
shared.UISignalQueue.put(('displayNewInboxMessage', (
|
||||||
|
@ -845,10 +874,18 @@ class singleWorker(threading.Thread):
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
sys.stderr.write('Very abnormal error occurred in requestPubKey. toAddress is: ' + repr(
|
sys.stderr.write('Very abnormal error occurred in requestPubKey. toAddress is: ' + repr(
|
||||||
toAddress) + '. Please report this error to Atheros.')
|
toAddress) + '. Please report this error to Atheros.')
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
queryReturn = sqlQuery(
|
||||||
|
'''SELECT retrynumber FROM sent WHERE toaddress=? AND (status='doingpubkeypow' OR status='awaitingpubkey') LIMIT 1''',
|
||||||
|
toAddress)
|
||||||
|
if len(queryReturn) == 0:
|
||||||
|
logger.critical("BUG: Why are we requesting the pubkey for %s if there are no messages in the sent folder to that address?" % toAddress)
|
||||||
|
return
|
||||||
|
retryNumber = queryReturn[0][0]
|
||||||
|
|
||||||
if addressVersionNumber <= 3:
|
if addressVersionNumber <= 3:
|
||||||
shared.neededPubkeys[ripe] = 0
|
shared.neededPubkeys[toAddress] = 0
|
||||||
elif addressVersionNumber >= 4:
|
elif addressVersionNumber >= 4:
|
||||||
# If the user just clicked 'send' then the tag (and other information) will already
|
# If the user just clicked 'send' then the tag (and other information) will already
|
||||||
# be in the neededPubkeys dictionary. But if we are recovering from a restart
|
# be in the neededPubkeys dictionary. But if we are recovering from a restart
|
||||||
|
@ -858,7 +895,11 @@ class singleWorker(threading.Thread):
|
||||||
if tag not in shared.neededPubkeys:
|
if tag not in shared.neededPubkeys:
|
||||||
shared.neededPubkeys[tag] = (toAddress, highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex'))) # We'll need this for when we receive a pubkey reply: it will be encrypted and we'll need to decrypt it.
|
shared.neededPubkeys[tag] = (toAddress, highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex'))) # We'll need this for when we receive a pubkey reply: it will be encrypted and we'll need to decrypt it.
|
||||||
|
|
||||||
TTL = int(2.5 * 24 * 60 * 60 + random.randrange(-300, 300)) # 2.5 days from now plus or minus five minutes
|
if retryNumber == 0:
|
||||||
|
TTL = 2.5*24*60*60 # 2.5 days. This was chosen fairly arbitrarily.
|
||||||
|
else:
|
||||||
|
TTL = 28*24*60*60
|
||||||
|
TTL = TTL + random.randrange(-300, 300) # add some randomness to the TTL
|
||||||
embeddedTime = int(time.time() + TTL)
|
embeddedTime = int(time.time() + TTL)
|
||||||
payload = pack('>Q', embeddedTime)
|
payload = pack('>Q', embeddedTime)
|
||||||
payload += '\x00\x00\x00\x00' # object type: getpubkey
|
payload += '\x00\x00\x00\x00' # object type: getpubkey
|
||||||
|
@ -876,8 +917,8 @@ class singleWorker(threading.Thread):
|
||||||
# print 'trial value', trialValue
|
# print 'trial value', trialValue
|
||||||
statusbar = 'Doing the computations necessary to request the recipient\'s public key.'
|
statusbar = 'Doing the computations necessary to request the recipient\'s public key.'
|
||||||
shared.UISignalQueue.put(('updateStatusBar', statusbar))
|
shared.UISignalQueue.put(('updateStatusBar', statusbar))
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByHash', (
|
shared.UISignalQueue.put(('updateSentItemStatusByToAddress', (
|
||||||
ripe, tr.translateText("MainWindow",'Doing work necessary to request encryption key.'))))
|
toAddress, tr.translateText("MainWindow",'Doing work necessary to request encryption key.'))))
|
||||||
|
|
||||||
target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16))))
|
target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16))))
|
||||||
initialHash = hashlib.sha512(payload).digest()
|
initialHash = hashlib.sha512(payload).digest()
|
||||||
|
@ -895,16 +936,39 @@ class singleWorker(threading.Thread):
|
||||||
shared.broadcastToSendDataQueues((
|
shared.broadcastToSendDataQueues((
|
||||||
streamNumber, 'advertiseobject', inventoryHash))
|
streamNumber, 'advertiseobject', inventoryHash))
|
||||||
|
|
||||||
|
if retryNumber == 0:
|
||||||
|
sleeptill = int(time.time()) + TTL
|
||||||
|
else:
|
||||||
|
sleeptill = int(time.time()) + 28*24*60*60 * 2**retryNumber
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''UPDATE sent SET status='awaitingpubkey' WHERE toaddress=? AND status='doingpubkeypow' ''',
|
'''UPDATE sent SET lastactiontime=?, status='awaitingpubkey', retrynumber=?, sleeptill=? WHERE toaddress=? AND (status='doingpubkeypow' OR status='awaitingpubkey') ''',
|
||||||
|
int(time.time()),
|
||||||
|
retryNumber+1,
|
||||||
|
sleeptill,
|
||||||
toAddress)
|
toAddress)
|
||||||
|
|
||||||
shared.UISignalQueue.put((
|
shared.UISignalQueue.put((
|
||||||
'updateStatusBar', tr.translateText("MainWindow",'Broacasting the public key request. This program will auto-retry if they are offline.')))
|
'updateStatusBar', tr.translateText("MainWindow",'Broacasting the public key request. This program will auto-retry if they are offline.')))
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByHash', (ripe, tr.translateText("MainWindow",'Sending public key request. Waiting for reply. Requested at %1').arg(l10n.formatTimestamp()))))
|
shared.UISignalQueue.put(('updateSentItemStatusByToAddress', (toAddress, tr.translateText("MainWindow",'Sending public key request. Waiting for reply. Requested at %1').arg(l10n.formatTimestamp()))))
|
||||||
|
|
||||||
def generateFullAckMessage(self, ackdata, toStreamNumber):
|
def generateFullAckMessage(self, ackdata, toStreamNumber, TTL):
|
||||||
TTL = int(2.5 * 24 * 60 * 60 + random.randrange(-300, 300)) # 2.5 days plus or minus 5 minutes
|
|
||||||
|
# It might be perfectly fine to just use the same TTL for
|
||||||
|
# the ackdata that we use for the message. But I would rather
|
||||||
|
# it be more difficult for attackers to associate ackData with
|
||||||
|
# the associated msg object. However, users would want the TTL
|
||||||
|
# of the acknowledgement to be about the same as they set
|
||||||
|
# for the message itself. So let's set the TTL of the
|
||||||
|
# acknowledgement to be in one of three 'buckets': 1 hour, 7
|
||||||
|
# days, or 28 days, whichever is relatively close to what the
|
||||||
|
# user specified.
|
||||||
|
if TTL < 24*60*60: # 1 day
|
||||||
|
TTL = 24*60*60 # 1 day
|
||||||
|
elif TTL < 7*24*60*60: # 1 week
|
||||||
|
TTL = 7*24*60*60 # 1 week
|
||||||
|
else:
|
||||||
|
TTL = 28*24*60*60 # 4 weeks
|
||||||
|
TTL = int(TTL + random.randrange(-300, 300)) # Add some randomness to the TTL
|
||||||
embeddedTime = int(time.time() + TTL)
|
embeddedTime = int(time.time() + TTL)
|
||||||
payload = pack('>Q', (embeddedTime))
|
payload = pack('>Q', (embeddedTime))
|
||||||
payload += '\x00\x00\x00\x02' # object type: msg
|
payload += '\x00\x00\x00\x02' # object type: msg
|
||||||
|
@ -913,7 +977,7 @@ class singleWorker(threading.Thread):
|
||||||
|
|
||||||
target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16))))
|
target = 2 ** 64 / (shared.networkDefaultProofOfWorkNonceTrialsPerByte*(len(payload) + 8 + shared.networkDefaultPayloadLengthExtraBytes + ((TTL*(len(payload)+8+shared.networkDefaultPayloadLengthExtraBytes))/(2 ** 16))))
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print '(For ack message) Doing proof of work...'
|
print '(For ack message) Doing proof of work. TTL set to', TTL
|
||||||
|
|
||||||
powStartTime = time.time()
|
powStartTime = time.time()
|
||||||
initialHash = hashlib.sha512(payload).digest()
|
initialHash = hashlib.sha512(payload).digest()
|
||||||
|
|
|
@ -28,9 +28,9 @@ class sqlThread(threading.Thread):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''CREATE TABLE inbox (msgid blob, toaddress text, fromaddress text, subject text, received text, message text, folder text, encodingtype int, read bool, UNIQUE(msgid) ON CONFLICT REPLACE)''' )
|
'''CREATE TABLE inbox (msgid blob, toaddress text, fromaddress text, subject text, received text, message text, folder text, encodingtype int, read bool, sighash blob, UNIQUE(msgid) ON CONFLICT REPLACE)''' )
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''CREATE TABLE sent (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, lastactiontime integer, status text, pubkeyretrynumber integer, msgretrynumber integer, folder text, encodingtype int)''' )
|
'''CREATE TABLE sent (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, senttime integer, lastactiontime integer, sleeptill integer, status text, retrynumber integer, folder text, encodingtype int, ttl int)''' )
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''CREATE TABLE subscriptions (label text, address text, enabled bool)''' )
|
'''CREATE TABLE subscriptions (label text, address text, enabled bool)''' )
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
|
@ -39,29 +39,15 @@ class sqlThread(threading.Thread):
|
||||||
'''CREATE TABLE blacklist (label text, address text, enabled bool)''' )
|
'''CREATE TABLE blacklist (label text, address text, enabled bool)''' )
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''CREATE TABLE whitelist (label text, address text, enabled bool)''' )
|
'''CREATE TABLE whitelist (label text, address text, enabled bool)''' )
|
||||||
"""
|
|
||||||
Explanation of what is in the pubkeys table:
|
|
||||||
The hash is the RIPEMD160 hash that is encoded in the Bitmessage address.
|
|
||||||
|
|
||||||
transmitdata /was/ literally the data that was included in the Bitmessage pubkey message when it arrived,
|
|
||||||
except for the 24 byte protocol header- ie, it started with the POW nonce. Since protocol v3, to maintain
|
|
||||||
backwards compability, the data format of the data on disk is staying the same even though the wire format has changed.
|
|
||||||
|
|
||||||
time is the time that the pubkey was broadcast on the network same as with every other type of Bitmessage object.
|
|
||||||
|
|
||||||
usedpersonally is set to "yes" if we have used the key personally. This keeps us from deleting it because we may want to
|
|
||||||
reply to a message in the future. This field is not a bool because we may need more flexability in the future and it doesn't
|
|
||||||
take up much more space anyway.
|
|
||||||
"""
|
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''CREATE TABLE pubkeys (hash blob, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(hash, addressversion) ON CONFLICT REPLACE)''' )
|
'''CREATE TABLE pubkeys (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)''' )
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''CREATE TABLE inventory (hash blob, objecttype int, streamnumber int, payload blob, expirestime integer, tag blob, UNIQUE(hash) ON CONFLICT REPLACE)''' )
|
'''CREATE TABLE inventory (hash blob, objecttype int, streamnumber int, payload blob, expirestime integer, tag blob, UNIQUE(hash) ON CONFLICT REPLACE)''' )
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''INSERT INTO subscriptions VALUES('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''')
|
'''INSERT INTO subscriptions VALUES('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''')
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''CREATE TABLE settings (key blob, value blob, UNIQUE(key) ON CONFLICT REPLACE)''' )
|
'''CREATE TABLE settings (key blob, value blob, UNIQUE(key) ON CONFLICT REPLACE)''' )
|
||||||
self.cur.execute( '''INSERT INTO settings VALUES('version','8')''')
|
self.cur.execute( '''INSERT INTO settings VALUES('version','10')''')
|
||||||
self.cur.execute( '''INSERT INTO settings VALUES('lastvacuumtime',?)''', (
|
self.cur.execute( '''INSERT INTO settings VALUES('lastvacuumtime',?)''', (
|
||||||
int(time.time()),))
|
int(time.time()),))
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
|
@ -361,6 +347,70 @@ class sqlThread(threading.Thread):
|
||||||
self.cur.execute(query, parameters)
|
self.cur.execute(query, parameters)
|
||||||
logger.debug('Finished clearing currently held pubkeys.')
|
logger.debug('Finished clearing currently held pubkeys.')
|
||||||
|
|
||||||
|
# Add a new column to the inbox table to store the hash of the message signature.
|
||||||
|
# We'll use this as temporary message UUID in order to detect duplicates.
|
||||||
|
item = '''SELECT value FROM settings WHERE key='version';'''
|
||||||
|
parameters = ''
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
currentVersion = int(self.cur.fetchall()[0][0])
|
||||||
|
if currentVersion == 8:
|
||||||
|
logger.debug('In messages.dat database, adding sighash field to the inbox table.')
|
||||||
|
item = '''ALTER TABLE inbox ADD sighash blob DEFAULT '' '''
|
||||||
|
parameters = ''
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
item = '''update settings set value=? WHERE key='version';'''
|
||||||
|
parameters = (9,)
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
|
||||||
|
# TTL is now user-specifiable. Let's add an option to save whatever the user selects.
|
||||||
|
if not shared.config.has_option('bitmessagesettings', 'ttl'):
|
||||||
|
shared.config.set('bitmessagesettings', 'ttl', '367200')
|
||||||
|
# We'll also need a `sleeptill` field and a `ttl` field. Also we can combine
|
||||||
|
# the pubkeyretrynumber and msgretrynumber into one.
|
||||||
|
item = '''SELECT value FROM settings WHERE key='version';'''
|
||||||
|
parameters = ''
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
currentVersion = int(self.cur.fetchall()[0][0])
|
||||||
|
if currentVersion == 9:
|
||||||
|
logger.info('In messages.dat database, making TTL-related changes: combining the pubkeyretrynumber and msgretrynumber fields into the retrynumber field and adding the sleeptill and ttl fields...')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TEMPORARY TABLE sent_backup (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, lastactiontime integer, status text, retrynumber integer, folder text, encodingtype int)''' )
|
||||||
|
self.cur.execute(
|
||||||
|
'''INSERT INTO sent_backup SELECT msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, 0, folder, encodingtype FROM sent;''')
|
||||||
|
self.cur.execute( '''DROP TABLE sent''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TABLE sent (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, senttime integer, lastactiontime integer, sleeptill int, status text, retrynumber integer, folder text, encodingtype int, ttl int)''' )
|
||||||
|
self.cur.execute(
|
||||||
|
'''INSERT INTO sent SELECT msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, lastactiontime, 0, status, 0, folder, encodingtype, 216000 FROM sent_backup;''')
|
||||||
|
self.cur.execute( '''DROP TABLE sent_backup''')
|
||||||
|
logger.info('In messages.dat database, finished making TTL-related changes.')
|
||||||
|
logger.debug('In messages.dat database, adding address field to the pubkeys table.')
|
||||||
|
# We're going to have to calculate the address for each row in the pubkeys
|
||||||
|
# table. Then we can take out the hash field.
|
||||||
|
self.cur.execute('''ALTER TABLE pubkeys ADD address text DEFAULT '' ''')
|
||||||
|
self.cur.execute('''SELECT hash, addressversion FROM pubkeys''')
|
||||||
|
queryResult = self.cur.fetchall()
|
||||||
|
from addresses import encodeAddress
|
||||||
|
for row in queryResult:
|
||||||
|
hash, addressVersion = row
|
||||||
|
address = encodeAddress(addressVersion, 1, hash)
|
||||||
|
item = '''UPDATE pubkeys SET address=? WHERE hash=?;'''
|
||||||
|
parameters = (address, hash)
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
# Now we can remove the hash field from the pubkeys table.
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TEMPORARY TABLE pubkeys_backup (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)''' )
|
||||||
|
self.cur.execute(
|
||||||
|
'''INSERT INTO pubkeys_backup SELECT address, addressversion, transmitdata, time, usedpersonally FROM pubkeys;''')
|
||||||
|
self.cur.execute( '''DROP TABLE pubkeys''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TABLE pubkeys (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)''' )
|
||||||
|
self.cur.execute(
|
||||||
|
'''INSERT INTO pubkeys SELECT address, addressversion, transmitdata, time, usedpersonally FROM pubkeys_backup;''')
|
||||||
|
self.cur.execute( '''DROP TABLE pubkeys_backup''')
|
||||||
|
logger.debug('In messages.dat database, done adding address field to the pubkeys table and removing the hash field.')
|
||||||
|
self.cur.execute('''update settings set value=10 WHERE key='version';''')
|
||||||
|
|
||||||
|
|
||||||
# Are you hoping to add a new option to the keys.dat file of existing
|
# Are you hoping to add a new option to the keys.dat file of existing
|
||||||
# Bitmessage users or modify the SQLite database? Add it right above this line!
|
# Bitmessage users or modify the SQLite database? Add it right above this line!
|
||||||
|
@ -371,11 +421,11 @@ class sqlThread(threading.Thread):
|
||||||
self.cur.execute( '''INSERT INTO pubkeys VALUES(?,?,?,?,?)''', t)
|
self.cur.execute( '''INSERT INTO pubkeys VALUES(?,?,?,?,?)''', t)
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''SELECT transmitdata FROM pubkeys WHERE hash='1234' ''')
|
'''SELECT transmitdata FROM pubkeys WHERE address='1234' ''')
|
||||||
queryreturn = self.cur.fetchall()
|
queryreturn = self.cur.fetchall()
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
transmitdata, = row
|
transmitdata, = row
|
||||||
self.cur.execute('''DELETE FROM pubkeys WHERE hash='1234' ''')
|
self.cur.execute('''DELETE FROM pubkeys WHERE address='1234' ''')
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
if transmitdata == '':
|
if transmitdata == '':
|
||||||
logger.fatal('Problem: The version of SQLite you have cannot store Null values. Please download and install the latest revision of your version of Python (for example, the latest Python 2.7 revision) and try again.\n')
|
logger.fatal('Problem: The version of SQLite you have cannot store Null values. Please download and install the latest revision of your version of Python (for example, the latest Python 2.7 revision) and try again.\n')
|
||||||
|
|
|
@ -12,16 +12,15 @@ def createDefaultKnownNodes(appdata):
|
||||||
stream1 = {}
|
stream1 = {}
|
||||||
|
|
||||||
#stream1[shared.Peer('2604:2000:1380:9f:82e:148b:2746:d0c7', 8080)] = int(time.time())
|
#stream1[shared.Peer('2604:2000:1380:9f:82e:148b:2746:d0c7', 8080)] = int(time.time())
|
||||||
stream1[shared.Peer('23.239.9.147', 8444)] = int(time.time())
|
stream1[shared.Peer('5.45.99.75', 8444)] = int(time.time())
|
||||||
stream1[shared.Peer('98.218.125.214', 8444)] = int(time.time())
|
stream1[shared.Peer('75.167.159.54', 8444)] = int(time.time())
|
||||||
stream1[shared.Peer('192.121.170.162', 8444)] = int(time.time())
|
stream1[shared.Peer('95.165.168.168', 8444)] = int(time.time())
|
||||||
stream1[shared.Peer('108.61.72.12', 28444)] = int(time.time())
|
stream1[shared.Peer('85.180.139.241', 8444)] = int(time.time())
|
||||||
stream1[shared.Peer('158.222.211.81', 8080)] = int(time.time())
|
stream1[shared.Peer('158.222.211.81', 8080)] = int(time.time())
|
||||||
stream1[shared.Peer('79.163.240.110', 8446)] = int(time.time())
|
stream1[shared.Peer('178.62.12.187', 8448)] = int(time.time())
|
||||||
stream1[shared.Peer('178.62.154.250', 8444)] = int(time.time())
|
stream1[shared.Peer('24.188.198.204', 8111)] = int(time.time())
|
||||||
stream1[shared.Peer('178.62.155.6', 8444)] = int(time.time())
|
stream1[shared.Peer('109.147.204.113', 1195)] = int(time.time())
|
||||||
stream1[shared.Peer('178.62.155.8', 8444)] = int(time.time())
|
stream1[shared.Peer('178.11.46.221', 8444)] = int(time.time())
|
||||||
stream1[shared.Peer('68.42.42.120', 8444)] = int(time.time())
|
|
||||||
|
|
||||||
############# Stream 2 #################
|
############# Stream 2 #################
|
||||||
stream2 = {}
|
stream2 = {}
|
||||||
|
|
|
@ -2,14 +2,14 @@ from helper_sql import *
|
||||||
import shared
|
import shared
|
||||||
|
|
||||||
def insert(t):
|
def insert(t):
|
||||||
sqlExecute('''INSERT INTO inbox VALUES (?,?,?,?,?,?,?,?,?)''', *t)
|
sqlExecute('''INSERT INTO inbox VALUES (?,?,?,?,?,?,?,?,?,?)''', *t)
|
||||||
shared.UISignalQueue.put(('changedInboxUnread', None))
|
shared.UISignalQueue.put(('changedInboxUnread', None))
|
||||||
|
|
||||||
def trash(msgid):
|
def trash(msgid):
|
||||||
sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', msgid)
|
sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', msgid)
|
||||||
shared.UISignalQueue.put(('removeInboxRowByMsgid',msgid))
|
shared.UISignalQueue.put(('removeInboxRowByMsgid',msgid))
|
||||||
|
|
||||||
def isMessageAlreadyInInbox(toAddress, fromAddress, subject, body, encodingType):
|
def isMessageAlreadyInInbox(sigHash):
|
||||||
queryReturn = sqlQuery(
|
queryReturn = sqlQuery(
|
||||||
'''SELECT COUNT(*) FROM inbox WHERE toaddress=? AND fromaddress=? AND subject=? AND message=? AND encodingtype=? ''', toAddress, fromAddress, subject, body, encodingType)
|
'''SELECT COUNT(*) FROM inbox WHERE sighash=?''', sigHash)
|
||||||
return queryReturn[0][0] != 0
|
return queryReturn[0][0] != 0
|
|
@ -1,4 +1,4 @@
|
||||||
from helper_sql import *
|
from helper_sql import *
|
||||||
|
|
||||||
def insert(t):
|
def insert(t):
|
||||||
sqlExecute('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)''', *t)
|
sqlExecute('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', *t)
|
||||||
|
|
|
@ -104,6 +104,7 @@ def loadConfig():
|
||||||
shared.config.set('bitmessagesettings', 'replybelow', 'False')
|
shared.config.set('bitmessagesettings', 'replybelow', 'False')
|
||||||
shared.config.set('bitmessagesettings', 'maxdownloadrate', '0')
|
shared.config.set('bitmessagesettings', 'maxdownloadrate', '0')
|
||||||
shared.config.set('bitmessagesettings', 'maxuploadrate', '0')
|
shared.config.set('bitmessagesettings', 'maxuploadrate', '0')
|
||||||
|
shared.config.set('bitmessagesettings', 'ttl', '367200')
|
||||||
|
|
||||||
#start:UI setting to stop trying to send messages after X days/months
|
#start:UI setting to stop trying to send messages after X days/months
|
||||||
shared.config.set(
|
shared.config.set(
|
||||||
|
@ -144,5 +145,5 @@ def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections():
|
||||||
return StrictVersion("5.1.2600")<=VER_THIS and StrictVersion("6.0.6000")>=VER_THIS
|
return StrictVersion("5.1.2600")<=VER_THIS and StrictVersion("6.0.6000")>=VER_THIS
|
||||||
return False
|
return False
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print 'An Exception occurred within isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections:', err
|
print "Info: we could not tell whether your OS is limited to having very view half open connections because we couldn't interpret the platform version. Don't worry; we'll assume that it is not limited. This tends to occur on Raspberry Pis. :", err
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -30,30 +30,63 @@ def decryptFast(msg,cryptor):
|
||||||
return cryptor.decrypt(msg)
|
return cryptor.decrypt(msg)
|
||||||
# Signs with hex private key
|
# Signs with hex private key
|
||||||
def sign(msg,hexPrivkey):
|
def sign(msg,hexPrivkey):
|
||||||
return makeCryptor(hexPrivkey).sign(msg)
|
# pyelliptic is upgrading from SHA1 to SHA256 for signing. We must
|
||||||
|
# upgrade PyBitmessage gracefully.
|
||||||
|
# https://github.com/yann2192/pyelliptic/pull/33
|
||||||
|
# More discussion: https://github.com/yann2192/pyelliptic/issues/32
|
||||||
|
return makeCryptor(hexPrivkey).sign(msg, digest_alg=OpenSSL.EVP_ecdsa) # SHA1
|
||||||
|
#return makeCryptor(hexPrivkey).sign(msg, digest_alg=OpenSSL.EVP_sha256) # SHA256. We should switch to this eventually.
|
||||||
# Verifies with hex public key
|
# Verifies with hex public key
|
||||||
def verify(msg,sig,hexPubkey):
|
def verify(msg,sig,hexPubkey):
|
||||||
|
# As mentioned above, we must upgrade gracefully to use SHA256. So
|
||||||
|
# let us check the signature using both SHA1 and SHA256 and if one
|
||||||
|
# of them passes then we will be satisfied. Eventually this can
|
||||||
|
# be simplified and we'll only check with SHA256.
|
||||||
try:
|
try:
|
||||||
return makePubCryptor(hexPubkey).verify(sig,msg)
|
sigVerifyPassed = makePubCryptor(hexPubkey).verify(sig,msg,digest_alg=OpenSSL.EVP_ecdsa) # old SHA1 algorithm.
|
||||||
|
except:
|
||||||
|
sigVerifyPassed = False
|
||||||
|
if sigVerifyPassed:
|
||||||
|
# The signature check passed using SHA1
|
||||||
|
return True
|
||||||
|
# The signature check using SHA1 failed. Let us try it with SHA256.
|
||||||
|
try:
|
||||||
|
return makePubCryptor(hexPubkey).verify(sig,msg,digest_alg=OpenSSL.EVP_sha256)
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Does an EC point multiplication; turns a private key into a public key.
|
# Does an EC point multiplication; turns a private key into a public key.
|
||||||
def pointMult(secret):
|
def pointMult(secret):
|
||||||
k = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1'))
|
while True:
|
||||||
priv_key = OpenSSL.BN_bin2bn(secret, 32, None)
|
try:
|
||||||
group = OpenSSL.EC_KEY_get0_group(k)
|
"""
|
||||||
pub_key = OpenSSL.EC_POINT_new(group)
|
Evidently, this type of error can occur very rarely:
|
||||||
|
|
||||||
OpenSSL.EC_POINT_mul(group, pub_key, priv_key, None, None, None)
|
File "highlevelcrypto.py", line 54, in pointMult
|
||||||
OpenSSL.EC_KEY_set_private_key(k, priv_key)
|
group = OpenSSL.EC_KEY_get0_group(k)
|
||||||
OpenSSL.EC_KEY_set_public_key(k, pub_key)
|
WindowsError: exception: access violation reading 0x0000000000000008
|
||||||
|
"""
|
||||||
|
k = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1'))
|
||||||
|
priv_key = OpenSSL.BN_bin2bn(secret, 32, None)
|
||||||
|
group = OpenSSL.EC_KEY_get0_group(k)
|
||||||
|
pub_key = OpenSSL.EC_POINT_new(group)
|
||||||
|
|
||||||
size = OpenSSL.i2o_ECPublicKey(k, None)
|
OpenSSL.EC_POINT_mul(group, pub_key, priv_key, None, None, None)
|
||||||
mb = OpenSSL.create_string_buffer(size)
|
OpenSSL.EC_KEY_set_private_key(k, priv_key)
|
||||||
OpenSSL.i2o_ECPublicKey(k, OpenSSL.byref(OpenSSL.pointer(mb)))
|
OpenSSL.EC_KEY_set_public_key(k, pub_key)
|
||||||
|
|
||||||
|
size = OpenSSL.i2o_ECPublicKey(k, None)
|
||||||
|
mb = OpenSSL.create_string_buffer(size)
|
||||||
|
OpenSSL.i2o_ECPublicKey(k, OpenSSL.byref(OpenSSL.pointer(mb)))
|
||||||
|
|
||||||
|
OpenSSL.EC_POINT_free(pub_key)
|
||||||
|
OpenSSL.BN_free(priv_key)
|
||||||
|
OpenSSL.EC_KEY_free(k)
|
||||||
|
return mb.raw
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
import time
|
||||||
|
traceback.print_exc()
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
||||||
OpenSSL.EC_POINT_free(pub_key)
|
|
||||||
OpenSSL.BN_free(priv_key)
|
|
||||||
OpenSSL.EC_KEY_free(k)
|
|
||||||
return mb.raw
|
|
||||||
|
|
|
@ -30,8 +30,8 @@ def readSent():
|
||||||
cur.execute(item, parameters)
|
cur.execute(item, parameters)
|
||||||
output = cur.fetchall()
|
output = cur.fetchall()
|
||||||
for row in output:
|
for row in output:
|
||||||
msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, pubkeyretrynumber, msgretrynumber, folder, encodingtype = row
|
msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, sleeptill, status, retrynumber, folder, encodingtype, ttl = row
|
||||||
print msgid.encode('hex'), toaddress, 'toripe:', toripe.encode('hex'), 'fromaddress:', fromaddress, 'ENCODING TYPE:', encodingtype, 'SUBJECT:', repr(subject), 'MESSAGE:', repr(message), 'ACKDATA:', ackdata.encode('hex'), lastactiontime, status, pubkeyretrynumber, msgretrynumber, folder
|
print msgid.encode('hex'), toaddress, 'toripe:', toripe.encode('hex'), 'fromaddress:', fromaddress, 'ENCODING TYPE:', encodingtype, 'SUBJECT:', repr(subject), 'MESSAGE:', repr(message), 'ACKDATA:', ackdata.encode('hex'), lastactiontime, status, retrynumber, folder
|
||||||
|
|
||||||
def readSubscriptions():
|
def readSubscriptions():
|
||||||
print 'Printing everything in subscriptions table:'
|
print 'Printing everything in subscriptions table:'
|
||||||
|
@ -44,13 +44,13 @@ def readSubscriptions():
|
||||||
|
|
||||||
def readPubkeys():
|
def readPubkeys():
|
||||||
print 'Printing everything in pubkeys table:'
|
print 'Printing everything in pubkeys table:'
|
||||||
item = '''select hash, transmitdata, time, usedpersonally from pubkeys'''
|
item = '''select address, transmitdata, time, usedpersonally from pubkeys'''
|
||||||
parameters = ''
|
parameters = ''
|
||||||
cur.execute(item, parameters)
|
cur.execute(item, parameters)
|
||||||
output = cur.fetchall()
|
output = cur.fetchall()
|
||||||
for row in output:
|
for row in output:
|
||||||
hash, transmitdata, time, usedpersonally = row
|
address, transmitdata, time, usedpersonally = row
|
||||||
print 'Hash:', hash.encode('hex'), '\tTime first broadcast:', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(time)),'utf-8'), '\tUsed by me personally:', usedpersonally, '\tFull pubkey message:', transmitdata.encode('hex')
|
print 'Address:', address, '\tTime first broadcast:', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(time)),'utf-8'), '\tUsed by me personally:', usedpersonally, '\tFull pubkey message:', transmitdata.encode('hex')
|
||||||
|
|
||||||
def readInventory():
|
def readInventory():
|
||||||
print 'Printing everything in inventory table:'
|
print 'Printing everything in inventory table:'
|
||||||
|
|
|
@ -81,6 +81,7 @@ def _doGPUPow(target, initialHash):
|
||||||
return [trialValue, nonce]
|
return [trialValue, nonce]
|
||||||
|
|
||||||
def run(target, initialHash):
|
def run(target, initialHash):
|
||||||
|
target = int(target)
|
||||||
if openclpow.has_opencl():
|
if openclpow.has_opencl():
|
||||||
return _doGPUPow(target, initialHash)
|
return _doGPUPow(target, initialHash)
|
||||||
elif frozen == "macosx_app" or not frozen:
|
elif frozen == "macosx_app" or not frozen:
|
||||||
|
|
|
@ -299,7 +299,7 @@ class ECC:
|
||||||
if privkey is not None:
|
if privkey is not None:
|
||||||
OpenSSL.BN_free(priv_key)
|
OpenSSL.BN_free(priv_key)
|
||||||
|
|
||||||
def sign(self, inputb):
|
def sign(self, inputb, digest_alg=OpenSSL.EVP_ecdsa):
|
||||||
"""
|
"""
|
||||||
Sign the input with ECDSA method and returns the signature
|
Sign the input with ECDSA method and returns the signature
|
||||||
"""
|
"""
|
||||||
|
@ -338,11 +338,11 @@ class ECC:
|
||||||
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
|
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
|
||||||
|
|
||||||
OpenSSL.EVP_MD_CTX_init(md_ctx)
|
OpenSSL.EVP_MD_CTX_init(md_ctx)
|
||||||
OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa())
|
OpenSSL.EVP_DigestInit_ex(md_ctx, digest_alg(), None)
|
||||||
|
|
||||||
if (OpenSSL.EVP_DigestUpdate(md_ctx, buff, size)) == 0:
|
if (OpenSSL.EVP_DigestUpdate(md_ctx, buff, size)) == 0:
|
||||||
raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...")
|
raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...")
|
||||||
OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len)
|
OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len)
|
||||||
OpenSSL.ECDSA_sign(0, digest, dgst_len.contents, sig, siglen, key)
|
OpenSSL.ECDSA_sign(0, digest, dgst_len.contents, sig, siglen, key)
|
||||||
if (OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, sig,
|
if (OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, sig,
|
||||||
siglen.contents, key)) != 1:
|
siglen.contents, key)) != 1:
|
||||||
|
@ -358,7 +358,7 @@ class ECC:
|
||||||
OpenSSL.EC_POINT_free(pub_key)
|
OpenSSL.EC_POINT_free(pub_key)
|
||||||
OpenSSL.EVP_MD_CTX_destroy(md_ctx)
|
OpenSSL.EVP_MD_CTX_destroy(md_ctx)
|
||||||
|
|
||||||
def verify(self, sig, inputb):
|
def verify(self, sig, inputb, digest_alg=OpenSSL.EVP_ecdsa):
|
||||||
"""
|
"""
|
||||||
Verify the signature with the input and the local public key.
|
Verify the signature with the input and the local public key.
|
||||||
Returns a boolean
|
Returns a boolean
|
||||||
|
@ -392,11 +392,11 @@ class ECC:
|
||||||
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
|
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
|
||||||
|
|
||||||
OpenSSL.EVP_MD_CTX_init(md_ctx)
|
OpenSSL.EVP_MD_CTX_init(md_ctx)
|
||||||
OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa())
|
OpenSSL.EVP_DigestInit_ex(md_ctx, digest_alg(), None)
|
||||||
if (OpenSSL.EVP_DigestUpdate(md_ctx, binputb, len(inputb))) == 0:
|
if (OpenSSL.EVP_DigestUpdate(md_ctx, binputb, len(inputb))) == 0:
|
||||||
raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...")
|
raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...")
|
||||||
|
|
||||||
OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len)
|
OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len)
|
||||||
ret = OpenSSL.ECDSA_verify(
|
ret = OpenSSL.ECDSA_verify(
|
||||||
0, digest, dgst_len.contents, bsig, len(sig), key)
|
0, digest, dgst_len.contents, bsig, len(sig), key)
|
||||||
|
|
||||||
|
|
|
@ -231,6 +231,10 @@ class _OpenSSL:
|
||||||
self.EVP_DigestInit.restype = ctypes.c_int
|
self.EVP_DigestInit.restype = ctypes.c_int
|
||||||
self._lib.EVP_DigestInit.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
self._lib.EVP_DigestInit.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
||||||
|
|
||||||
|
self.EVP_DigestInit_ex = self._lib.EVP_DigestInit_ex
|
||||||
|
self.EVP_DigestInit_ex.restype = ctypes.c_int
|
||||||
|
self._lib.EVP_DigestInit_ex.argtypes = 3 * [ctypes.c_void_p]
|
||||||
|
|
||||||
self.EVP_DigestUpdate = self._lib.EVP_DigestUpdate
|
self.EVP_DigestUpdate = self._lib.EVP_DigestUpdate
|
||||||
self.EVP_DigestUpdate.restype = ctypes.c_int
|
self.EVP_DigestUpdate.restype = ctypes.c_int
|
||||||
self.EVP_DigestUpdate.argtypes = [ctypes.c_void_p,
|
self.EVP_DigestUpdate.argtypes = [ctypes.c_void_p,
|
||||||
|
@ -241,6 +245,11 @@ class _OpenSSL:
|
||||||
self.EVP_DigestFinal.argtypes = [ctypes.c_void_p,
|
self.EVP_DigestFinal.argtypes = [ctypes.c_void_p,
|
||||||
ctypes.c_void_p, ctypes.c_void_p]
|
ctypes.c_void_p, ctypes.c_void_p]
|
||||||
|
|
||||||
|
self.EVP_DigestFinal_ex = self._lib.EVP_DigestFinal_ex
|
||||||
|
self.EVP_DigestFinal_ex.restype = ctypes.c_int
|
||||||
|
self.EVP_DigestFinal_ex.argtypes = [ctypes.c_void_p,
|
||||||
|
ctypes.c_void_p, ctypes.c_void_p]
|
||||||
|
|
||||||
self.EVP_ecdsa = self._lib.EVP_ecdsa
|
self.EVP_ecdsa = self._lib.EVP_ecdsa
|
||||||
self._lib.EVP_ecdsa.restype = ctypes.c_void_p
|
self._lib.EVP_ecdsa.restype = ctypes.c_void_p
|
||||||
self._lib.EVP_ecdsa.argtypes = []
|
self._lib.EVP_ecdsa.argtypes = []
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
softwareVersion = '0.4.4'
|
softwareVersion = '0.4.4'
|
||||||
verbose = 1
|
verbose = 1
|
||||||
maximumAgeOfAnObjectThatIAmWillingToAccept = 216000 # This is obsolete with the change to protocol v3 but the singleCleaner thread still hasn't been updated so we need this a little longer.
|
maximumAgeOfAnObjectThatIAmWillingToAccept = 216000 # This is obsolete with the change to protocol v3 but the singleCleaner thread still hasn't been updated so we need this a little longer.
|
||||||
|
@ -568,7 +570,7 @@ def decryptAndCheckPubkeyPayload(data, address):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
t = (ripe, addressVersion, storedData, int(time.time()), 'yes')
|
t = (address, addressVersion, storedData, int(time.time()), 'yes')
|
||||||
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
||||||
return 'successful'
|
return 'successful'
|
||||||
except varintDecodeError as e:
|
except varintDecodeError as e:
|
||||||
|
@ -589,7 +591,7 @@ def checkAndShareObjectWithPeers(data):
|
||||||
"""
|
"""
|
||||||
if len(data) > 2 ** 18:
|
if len(data) > 2 ** 18:
|
||||||
logger.info('The payload length of this object is too large (%s bytes). Ignoring it.' % len(data))
|
logger.info('The payload length of this object is too large (%s bytes). Ignoring it.' % len(data))
|
||||||
return
|
return 0
|
||||||
# Let us check to make sure that the proof of work is sufficient.
|
# Let us check to make sure that the proof of work is sufficient.
|
||||||
if not isProofOfWorkSufficient(data):
|
if not isProofOfWorkSufficient(data):
|
||||||
logger.info('Proof of work is insufficient.')
|
logger.info('Proof of work is insufficient.')
|
||||||
|
@ -661,6 +663,9 @@ def _checkAndShareUndefinedObjectWithPeers(data):
|
||||||
def _checkAndShareMsgWithPeers(data):
|
def _checkAndShareMsgWithPeers(data):
|
||||||
embeddedTime, = unpack('>Q', data[8:16])
|
embeddedTime, = unpack('>Q', data[8:16])
|
||||||
readPosition = 20 # bypass nonce, time, and object type
|
readPosition = 20 # bypass nonce, time, and object type
|
||||||
|
objectVersion, objectVersionLength = decodeVarint(
|
||||||
|
data[readPosition:readPosition + 9])
|
||||||
|
readPosition += objectVersionLength
|
||||||
streamNumber, streamNumberLength = decodeVarint(
|
streamNumber, streamNumberLength = decodeVarint(
|
||||||
data[readPosition:readPosition + 9])
|
data[readPosition:readPosition + 9])
|
||||||
if not streamNumber in streamsInWhichIAmParticipating:
|
if not streamNumber in streamsInWhichIAmParticipating:
|
||||||
|
|
Binary file not shown.
|
@ -991,7 +991,7 @@ p, li { white-space: pre-wrap; }
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/__init__.py" line="3287"/>
|
<location filename="../bitmessageqt/__init__.py" line="3287"/>
|
||||||
<source>Start-on-login not yet supported on your OS.</source>
|
<source>Start-on-login not yet supported on your OS.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">Mit Betriebssystem starten, noch nicht unterstützt</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/__init__.py" line="3290"/>
|
<location filename="../bitmessageqt/__init__.py" line="3290"/>
|
||||||
|
@ -1627,12 +1627,12 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="392"/>
|
<location filename="../bitmessageqt/settings.py" line="392"/>
|
||||||
<source>Use Identicons</source>
|
<source>Use Identicons</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">Benutze Identicons (Automatisch generierte Icons zu einer Bitcoinadresse)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="393"/>
|
<location filename="../bitmessageqt/settings.py" line="393"/>
|
||||||
<source>Interface Language</source>
|
<source>Interface Language</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">Sprachauswahl</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="394"/>
|
<location filename="../bitmessageqt/settings.py" line="394"/>
|
||||||
|
@ -1697,32 +1697,52 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="439"/>
|
<location filename="../bitmessageqt/settings.py" line="439"/>
|
||||||
<source><html><head/><body><p>By default, if you send a message to someone and he is offline for more than two days, Bitmessage will send the message again after an additional two days. This will be continued with exponential backoff forever; messages will be resent after 5, 10, 20 days ect. until the receiver acknowledges them. Here you may change that behavior by having Bitmessage give up after a certain number of days or months.</p><p>Leave these input fields blank for the default behavior. </p></body></html></source>
|
<source><html><head/><body><p>By default, if you send a message to someone and he is offline for more than two days, Bitmessage will send the message again after an additional two days. This will be continued with exponential backoff forever; messages will be resent after 5, 10, 20 days ect. until the receiver acknowledges them. Here you may change that behavior by having Bitmessage give up after a certain number of days or months.</p><p>Leave these input fields blank for the default behavior. </p></body></html></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"><html><head/><body><p>Wurde eine Nachricht innerhalb von zwei Tagen nicht bestätigt, wird sie in zwei Tag noch einmal gesendet. Schlägt dies wieder fehl, wird es in 5, dann in 10, dann in 20 usw. Tagen wieder versucht. Sendet der Empfänger keine Bestätigung, geht dies unendlich so weiter.</p><p>Dieses Verhalten kann hier begrenz werden.</p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="440"/>
|
<location filename="../bitmessageqt/settings.py" line="440"/>
|
||||||
<source>Give up after</source>
|
<source>Give up after</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">Gib auf nach</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="441"/>
|
<location filename="../bitmessageqt/settings.py" line="441"/>
|
||||||
<source>and</source>
|
<source>and</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">und</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="442"/>
|
<location filename="../bitmessageqt/settings.py" line="442"/>
|
||||||
<source>days</source>
|
<source>days</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">Tagen</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="443"/>
|
<location filename="../bitmessageqt/settings.py" line="443"/>
|
||||||
<source>months.</source>
|
<source>months.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">Monaten</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../bitmessageqt/settings.py" line="444"/>
|
<location filename="../bitmessageqt/settings.py" line="444"/>
|
||||||
<source>Resends Expire</source>
|
<source>Resends Expire</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">Neusendung</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../bitmessageqt/settings.py" line="442"/>
|
||||||
|
<source>Reply below Quote</source>
|
||||||
|
<translation>Antworte unter zitierter Nachricht</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../bitmessageqt/settings.py" line="450"/>
|
||||||
|
<source>Bandwidth limit</source>
|
||||||
|
<translation>Bandbreite begrenzen</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../bitmessageqt/settings.py" line="451"/>
|
||||||
|
<source>Maximum download rate (kB/s): [0: unlimited]</source>
|
||||||
|
<translation>Maximale Downloadrate in kB/s, 0 bedeutet kein Limit</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../bitmessageqt/settings.py" line="452"/>
|
||||||
|
<source>Maximum upload rate (kB/s): [0: unlimited]</source>
|
||||||
|
<translation>Maximale Uploadrate in kB/s, 0 bedeutet kein Limit</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user