Compare commits
2 Commits
v0.6
...
navjotcis/
Author | SHA1 | Date | |
---|---|---|---|
|
74188cfbf4 | ||
|
1533d6c8e6 |
3
.gitattributes
vendored
3
.gitattributes
vendored
|
@ -1,3 +0,0 @@
|
||||||
# Pickle files (for testing) should always have UNIX line endings.
|
|
||||||
# Windows issue like here https://stackoverflow.com/questions/556269
|
|
||||||
knownnodes.dat text eol=lf
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
||||||
[submodule "packages/flatpak/shared-modules"]
|
|
||||||
path = packages/flatpak/shared-modules
|
|
||||||
url = https://github.com/flathub/shared-modules.git
|
|
|
@ -1,9 +1,6 @@
|
||||||
language: python
|
language: python
|
||||||
cache: pip
|
|
||||||
dist: bionic
|
|
||||||
python:
|
python:
|
||||||
- "2.7_with_system_site_packages"
|
- "2.7"
|
||||||
- "3.7"
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
|
@ -14,9 +11,9 @@ addons:
|
||||||
- xvfb
|
- xvfb
|
||||||
install:
|
install:
|
||||||
- pip install -r requirements.txt
|
- pip install -r requirements.txt
|
||||||
|
- ln -s src pybitmessage # tests environment
|
||||||
- python setup.py install
|
- python setup.py install
|
||||||
- export PYTHONWARNINGS=all
|
|
||||||
script:
|
script:
|
||||||
- python checkdeps.py
|
- python checkdeps.py
|
||||||
- xvfb-run src/bitmessagemain.py -t
|
- xvfb-run src/bitmessagemain.py -t
|
||||||
- python -bm tests
|
- python setup.py test
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
FROM ubuntu:bionic AS pybm-travis-bionic
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
|
||||||
ENV TRAVIS_SKIP_APT_UPDATE 1
|
|
||||||
|
|
||||||
RUN apt-get update
|
|
||||||
|
|
||||||
RUN apt-get install -yq --no-install-suggests --no-install-recommends \
|
|
||||||
software-properties-common
|
|
||||||
|
|
||||||
RUN dpkg --add-architecture i386
|
|
||||||
|
|
||||||
RUN add-apt-repository ppa:deadsnakes/ppa
|
|
||||||
|
|
||||||
RUN apt-get -y install sudo
|
|
||||||
|
|
||||||
RUN apt-get install -yq --no-install-suggests --no-install-recommends \
|
|
||||||
# travis xenial bionic
|
|
||||||
python-setuptools libssl-dev libpq-dev python-prctl python-dev \
|
|
||||||
python-dev python-virtualenv python-pip virtualenv \
|
|
||||||
# dpkg
|
|
||||||
python-minimal python-setuptools python-all python openssl libssl-dev \
|
|
||||||
dh-apparmor debhelper dh-python python-msgpack python-qt4 python-stdeb \
|
|
||||||
python-all-dev python-crypto python-psutil \
|
|
||||||
fakeroot python-pytest \
|
|
||||||
# Code quality
|
|
||||||
pylint python-pycodestyle python3-pycodestyle pycodestyle python-flake8 \
|
|
||||||
python3-flake8 flake8 python-pyflakes python3-pyflakes pyflakes pyflakes3 \
|
|
||||||
curl \
|
|
||||||
# Wine
|
|
||||||
python python-pip wget wine-stable winetricks mingw-w64 wine32 wine64 xvfb \
|
|
||||||
# Buildbot
|
|
||||||
python3-dev libffi-dev python3-setuptools \
|
|
||||||
python3-pip \
|
|
||||||
# python 3.7
|
|
||||||
python3.7 python3.7-dev \
|
|
||||||
# .travis.yml
|
|
||||||
build-essential libcap-dev tor \
|
|
||||||
language-pack-en
|
|
||||||
|
|
||||||
# cleanup
|
|
||||||
RUN rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN useradd -m -U builder
|
|
||||||
|
|
||||||
RUN echo 'builder ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
|
||||||
|
|
||||||
# travis2bash
|
|
||||||
RUN wget -O /usr/local/bin/travis2bash.sh https://git.bitmessage.org/Bitmessage/buildbot-scripts/raw/branch/master/travis2bash.sh
|
|
||||||
RUN chmod +x /usr/local/bin/travis2bash.sh
|
|
||||||
|
|
||||||
# copy sources
|
|
||||||
COPY . /home/builder/src
|
|
||||||
RUN chown -R builder.builder /home/builder/src
|
|
||||||
|
|
||||||
USER builder
|
|
||||||
|
|
||||||
ENV LANG en_US.UTF-8
|
|
||||||
ENV LANGUAGE en_US:en
|
|
||||||
ENV LC_ALL en_US.UTF-8
|
|
||||||
|
|
||||||
WORKDIR /home/builder/src
|
|
||||||
|
|
||||||
ENTRYPOINT /usr/local/bin/travis2bash.sh
|
|
43
android_instruction.rst
Normal file
43
android_instruction.rst
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
PyBitmessage(Android)
|
||||||
|
|
||||||
|
This sample aims to be as close to a real world example of a mobile. It has a more refined design and also provides a practical example of how a mobile app would interact and communicate with its addresses.
|
||||||
|
|
||||||
|
Steps for trying out this sample:
|
||||||
|
|
||||||
|
Compile and install the mobile app onto your mobile device or emulator.
|
||||||
|
|
||||||
|
|
||||||
|
Getting Started
|
||||||
|
|
||||||
|
This sample uses the kivy as Kivy is an open source, cross-platform Python framework for the development of applications that make use of innovative, multi-touch user interfaces. The aim is to allow for quick and easy interaction design and rapid prototyping whilst making your code reusable and deployable.
|
||||||
|
|
||||||
|
Kivy is written in Python and Cython, supports various input devices and has an extensive widget library. With the same codebase, you can target Windows, OS X, Linux, Android and iOS. All Kivy widgets are built with multitouch support.
|
||||||
|
|
||||||
|
Kivy in support take Buildozer which is a tool that automates the entire build process. It downloads and sets up all the prerequisite for python-for-android, including the android SDK and NDK, then builds an apk that can be automatically pushed to the device.
|
||||||
|
|
||||||
|
Buildozer currently works only in Linux, and is an alpha release, but it already works well and can significantly simplify the apk build.
|
||||||
|
|
||||||
|
To build this project, use the "Buildozer android release deploy run" command or use.
|
||||||
|
Buildozer ue=sed for creating application packages easily.The goal is to have one "buildozer.spec" file in your app directory, describing your application requirements and settings such as title, icon, included modules etc. Buildozer will use that spec to create a package for Android, iOS, Windows, OSX and/or Linux.
|
||||||
|
|
||||||
|
Installing Requirements
|
||||||
|
|
||||||
|
You can create a package for android using the python-for-android project as with using the Buildozer tool to automate the entire process. You can also see Packaging your application for the Kivy Launcher to run kivy programs without compiling them.
|
||||||
|
|
||||||
|
You can get buildozer at https://github.com/kivy/buildozer or you can directly install using pip install buildozer
|
||||||
|
|
||||||
|
This will install buildozer in your system. Afterwards, navigate to your project directory and run:
|
||||||
|
|
||||||
|
buildozer init
|
||||||
|
|
||||||
|
This creates a buildozer.spec file controlling your build configuration. You should edit it appropriately with your app name etc. You can set variables to control most or all of the parameters passed to python-for-android.
|
||||||
|
|
||||||
|
Install buildozer’s dependencies.
|
||||||
|
|
||||||
|
Finally, plug in your android device and run:
|
||||||
|
|
||||||
|
buildozer android debug deploy run >> To build, push and automatically run the apk on your device. Here we used debug as tested in debug mode for now.
|
||||||
|
|
||||||
|
Packaging your application for the Kivy Launcher
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
"""
|
"""
|
||||||
Check dependencies and give recommendations about how to satisfy them
|
Check dependencies and give recommendations about how to satisfy them
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,4 @@ Comment=Send encrypted messages
|
||||||
Exec=pybitmessage %F
|
Exec=pybitmessage %F
|
||||||
Icon=pybitmessage
|
Icon=pybitmessage
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Categories=Office;Email;Network;
|
Categories=Office;Email;
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
{
|
|
||||||
"id": "org.bitmessage.BaseApp",
|
|
||||||
"branch": "19.08",
|
|
||||||
"runtime": "org.freedesktop.Platform",
|
|
||||||
"sdk": "org.freedesktop.Sdk",
|
|
||||||
"runtime-version": "19.08",
|
|
||||||
"separate-locales": false,
|
|
||||||
"modules": [
|
|
||||||
"shared-modules/python2.7/python-2.7.json",
|
|
||||||
"shared-modules/qt4/qt4-4.8.7-minimal.json",
|
|
||||||
{
|
|
||||||
"name": "python-sip",
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"url": "https://www.riverbankcomputing.com/static/Downloads/sip/4.19.25/sip-4.19.25.tar.gz",
|
|
||||||
"sha256": "b39d93e937647807bac23579edbff25fe46d16213f708370072574ab1f1b4211"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buildsystem": "simple",
|
|
||||||
"build-commands": [
|
|
||||||
"python configure.py --sip-module PyQt4.sip --no-dist-info",
|
|
||||||
"make",
|
|
||||||
"make install"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "python-qt4",
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"url": "http://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.12.3/PyQt4_gpl_x11-4.12.3.tar.gz",
|
|
||||||
"sha256": "a00f5abef240a7b5852b7924fa5fdf5174569525dc076cd368a566619e56d472"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buildsystem": "simple",
|
|
||||||
"build-commands": [
|
|
||||||
"python configure.py -w --confirm-license",
|
|
||||||
"make",
|
|
||||||
"make install"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name" : "PyBitmessage-dependencies",
|
|
||||||
"buildsystem" : "simple",
|
|
||||||
"build-options": {
|
|
||||||
"build-args": [
|
|
||||||
"--share=network"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"build-commands": [
|
|
||||||
"pip --version",
|
|
||||||
"pip install setuptools msgpack"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
"app-id": "org.bitmessage.PyBitmessage",
|
|
||||||
"runtime": "org.freedesktop.Platform",
|
|
||||||
"runtime-version": "19.08",
|
|
||||||
"branch": "stable",
|
|
||||||
"sdk": "org.freedesktop.Sdk",
|
|
||||||
"base": "org.bitmessage.BaseApp",
|
|
||||||
"command": "pybitmessage",
|
|
||||||
"base-version":"stable",
|
|
||||||
"finish-args" : [
|
|
||||||
"--share=network",
|
|
||||||
"--socket=x11",
|
|
||||||
"--share=ipc",
|
|
||||||
"--filesystem=xdg-config/PyBitmessage:create"
|
|
||||||
],
|
|
||||||
"modules": [
|
|
||||||
{
|
|
||||||
"name" : "PyBitmessage",
|
|
||||||
"buildsystem" : "simple",
|
|
||||||
"build-options": {
|
|
||||||
"build-args": [
|
|
||||||
"--share=network"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"build-commands": [
|
|
||||||
"python --version",
|
|
||||||
"pwd",
|
|
||||||
"ls",
|
|
||||||
"python checkdeps.py",
|
|
||||||
"python setup.py install --prefix=/app --exec-prefix=/app",
|
|
||||||
"sed -i 's~/usr/bin/~/app/bin/~' /app/bin/pybitmessage",
|
|
||||||
"cat /app/bin/pybitmessage",
|
|
||||||
"mv /app/share/applications/pybitmessage.desktop /app/share/applications/org.bitmessage.PyBitmessage.desktop",
|
|
||||||
"sed -i 's~Icon=pybitmessage~Icon=org.bitmessage.PyBitmessage~' /app/share/applications/org.bitmessage.PyBitmessage.desktop",
|
|
||||||
"mv /app/share/icons/hicolor/scalable/apps/pybitmessage.svg /app/share/icons/hicolor/scalable/apps/org.bitmessage.PyBitmessage.svg",
|
|
||||||
"mv /app/share/icons/hicolor/24x24/apps/pybitmessage.png /app/share/icons/hicolor/24x24/apps/org.bitmessage.PyBitmessage.png",
|
|
||||||
"which pybitmessage"
|
|
||||||
],
|
|
||||||
"sources" : [
|
|
||||||
{
|
|
||||||
"type" : "dir",
|
|
||||||
"path" : "../../"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit fd4d38328ccb078b88ad4a891807e593ae8de806
|
|
|
@ -1,54 +1,52 @@
|
||||||
# -*- mode: python -*-
|
|
||||||
import ctypes
|
import ctypes
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if ctypes.sizeof(ctypes.c_voidp) == 4:
|
||||||
|
arch=32
|
||||||
|
else:
|
||||||
|
arch=64
|
||||||
|
|
||||||
|
sslName = 'OpenSSL-Win%s' % ("32" if arch == 32 else "64")
|
||||||
site_root = os.path.abspath(HOMEPATH)
|
site_root = os.path.abspath(HOMEPATH)
|
||||||
spec_root = os.path.abspath(SPECPATH)
|
spec_root = os.path.abspath(SPECPATH)
|
||||||
arch = 32 if ctypes.sizeof(ctypes.c_voidp) == 4 else 64
|
|
||||||
cdrivePath = site_root[0:3]
|
cdrivePath = site_root[0:3]
|
||||||
srcPath = os.path.join(spec_root[:-20], "src")
|
srcPath = os.path.join(spec_root[:-20], "src")
|
||||||
sslName = 'OpenSSL-Win%i' % arch
|
qtBase = "PyQt4"
|
||||||
openSSLPath = os.path.join(cdrivePath, sslName)
|
openSSLPath = os.path.join(cdrivePath, sslName)
|
||||||
msvcrDllPath = os.path.join(cdrivePath, "windows", "system32")
|
msvcrDllPath = os.path.join(cdrivePath, "windows", "system32")
|
||||||
|
pythonDllPath = os.path.join(cdrivePath, "Python27")
|
||||||
outPath = os.path.join(spec_root, "bitmessagemain")
|
outPath = os.path.join(spec_root, "bitmessagemain")
|
||||||
qtBase = "PyQt4"
|
|
||||||
|
|
||||||
sys.path.insert(0, srcPath)
|
importPath = srcPath
|
||||||
os.chdir(srcPath)
|
sys.path.insert(0,importPath)
|
||||||
|
os.chdir(sys.path[0])
|
||||||
|
from version import softwareVersion
|
||||||
|
|
||||||
|
today = time.strftime("%Y%m%d")
|
||||||
snapshot = False
|
snapshot = False
|
||||||
|
|
||||||
os.rename(
|
os.rename(os.path.join(srcPath, '__init__.py'), os.path.join(srcPath, '__init__.py.backup'))
|
||||||
os.path.join(srcPath, '__init__.py'),
|
|
||||||
os.path.join(srcPath, '__init__.py.backup'))
|
|
||||||
|
|
||||||
|
# -*- mode: python -*-
|
||||||
a = Analysis(
|
a = Analysis(
|
||||||
[os.path.join(srcPath, 'bitmessagemain.py')],
|
[os.path.join(srcPath, 'bitmessagemain.py')],
|
||||||
pathex=[outPath],
|
pathex=[outPath],
|
||||||
hiddenimports=[
|
hiddenimports=['bitmessageqt.languagebox', 'pyopencl','numpy', 'win32com' , 'setuptools.msvc' ,'_cffi_backend'],
|
||||||
'bitmessageqt.languagebox', 'pyopencl', 'numpy', 'win32com',
|
hookspath=None,
|
||||||
'setuptools.msvc', '_cffi_backend'
|
runtime_hooks=None
|
||||||
],
|
)
|
||||||
hookspath=None,
|
|
||||||
runtime_hooks=None,
|
|
||||||
excludes=['bsddb', 'bz2', 'tcl', 'tk', 'Tkinter']
|
|
||||||
)
|
|
||||||
|
|
||||||
os.rename(
|
|
||||||
os.path.join(srcPath, '__init__.py.backup'),
|
|
||||||
os.path.join(srcPath, '__init__.py'))
|
|
||||||
|
|
||||||
|
os.rename(os.path.join(srcPath, '__init__.py.backup'), os.path.join(srcPath, '__init__.py'))
|
||||||
|
|
||||||
def addTranslations():
|
def addTranslations():
|
||||||
|
import os
|
||||||
extraDatas = []
|
extraDatas = []
|
||||||
for file_ in os.listdir(os.path.join(srcPath, 'translations')):
|
for file_ in os.listdir(os.path.join(srcPath, 'translations')):
|
||||||
if file_[-3:] != ".qm":
|
if file_[-3:] != ".qm":
|
||||||
continue
|
continue
|
||||||
extraDatas.append((
|
extraDatas.append((os.path.join('translations', file_),
|
||||||
os.path.join('translations', file_),
|
|
||||||
os.path.join(srcPath, 'translations', file_), 'DATA'))
|
os.path.join(srcPath, 'translations', file_), 'DATA'))
|
||||||
for libdir in sys.path:
|
for libdir in sys.path:
|
||||||
qtdir = os.path.join(libdir, qtBase, 'translations')
|
qtdir = os.path.join(libdir, qtBase, 'translations')
|
||||||
|
@ -59,74 +57,57 @@ def addTranslations():
|
||||||
for file_ in os.listdir(qtdir):
|
for file_ in os.listdir(qtdir):
|
||||||
if file_[0:3] != "qt_" or file_[5:8] != ".qm":
|
if file_[0:3] != "qt_" or file_[5:8] != ".qm":
|
||||||
continue
|
continue
|
||||||
extraDatas.append((
|
extraDatas.append((os.path.join('translations', file_),
|
||||||
os.path.join('translations', file_),
|
|
||||||
os.path.join(qtdir, file_), 'DATA'))
|
os.path.join(qtdir, file_), 'DATA'))
|
||||||
return extraDatas
|
return extraDatas
|
||||||
|
|
||||||
|
def addUIs():
|
||||||
dir_append = os.path.join(srcPath, 'bitmessageqt')
|
import os
|
||||||
|
extraDatas = []
|
||||||
a.datas += [
|
for file_ in os.listdir(os.path.join(srcPath, 'bitmessageqt')):
|
||||||
(os.path.join('ui', file_), os.path.join(dir_append, file_), 'DATA')
|
if file_[-3:] != ".ui":
|
||||||
for file_ in os.listdir(dir_append) if file_.endswith('.ui')
|
continue
|
||||||
]
|
extraDatas.append((os.path.join('ui', file_), os.path.join(srcPath,
|
||||||
|
'bitmessageqt', file_), 'DATA'))
|
||||||
|
return extraDatas
|
||||||
|
|
||||||
# append the translations directory
|
# append the translations directory
|
||||||
a.datas += addTranslations()
|
a.datas += addTranslations()
|
||||||
|
a.datas += addUIs()
|
||||||
|
|
||||||
|
|
||||||
excluded_binaries = [
|
a.binaries += [('libeay32.dll', os.path.join(openSSLPath, 'libeay32.dll'), 'BINARY'),
|
||||||
'QtOpenGL4.dll',
|
('python27.dll', os.path.join(pythonDllPath, 'python27.dll'), 'BINARY'),
|
||||||
'QtSvg4.dll',
|
(os.path.join('bitmsghash', 'bitmsghash%i.dll' % (arch)), os.path.join(srcPath, 'bitmsghash', 'bitmsghash%i.dll' % (arch)), 'BINARY'),
|
||||||
'QtXml4.dll',
|
(os.path.join('bitmsghash', 'bitmsghash.cl'), os.path.join(srcPath, 'bitmsghash', 'bitmsghash.cl'), 'BINARY'),
|
||||||
]
|
(os.path.join('sslkeys', 'cert.pem'), os.path.join(srcPath, 'sslkeys', 'cert.pem'), 'BINARY'),
|
||||||
a.binaries = TOC([x for x in a.binaries if x[0] not in excluded_binaries])
|
(os.path.join('sslkeys', 'key.pem'), os.path.join(srcPath, 'sslkeys', 'key.pem'), 'BINARY')
|
||||||
|
]
|
||||||
a.binaries += [
|
|
||||||
# No effect: libeay32.dll will be taken from PyQt if installed
|
|
||||||
('libeay32.dll', os.path.join(openSSLPath, 'libeay32.dll'), 'BINARY'),
|
|
||||||
(os.path.join('bitmsghash', 'bitmsghash%i.dll' % arch),
|
|
||||||
os.path.join(srcPath, 'bitmsghash', 'bitmsghash%i.dll' % arch),
|
|
||||||
'BINARY'),
|
|
||||||
(os.path.join('bitmsghash', 'bitmsghash.cl'),
|
|
||||||
os.path.join(srcPath, 'bitmsghash', 'bitmsghash.cl'), 'BINARY'),
|
|
||||||
(os.path.join('sslkeys', 'cert.pem'),
|
|
||||||
os.path.join(srcPath, 'sslkeys', 'cert.pem'), 'BINARY'),
|
|
||||||
(os.path.join('sslkeys', 'key.pem'),
|
|
||||||
os.path.join(srcPath, 'sslkeys', 'key.pem'), 'BINARY')
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
from version import softwareVersion
|
fname = 'Bitmessage_%s_%s.exe' % ("x86" if arch == 32 else "x64", softwareVersion)
|
||||||
|
if snapshot:
|
||||||
today = time.strftime("%Y%m%d")
|
fname = 'Bitmessagedev_%s_%s.exe' % ("x86" if arch == 32 else "x64", today)
|
||||||
|
|
||||||
fname = '%s_%%s_%s.exe' % (
|
|
||||||
('Bitmessagedev', today) if snapshot else ('Bitmessage', softwareVersion)
|
|
||||||
) % ("x86" if arch == 32 else "x64")
|
|
||||||
|
|
||||||
|
|
||||||
pyz = PYZ(a.pure)
|
pyz = PYZ(a.pure)
|
||||||
exe = EXE(
|
exe = EXE(pyz,
|
||||||
pyz,
|
a.scripts,
|
||||||
a.scripts,
|
a.binaries,
|
||||||
a.binaries,
|
a.zipfiles,
|
||||||
a.zipfiles,
|
a.datas,
|
||||||
a.datas,
|
a.binaries,
|
||||||
name=fname,
|
[],
|
||||||
debug=False,
|
name=fname,
|
||||||
strip=None,
|
debug=False,
|
||||||
upx=False,
|
strip=None,
|
||||||
console=False, icon=os.path.join(srcPath, 'images', 'can-icon.ico')
|
upx=False,
|
||||||
)
|
console=False, icon= os.path.join(srcPath, 'images', 'can-icon.ico'))
|
||||||
|
|
||||||
|
coll = COLLECT(exe,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
strip=False,
|
||||||
|
upx=False,
|
||||||
|
name='main')
|
||||||
|
|
||||||
coll = COLLECT(
|
|
||||||
exe,
|
|
||||||
a.binaries,
|
|
||||||
a.zipfiles,
|
|
||||||
a.datas,
|
|
||||||
strip=False,
|
|
||||||
upx=False,
|
|
||||||
name='main'
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
coverage
|
|
||||||
python_prctl
|
python_prctl
|
||||||
psutil
|
psutil
|
||||||
pycrypto
|
pycrypto
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
docker build -t pybm-travis-bionic -f Dockerfile.travis .
|
|
||||||
docker run pybm-travis-bionic
|
|
22
setup.py
22
setup.py
|
@ -12,7 +12,6 @@ from src.version import softwareVersion
|
||||||
|
|
||||||
|
|
||||||
EXTRAS_REQUIRE = {
|
EXTRAS_REQUIRE = {
|
||||||
'docs': ['sphinx', 'sphinxcontrib-apidoc', 'm2r'],
|
|
||||||
'gir': ['pygobject'],
|
'gir': ['pygobject'],
|
||||||
'json': ['jsonrpclib'],
|
'json': ['jsonrpclib'],
|
||||||
'notify2': ['notify2'],
|
'notify2': ['notify2'],
|
||||||
|
@ -21,8 +20,8 @@ EXTRAS_REQUIRE = {
|
||||||
'qrcode': ['qrcode'],
|
'qrcode': ['qrcode'],
|
||||||
'sound;platform_system=="Windows"': ['winsound'],
|
'sound;platform_system=="Windows"': ['winsound'],
|
||||||
'tor': ['stem'],
|
'tor': ['stem'],
|
||||||
'xdg': ['pyxdg'],
|
'xml': ['defusedxml'],
|
||||||
'xml': ['defusedxml']
|
'docs': ['sphinx', 'sphinxcontrib-apidoc', 'm2r']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,14 +94,11 @@ if __name__ == "__main__":
|
||||||
['desktop/icons/24x24/pybitmessage.png'])
|
['desktop/icons/24x24/pybitmessage.png'])
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
if platform.dist()[0] in ('Debian', 'Ubuntu'):
|
||||||
if platform.dist()[0] in ('Debian', 'Ubuntu'):
|
data_files += [
|
||||||
data_files += [
|
("etc/apparmor.d/",
|
||||||
("etc/apparmor.d/",
|
['packages/apparmor/pybitmessage'])
|
||||||
['packages/apparmor/pybitmessage'])
|
]
|
||||||
]
|
|
||||||
except AttributeError:
|
|
||||||
pass # FIXME: use distro for more recent python
|
|
||||||
|
|
||||||
dist = setup(
|
dist = setup(
|
||||||
name='pybitmessage',
|
name='pybitmessage',
|
||||||
|
@ -119,7 +115,6 @@ if __name__ == "__main__":
|
||||||
#keywords='',
|
#keywords='',
|
||||||
install_requires=installRequires,
|
install_requires=installRequires,
|
||||||
tests_require=requirements,
|
tests_require=requirements,
|
||||||
test_suite='tests.unittest_discover',
|
|
||||||
extras_require=EXTRAS_REQUIRE,
|
extras_require=EXTRAS_REQUIRE,
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"License :: OSI Approved :: MIT License"
|
"License :: OSI Approved :: MIT License"
|
||||||
|
@ -158,9 +153,6 @@ if __name__ == "__main__":
|
||||||
'libmessaging ='
|
'libmessaging ='
|
||||||
'pybitmessage.plugins.indicator_libmessaging [gir]'
|
'pybitmessage.plugins.indicator_libmessaging [gir]'
|
||||||
],
|
],
|
||||||
'bitmessage.desktop': [
|
|
||||||
'freedesktop = pybitmessage.plugins.desktop_xdg [xdg]'
|
|
||||||
],
|
|
||||||
'bitmessage.proxyconfig': [
|
'bitmessage.proxyconfig': [
|
||||||
'stem = pybitmessage.plugins.proxyconfig_stem [tor]'
|
'stem = pybitmessage.plugins.proxyconfig_stem [tor]'
|
||||||
],
|
],
|
||||||
|
|
|
@ -3,12 +3,10 @@ Operations with addresses
|
||||||
"""
|
"""
|
||||||
# pylint: disable=redefined-outer-name,inconsistent-return-statements
|
# pylint: disable=redefined-outer-name,inconsistent-return-statements
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
|
||||||
from binascii import hexlify, unhexlify
|
from binascii import hexlify, unhexlify
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
|
|
||||||
|
from debug import logger
|
||||||
logger = logging.getLogger('default')
|
|
||||||
|
|
||||||
ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
@ -25,7 +23,8 @@ def encodeBase58(num, alphabet=ALPHABET):
|
||||||
arr = []
|
arr = []
|
||||||
base = len(alphabet)
|
base = len(alphabet)
|
||||||
while num:
|
while num:
|
||||||
num, rem = divmod(num, base)
|
rem = num % base
|
||||||
|
num = num // base
|
||||||
arr.append(alphabet[rem])
|
arr.append(alphabet[rem])
|
||||||
arr.reverse()
|
arr.reverse()
|
||||||
return ''.join(arr)
|
return ''.join(arr)
|
||||||
|
@ -149,16 +148,16 @@ def encodeAddress(version, stream, ripe):
|
||||||
'Programming error in encodeAddress: The length of'
|
'Programming error in encodeAddress: The length of'
|
||||||
' a given ripe hash was not 20.'
|
' a given ripe hash was not 20.'
|
||||||
)
|
)
|
||||||
if ripe[:2] == b'\x00\x00':
|
if ripe[:2] == '\x00\x00':
|
||||||
ripe = ripe[2:]
|
ripe = ripe[2:]
|
||||||
elif ripe[:1] == b'\x00':
|
elif ripe[:1] == '\x00':
|
||||||
ripe = ripe[1:]
|
ripe = ripe[1:]
|
||||||
elif version == 4:
|
elif version == 4:
|
||||||
if len(ripe) != 20:
|
if len(ripe) != 20:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Programming error in encodeAddress: The length of'
|
'Programming error in encodeAddress: The length of'
|
||||||
' a given ripe hash was not 20.')
|
' a given ripe hash was not 20.')
|
||||||
ripe = ripe.lstrip(b'\x00')
|
ripe = ripe.lstrip('\x00')
|
||||||
|
|
||||||
storedBinaryData = encodeVarint(version) + encodeVarint(stream) + ripe
|
storedBinaryData = encodeVarint(version) + encodeVarint(stream) + ripe
|
||||||
|
|
||||||
|
@ -192,8 +191,8 @@ def decodeAddress(address):
|
||||||
status = 'invalidcharacters'
|
status = 'invalidcharacters'
|
||||||
return status, 0, 0, ''
|
return status, 0, 0, ''
|
||||||
# after converting to hex, the string will be prepended
|
# after converting to hex, the string will be prepended
|
||||||
# with a 0x and appended with a L in python2
|
# with a 0x and appended with a L
|
||||||
hexdata = hex(integer)[2:].rstrip('L')
|
hexdata = hex(integer)[2:-1]
|
||||||
|
|
||||||
if len(hexdata) % 2 != 0:
|
if len(hexdata) % 2 != 0:
|
||||||
hexdata = '0' + hexdata
|
hexdata = '0' + hexdata
|
||||||
|
@ -243,13 +242,13 @@ def decodeAddress(address):
|
||||||
data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4]
|
data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4]
|
||||||
if len(embeddedRipeData) == 19:
|
if len(embeddedRipeData) == 19:
|
||||||
return status, addressVersionNumber, streamNumber, \
|
return status, addressVersionNumber, streamNumber, \
|
||||||
b'\x00' + embeddedRipeData
|
'\x00' + embeddedRipeData
|
||||||
elif len(embeddedRipeData) == 20:
|
elif len(embeddedRipeData) == 20:
|
||||||
return status, addressVersionNumber, streamNumber, \
|
return status, addressVersionNumber, streamNumber, \
|
||||||
embeddedRipeData
|
embeddedRipeData
|
||||||
elif len(embeddedRipeData) == 18:
|
elif len(embeddedRipeData) == 18:
|
||||||
return status, addressVersionNumber, streamNumber, \
|
return status, addressVersionNumber, streamNumber, \
|
||||||
b'\x00\x00' + embeddedRipeData
|
'\x00\x00' + embeddedRipeData
|
||||||
elif len(embeddedRipeData) < 18:
|
elif len(embeddedRipeData) < 18:
|
||||||
return 'ripetooshort', 0, 0, ''
|
return 'ripetooshort', 0, 0, ''
|
||||||
elif len(embeddedRipeData) > 20:
|
elif len(embeddedRipeData) > 20:
|
||||||
|
@ -258,7 +257,7 @@ def decodeAddress(address):
|
||||||
elif addressVersionNumber == 4:
|
elif addressVersionNumber == 4:
|
||||||
embeddedRipeData = \
|
embeddedRipeData = \
|
||||||
data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4]
|
data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4]
|
||||||
if embeddedRipeData[0:1] == b'\x00':
|
if embeddedRipeData[0:1] == '\x00':
|
||||||
# In order to enforce address non-malleability, encoded
|
# In order to enforce address non-malleability, encoded
|
||||||
# RIPE data must have NULL bytes removed from the front
|
# RIPE data must have NULL bytes removed from the front
|
||||||
return 'encodingproblem', 0, 0, ''
|
return 'encodingproblem', 0, 0, ''
|
||||||
|
@ -266,7 +265,7 @@ def decodeAddress(address):
|
||||||
return 'ripetoolong', 0, 0, ''
|
return 'ripetoolong', 0, 0, ''
|
||||||
elif len(embeddedRipeData) < 4:
|
elif len(embeddedRipeData) < 4:
|
||||||
return 'ripetooshort', 0, 0, ''
|
return 'ripetooshort', 0, 0, ''
|
||||||
x00string = b'\x00' * (20 - len(embeddedRipeData))
|
x00string = '\x00' * (20 - len(embeddedRipeData))
|
||||||
return status, addressVersionNumber, streamNumber, \
|
return status, addressVersionNumber, streamNumber, \
|
||||||
x00string + embeddedRipeData
|
x00string + embeddedRipeData
|
||||||
|
|
||||||
|
|
|
@ -983,7 +983,7 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
|
||||||
def loadInbox():
|
def loadInbox():
|
||||||
"""Load the list of messages"""
|
"""Load the list of messages"""
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
print("Loading inbox messages...")
|
print "Loading inbox messages..."
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
|
|
||||||
where = "toaddress || fromaddress || subject || message"
|
where = "toaddress || fromaddress || subject || message"
|
||||||
|
@ -1035,7 +1035,7 @@ def loadInbox():
|
||||||
def loadSent():
|
def loadSent():
|
||||||
"""Load the messages that sent"""
|
"""Load the messages that sent"""
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
print("Loading sent messages...")
|
print "Loading sent messages..."
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
|
|
||||||
where = "toaddress || fromaddress || subject || message"
|
where = "toaddress || fromaddress || subject || message"
|
||||||
|
@ -1121,7 +1121,7 @@ def loadSent():
|
||||||
def loadAddrBook():
|
def loadAddrBook():
|
||||||
"""Load address book"""
|
"""Load address book"""
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
print("Loading address book...")
|
print "Loading address book..."
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
|
|
||||||
ret = sqlQuery("SELECT label, address FROM addressbook")
|
ret = sqlQuery("SELECT label, address FROM addressbook")
|
||||||
|
@ -1228,7 +1228,7 @@ def run(stdscr):
|
||||||
def doShutdown():
|
def doShutdown():
|
||||||
"""Shutting the app down"""
|
"""Shutting the app down"""
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
print("Shutting down...")
|
print "Shutting down..."
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
shutdown.doCleanShutdown()
|
shutdown.doCleanShutdown()
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/python2.7
|
||||||
"""
|
"""
|
||||||
The PyBitmessage startup script
|
The PyBitmessage startup script
|
||||||
"""
|
"""
|
||||||
|
@ -12,11 +12,10 @@ The PyBitmessage startup script
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
try:
|
app_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
import pathmagic
|
os.chdir(app_dir)
|
||||||
except ImportError:
|
sys.path.insert(0, app_dir)
|
||||||
from pybitmessage import pathmagic
|
|
||||||
app_dir = pathmagic.setup()
|
|
||||||
|
|
||||||
import depends
|
import depends
|
||||||
depends.check_dependencies()
|
depends.check_dependencies()
|
||||||
|
@ -321,10 +320,9 @@ class Main(object):
|
||||||
receiveQueueThread = ReceiveQueueThread(i)
|
receiveQueueThread = ReceiveQueueThread(i)
|
||||||
receiveQueueThread.daemon = True
|
receiveQueueThread.daemon = True
|
||||||
receiveQueueThread.start()
|
receiveQueueThread.start()
|
||||||
if config.safeGetBoolean('bitmessagesettings', 'udp'):
|
announceThread = AnnounceThread()
|
||||||
state.announceThread = AnnounceThread()
|
announceThread.daemon = True
|
||||||
state.announceThread.daemon = True
|
announceThread.start()
|
||||||
state.announceThread.start()
|
|
||||||
state.invThread = InvThread()
|
state.invThread = InvThread()
|
||||||
state.invThread.daemon = True
|
state.invThread.daemon = True
|
||||||
state.invThread.start()
|
state.invThread.start()
|
||||||
|
@ -353,6 +351,10 @@ class Main(object):
|
||||||
print('Running with curses')
|
print('Running with curses')
|
||||||
import bitmessagecurses
|
import bitmessagecurses
|
||||||
bitmessagecurses.runwrapper()
|
bitmessagecurses.runwrapper()
|
||||||
|
elif state.kivy:
|
||||||
|
config.remove_option('bitmessagesettings', 'dontconnect')
|
||||||
|
# from bitmessagekivy.mpybit import NavigateApp
|
||||||
|
# NavigateApp().run()
|
||||||
else:
|
else:
|
||||||
import bitmessageqt
|
import bitmessageqt
|
||||||
bitmessageqt.run()
|
bitmessageqt.run()
|
||||||
|
@ -379,7 +381,11 @@ class Main(object):
|
||||||
test_core_result = test_core.run()
|
test_core_result = test_core.run()
|
||||||
self.stop()
|
self.stop()
|
||||||
test_core.cleanup()
|
test_core.cleanup()
|
||||||
sys.exit(not test_core_result.wasSuccessful())
|
sys.exit(
|
||||||
|
'Core tests failed!'
|
||||||
|
if test_core_result.errors or test_core_result.failures
|
||||||
|
else 0
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def daemonize():
|
def daemonize():
|
||||||
|
|
|
@ -640,6 +640,8 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
BMConfigParser().remove_section(addressInKeysFile)
|
BMConfigParser().remove_section(addressInKeysFile)
|
||||||
BMConfigParser().save()
|
BMConfigParser().save()
|
||||||
|
|
||||||
|
self.updateStartOnLogon()
|
||||||
|
|
||||||
self.change_translation()
|
self.change_translation()
|
||||||
|
|
||||||
# e.g. for editing labels
|
# e.g. for editing labels
|
||||||
|
@ -824,7 +826,6 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
self.sqlInit()
|
self.sqlInit()
|
||||||
self.indicatorInit()
|
self.indicatorInit()
|
||||||
self.notifierInit()
|
self.notifierInit()
|
||||||
self.updateStartOnLogon()
|
|
||||||
|
|
||||||
self.ui.updateNetworkSwitchMenuLabel()
|
self.ui.updateNetworkSwitchMenuLabel()
|
||||||
|
|
||||||
|
@ -843,28 +844,26 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
self._contact_selected = None
|
self._contact_selected = None
|
||||||
|
|
||||||
def updateStartOnLogon(self):
|
def updateStartOnLogon(self):
|
||||||
"""
|
# Configure Bitmessage to start on startup (or remove the
|
||||||
Configure Bitmessage to start on startup (or remove the
|
# configuration) based on the setting in the keys.dat file
|
||||||
configuration) based on the setting in the keys.dat file
|
if 'win32' in sys.platform or 'win64' in sys.platform:
|
||||||
"""
|
# Auto-startup for Windows
|
||||||
startonlogon = BMConfigParser().safeGetBoolean(
|
|
||||||
'bitmessagesettings', 'startonlogon')
|
|
||||||
if sys.platform.startswith('win'): # Auto-startup for Windows
|
|
||||||
RUN_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
|
RUN_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
|
||||||
settings = QtCore.QSettings(
|
self.settings = QtCore.QSettings(
|
||||||
RUN_PATH, QtCore.QSettings.NativeFormat)
|
RUN_PATH, QtCore.QSettings.NativeFormat)
|
||||||
# In case the user moves the program and the registry entry is
|
# In case the user moves the program and the registry entry is
|
||||||
# no longer valid, this will delete the old registry entry.
|
# no longer valid, this will delete the old registry entry.
|
||||||
if startonlogon:
|
self.settings.remove("PyBitmessage")
|
||||||
settings.setValue("PyBitmessage", sys.argv[0])
|
if BMConfigParser().getboolean(
|
||||||
else:
|
'bitmessagesettings', 'startonlogon'
|
||||||
settings.remove("PyBitmessage")
|
):
|
||||||
else:
|
self.settings.setValue("PyBitmessage", sys.argv[0])
|
||||||
try: # get desktop plugin if any
|
elif 'darwin' in sys.platform:
|
||||||
self.desktop = get_plugin('desktop')()
|
# startup for mac
|
||||||
self.desktop.adjust_startonlogon(startonlogon)
|
pass
|
||||||
except (NameError, TypeError):
|
elif 'linux' in sys.platform:
|
||||||
self.desktop = False
|
# startup for linux
|
||||||
|
pass
|
||||||
|
|
||||||
def updateTTL(self, sliderPosition):
|
def updateTTL(self, sliderPosition):
|
||||||
TTL = int(sliderPosition ** 3.199 + 3600)
|
TTL = int(sliderPosition ** 3.199 + 3600)
|
||||||
|
@ -1424,11 +1423,9 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
def sqlInit(self):
|
def sqlInit(self):
|
||||||
register_adapter(QtCore.QByteArray, str)
|
register_adapter(QtCore.QByteArray, str)
|
||||||
|
|
||||||
|
# Try init the distro specific appindicator,
|
||||||
|
# for example the Ubuntu MessagingMenu
|
||||||
def indicatorInit(self):
|
def indicatorInit(self):
|
||||||
"""
|
|
||||||
Try init the distro specific appindicator,
|
|
||||||
for example the Ubuntu MessagingMenu
|
|
||||||
"""
|
|
||||||
def _noop_update(*args, **kwargs):
|
def _noop_update(*args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import widgets
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from helper_sql import sqlExecute, sqlStoredProcedure
|
from helper_sql import sqlExecute, sqlStoredProcedure
|
||||||
from helper_startup import start_proxyconfig
|
from helper_startup import start_proxyconfig
|
||||||
from network import knownnodes, AnnounceThread
|
from network import knownnodes
|
||||||
from network.asyncore_pollchoose import set_rates
|
from network.asyncore_pollchoose import set_rates
|
||||||
from tr import _translate
|
from tr import _translate
|
||||||
|
|
||||||
|
@ -119,6 +119,9 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
self.checkBoxPortableMode.setDisabled(True)
|
self.checkBoxPortableMode.setDisabled(True)
|
||||||
|
|
||||||
if 'darwin' in sys.platform:
|
if 'darwin' in sys.platform:
|
||||||
|
self.checkBoxStartOnLogon.setDisabled(True)
|
||||||
|
self.checkBoxStartOnLogon.setText(_translate(
|
||||||
|
"MainWindow", "Start-on-login not yet supported on your OS."))
|
||||||
self.checkBoxMinimizeToTray.setDisabled(True)
|
self.checkBoxMinimizeToTray.setDisabled(True)
|
||||||
self.checkBoxMinimizeToTray.setText(_translate(
|
self.checkBoxMinimizeToTray.setText(_translate(
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
|
@ -127,19 +130,15 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
self.checkBoxShowTrayNotifications.setText(_translate(
|
self.checkBoxShowTrayNotifications.setText(_translate(
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
"Tray notifications not yet supported on your OS."))
|
"Tray notifications not yet supported on your OS."))
|
||||||
|
elif 'linux' in sys.platform:
|
||||||
if 'win' not in sys.platform and not self.parent.desktop:
|
|
||||||
self.checkBoxStartOnLogon.setDisabled(True)
|
self.checkBoxStartOnLogon.setDisabled(True)
|
||||||
self.checkBoxStartOnLogon.setText(_translate(
|
self.checkBoxStartOnLogon.setText(_translate(
|
||||||
"MainWindow", "Start-on-login not yet supported on your OS."))
|
"MainWindow", "Start-on-login not yet supported on your OS."))
|
||||||
|
|
||||||
# On the Network settings tab:
|
# On the Network settings tab:
|
||||||
self.lineEditTCPPort.setText(str(
|
self.lineEditTCPPort.setText(str(
|
||||||
config.get('bitmessagesettings', 'port')))
|
config.get('bitmessagesettings', 'port')))
|
||||||
self.checkBoxUPnP.setChecked(
|
self.checkBoxUPnP.setChecked(
|
||||||
config.safeGetBoolean('bitmessagesettings', 'upnp'))
|
config.safeGetBoolean('bitmessagesettings', 'upnp'))
|
||||||
self.checkBoxUDP.setChecked(
|
|
||||||
config.safeGetBoolean('bitmessagesettings', 'udp'))
|
|
||||||
self.checkBoxAuthentication.setChecked(
|
self.checkBoxAuthentication.setChecked(
|
||||||
config.getboolean('bitmessagesettings', 'socksauthentication'))
|
config.getboolean('bitmessagesettings', 'socksauthentication'))
|
||||||
self.checkBoxSocksListen.setChecked(
|
self.checkBoxSocksListen.setChecked(
|
||||||
|
@ -328,8 +327,7 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
self.lineEditTCPPort.text()):
|
self.lineEditTCPPort.text()):
|
||||||
self.config.set(
|
self.config.set(
|
||||||
'bitmessagesettings', 'port', str(self.lineEditTCPPort.text()))
|
'bitmessagesettings', 'port', str(self.lineEditTCPPort.text()))
|
||||||
if not self.config.safeGetBoolean(
|
if not self.config.safeGetBoolean('bitmessagesettings', 'dontconnect'):
|
||||||
'bitmessagesettings', 'dontconnect'):
|
|
||||||
self.net_restart_needed = True
|
self.net_restart_needed = True
|
||||||
|
|
||||||
if self.checkBoxUPnP.isChecked() != self.config.safeGetBoolean(
|
if self.checkBoxUPnP.isChecked() != self.config.safeGetBoolean(
|
||||||
|
@ -342,26 +340,11 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
upnpThread = upnp.uPnPThread()
|
upnpThread = upnp.uPnPThread()
|
||||||
upnpThread.start()
|
upnpThread.start()
|
||||||
|
|
||||||
udp_enabled = self.checkBoxUDP.isChecked()
|
|
||||||
if udp_enabled != self.config.safeGetBoolean(
|
|
||||||
'bitmessagesettings', 'udp'):
|
|
||||||
self.config.set('bitmessagesettings', 'udp', str(udp_enabled))
|
|
||||||
if udp_enabled:
|
|
||||||
announceThread = AnnounceThread()
|
|
||||||
announceThread.daemon = True
|
|
||||||
announceThread.start()
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
state.announceThread.stopThread()
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
proxytype_index = self.comboBoxProxyType.currentIndex()
|
proxytype_index = self.comboBoxProxyType.currentIndex()
|
||||||
if proxytype_index == 0:
|
if proxytype_index == 0:
|
||||||
if self._proxy_type and state.statusIconColor != 'red':
|
if self._proxy_type and state.statusIconColor != 'red':
|
||||||
self.net_restart_needed = True
|
self.net_restart_needed = True
|
||||||
elif state.statusIconColor == 'red' and self.config.safeGetBoolean(
|
elif state.statusIconColor == 'red' and self.config.safeGetBoolean('bitmessagesettings', 'dontconnect'):
|
||||||
'bitmessagesettings', 'dontconnect'):
|
|
||||||
self.net_restart_needed = False
|
self.net_restart_needed = False
|
||||||
elif self.comboBoxProxyType.currentText() != self._proxy_type:
|
elif self.comboBoxProxyType.currentText() != self._proxy_type:
|
||||||
self.net_restart_needed = True
|
self.net_restart_needed = True
|
||||||
|
@ -387,11 +370,8 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
self.lineEditSocksPassword.text()))
|
self.lineEditSocksPassword.text()))
|
||||||
self.config.set('bitmessagesettings', 'sockslisten', str(
|
self.config.set('bitmessagesettings', 'sockslisten', str(
|
||||||
self.checkBoxSocksListen.isChecked()))
|
self.checkBoxSocksListen.isChecked()))
|
||||||
if (
|
if self.checkBoxOnionOnly.isChecked() \
|
||||||
self.checkBoxOnionOnly.isChecked()
|
and not self.config.safeGetBoolean('bitmessagesettings', 'onionservicesonly'):
|
||||||
and not self.config.safeGetBoolean(
|
|
||||||
'bitmessagesettings', 'onionservicesonly')
|
|
||||||
):
|
|
||||||
self.net_restart_needed = True
|
self.net_restart_needed = True
|
||||||
self.config.set('bitmessagesettings', 'onionservicesonly', str(
|
self.config.set('bitmessagesettings', 'onionservicesonly', str(
|
||||||
self.checkBoxOnionOnly.isChecked()))
|
self.checkBoxOnionOnly.isChecked()))
|
||||||
|
@ -453,8 +433,8 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
acceptableDifficultyChanged = False
|
acceptableDifficultyChanged = False
|
||||||
|
|
||||||
if (
|
if (
|
||||||
float(self.lineEditMaxAcceptableTotalDifficulty.text()) >= 1
|
float(self.lineEditMaxAcceptableTotalDifficulty.text()) >= 1
|
||||||
or float(self.lineEditMaxAcceptableTotalDifficulty.text()) == 0
|
or float(self.lineEditMaxAcceptableTotalDifficulty.text()) == 0
|
||||||
):
|
):
|
||||||
if self.config.get(
|
if self.config.get(
|
||||||
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte'
|
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte'
|
||||||
|
@ -470,8 +450,8 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
* defaults.networkDefaultProofOfWorkNonceTrialsPerByte))
|
* defaults.networkDefaultProofOfWorkNonceTrialsPerByte))
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
float(self.lineEditMaxAcceptableSmallMessageDifficulty.text()) >= 1
|
float(self.lineEditMaxAcceptableSmallMessageDifficulty.text()) >= 1
|
||||||
or float(self.lineEditMaxAcceptableSmallMessageDifficulty.text()) == 0
|
or float(self.lineEditMaxAcceptableSmallMessageDifficulty.text()) == 0
|
||||||
):
|
):
|
||||||
if self.config.get(
|
if self.config.get(
|
||||||
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes'
|
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes'
|
||||||
|
@ -562,8 +542,8 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
self.parent.updateStartOnLogon()
|
self.parent.updateStartOnLogon()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
state.appdata != paths.lookupExeFolder()
|
state.appdata != paths.lookupExeFolder()
|
||||||
and self.checkBoxPortableMode.isChecked()
|
and self.checkBoxPortableMode.isChecked()
|
||||||
):
|
):
|
||||||
# If we are NOT using portable mode now but the user selected
|
# If we are NOT using portable mode now but the user selected
|
||||||
# that we should...
|
# that we should...
|
||||||
|
@ -585,8 +565,8 @@ class SettingsDialog(QtGui.QDialog):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if (
|
if (
|
||||||
state.appdata == paths.lookupExeFolder()
|
state.appdata == paths.lookupExeFolder()
|
||||||
and not self.checkBoxPortableMode.isChecked()
|
and not self.checkBoxPortableMode.isChecked()
|
||||||
):
|
):
|
||||||
# If we ARE using portable mode now but the user selected
|
# If we ARE using portable mode now but the user selected
|
||||||
# that we shouldn't...
|
# that we shouldn't...
|
||||||
|
|
|
@ -231,7 +231,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QGroupBox" name="groupBox_3">
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Bandwidth limit</string>
|
<string>Bandwidth limit</string>
|
||||||
|
@ -322,7 +322,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Proxy server / Tor</string>
|
<string>Proxy server / Tor</string>
|
||||||
|
@ -432,14 +432,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QCheckBox" name="checkBoxUDP">
|
|
||||||
<property name="text">
|
|
||||||
<string>Announce self by UDP</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
"""bitmessageqt tests"""
|
"""bitmessageqt tests"""
|
||||||
|
|
||||||
from addressbook import TestAddressbook
|
|
||||||
from main import TestMain, TestUISignaler
|
from main import TestMain, TestUISignaler
|
||||||
from settings import TestSettings
|
|
||||||
from support import TestSupport
|
from support import TestSupport
|
||||||
|
|
||||||
__all__ = [
|
__all__ = ["TestMain", "TestSupport", "TestUISignaler"]
|
||||||
"TestAddressbook", "TestMain", "TestSettings", "TestSupport",
|
|
||||||
"TestUISignaler"
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import helper_addressbook
|
|
||||||
from bitmessageqt.support import createAddressIfNeeded
|
|
||||||
|
|
||||||
from main import TestBase
|
|
||||||
|
|
||||||
|
|
||||||
class TestAddressbook(TestBase):
|
|
||||||
"""Test case for addressbook"""
|
|
||||||
|
|
||||||
def test_add_own_address_to_addressbook(self):
|
|
||||||
"""Checking own address adding in addressbook"""
|
|
||||||
try:
|
|
||||||
address = createAddressIfNeeded(self.window)
|
|
||||||
self.assertFalse(
|
|
||||||
helper_addressbook.insert(label='test', address=address))
|
|
||||||
except IndexError:
|
|
||||||
self.fail("Can't generate addresses")
|
|
|
@ -1,34 +0,0 @@
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
|
|
||||||
from main import TestBase
|
|
||||||
from bmconfigparser import BMConfigParser
|
|
||||||
from bitmessageqt import settings
|
|
||||||
|
|
||||||
|
|
||||||
class TestSettings(TestBase):
|
|
||||||
"""A test case for the "Settings" dialog"""
|
|
||||||
def setUp(self):
|
|
||||||
super(TestSettings, self).setUp()
|
|
||||||
self.dialog = settings.SettingsDialog(self.window)
|
|
||||||
|
|
||||||
def test_udp(self):
|
|
||||||
"""Test the effect of checkBoxUDP"""
|
|
||||||
udp_setting = BMConfigParser().safeGetBoolean(
|
|
||||||
'bitmessagesettings', 'udp')
|
|
||||||
self.assertEqual(udp_setting, self.dialog.checkBoxUDP.isChecked())
|
|
||||||
self.dialog.checkBoxUDP.setChecked(not udp_setting)
|
|
||||||
self.dialog.accept()
|
|
||||||
self.assertEqual(
|
|
||||||
not udp_setting,
|
|
||||||
BMConfigParser().safeGetBoolean('bitmessagesettings', 'udp'))
|
|
||||||
time.sleep(5)
|
|
||||||
for thread in threading.enumerate():
|
|
||||||
if thread.name == 'Announcer': # find Announcer thread
|
|
||||||
if udp_setting:
|
|
||||||
self.fail(
|
|
||||||
'Announcer thread is running while udp set to False')
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if not udp_setting:
|
|
||||||
self.fail('No Announcer thread found while udp set to True')
|
|
|
@ -2,22 +2,13 @@
|
||||||
BMConfigParser class definition and default configuration settings
|
BMConfigParser class definition and default configuration settings
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import ConfigParser
|
||||||
if sys.version_info[0] == 3:
|
|
||||||
# python 3
|
|
||||||
import configparser as ConfigParser
|
|
||||||
SafeConfigParser = ConfigParser.ConfigParser
|
|
||||||
else:
|
|
||||||
# python 2
|
|
||||||
import ConfigParser
|
|
||||||
SafeConfigParser = ConfigParser.SafeConfigParser
|
|
||||||
|
|
||||||
import state
|
|
||||||
from singleton import Singleton
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import state
|
||||||
|
from singleton import Singleton
|
||||||
|
|
||||||
BMConfigDefaults = {
|
BMConfigDefaults = {
|
||||||
"bitmessagesettings": {
|
"bitmessagesettings": {
|
||||||
|
@ -28,32 +19,30 @@ BMConfigDefaults = {
|
||||||
"maxtotalconnections": 200,
|
"maxtotalconnections": 200,
|
||||||
"maxuploadrate": 0,
|
"maxuploadrate": 0,
|
||||||
"apiinterface": "127.0.0.1",
|
"apiinterface": "127.0.0.1",
|
||||||
"apiport": 8442,
|
"apiport": 8442
|
||||||
"udp": "True"
|
|
||||||
},
|
},
|
||||||
"threads": {
|
"threads": {
|
||||||
"receive": 3,
|
"receive": 3,
|
||||||
},
|
},
|
||||||
"network": {
|
"network": {
|
||||||
"bind": "",
|
"bind": '',
|
||||||
"dandelion": 90,
|
"dandelion": 90,
|
||||||
},
|
},
|
||||||
"inventory": {
|
"inventory": {
|
||||||
"storage": "sqlite",
|
"storage": "sqlite",
|
||||||
"acceptmismatch": "False",
|
"acceptmismatch": False,
|
||||||
},
|
},
|
||||||
"knownnodes": {
|
"knownnodes": {
|
||||||
"maxnodes": 20000,
|
"maxnodes": 20000,
|
||||||
},
|
},
|
||||||
"zlib": {
|
"zlib": {
|
||||||
"maxsize": 1048576
|
'maxsize': 1048576
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class BMConfigParser(SafeConfigParser):
|
class BMConfigParser(ConfigParser.SafeConfigParser):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Singleton class inherited from :class:`ConfigParser.SafeConfigParser`
|
Singleton class inherited from :class:`ConfigParser.SafeConfigParser`
|
||||||
with additional methods specific to bitmessage config.
|
with additional methods specific to bitmessage config.
|
||||||
|
@ -70,47 +59,26 @@ class BMConfigParser(SafeConfigParser):
|
||||||
raise ValueError("Invalid value %s" % value)
|
raise ValueError("Invalid value %s" % value)
|
||||||
return ConfigParser.ConfigParser.set(self, section, option, value)
|
return ConfigParser.ConfigParser.set(self, section, option, value)
|
||||||
|
|
||||||
def get(self, section, option, raw=False, vars=None):
|
def get(self, section, option, raw=False, variables=None):
|
||||||
if sys.version_info[0] == 3:
|
# pylint: disable=arguments-differ
|
||||||
# pylint: disable=arguments-differ
|
try:
|
||||||
try:
|
if section == "bitmessagesettings" and option == "timeformat":
|
||||||
if section == "bitmessagesettings" and option == "timeformat":
|
|
||||||
return ConfigParser.ConfigParser.get(
|
|
||||||
self, section, option)
|
|
||||||
try:
|
|
||||||
return self._temp[section][option]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
return ConfigParser.ConfigParser.get(
|
return ConfigParser.ConfigParser.get(
|
||||||
self, section, option)
|
self, section, option, raw, variables)
|
||||||
except ConfigParser.InterpolationError:
|
|
||||||
return ConfigParser.ConfigParser.get(
|
|
||||||
self, section, option)
|
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as e:
|
|
||||||
try:
|
|
||||||
return BMConfigDefaults[section][option]
|
|
||||||
except (KeyError, ValueError, AttributeError):
|
|
||||||
raise e
|
|
||||||
else:
|
|
||||||
# pylint: disable=arguments-differ
|
|
||||||
try:
|
try:
|
||||||
if section == "bitmessagesettings" and option == "timeformat":
|
return self._temp[section][option]
|
||||||
return ConfigParser.ConfigParser.get(
|
except KeyError:
|
||||||
self, section, option, raw, vars)
|
pass
|
||||||
try:
|
return ConfigParser.ConfigParser.get(
|
||||||
return self._temp[section][option]
|
self, section, option, True, variables)
|
||||||
except KeyError:
|
except ConfigParser.InterpolationError:
|
||||||
pass
|
return ConfigParser.ConfigParser.get(
|
||||||
return ConfigParser.ConfigParser.get(
|
self, section, option, True, variables)
|
||||||
self, section, option, True, vars)
|
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as e:
|
||||||
except ConfigParser.InterpolationError:
|
try:
|
||||||
return ConfigParser.ConfigParser.get(
|
return BMConfigDefaults[section][option]
|
||||||
self, section, option, True, vars)
|
except (KeyError, ValueError, AttributeError):
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as e:
|
raise e
|
||||||
try:
|
|
||||||
return BMConfigDefaults[section][option]
|
|
||||||
except (KeyError, ValueError, AttributeError):
|
|
||||||
raise e
|
|
||||||
|
|
||||||
def setTemp(self, section, option, value=None):
|
def setTemp(self, section, option, value=None):
|
||||||
"""Temporary set option to value, not saving."""
|
"""Temporary set option to value, not saving."""
|
||||||
|
@ -222,4 +190,3 @@ class BMConfigParser(SafeConfigParser):
|
||||||
if value < 0 or value > 8:
|
if value < 0 or value > 8:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
275
src/buildozer.spec
Normal file
275
src/buildozer.spec
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
[app]
|
||||||
|
|
||||||
|
# (str) Title of your application
|
||||||
|
title = PyBitmessage
|
||||||
|
|
||||||
|
# (str) Package name
|
||||||
|
package.name = PyBitmessage
|
||||||
|
|
||||||
|
# (str) Package domain (needed for android/ios packaging)
|
||||||
|
package.domain = org.test
|
||||||
|
|
||||||
|
# (str) Source code where the main.py live
|
||||||
|
source.dir = .
|
||||||
|
|
||||||
|
# (list) Source files to include (let empty to include all the files)
|
||||||
|
source.include_exts = py,png,jpg,kv,atlas
|
||||||
|
|
||||||
|
# (list) List of inclusions using pattern matching
|
||||||
|
#source.include_patterns = assets/*,images/*.png
|
||||||
|
|
||||||
|
# (list) Source files to exclude (let empty to not exclude anything)
|
||||||
|
#source.exclude_exts = spec
|
||||||
|
|
||||||
|
# (list) List of directory to exclude (let empty to not exclude anything)
|
||||||
|
#source.exclude_dirs = tests, bin
|
||||||
|
|
||||||
|
# (list) List of exclusions using pattern matching
|
||||||
|
#source.exclude_patterns = license,images/*/*.jpg
|
||||||
|
|
||||||
|
# (str) Application versioning (method 1)
|
||||||
|
version = 0.1
|
||||||
|
|
||||||
|
# (str) Application versioning (method 2)
|
||||||
|
# version.regex = __version__ = ['"](.*)['"]
|
||||||
|
# version.filename = %(source.dir)s/main.py
|
||||||
|
|
||||||
|
# (list) Application requirements
|
||||||
|
# comma seperated e.g. requirements = sqlite3,kivy
|
||||||
|
requirements = python2, sqlite3, kivy, openssl
|
||||||
|
|
||||||
|
# (str) Custom source folders for requirements
|
||||||
|
# Sets custom source for any requirements with recipes
|
||||||
|
# requirements.source.kivy = ../../kivy
|
||||||
|
#requirements.source.sqlite3 =
|
||||||
|
|
||||||
|
# (list) Garden requirements
|
||||||
|
#garden_requirements =
|
||||||
|
|
||||||
|
# (str) Presplash of the application
|
||||||
|
#presplash.filename = %(source.dir)s/data/presplash.png
|
||||||
|
|
||||||
|
# (str) Icon of the application
|
||||||
|
#icon.filename = %(source.dir)s/data/icon.png
|
||||||
|
|
||||||
|
# (str) Supported orientation (one of landscape, portrait or all)
|
||||||
|
orientation = portrait
|
||||||
|
|
||||||
|
# (list) List of service to declare
|
||||||
|
#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
|
||||||
|
|
||||||
|
#
|
||||||
|
# OSX Specific
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# author = © Copyright Info
|
||||||
|
|
||||||
|
# change the major version of python used by the app
|
||||||
|
#osx.python_version = 2
|
||||||
|
|
||||||
|
|
||||||
|
# Kivy version to use
|
||||||
|
osx.kivy_version = 1.9.1
|
||||||
|
|
||||||
|
#
|
||||||
|
# Android specific
|
||||||
|
#
|
||||||
|
|
||||||
|
# (bool) Indicate if the application should be fullscreen or not
|
||||||
|
fullscreen = 0
|
||||||
|
|
||||||
|
# (string) Presplash background color (for new android toolchain)
|
||||||
|
# Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
|
||||||
|
# red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
|
||||||
|
# darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
|
||||||
|
# olive, purple, silver, teal.
|
||||||
|
#android.presplash_color = #FFFFFF
|
||||||
|
|
||||||
|
# (list) Permissions
|
||||||
|
android.permissions = INTERNET
|
||||||
|
|
||||||
|
# (int) Android API to use
|
||||||
|
#android.api = 19
|
||||||
|
|
||||||
|
# (int) Minimum API required
|
||||||
|
#android.minapi = 9
|
||||||
|
|
||||||
|
# (int) Android SDK version to use
|
||||||
|
#android.sdk = 20
|
||||||
|
|
||||||
|
# (str) Android NDK version to use
|
||||||
|
#android.ndk = 9c
|
||||||
|
|
||||||
|
# (bool) Use --private data storage (True) or --dir public storage (False)
|
||||||
|
#android.private_storage = True
|
||||||
|
|
||||||
|
# (str) Android NDK directory (if empty, it will be automatically downloaded.)
|
||||||
|
#android.ndk_path =
|
||||||
|
|
||||||
|
# (str) Android SDK directory (if empty, it will be automatically downloaded.)
|
||||||
|
#android.sdk_path =
|
||||||
|
|
||||||
|
# (str) ANT directory (if empty, it will be automatically downloaded.)
|
||||||
|
#android.ant_path =
|
||||||
|
|
||||||
|
# (bool) If True, then skip trying to update the Android sdk
|
||||||
|
# This can be useful to avoid excess Internet downloads or save time
|
||||||
|
# when an update is due and you just want to test/build your package
|
||||||
|
# android.skip_update = False
|
||||||
|
|
||||||
|
# (str) Android entry point, default is ok for Kivy-based app
|
||||||
|
#android.entrypoint = org.renpy.android.PythonActivity
|
||||||
|
|
||||||
|
# (list) Pattern to whitelist for the whole project
|
||||||
|
#android.whitelist =
|
||||||
|
|
||||||
|
android.whitelist = /usr/lib/komodo-edit/python/lib/python2.7/lib-dynload/_sqlite3.so
|
||||||
|
|
||||||
|
|
||||||
|
# (str) Path to a custom whitelist file
|
||||||
|
#android.whitelist_src =
|
||||||
|
|
||||||
|
# (str) Path to a custom blacklist file
|
||||||
|
#android.blacklist_src =
|
||||||
|
|
||||||
|
# (list) List of Java .jar files to add to the libs so that pyjnius can access
|
||||||
|
# their classes. Don't add jars that you do not need, since extra jars can slow
|
||||||
|
# down the build process. Allows wildcards matching, for example:
|
||||||
|
# OUYA-ODK/libs/*.jar
|
||||||
|
#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
|
||||||
|
|
||||||
|
# (list) List of Java files to add to the android project (can be java or a
|
||||||
|
# directory containing the files)
|
||||||
|
#android.add_src =
|
||||||
|
|
||||||
|
# (list) Android AAR archives to add (currently works only with sdl2_gradle
|
||||||
|
# bootstrap)
|
||||||
|
#android.add_aars =
|
||||||
|
|
||||||
|
# (list) Gradle dependencies to add (currently works only with sdl2_gradle
|
||||||
|
# bootstrap)
|
||||||
|
#android.gradle_dependencies =
|
||||||
|
, /home/cis/Downloads/libssl1.0.2_1.0.2l-2+deb9u2_amd64
|
||||||
|
# (str) python-for-android branch to use, defaults to stable
|
||||||
|
#p4a.branch = stable
|
||||||
|
|
||||||
|
# (str) OUYA Console category. Should be one of GAME or APP
|
||||||
|
# If you leave this blank, OUYA support will not be enabled
|
||||||
|
#android.ouya.category = GAME
|
||||||
|
|
||||||
|
# (str) Filename of OUYA Console icon. It must be a 732x412 png image.
|
||||||
|
#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
|
||||||
|
|
||||||
|
# (str) XML file to include as an intent filters in <activity> tag
|
||||||
|
#android.manifest.intent_filters =
|
||||||
|
|
||||||
|
# (list) Android additionnal libraries to copy into libs/armeabi
|
||||||
|
#android.add_libs_armeabi = libs/android/*.so
|
||||||
|
#android.add_libs_armeabi_v7a = libs/android-v7/*.so
|
||||||
|
#android.add_libs_x86 = libs/android-x86/*.so
|
||||||
|
#android.add_libs_mips = libs/android-mips/*.so
|
||||||
|
|
||||||
|
# (bool) Indicate whether the screen should stay on
|
||||||
|
# Don't forget to add the WAKE_LOCK permission if you set this to True
|
||||||
|
#android.wakelock = False
|
||||||
|
|
||||||
|
# (list) Android application meta-data to set (key=value format)
|
||||||
|
#android.meta_data =
|
||||||
|
|
||||||
|
# (list) Android library project to add (will be added in the
|
||||||
|
# project.properties automatically.)
|
||||||
|
#android.library_references =
|
||||||
|
|
||||||
|
# (str) Android logcat filters to use
|
||||||
|
#android.logcat_filters = *:S python:D
|
||||||
|
|
||||||
|
# (bool) Copy library instead of making a libpymodules.so
|
||||||
|
#android.copy_libs = 1
|
||||||
|
|
||||||
|
# (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86
|
||||||
|
android.arch = armeabi-v7a
|
||||||
|
|
||||||
|
#
|
||||||
|
# Python for android (p4a) specific
|
||||||
|
#
|
||||||
|
|
||||||
|
# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
|
||||||
|
#p4a.source_dir =
|
||||||
|
|
||||||
|
# (str) The directory in which python-for-android should look for your own build recipes (if any)
|
||||||
|
#p4a.local_recipes =
|
||||||
|
|
||||||
|
# (str) Filename to the hook for p4a
|
||||||
|
#p4a.hook =
|
||||||
|
|
||||||
|
# (str) Bootstrap to use for android builds
|
||||||
|
# p4a.bootstrap = sdl2
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# iOS specific
|
||||||
|
#
|
||||||
|
|
||||||
|
# (str) Path to a custom kivy-ios folder
|
||||||
|
#ios.kivy_ios_dir = ../kivy-ios
|
||||||
|
|
||||||
|
# (str) Name of the certificate to use for signing the debug version
|
||||||
|
# Get a list of available identities: buildozer ios list_identities
|
||||||
|
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"
|
||||||
|
|
||||||
|
# (str) Name of the certificate to use for signing the release version
|
||||||
|
#ios.codesign.release = %(ios.codesign.debug)s
|
||||||
|
|
||||||
|
|
||||||
|
[buildozer]
|
||||||
|
|
||||||
|
# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
|
||||||
|
log_level = 2
|
||||||
|
|
||||||
|
# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
|
||||||
|
warn_on_root = 1
|
||||||
|
|
||||||
|
# (str) Path to build artifact storage, absolute or relative to spec file
|
||||||
|
# build_dir = ./.buildozer
|
||||||
|
|
||||||
|
# (str) Path to build output (i.e. .apk, .ipa) storage
|
||||||
|
# bin_dir = ./bin
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# List as sections
|
||||||
|
#
|
||||||
|
# You can define all the "list" as [section:key].
|
||||||
|
# Each line will be considered as a option to the list.
|
||||||
|
# Let's take [app] / source.exclude_patterns.
|
||||||
|
# Instead of doing:
|
||||||
|
#
|
||||||
|
#[app]
|
||||||
|
#source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
|
||||||
|
#
|
||||||
|
# This can be translated into:
|
||||||
|
#
|
||||||
|
#[app:source.exclude_patterns]
|
||||||
|
#license
|
||||||
|
#data/audio/*.wav
|
||||||
|
#data/images/original/*
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Profiles
|
||||||
|
#
|
||||||
|
# You can extend section / key with a profile
|
||||||
|
# For example, you want to deploy a demo version of your application without
|
||||||
|
# HD content. You could first change the title to add "(demo)" in the name
|
||||||
|
# and extend the excluded directories to remove the HD content.
|
||||||
|
#
|
||||||
|
#[app@demo]
|
||||||
|
#title = My Application (demo)
|
||||||
|
#
|
||||||
|
#[app:source.exclude_patterns@demo]
|
||||||
|
#images/hd/*
|
||||||
|
#
|
||||||
|
# Then, invoke the command line with the "demo" profile:
|
||||||
|
#
|
||||||
|
#buildozer --profile demo android debug
|
|
@ -20,12 +20,273 @@ from debug import logger
|
||||||
# pylint: disable=attribute-defined-outside-init,protected-access
|
# pylint: disable=attribute-defined-outside-init,protected-access
|
||||||
|
|
||||||
|
|
||||||
|
upgrade_dict = {}
|
||||||
|
|
||||||
|
|
||||||
|
def db_upgrade(*args, **kwargs): # pylint: disable=unused-argument
|
||||||
|
"""upgrade the migration"""
|
||||||
|
version_dict = kwargs
|
||||||
|
|
||||||
|
def inner(func):
|
||||||
|
"""this is inner method"""
|
||||||
|
upgrade_dict.update(version_dict)
|
||||||
|
|
||||||
|
def wrapped(*args):
|
||||||
|
"""used for calling main method"""
|
||||||
|
func(*args)
|
||||||
|
return wrapped
|
||||||
|
return inner
|
||||||
|
|
||||||
|
|
||||||
class sqlThread(threading.Thread):
|
class sqlThread(threading.Thread):
|
||||||
"""A thread for all SQL operations"""
|
"""A thread for all SQL operations"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
threading.Thread.__init__(self, name="SQL")
|
threading.Thread.__init__(self, name="SQL")
|
||||||
|
|
||||||
|
def update_sent(self):
|
||||||
|
"""
|
||||||
|
After code refactoring, the possible status values for sent messages
|
||||||
|
have changed.
|
||||||
|
"""
|
||||||
|
self.cur.execute(
|
||||||
|
'''update sent set status='doingmsgpow' where status='doingpow' ''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''update sent set status='msgsent' where status='sentmessage' ''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''update sent set status='doingpubkeypow' where status='findingpubkey' ''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''update sent set status='broadcastqueued' where status='broadcastpending' ''')
|
||||||
|
self.conn.commit()
|
||||||
|
|
||||||
|
def inventory_upgrade(self):
|
||||||
|
"""Adding a new column to the inventory table to store tags."""
|
||||||
|
logger.debug(
|
||||||
|
'In messages.dat database, adding tag field to'
|
||||||
|
' the inventory table.')
|
||||||
|
item = '''ALTER TABLE inventory ADD tag blob DEFAULT '' '''
|
||||||
|
param = ''
|
||||||
|
self.cur.execute(item, param)
|
||||||
|
item = '''update settings set value=? WHERE key='version';'''
|
||||||
|
parameters = (4,)
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
|
||||||
|
@db_upgrade(version_one=1)
|
||||||
|
def version_one(self):
|
||||||
|
"""version_one for upgrading inventory"""
|
||||||
|
self.inventory_upgrade()
|
||||||
|
|
||||||
|
@db_upgrade(version_two=2)
|
||||||
|
def version_two(self):
|
||||||
|
"""
|
||||||
|
method for getting rid of the first20bytesofencryptedmessage field in
|
||||||
|
the inventory table.
|
||||||
|
"""
|
||||||
|
logger.debug(
|
||||||
|
'In messages.dat database, removing an obsolete field from'
|
||||||
|
' the inventory table.')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TEMPORARY TABLE inventory_backup'''
|
||||||
|
'''(hash blob, objecttype text, streamnumber int, payload blob,'''
|
||||||
|
''' receivedtime integer, UNIQUE(hash) ON CONFLICT REPLACE);''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''INSERT INTO inventory_backup SELECT hash, objecttype, streamnumber, payload, receivedtime'''
|
||||||
|
''' FROM inventory;''')
|
||||||
|
self.cur.execute('''DROP TABLE inventory''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TABLE inventory'''
|
||||||
|
''' (hash blob, objecttype text, streamnumber int, payload blob, receivedtime integer,'''
|
||||||
|
''' UNIQUE(hash) ON CONFLICT REPLACE)''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''INSERT INTO inventory SELECT hash, objecttype, streamnumber, payload, receivedtime'''
|
||||||
|
''' FROM inventory_backup;''')
|
||||||
|
self.cur.execute('''DROP TABLE inventory_backup;''')
|
||||||
|
item = '''update settings set value=? WHERE key='version';'''
|
||||||
|
parameters = (3,)
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
|
||||||
|
@db_upgrade(version_three=3)
|
||||||
|
def version_three(self):
|
||||||
|
"""version_three for upgrading inventory"""
|
||||||
|
self.inventory_upgrade()
|
||||||
|
|
||||||
|
@db_upgrade(versio_four=4)
|
||||||
|
def versio_four(self):
|
||||||
|
"""
|
||||||
|
Add a new column to the pubkeys table to store the address version.
|
||||||
|
We're going to trash all of our pubkeys and let them be redownloaded.
|
||||||
|
"""
|
||||||
|
self.cur.execute('''DROP TABLE pubkeys''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TABLE pubkeys (hash blob, addressversion int, transmitdata blob, time int,'''
|
||||||
|
'''usedpersonally text, UNIQUE(hash, addressversion) ON CONFLICT REPLACE)''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''delete from inventory where objecttype = 'pubkey';''')
|
||||||
|
item = '''update settings set value=? WHERE key='version';'''
|
||||||
|
parameters = (5,)
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
|
||||||
|
@db_upgrade(versio_five=5)
|
||||||
|
def versio_five(self):
|
||||||
|
"""
|
||||||
|
Add a new table: objectprocessorqueue with which to hold objects
|
||||||
|
that have yet to be processed if the user shuts down Bitmessage.
|
||||||
|
"""
|
||||||
|
self.cur.execute('''DROP TABLE knownnodes''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TABLE objectprocessorqueue'''
|
||||||
|
''' (objecttype text, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''')
|
||||||
|
item = '''update settings set value=? WHERE key='version';'''
|
||||||
|
parameters = (6,)
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
|
||||||
|
@db_upgrade(version_six=6)
|
||||||
|
def version_six(self):
|
||||||
|
"""
|
||||||
|
changes related to protocol v3
|
||||||
|
In table inventory and objectprocessorqueue, objecttype is now
|
||||||
|
an integer (it was a human-friendly string previously)
|
||||||
|
"""
|
||||||
|
logger.debug(
|
||||||
|
'In messages.dat database, dropping and recreating'
|
||||||
|
' the inventory table.')
|
||||||
|
self.cur.execute('''DROP TABLE inventory''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TABLE inventory'''
|
||||||
|
''' (hash blob, objecttype int, streamnumber int, payload blob, expirestime integer,'''
|
||||||
|
''' tag blob, UNIQUE(hash) ON CONFLICT REPLACE)''')
|
||||||
|
self.cur.execute('''DROP TABLE objectprocessorqueue''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TABLE objectprocessorqueue'''
|
||||||
|
''' (objecttype int, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''')
|
||||||
|
item = '''update settings set value=? WHERE key='version';'''
|
||||||
|
parameters = (7,)
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
logger.debug(
|
||||||
|
'Finished dropping and recreating the inventory table.')
|
||||||
|
|
||||||
|
@db_upgrade(version_seven=7)
|
||||||
|
def version_seven(self):
|
||||||
|
"""
|
||||||
|
The format of data stored in the pubkeys table has changed. Let's
|
||||||
|
clear it, and the pubkeys from inventory, so that they'll
|
||||||
|
be re-downloaded.
|
||||||
|
"""
|
||||||
|
logger.debug(
|
||||||
|
'In messages.dat database, clearing pubkeys table'
|
||||||
|
' because the data format has been updated.')
|
||||||
|
self.cur.execute(
|
||||||
|
'''delete from inventory where objecttype = 1;''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''delete from pubkeys;''')
|
||||||
|
# Any sending messages for which we *thought* that we had
|
||||||
|
# the pubkey must be rechecked.
|
||||||
|
self.cur.execute(
|
||||||
|
'''UPDATE sent SET status='msgqueued' WHERE status='doingmsgpow' or status='badkey';''')
|
||||||
|
query = '''update settings set value=? WHERE key='version';'''
|
||||||
|
parameters = (8,)
|
||||||
|
self.cur.execute(query, parameters)
|
||||||
|
logger.debug('Finished clearing currently held pubkeys.')
|
||||||
|
|
||||||
|
@db_upgrade(version_eight=8)
|
||||||
|
def version_eight(self):
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
logger.debug(
|
||||||
|
'In messages.dat database, adding sighash field to'
|
||||||
|
' the inbox table.')
|
||||||
|
item = '''ALTER TABLE inbox ADD sighash blob DEFAULT '' '''
|
||||||
|
param = ''
|
||||||
|
self.cur.execute(item, param)
|
||||||
|
item = '''update settings set value=? WHERE key='version';'''
|
||||||
|
parameters = (9,)
|
||||||
|
self.cur.execute(item, parameters)
|
||||||
|
|
||||||
|
@db_upgrade(version_nine=9)
|
||||||
|
def version_nine(self):
|
||||||
|
"""
|
||||||
|
We'll also need a `sleeptill` field and a `ttl` field. Also we
|
||||||
|
can combine the pubkeyretrynumber and msgretrynumber into one.
|
||||||
|
"""
|
||||||
|
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:
|
||||||
|
addressHash, addressVersion = row
|
||||||
|
address = encodeAddress(addressVersion, 1, hash)
|
||||||
|
item = '''UPDATE pubkeys SET address=? WHERE hash=?;'''
|
||||||
|
parameters = (address, addressHash)
|
||||||
|
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';''')
|
||||||
|
|
||||||
|
@db_upgrade(version_ten=10)
|
||||||
|
def version_ten(self):
|
||||||
|
"""Update the address colunm to unique in addressbook table"""
|
||||||
|
logger.debug(
|
||||||
|
'In messages.dat database, updating address column to UNIQUE'
|
||||||
|
' in the addressbook table.')
|
||||||
|
self.cur.execute(
|
||||||
|
'''ALTER TABLE addressbook RENAME TO old_addressbook''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''CREATE TABLE addressbook'''
|
||||||
|
''' (label text, address text, UNIQUE(address) ON CONFLICT IGNORE)''')
|
||||||
|
self.cur.execute(
|
||||||
|
'''INSERT INTO addressbook SELECT label, address FROM old_addressbook;''')
|
||||||
|
self.cur.execute('''DROP TABLE old_addressbook''')
|
||||||
|
self.cur.execute('''update settings set value=11 WHERE key='version';''')
|
||||||
|
|
||||||
def run(self): # pylint: disable=too-many-locals, too-many-branches, too-many-statements
|
def run(self): # pylint: disable=too-many-locals, too-many-branches, too-many-statements
|
||||||
"""Process SQL queries from `.helper_sql.sqlSubmitQueue`"""
|
"""Process SQL queries from `.helper_sql.sqlSubmitQueue`"""
|
||||||
helper_sql.sql_available = True
|
helper_sql.sql_available = True
|
||||||
|
@ -47,7 +308,7 @@ class sqlThread(threading.Thread):
|
||||||
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(
|
||||||
'''CREATE TABLE addressbook (label text, address text, UNIQUE(address) ON CONFLICT IGNORE)''')
|
'''CREATE TABLE addressbook (label text, address text)''')
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
'''CREATE TABLE blacklist (label text, address text, enabled bool)''')
|
'''CREATE TABLE blacklist (label text, address text, enabled bool)''')
|
||||||
self.cur.execute(
|
self.cur.execute(
|
||||||
|
@ -63,7 +324,7 @@ class sqlThread(threading.Thread):
|
||||||
'''('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''')
|
'''('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','11')''')
|
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(
|
||||||
|
@ -166,248 +427,16 @@ class sqlThread(threading.Thread):
|
||||||
logger.debug('Vacuuming message.dat. You might notice that the file size gets much smaller.')
|
logger.debug('Vacuuming message.dat. You might notice that the file size gets much smaller.')
|
||||||
self.cur.execute(''' VACUUM ''')
|
self.cur.execute(''' VACUUM ''')
|
||||||
|
|
||||||
# After code refactoring, the possible status values for sent messages
|
self.update_sent()
|
||||||
# have changed.
|
|
||||||
self.cur.execute(
|
|
||||||
'''update sent set status='doingmsgpow' where status='doingpow' ''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''update sent set status='msgsent' where status='sentmessage' ''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''update sent set status='doingpubkeypow' where status='findingpubkey' ''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''update sent set status='broadcastqueued' where status='broadcastpending' ''')
|
|
||||||
self.conn.commit()
|
|
||||||
|
|
||||||
# Let's get rid of the first20bytesofencryptedmessage field in
|
|
||||||
# the inventory table.
|
|
||||||
item = '''SELECT value FROM settings WHERE key='version';'''
|
|
||||||
parameters = ''
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
if int(self.cur.fetchall()[0][0]) == 2:
|
|
||||||
logger.debug(
|
|
||||||
'In messages.dat database, removing an obsolete field from'
|
|
||||||
' the inventory table.')
|
|
||||||
self.cur.execute(
|
|
||||||
'''CREATE TEMPORARY TABLE inventory_backup'''
|
|
||||||
'''(hash blob, objecttype text, streamnumber int, payload blob,'''
|
|
||||||
''' receivedtime integer, UNIQUE(hash) ON CONFLICT REPLACE);''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''INSERT INTO inventory_backup SELECT hash, objecttype, streamnumber, payload, receivedtime'''
|
|
||||||
''' FROM inventory;''')
|
|
||||||
self.cur.execute('''DROP TABLE inventory''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''CREATE TABLE inventory'''
|
|
||||||
''' (hash blob, objecttype text, streamnumber int, payload blob, receivedtime integer,'''
|
|
||||||
''' UNIQUE(hash) ON CONFLICT REPLACE)''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''INSERT INTO inventory SELECT hash, objecttype, streamnumber, payload, receivedtime'''
|
|
||||||
''' FROM inventory_backup;''')
|
|
||||||
self.cur.execute('''DROP TABLE inventory_backup;''')
|
|
||||||
item = '''update settings set value=? WHERE key='version';'''
|
|
||||||
parameters = (3,)
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
|
|
||||||
# Add a new column to the inventory table to store tags.
|
|
||||||
item = '''SELECT value FROM settings WHERE key='version';'''
|
item = '''SELECT value FROM settings WHERE key='version';'''
|
||||||
parameters = ''
|
parameters = ''
|
||||||
self.cur.execute(item, parameters)
|
self.cur.execute(item, parameters)
|
||||||
currentVersion = int(self.cur.fetchall()[0][0])
|
currentVersion = int(self.cur.fetchall()[0][0])
|
||||||
if currentVersion == 1 or currentVersion == 3:
|
temp_dict = {val: key for key, val in upgrade_dict.items()}
|
||||||
logger.debug(
|
|
||||||
'In messages.dat database, adding tag field to'
|
|
||||||
' the inventory table.')
|
|
||||||
item = '''ALTER TABLE inventory ADD tag blob DEFAULT '' '''
|
|
||||||
parameters = ''
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
item = '''update settings set value=? WHERE key='version';'''
|
|
||||||
parameters = (4,)
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
|
|
||||||
# Add a new column to the pubkeys table to store the address version.
|
if temp_dict.get(currentVersion):
|
||||||
# We're going to trash all of our pubkeys and let them be redownloaded.
|
getattr(self, temp_dict.get(currentVersion))()
|
||||||
item = '''SELECT value FROM settings WHERE key='version';'''
|
|
||||||
parameters = ''
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
currentVersion = int(self.cur.fetchall()[0][0])
|
|
||||||
if currentVersion == 4:
|
|
||||||
self.cur.execute('''DROP TABLE pubkeys''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''CREATE TABLE pubkeys (hash blob, addressversion int, transmitdata blob, time int,'''
|
|
||||||
'''usedpersonally text, UNIQUE(hash, addressversion) ON CONFLICT REPLACE)''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''delete from inventory where objecttype = 'pubkey';''')
|
|
||||||
item = '''update settings set value=? WHERE key='version';'''
|
|
||||||
parameters = (5,)
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
|
|
||||||
# Add a new table: objectprocessorqueue with which to hold objects
|
|
||||||
# that have yet to be processed if the user shuts down Bitmessage.
|
|
||||||
item = '''SELECT value FROM settings WHERE key='version';'''
|
|
||||||
parameters = ''
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
currentVersion = int(self.cur.fetchall()[0][0])
|
|
||||||
if currentVersion == 5:
|
|
||||||
self.cur.execute('''DROP TABLE knownnodes''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''CREATE TABLE objectprocessorqueue'''
|
|
||||||
''' (objecttype text, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''')
|
|
||||||
item = '''update settings set value=? WHERE key='version';'''
|
|
||||||
parameters = (6,)
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
|
|
||||||
# changes related to protocol v3
|
|
||||||
# In table inventory and objectprocessorqueue, objecttype is now
|
|
||||||
# an integer (it was a human-friendly string previously)
|
|
||||||
item = '''SELECT value FROM settings WHERE key='version';'''
|
|
||||||
parameters = ''
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
currentVersion = int(self.cur.fetchall()[0][0])
|
|
||||||
if currentVersion == 6:
|
|
||||||
logger.debug(
|
|
||||||
'In messages.dat database, dropping and recreating'
|
|
||||||
' the inventory table.')
|
|
||||||
self.cur.execute('''DROP TABLE inventory''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''CREATE TABLE inventory'''
|
|
||||||
''' (hash blob, objecttype int, streamnumber int, payload blob, expirestime integer,'''
|
|
||||||
''' tag blob, UNIQUE(hash) ON CONFLICT REPLACE)''')
|
|
||||||
self.cur.execute('''DROP TABLE objectprocessorqueue''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''CREATE TABLE objectprocessorqueue'''
|
|
||||||
''' (objecttype int, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''')
|
|
||||||
item = '''update settings set value=? WHERE key='version';'''
|
|
||||||
parameters = (7,)
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
logger.debug(
|
|
||||||
'Finished dropping and recreating the inventory table.')
|
|
||||||
|
|
||||||
# The format of data stored in the pubkeys table has changed. Let's
|
|
||||||
# clear it, and the pubkeys from inventory, so that they'll
|
|
||||||
# be re-downloaded.
|
|
||||||
item = '''SELECT value FROM settings WHERE key='version';'''
|
|
||||||
parameters = ''
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
currentVersion = int(self.cur.fetchall()[0][0])
|
|
||||||
if currentVersion == 7:
|
|
||||||
logger.debug(
|
|
||||||
'In messages.dat database, clearing pubkeys table'
|
|
||||||
' because the data format has been updated.')
|
|
||||||
self.cur.execute(
|
|
||||||
'''delete from inventory where objecttype = 1;''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''delete from pubkeys;''')
|
|
||||||
# Any sending messages for which we *thought* that we had
|
|
||||||
# the pubkey must be rechecked.
|
|
||||||
self.cur.execute(
|
|
||||||
'''UPDATE sent SET status='msgqueued' WHERE status='doingmsgpow' or status='badkey';''')
|
|
||||||
query = '''update settings set value=? WHERE key='version';'''
|
|
||||||
parameters = (8,)
|
|
||||||
self.cur.execute(query, parameters)
|
|
||||||
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)
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
addressHash, addressVersion = row
|
|
||||||
address = encodeAddress(addressVersion, 1, hash)
|
|
||||||
item = '''UPDATE pubkeys SET address=? WHERE hash=?;'''
|
|
||||||
parameters = (address, addressHash)
|
|
||||||
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';''')
|
|
||||||
|
|
||||||
# Update the address colunm to unique in addressbook table
|
|
||||||
item = '''SELECT value FROM settings WHERE key='version';'''
|
|
||||||
parameters = ''
|
|
||||||
self.cur.execute(item, parameters)
|
|
||||||
currentVersion = int(self.cur.fetchall()[0][0])
|
|
||||||
if currentVersion == 10:
|
|
||||||
logger.debug(
|
|
||||||
'In messages.dat database, updating address column to UNIQUE'
|
|
||||||
' in the addressbook table.')
|
|
||||||
self.cur.execute(
|
|
||||||
'''ALTER TABLE addressbook RENAME TO old_addressbook''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''CREATE TABLE addressbook'''
|
|
||||||
''' (label text, address text, UNIQUE(address) ON CONFLICT IGNORE)''')
|
|
||||||
self.cur.execute(
|
|
||||||
'''INSERT INTO addressbook SELECT label, address FROM old_addressbook;''')
|
|
||||||
self.cur.execute('''DROP TABLE old_addressbook''')
|
|
||||||
self.cur.execute('''update settings set value=11 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
|
# Bitmessage users or modify the SQLite database? Add it right
|
||||||
|
|
|
@ -421,8 +421,8 @@ def check_dependencies(verbose=False, optional=False):
|
||||||
if sys.hexversion >= 0x3000000:
|
if sys.hexversion >= 0x3000000:
|
||||||
logger.error(
|
logger.error(
|
||||||
'PyBitmessage does not support Python 3+. Python 2.7.4'
|
'PyBitmessage does not support Python 3+. Python 2.7.4'
|
||||||
' or greater is required. Python 2.7.18 is recommended.')
|
' or greater is required.')
|
||||||
sys.exit()
|
has_all_dependencies = False
|
||||||
|
|
||||||
check_functions = [check_ripemd160, check_sqlite, check_openssl]
|
check_functions = [check_ripemd160, check_sqlite, check_openssl]
|
||||||
if optional:
|
if optional:
|
||||||
|
|
35
src/helper_addressGenerator.py
Normal file
35
src/helper_addressGenerator.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
"""
|
||||||
|
Create random address
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
import defaults
|
||||||
|
import queues
|
||||||
|
import state
|
||||||
|
|
||||||
|
from bmconfigparser import BMConfigParser
|
||||||
|
|
||||||
|
|
||||||
|
def checkHasNormalAddress():
|
||||||
|
"""method for checking address"""
|
||||||
|
for address in BMConfigParser().addresses():
|
||||||
|
|
||||||
|
if BMConfigParser().safeGetBoolean(address, 'enabled'):
|
||||||
|
return address
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def createAddressIfNeeded(label_text, streamNumberForAddress=1):
|
||||||
|
"""method for creating random address"""
|
||||||
|
if not checkHasNormalAddress():
|
||||||
|
queues.addressGeneratorQueue.put((
|
||||||
|
'createRandomAddress', 4, streamNumberForAddress,
|
||||||
|
label_text,
|
||||||
|
1, "", False,
|
||||||
|
defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
|
||||||
|
defaults.networkDefaultPayloadLengthExtraBytes
|
||||||
|
))
|
||||||
|
start_time = time.time()
|
||||||
|
while int(time.time() - start_time) < 10 and state.shutdown == 0 and not checkHasNormalAddress():
|
||||||
|
time.sleep(.2)
|
||||||
|
return checkHasNormalAddress()
|
|
@ -7,6 +7,7 @@ import state
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from network.assemble import assemble_addr
|
from network.assemble import assemble_addr
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
|
from network.udp import UDPSocket
|
||||||
from node import Peer
|
from node import Peer
|
||||||
from threads import StoppableThread
|
from threads import StoppableThread
|
||||||
|
|
||||||
|
@ -14,13 +15,12 @@ from threads import StoppableThread
|
||||||
class AnnounceThread(StoppableThread):
|
class AnnounceThread(StoppableThread):
|
||||||
"""A thread to manage regular announcing of this node"""
|
"""A thread to manage regular announcing of this node"""
|
||||||
name = "Announcer"
|
name = "Announcer"
|
||||||
announceInterval = 60
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
lastSelfAnnounced = 0
|
lastSelfAnnounced = 0
|
||||||
while not self._stopped and state.shutdown == 0:
|
while not self._stopped and state.shutdown == 0:
|
||||||
processed = 0
|
processed = 0
|
||||||
if lastSelfAnnounced < time.time() - self.announceInterval:
|
if lastSelfAnnounced < time.time() - UDPSocket.announceInterval:
|
||||||
self.announceSelf()
|
self.announceSelf()
|
||||||
lastSelfAnnounced = time.time()
|
lastSelfAnnounced = time.time()
|
||||||
if processed == 0:
|
if processed == 0:
|
||||||
|
|
|
@ -749,7 +749,7 @@ class dispatcher(object):
|
||||||
def log_info(self, message, log_type='info'):
|
def log_info(self, message, log_type='info'):
|
||||||
"""Conditionally print a message"""
|
"""Conditionally print a message"""
|
||||||
if log_type not in self.ignore_log_types:
|
if log_type not in self.ignore_log_types:
|
||||||
print('%s: %s' % (log_type, message))
|
print '%s: %s' % (log_type, message)
|
||||||
|
|
||||||
def handle_read_event(self):
|
def handle_read_event(self):
|
||||||
"""Handle a read event"""
|
"""Handle a read event"""
|
||||||
|
|
|
@ -18,19 +18,19 @@ class HttpConnection(AdvancedDispatcher):
|
||||||
self.destination = (host, 80)
|
self.destination = (host, 80)
|
||||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.connect(self.destination)
|
self.connect(self.destination)
|
||||||
print("connecting in background to %s:%i" % self.destination)
|
print "connecting in background to %s:%i" % (self.destination[0], self.destination[1])
|
||||||
|
|
||||||
def state_init(self):
|
def state_init(self):
|
||||||
self.append_write_buf(
|
self.append_write_buf(
|
||||||
"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n" % (
|
"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n" % (
|
||||||
self.path, self.destination[0]))
|
self.path, self.destination[0]))
|
||||||
print("Sending %ib" % len(self.write_buf))
|
print "Sending %ib" % (len(self.write_buf))
|
||||||
self.set_state("http_request_sent", 0)
|
self.set_state("http_request_sent", 0)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def state_http_request_sent(self):
|
def state_http_request_sent(self):
|
||||||
if self.read_buf:
|
if self.read_buf:
|
||||||
print("Received %ib" % len(self.read_buf))
|
print "Received %ib" % (len(self.read_buf))
|
||||||
self.read_buf = b""
|
self.read_buf = b""
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
self.set_state("close", 0)
|
self.set_state("close", 0)
|
||||||
|
@ -62,13 +62,13 @@ if __name__ == "__main__":
|
||||||
for host in ("bootstrap8080.bitmessage.org", "bootstrap8444.bitmessage.org"):
|
for host in ("bootstrap8080.bitmessage.org", "bootstrap8444.bitmessage.org"):
|
||||||
proxy = Socks5Resolver(host=host)
|
proxy = Socks5Resolver(host=host)
|
||||||
while asyncore.socket_map:
|
while asyncore.socket_map:
|
||||||
print("loop %s, len %i" % (proxy.state, len(asyncore.socket_map)))
|
print "loop %s, len %i" % (proxy.state, len(asyncore.socket_map))
|
||||||
asyncore.loop(timeout=1, count=1)
|
asyncore.loop(timeout=1, count=1)
|
||||||
proxy.resolved()
|
proxy.resolved()
|
||||||
|
|
||||||
proxy = Socks4aResolver(host=host)
|
proxy = Socks4aResolver(host=host)
|
||||||
while asyncore.socket_map:
|
while asyncore.socket_map:
|
||||||
print("loop %s, len %i" % (proxy.state, len(asyncore.socket_map)))
|
print "loop %s, len %i" % (proxy.state, len(asyncore.socket_map))
|
||||||
asyncore.loop(timeout=1, count=1)
|
asyncore.loop(timeout=1, count=1)
|
||||||
proxy.resolved()
|
proxy.resolved()
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import time
|
||||||
import protocol
|
import protocol
|
||||||
import state
|
import state
|
||||||
from bmproto import BMProto
|
from bmproto import BMProto
|
||||||
from constants import MAX_TIME_OFFSET
|
|
||||||
from node import Peer
|
from node import Peer
|
||||||
from objectracker import ObjectTracker
|
from objectracker import ObjectTracker
|
||||||
from queues import receiveDataQueue
|
from queues import receiveDataQueue
|
||||||
|
@ -19,6 +18,7 @@ logger = logging.getLogger('default')
|
||||||
class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
||||||
"""Bitmessage protocol over UDP (class)"""
|
"""Bitmessage protocol over UDP (class)"""
|
||||||
port = 8444
|
port = 8444
|
||||||
|
announceInterval = 60
|
||||||
|
|
||||||
def __init__(self, host=None, sock=None, announcing=False):
|
def __init__(self, host=None, sock=None, announcing=False):
|
||||||
# pylint: disable=bad-super-call
|
# pylint: disable=bad-super-call
|
||||||
|
@ -82,8 +82,8 @@ class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
||||||
decodedIP = protocol.checkIPAddress(str(ip))
|
decodedIP = protocol.checkIPAddress(str(ip))
|
||||||
if stream not in state.streamsInWhichIAmParticipating:
|
if stream not in state.streamsInWhichIAmParticipating:
|
||||||
continue
|
continue
|
||||||
if (seenTime < time.time() - MAX_TIME_OFFSET
|
if (seenTime < time.time() - self.maxTimeOffset
|
||||||
or seenTime > time.time() + MAX_TIME_OFFSET):
|
or seenTime > time.time() + self.maxTimeOffset):
|
||||||
continue
|
continue
|
||||||
if decodedIP is False:
|
if decodedIP is False:
|
||||||
# if the address isn't local, interpret it as
|
# if the address isn't local, interpret it as
|
||||||
|
@ -94,8 +94,9 @@ class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"received peer discovery from %s:%i (port %i):",
|
"received peer discovery from %s:%i (port %i):",
|
||||||
self.destination.host, self.destination.port, remoteport)
|
self.destination.host, self.destination.port, remoteport)
|
||||||
state.discoveredPeers[Peer(self.destination.host, remoteport)] = \
|
if self.local:
|
||||||
time.time()
|
state.discoveredPeers[Peer(self.destination.host, remoteport)] = \
|
||||||
|
time.time()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def bm_command_portcheck(self):
|
def bm_command_portcheck(self):
|
||||||
|
@ -124,9 +125,9 @@ class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
||||||
|
|
||||||
def handle_read(self):
|
def handle_read(self):
|
||||||
try:
|
try:
|
||||||
recdata, addr = self.socket.recvfrom(self._buf_len)
|
(recdata, addr) = self.socket.recvfrom(self._buf_len)
|
||||||
except socket.error:
|
except socket.error as e:
|
||||||
logger.error("socket error on recvfrom:", exc_info=True)
|
logger.error("socket error: %s", e)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.destination = Peer(*addr)
|
self.destination = Peer(*addr)
|
||||||
|
@ -142,7 +143,7 @@ class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
||||||
try:
|
try:
|
||||||
retval = self.socket.sendto(
|
retval = self.socket.sendto(
|
||||||
self.write_buf, ('<broadcast>', self.port))
|
self.write_buf, ('<broadcast>', self.port))
|
||||||
except socket.error:
|
except socket.error as e:
|
||||||
logger.error("socket error on sendto:", exc_info=True)
|
logger.error("socket error on sendto: %s", e)
|
||||||
retval = len(self.write_buf)
|
retval = len(self.write_buf)
|
||||||
self.slice_write_buf(retval)
|
self.slice_write_buf(retval)
|
||||||
|
|
|
@ -1,24 +1,16 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
"""
|
"""
|
||||||
Module for Proof of Work using OpenCL
|
Module for Proof of Work using OpenCL
|
||||||
"""
|
"""
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
from struct import pack
|
from struct import pack
|
||||||
|
|
||||||
import paths
|
import paths
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
|
from debug import logger
|
||||||
from state import shutdown
|
from state import shutdown
|
||||||
|
|
||||||
try:
|
libAvailable = True
|
||||||
import numpy
|
|
||||||
import pyopencl as cl
|
|
||||||
libAvailable = True
|
|
||||||
except ImportError:
|
|
||||||
libAvailable = False
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('default')
|
|
||||||
|
|
||||||
ctx = False
|
ctx = False
|
||||||
queue = False
|
queue = False
|
||||||
program = False
|
program = False
|
||||||
|
@ -27,10 +19,17 @@ enabledGpus = []
|
||||||
vendors = []
|
vendors = []
|
||||||
hash_dt = None
|
hash_dt = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pyopencl as cl
|
||||||
|
import numpy
|
||||||
|
except ImportError:
|
||||||
|
libAvailable = False
|
||||||
|
|
||||||
|
|
||||||
def initCL():
|
def initCL():
|
||||||
"""Initlialise OpenCL engine"""
|
"""Initlialise OpenCL engine"""
|
||||||
global ctx, queue, program, hash_dt # pylint: disable=global-statement
|
# pylint: disable=global-statement
|
||||||
|
global ctx, queue, program, hash_dt, libAvailable
|
||||||
if libAvailable is False:
|
if libAvailable is False:
|
||||||
return
|
return
|
||||||
del enabledGpus[:]
|
del enabledGpus[:]
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def setup():
|
|
||||||
"""Add path to this file to sys.path"""
|
|
||||||
app_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
os.chdir(app_dir)
|
|
||||||
sys.path.insert(0, app_dir)
|
|
||||||
return app_dir
|
|
|
@ -1,31 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from xdg import BaseDirectory, Menu
|
|
||||||
|
|
||||||
|
|
||||||
class DesktopXDG(object):
|
|
||||||
"""pyxdg Freedesktop desktop implementation"""
|
|
||||||
def __init__(self):
|
|
||||||
menu_entry = Menu.parse().getMenu('Office').getMenuEntry(
|
|
||||||
'pybitmessage.desktop')
|
|
||||||
self.desktop = menu_entry.DesktopEntry if menu_entry else None
|
|
||||||
|
|
||||||
def adjust_startonlogon(self, autostart=False):
|
|
||||||
"""Configure autostart according to settings"""
|
|
||||||
if not self.desktop:
|
|
||||||
return
|
|
||||||
|
|
||||||
autostart_path = os.path.join(
|
|
||||||
BaseDirectory.xdg_config_home, 'autostart', 'pybitmessage.desktop')
|
|
||||||
if autostart:
|
|
||||||
self.desktop.write(autostart_path)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
os.remove(autostart_path)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
connect_plugin = DesktopXDG
|
|
|
@ -16,7 +16,7 @@ def inv(a, n):
|
||||||
lm, hm = 1, 0
|
lm, hm = 1, 0
|
||||||
low, high = a % n, n
|
low, high = a % n, n
|
||||||
while low > 1:
|
while low > 1:
|
||||||
r = high // low
|
r = high / low
|
||||||
nm, new = hm - lm * r, high - low * r
|
nm, new = hm - lm * r, high - low * r
|
||||||
lm, low, hm, high = nm, new, lm, low
|
lm, low, hm, high = nm, new, lm, low
|
||||||
return lm % n
|
return lm % n
|
||||||
|
@ -43,8 +43,8 @@ def encode(val, base, minlen=0):
|
||||||
code_string = get_code_string(base)
|
code_string = get_code_string(base)
|
||||||
result = ""
|
result = ""
|
||||||
while val > 0:
|
while val > 0:
|
||||||
val, i = divmod(val, base)
|
result = code_string[val % base] + result
|
||||||
result = code_string[i] + result
|
val /= base
|
||||||
if len(result) < minlen:
|
if len(result) < minlen:
|
||||||
result = code_string[0] * (minlen - len(result)) + result
|
result = code_string[0] * (minlen - len(result)) + result
|
||||||
return result
|
return result
|
||||||
|
@ -101,11 +101,10 @@ def base10_multiply(a, n):
|
||||||
return G
|
return G
|
||||||
if n == 1:
|
if n == 1:
|
||||||
return a
|
return a
|
||||||
n, m = divmod(n, 2)
|
if (n % 2) == 0:
|
||||||
if m == 0:
|
return base10_double(base10_multiply(a, n / 2))
|
||||||
return base10_double(base10_multiply(a, n))
|
if (n % 2) == 1:
|
||||||
if m == 1:
|
return base10_add(base10_double(base10_multiply(a, n / 2)), a)
|
||||||
return base10_add(base10_double(base10_multiply(a, n)), a)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
Symmetric Encryption
|
Symmetric Encryption
|
||||||
"""
|
"""
|
||||||
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
|
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
|
||||||
# See LICENSE for details.
|
# See LICENSE for details.
|
||||||
|
|
||||||
from .openssl import OpenSSL
|
from openssl import OpenSSL
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=redefined-builtin
|
# pylint: disable=redefined-builtin
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
Asymmetric cryptography using elliptic curves
|
Asymmetric cryptography using elliptic curves
|
||||||
"""
|
"""
|
||||||
|
@ -8,9 +10,9 @@ Asymmetric cryptography using elliptic curves
|
||||||
from hashlib import sha512
|
from hashlib import sha512
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
|
|
||||||
from .cipher import Cipher
|
from cipher import Cipher
|
||||||
from .hash import equals, hmac_sha256
|
from hash import equals, hmac_sha256
|
||||||
from .openssl import OpenSSL
|
from openssl import OpenSSL
|
||||||
|
|
||||||
|
|
||||||
class ECC(object):
|
class ECC(object):
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
"""
|
"""
|
||||||
ECC blind signature functionality based on
|
ECC blind signature functionality based on
|
||||||
"An Efficient Blind Signature Scheme
|
"An Efficient Blind Signature Scheme
|
||||||
|
@ -150,7 +151,7 @@ class ECCBlind(object): # pylint: disable=too-many-instance-attributes
|
||||||
# padding manually
|
# padding manually
|
||||||
bx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(x))
|
bx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(x))
|
||||||
OpenSSL.BN_bn2bin(x, bx)
|
OpenSSL.BN_bn2bin(x, bx)
|
||||||
out = bx.raw.rjust(l_, b'\x00')
|
out = bx.raw.rjust(l_, chr(0))
|
||||||
return pack(EC, y_byte, out)
|
return pack(EC, y_byte, out)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
@ -180,7 +181,7 @@ class ECCBlind(object): # pylint: disable=too-many-instance-attributes
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
o = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(bn))
|
o = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(bn))
|
||||||
OpenSSL.BN_bn2bin(bn, o)
|
OpenSSL.BN_bn2bin(bn, o)
|
||||||
return o.raw.rjust(l_, b'\x00')
|
return o.raw.rjust(l_, chr(0))
|
||||||
|
|
||||||
def _bn_deserialize(self, data):
|
def _bn_deserialize(self, data):
|
||||||
"""Make a BigNum out of string"""
|
"""Make a BigNum out of string"""
|
||||||
|
|
|
@ -4,7 +4,7 @@ Wrappers for hash functions from OpenSSL.
|
||||||
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
|
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
|
||||||
# See LICENSE for details.
|
# See LICENSE for details.
|
||||||
|
|
||||||
from .openssl import OpenSSL
|
from openssl import OpenSSL
|
||||||
|
|
||||||
|
|
||||||
# For python3
|
# For python3
|
||||||
|
|
|
@ -83,7 +83,7 @@ class _OpenSSL(object):
|
||||||
"""
|
"""
|
||||||
self._lib = ctypes.CDLL(library)
|
self._lib = ctypes.CDLL(library)
|
||||||
self._version, self._hexversion, self._cflags = get_version(self._lib)
|
self._version, self._hexversion, self._cflags = get_version(self._lib)
|
||||||
self._libreSSL = self._version.startswith(b"LibreSSL")
|
self._libreSSL = self._version.startswith("LibreSSL")
|
||||||
|
|
||||||
self.pointer = ctypes.pointer
|
self.pointer = ctypes.pointer
|
||||||
self.c_int = ctypes.c_int
|
self.c_int = ctypes.c_int
|
||||||
|
|
|
@ -51,6 +51,10 @@ dandelion = 0
|
||||||
|
|
||||||
testmode = False
|
testmode = False
|
||||||
|
|
||||||
|
kivy = False
|
||||||
|
|
||||||
|
association = ''
|
||||||
|
|
||||||
clientHasReceivedIncomingConnections = False
|
clientHasReceivedIncomingConnections = False
|
||||||
"""used by API command clientStatus"""
|
"""used by API command clientStatus"""
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ when pybitmessage started in test mode.
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from common import put_signal_file
|
from test_process import put_signal_file
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
_files = (
|
_files = (
|
||||||
|
@ -20,15 +17,3 @@ def cleanup(home=None, files=_files):
|
||||||
os.remove(os.path.join(home, pfile))
|
os.remove(os.path.join(home, pfile))
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def skip_python3():
|
|
||||||
"""Raise unittest.SkipTest() if detected python3"""
|
|
||||||
if sys.hexversion >= 0x3000000:
|
|
||||||
raise unittest.SkipTest('Module is not ported to python3')
|
|
||||||
|
|
||||||
|
|
||||||
def put_signal_file(path, filename):
|
|
||||||
"""Creates file, presence of which is a signal about some event."""
|
|
||||||
with open(os.path.join(path, filename), 'wb') as outfile:
|
|
||||||
outfile.write(b'%i' % time.time())
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import shutil
|
||||||
import socket
|
import socket
|
||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
import threading
|
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
@ -62,13 +61,6 @@ class TestCore(unittest.TestCase):
|
||||||
"""Test case, which runs in main pybitmessage thread"""
|
"""Test case, which runs in main pybitmessage thread"""
|
||||||
addr = 'BM-2cVvkzJuQDsQHLqxRXc6HZGPLZnkBLzEZY'
|
addr = 'BM-2cVvkzJuQDsQHLqxRXc6HZGPLZnkBLzEZY'
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
"""Reset possible unexpected settings after test"""
|
|
||||||
knownnodes.addKnownNode(1, Peer('127.0.0.1', 8444), is_self=True)
|
|
||||||
BMConfigParser().remove_option('bitmessagesettings', 'dontconnect')
|
|
||||||
BMConfigParser().remove_option('bitmessagesettings', 'onionservicesonly')
|
|
||||||
BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'none')
|
|
||||||
|
|
||||||
def test_msgcoding(self):
|
def test_msgcoding(self):
|
||||||
"""test encoding and decoding (originally from helper_msgcoding)"""
|
"""test encoding and decoding (originally from helper_msgcoding)"""
|
||||||
msg_data = {
|
msg_data = {
|
||||||
|
@ -278,36 +270,6 @@ class TestCore(unittest.TestCase):
|
||||||
return
|
return
|
||||||
self.fail('Failed to connect to at least 3 nodes within 360 sec')
|
self.fail('Failed to connect to at least 3 nodes within 360 sec')
|
||||||
|
|
||||||
def test_udp(self):
|
|
||||||
"""check default udp setting and presence of Announcer thread"""
|
|
||||||
self.assertTrue(
|
|
||||||
BMConfigParser().safeGetBoolean('bitmessagesettings', 'udp'))
|
|
||||||
for thread in threading.enumerate():
|
|
||||||
if thread.name == 'Announcer': # find Announcer thread
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
return self.fail('No Announcer thread found')
|
|
||||||
|
|
||||||
for _ in range(20): # wait for UDP socket
|
|
||||||
for sock in BMConnectionPool().udpSockets.values():
|
|
||||||
thread.announceSelf()
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
time.sleep(1)
|
|
||||||
continue
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
self.fail('UDP socket is not started')
|
|
||||||
|
|
||||||
for _ in range(20):
|
|
||||||
if state.discoveredPeers:
|
|
||||||
peer = state.discoveredPeers.keys()[0]
|
|
||||||
self.assertEqual(peer.port, 8444)
|
|
||||||
break
|
|
||||||
time.sleep(1)
|
|
||||||
else:
|
|
||||||
self.fail('No self in discovered peers')
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _decode_msg(data, pattern):
|
def _decode_msg(data, pattern):
|
||||||
proto = BMProto()
|
proto = BMProto()
|
||||||
|
@ -381,6 +343,15 @@ class TestCore(unittest.TestCase):
|
||||||
self.assertEqual(queryreturn[0][0], 1)
|
self.assertEqual(queryreturn[0][0], 1)
|
||||||
self.delete_address_from_addressbook(self.addr)
|
self.delete_address_from_addressbook(self.addr)
|
||||||
|
|
||||||
|
def test_is_own_address_add_to_addressbook(self):
|
||||||
|
"""Checking own address adding in addressbook"""
|
||||||
|
from helper_addressGenerator import createAddressIfNeeded
|
||||||
|
try:
|
||||||
|
address = createAddressIfNeeded('test1')
|
||||||
|
self.assertFalse(helper_addressbook.insert(label='test', address=address))
|
||||||
|
except IndexError:
|
||||||
|
self.fail("Can't generate addresses")
|
||||||
|
|
||||||
def test_adding_two_same_case_sensitive_addresses(self):
|
def test_adding_two_same_case_sensitive_addresses(self):
|
||||||
"""Testing same case sensitive address store in addressbook"""
|
"""Testing same case sensitive address store in addressbook"""
|
||||||
address1 = 'BM-2cVWtdUzPwF7UNGDrZftWuHWiJ6xxBpiSP'
|
address1 = 'BM-2cVWtdUzPwF7UNGDrZftWuHWiJ6xxBpiSP'
|
||||||
|
|
|
@ -5,13 +5,9 @@ Tests using API.
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
import xmlrpclib # nosec
|
||||||
|
|
||||||
try: # nosec
|
from test_process import TestProcessProto, TestProcessShutdown
|
||||||
from xmlrpclib import ServerProxy, ProtocolError
|
|
||||||
except ImportError:
|
|
||||||
from xmlrpc.client import ServerProxy, ProtocolError
|
|
||||||
|
|
||||||
from .test_process import TestProcessProto, TestProcessShutdown
|
|
||||||
|
|
||||||
|
|
||||||
class TestAPIProto(TestProcessProto):
|
class TestAPIProto(TestProcessProto):
|
||||||
|
@ -23,7 +19,7 @@ class TestAPIProto(TestProcessProto):
|
||||||
"""Setup XMLRPC proxy for pybitmessage API"""
|
"""Setup XMLRPC proxy for pybitmessage API"""
|
||||||
super(TestAPIProto, cls).setUpClass()
|
super(TestAPIProto, cls).setUpClass()
|
||||||
cls.addresses = []
|
cls.addresses = []
|
||||||
cls.api = ServerProxy(
|
cls.api = xmlrpclib.ServerProxy(
|
||||||
"http://username:password@127.0.0.1:8442/")
|
"http://username:password@127.0.0.1:8442/")
|
||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
if cls._get_readline('.api_started'):
|
if cls._get_readline('.api_started'):
|
||||||
|
@ -69,8 +65,8 @@ class TestAPI(TestAPIProto):
|
||||||
|
|
||||||
def test_user_password(self):
|
def test_user_password(self):
|
||||||
"""Trying to connect with wrong username/password"""
|
"""Trying to connect with wrong username/password"""
|
||||||
api_wrong = ServerProxy("http://test:wrong@127.0.0.1:8442/")
|
api_wrong = xmlrpclib.ServerProxy("http://test:wrong@127.0.0.1:8442/")
|
||||||
with self.assertRaises(ProtocolError):
|
with self.assertRaises(xmlrpclib.ProtocolError):
|
||||||
api_wrong.clientStatus()
|
api_wrong.clientStatus()
|
||||||
|
|
||||||
def test_connection(self):
|
def test_connection(self):
|
||||||
|
|
|
@ -5,7 +5,9 @@ import os
|
||||||
import unittest
|
import unittest
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
|
|
||||||
from pybitmessage.pyelliptic import ECCBlind, ECCBlindChain, OpenSSL
|
from pybitmessage.pyelliptic.eccblind import ECCBlind
|
||||||
|
from pybitmessage.pyelliptic.eccblindchain import ECCBlindChain
|
||||||
|
from pybitmessage.pyelliptic.openssl import OpenSSL
|
||||||
|
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
|
|
||||||
|
@ -34,12 +36,12 @@ class TestBlindSig(unittest.TestCase):
|
||||||
|
|
||||||
# (3) Signature Generation
|
# (3) Signature Generation
|
||||||
signature_blinded = signer_obj.blind_sign(msg_blinded)
|
signature_blinded = signer_obj.blind_sign(msg_blinded)
|
||||||
assert isinstance(signature_blinded, bytes)
|
assert isinstance(signature_blinded, str)
|
||||||
self.assertEqual(len(signature_blinded), 32)
|
self.assertEqual(len(signature_blinded), 32)
|
||||||
|
|
||||||
# (4) Extraction
|
# (4) Extraction
|
||||||
signature = requester_obj.unblind(signature_blinded)
|
signature = requester_obj.unblind(signature_blinded)
|
||||||
assert isinstance(signature, bytes)
|
assert isinstance(signature, str)
|
||||||
self.assertEqual(len(signature), 65)
|
self.assertEqual(len(signature), 65)
|
||||||
|
|
||||||
self.assertNotEqual(signature, signature_blinded)
|
self.assertNotEqual(signature, signature_blinded)
|
||||||
|
@ -161,7 +163,7 @@ class TestBlindSig(unittest.TestCase):
|
||||||
output.extend(pubkey)
|
output.extend(pubkey)
|
||||||
output.extend(signature)
|
output.extend(signature)
|
||||||
signer_obj = child_obj
|
signer_obj = child_obj
|
||||||
verifychain = ECCBlindChain(ca=ca.pubkey(), chain=bytes(output))
|
verifychain = ECCBlindChain(ca=ca.pubkey(), chain=str(output))
|
||||||
self.assertTrue(verifychain.verify(msg=msg, value=1))
|
self.assertTrue(verifychain.verify(msg=msg, value=1))
|
||||||
|
|
||||||
def test_blind_sig_chain_wrong_ca(self): # pylint: disable=too-many-locals
|
def test_blind_sig_chain_wrong_ca(self): # pylint: disable=too-many-locals
|
||||||
|
|
|
@ -2,8 +2,12 @@
|
||||||
Various tests for config
|
Various tests for config
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
import tempfile
|
||||||
|
|
||||||
from pybitmessage.bmconfigparser import BMConfigParser
|
from pybitmessage.bmconfigparser import BMConfigParser
|
||||||
|
from test_process import TestProcessProto
|
||||||
|
|
||||||
|
|
||||||
class TestConfig(unittest.TestCase):
|
class TestConfig(unittest.TestCase):
|
||||||
|
@ -34,3 +38,32 @@ class TestConfig(unittest.TestCase):
|
||||||
BMConfigParser().safeGetInt('nonexistent', 'nonexistent'), 0)
|
BMConfigParser().safeGetInt('nonexistent', 'nonexistent'), 0)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
BMConfigParser().safeGetInt('nonexistent', 'nonexistent', 42), 42)
|
BMConfigParser().safeGetInt('nonexistent', 'nonexistent', 42), 42)
|
||||||
|
|
||||||
|
|
||||||
|
class TestProcessConfig(TestProcessProto):
|
||||||
|
"""A test case for keys.dat"""
|
||||||
|
home = tempfile.mkdtemp()
|
||||||
|
|
||||||
|
def test_config_defaults(self):
|
||||||
|
"""Test settings in the generated config"""
|
||||||
|
self._stop_process()
|
||||||
|
self._kill_process()
|
||||||
|
config = BMConfigParser()
|
||||||
|
config.read(os.path.join(self.home, 'keys.dat'))
|
||||||
|
|
||||||
|
self.assertEqual(config.safeGetInt(
|
||||||
|
'bitmessagesettings', 'settingsversion'), 10)
|
||||||
|
self.assertEqual(config.safeGetInt(
|
||||||
|
'bitmessagesettings', 'port'), 8444)
|
||||||
|
# don't connect
|
||||||
|
self.assertTrue(config.safeGetBoolean(
|
||||||
|
'bitmessagesettings', 'dontconnect'))
|
||||||
|
# API disabled
|
||||||
|
self.assertFalse(config.safeGetBoolean(
|
||||||
|
'bitmessagesettings', 'apienabled'))
|
||||||
|
|
||||||
|
# extralowdifficulty is false
|
||||||
|
self.assertEqual(config.safeGetInt(
|
||||||
|
'bitmessagesettings', 'defaultnoncetrialsperbyte'), 1000)
|
||||||
|
self.assertEqual(config.safeGetInt(
|
||||||
|
'bitmessagesettings', 'defaultpayloadlengthextrabytes'), 1000)
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
"""
|
|
||||||
Various tests for config
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import tempfile
|
|
||||||
from pybitmessage.bmconfigparser import BMConfigParser
|
|
||||||
from .test_process import TestProcessProto
|
|
||||||
|
|
||||||
|
|
||||||
class TestProcessConfig(TestProcessProto):
|
|
||||||
"""A test case for keys.dat"""
|
|
||||||
home = tempfile.mkdtemp()
|
|
||||||
|
|
||||||
|
|
||||||
def test_config_defaults(self):
|
|
||||||
"""Test settings in the generated config"""
|
|
||||||
config = BMConfigParser()
|
|
||||||
self._stop_process()
|
|
||||||
self._kill_process()
|
|
||||||
config.read(os.path.join(self.home, 'keys.dat'))
|
|
||||||
|
|
||||||
self.assertEqual(config.safeGetInt(
|
|
||||||
'bitmessagesettings', 'settingsversion'), 10)
|
|
||||||
self.assertEqual(config.safeGetInt(
|
|
||||||
'bitmessagesettings', 'port'), 8444)
|
|
||||||
# don't connect
|
|
||||||
self.assertTrue(config.safeGetBoolean(
|
|
||||||
'bitmessagesettings', 'dontconnect'))
|
|
||||||
# API disabled
|
|
||||||
self.assertFalse(config.safeGetBoolean(
|
|
||||||
'bitmessagesettings', 'apienabled'))
|
|
||||||
|
|
||||||
# extralowdifficulty is false
|
|
||||||
self.assertEqual(config.safeGetInt(
|
|
||||||
'bitmessagesettings', 'defaultnoncetrialsperbyte'), 1000)
|
|
||||||
self.assertEqual(config.safeGetInt(
|
|
||||||
'bitmessagesettings', 'defaultpayloadlengthextrabytes'), 1000)
|
|
|
@ -6,10 +6,8 @@ import hashlib
|
||||||
import unittest
|
import unittest
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
from binascii import hexlify, unhexlify
|
from binascii import hexlify, unhexlify
|
||||||
|
|
||||||
from pybitmessage.pyelliptic import arithmetic
|
from pybitmessage.pyelliptic import arithmetic
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from Crypto.Hash import RIPEMD
|
from Crypto.Hash import RIPEMD
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -23,21 +21,14 @@ sample_pubsigningkey = unhexlify(
|
||||||
sample_pubencryptionkey = unhexlify(
|
sample_pubencryptionkey = unhexlify(
|
||||||
'044597d59177fc1d89555d38915f581b5ff2286b39d022ca0283d2bdd5c36be5d3c'
|
'044597d59177fc1d89555d38915f581b5ff2286b39d022ca0283d2bdd5c36be5d3c'
|
||||||
'e7b9b97792327851a562752e4b79475d1f51f5a71352482b241227f45ed36a9')
|
'e7b9b97792327851a562752e4b79475d1f51f5a71352482b241227f45ed36a9')
|
||||||
sample_privsigningkey = \
|
sample_privatesigningkey = \
|
||||||
'93d0b61371a54b53df143b954035d612f8efa8a3ed1cf842c2186bfd8f876665'
|
'93d0b61371a54b53df143b954035d612f8efa8a3ed1cf842c2186bfd8f876665'
|
||||||
sample_privencryptionkey = \
|
sample_privateencryptionkey = \
|
||||||
'4b0b73a54e19b059dc274ab69df095fe699f43b17397bca26fdf40f4d7400a3a'
|
'4b0b73a54e19b059dc274ab69df095fe699f43b17397bca26fdf40f4d7400a3a'
|
||||||
sample_ripe = b'003cd097eb7f35c87b5dc8b4538c22cb55312a9f'
|
sample_ripe = '003cd097eb7f35c87b5dc8b4538c22cb55312a9f'
|
||||||
# stream: 1, version: 2
|
# stream: 1, version: 2
|
||||||
sample_address = 'BM-onkVu1KKL2UaUss5Upg9vXmqd3esTmV79'
|
sample_address = 'BM-onkVu1KKL2UaUss5Upg9vXmqd3esTmV79'
|
||||||
|
|
||||||
sample_factor = 66858749573256452658262553961707680376751171096153613379801854825275240965733
|
|
||||||
# G * sample_factor
|
|
||||||
sample_point = (
|
|
||||||
33567437183004486938355437500683826356288335339807546987348409590129959362313,
|
|
||||||
94730058721143827257669456336351159718085716196507891067256111928318063085006
|
|
||||||
)
|
|
||||||
|
|
||||||
_sha = hashlib.new('sha512')
|
_sha = hashlib.new('sha512')
|
||||||
_sha.update(sample_pubsigningkey + sample_pubencryptionkey)
|
_sha.update(sample_pubsigningkey + sample_pubencryptionkey)
|
||||||
|
|
||||||
|
@ -78,20 +69,14 @@ class TestCrypto(RIPEMD160TestCase, unittest.TestCase):
|
||||||
|
|
||||||
class TestAddresses(unittest.TestCase):
|
class TestAddresses(unittest.TestCase):
|
||||||
"""Test addresses manipulations"""
|
"""Test addresses manipulations"""
|
||||||
def test_base10_multiply(self):
|
|
||||||
"""Test arithmetic.base10_multiply"""
|
|
||||||
self.assertEqual(
|
|
||||||
sample_point,
|
|
||||||
arithmetic.base10_multiply(arithmetic.G, sample_factor))
|
|
||||||
|
|
||||||
def test_privtopub(self):
|
def test_privtopub(self):
|
||||||
"""Generate public keys and check the result"""
|
"""Generate public keys and check the result"""
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
arithmetic.privtopub(sample_privsigningkey).encode(),
|
arithmetic.privtopub(sample_privatesigningkey),
|
||||||
hexlify(sample_pubsigningkey)
|
hexlify(sample_pubsigningkey)
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
arithmetic.privtopub(sample_privencryptionkey).encode(),
|
arithmetic.privtopub(sample_privateencryptionkey),
|
||||||
hexlify(sample_pubencryptionkey)
|
hexlify(sample_pubencryptionkey)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ Testing the logger configuration
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from .test_process import TestProcessProto
|
from test_process import TestProcessProto
|
||||||
|
|
||||||
|
|
||||||
class TestLogger(TestProcessProto):
|
class TestLogger(TestProcessProto):
|
||||||
|
|
|
@ -3,10 +3,6 @@ Test for network group
|
||||||
"""
|
"""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from .common import skip_python3
|
|
||||||
|
|
||||||
skip_python3()
|
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkGroup(unittest.TestCase):
|
class TestNetworkGroup(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -3,16 +3,15 @@ Tests for openclpow module
|
||||||
"""
|
"""
|
||||||
import hashlib
|
import hashlib
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import pybitmessage.openclpow as openclpow
|
||||||
|
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
|
|
||||||
from .common import skip_python3
|
from test_process import TestProcessProto
|
||||||
|
|
||||||
skip_python3() # noqa:E402
|
|
||||||
|
|
||||||
from pybitmessage import openclpow
|
|
||||||
|
|
||||||
|
|
||||||
class TestOpenClPow(unittest.TestCase):
|
class TestOpenClPow(TestProcessProto):
|
||||||
"""
|
"""
|
||||||
Main opencl test case
|
Main opencl test case
|
||||||
"""
|
"""
|
||||||
|
@ -20,17 +19,16 @@ class TestOpenClPow(unittest.TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
openclpow.initCL()
|
openclpow.initCL()
|
||||||
|
super(TestOpenClPow, cls).setUpClass()
|
||||||
|
|
||||||
@unittest.skipUnless(openclpow.enabledGpus, "No GPUs found / enabled")
|
@unittest.skipIf(not openclpow.enabledGpus,
|
||||||
|
"No GPUs found / enabled")
|
||||||
def test_openclpow(self):
|
def test_openclpow(self):
|
||||||
"""Check the working of openclpow module"""
|
"""Check the working of openclpow module"""
|
||||||
target_ = 54227212183
|
target_ = 54227212183
|
||||||
initialHash = (
|
initialHash = ("3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590"
|
||||||
"3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590"
|
"b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3").decode("hex")
|
||||||
"b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3"
|
|
||||||
).decode("hex")
|
|
||||||
nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target_)
|
nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target_)
|
||||||
trialValue, = unpack(
|
trialValue, = unpack(
|
||||||
'>Q', hashlib.sha512(hashlib.sha512(
|
'>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
|
||||||
pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
|
|
||||||
self.assertLess((nonce - trialValue), target_)
|
self.assertLess((nonce - trialValue), target_)
|
||||||
|
|
|
@ -49,6 +49,6 @@ class TestOpenSSL(unittest.TestCase):
|
||||||
c = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(a))
|
c = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(a))
|
||||||
OpenSSL.BN_bn2binpad(a, b, OpenSSL.BN_num_bytes(n))
|
OpenSSL.BN_bn2binpad(a, b, OpenSSL.BN_num_bytes(n))
|
||||||
OpenSSL.BN_bn2bin(a, c)
|
OpenSSL.BN_bn2bin(a, c)
|
||||||
if b.raw != c.raw.rjust(OpenSSL.BN_num_bytes(n), b'\x00'):
|
if b.raw != c.raw.rjust(OpenSSL.BN_num_bytes(n), chr(0)):
|
||||||
bad += 1
|
bad += 1
|
||||||
self.assertEqual(bad, 0)
|
self.assertEqual(bad, 0)
|
||||||
|
|
|
@ -12,10 +12,13 @@ import unittest
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from .common import cleanup, put_signal_file, skip_python3
|
from common import cleanup
|
||||||
|
|
||||||
|
|
||||||
skip_python3()
|
def put_signal_file(path, filename):
|
||||||
|
"""Creates file, presence of which is a signal about some event."""
|
||||||
|
with open(os.path.join(path, filename), 'wb') as outfile:
|
||||||
|
outfile.write(str(time.time()))
|
||||||
|
|
||||||
|
|
||||||
class TestProcessProto(unittest.TestCase):
|
class TestProcessProto(unittest.TestCase):
|
||||||
|
@ -195,19 +198,6 @@ class TestProcess(TestProcessProto):
|
||||||
"""Check PyBitmessage process name"""
|
"""Check PyBitmessage process name"""
|
||||||
self.assertEqual(self.process.name(), 'PyBitmessage')
|
self.assertEqual(self.process.name(), 'PyBitmessage')
|
||||||
|
|
||||||
@unittest.skipIf(psutil.version_info < (4, 0), 'psutil is too old')
|
|
||||||
def test_home(self):
|
|
||||||
"""Ensure BITMESSAGE_HOME is used by process"""
|
|
||||||
self.assertEqual(
|
|
||||||
self.process.environ().get('BITMESSAGE_HOME'), self.home)
|
|
||||||
|
|
||||||
def test_listening(self):
|
|
||||||
"""Check that pybitmessage listens on port 8444"""
|
|
||||||
for c in self.process.connections():
|
|
||||||
if c.status == 'LISTEN':
|
|
||||||
self.assertEqual(c.laddr[1], 8444)
|
|
||||||
break
|
|
||||||
|
|
||||||
def test_files(self):
|
def test_files(self):
|
||||||
"""Check existence of PyBitmessage files"""
|
"""Check existence of PyBitmessage files"""
|
||||||
for pfile in self._files:
|
for pfile in self._files:
|
||||||
|
|
|
@ -4,10 +4,6 @@ Tests for common protocol functions
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from .common import skip_python3
|
|
||||||
|
|
||||||
skip_python3()
|
|
||||||
|
|
||||||
|
|
||||||
class TestProtocol(unittest.TestCase):
|
class TestProtocol(unittest.TestCase):
|
||||||
"""Main protocol test case"""
|
"""Main protocol test case"""
|
||||||
|
|
|
@ -15,7 +15,7 @@ class TestRandomTrackingDict(unittest.TestCase):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def randString():
|
def randString():
|
||||||
"""helper function for tests, generates a random string"""
|
"""helper function for tests, generates a random string"""
|
||||||
retval = ''
|
retval = b''
|
||||||
for _ in range(32):
|
for _ in range(32):
|
||||||
retval += chr(random.randint(0, 255))
|
retval += chr(random.randint(0, 255))
|
||||||
return retval
|
return retval
|
||||||
|
|
|
@ -6,4 +6,3 @@ Depends: openssl, python-setuptools
|
||||||
Recommends: apparmor, python-msgpack, python-qt4, python-stem, tor
|
Recommends: apparmor, python-msgpack, python-qt4, python-stem, tor
|
||||||
Suggests: python-pyopencl, python-jsonrpclib, python-defusedxml, python-qrcode
|
Suggests: python-pyopencl, python-jsonrpclib, python-defusedxml, python-qrcode
|
||||||
Suite: bionic
|
Suite: bionic
|
||||||
Setup-Env-Vars: DEB_BUILD_OPTIONS=nocheck
|
|
||||||
|
|
22
tests.py
22
tests.py
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
"""Custom tests runner script for tox and python3"""
|
|
||||||
import random # noseq
|
|
||||||
import sys
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
def unittest_discover():
|
|
||||||
"""Explicit test suite creation"""
|
|
||||||
if sys.hexversion >= 0x3000000:
|
|
||||||
from pybitmessage import pathmagic
|
|
||||||
pathmagic.setup()
|
|
||||||
loader = unittest.defaultTestLoader
|
|
||||||
# randomize the order of tests in test cases
|
|
||||||
loader.sortTestMethodsUsing = lambda a, b: random.randint(-1, 1)
|
|
||||||
# pybitmessage symlink may disappear on Windows
|
|
||||||
return loader.discover('src.tests')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
result = unittest.TextTestRunner(verbosity=2).run(unittest_discover())
|
|
||||||
sys.exit(not result.wasSuccessful())
|
|
34
tox.ini
34
tox.ini
|
@ -1,34 +0,0 @@
|
||||||
[tox]
|
|
||||||
envlist = reset,py{27,37,38},stats
|
|
||||||
skip_missing_interpreters = true
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
setenv =
|
|
||||||
BITMESSAGE_HOME = {envtmpdir}
|
|
||||||
PYTHONWARNINGS = all
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands =
|
|
||||||
python checkdeps.py
|
|
||||||
coverage run -a src/bitmessagemain.py -t
|
|
||||||
coverage run -a -m tests
|
|
||||||
|
|
||||||
[testenv:reset]
|
|
||||||
commands = coverage erase
|
|
||||||
|
|
||||||
[testenv:stats]
|
|
||||||
commands =
|
|
||||||
coverage report
|
|
||||||
coverage xml
|
|
||||||
|
|
||||||
[coverage:run]
|
|
||||||
source = src
|
|
||||||
omit =
|
|
||||||
*/lib*
|
|
||||||
tests.py
|
|
||||||
*/tests/*
|
|
||||||
src/version.py
|
|
||||||
*/__init__.py
|
|
||||||
src/fallback/umsgpack/*
|
|
||||||
|
|
||||||
[coverage:report]
|
|
||||||
ignore_errors = true
|
|
Loading…
Reference in New Issue
Block a user