Merge pull request #1653 from onionshare/pyside6-package

Pyside6 package
This commit is contained in:
Micah Lee 2023-05-21 09:47:18 -07:00 committed by GitHub
commit 8be0290fdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 2723 additions and 2757 deletions

View File

@ -1,5 +1,5 @@
name: Build
run-name: Build win32, win64, mac (Intel) 🚀
run-name: Build win64, mac (Intel) 🚀
on:
push:
branches:
@ -14,8 +14,13 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Install python
uses: actions/setup-python@v4
with:
python-version: '3.10.11'
- name: Install poetry
run: C:\hostedtoolcache\windows\Python\3.9.13\x64\python -m pip install poetry
run: C:\hostedtoolcache\windows\Python\3.10.11\x64\python -m pip install poetry
- name: Restore cache - poetry
uses: actions/cache@v3
@ -26,8 +31,8 @@ jobs:
- name: Install poetry dependencies
run: |
cd desktop
C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry install
C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry env list --full-path
C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry install
C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry env list --full-path
- name: Restore cache - tor
uses: actions/cache@v3
@ -36,7 +41,7 @@ jobs:
key: ${{ runner.os }}-win64-tor-${{ hashFiles('desktop/scripts/get-tor.py') }}
- name: Get tor binaries from Tor Browser (64-bit)
run: cd desktop && C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry run python .\scripts\get-tor.py win64
run: cd desktop && C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry run python .\scripts\get-tor.py win64
- name: Restore cache - obfs4proxy
uses: actions/cache@v3
@ -89,13 +94,13 @@ jobs:
- name: Build OnionShare
run: |
cd desktop
C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry run python .\setup-freeze.py build
C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry run python .\scripts\build-windows.py cleanup-build
C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry run python .\setup-freeze.py build
C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry run python .\scripts\build-windows.py cleanup-build
- name: Compress
shell: pwsh
run: |
mv desktop\build\exe.win-amd64-3.9\ ~\onionshare-win64
mv desktop\build\exe.win-amd64-3.10\ ~\onionshare-win64
Compress-Archive -LiteralPath ~\onionshare-win64 -DestinationPath ~\onionshare-win64.zip
- uses: actions/upload-artifact@v3
@ -103,118 +108,17 @@ jobs:
name: win64-build
path: ~\onionshare-win64.zip
build-win32:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
# TODO: Someday, build universal2 mac binaries. Right now it's blocked because Github Actions doesn't support
# M1 Mac VMs: https://github.com/actions/runner-images/issues/2187
- name: Install poetry
run: C:\hostedtoolcache\windows\Python\3.9.13\x86\python -m pip install poetry
- name: Restore cache - poetry
uses: actions/cache@v3
with:
path: ~\AppData\Local\pypoetry\Cache\virtualenvs
key: ${{ runner.os }}-win32-poetry-${{ hashFiles('desktop/poetry.lock') }}
- name: Install poetry dependencies
run: |
cd desktop
C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry install
C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry env list --full-path
- name: Restore cache - tor
uses: actions/cache@v3
with:
path: desktop\build\tor
key: ${{ runner.os }}-win32-tor-${{ hashFiles('desktop/scripts/get-tor.py') }}
- name: Get tor binaries from Tor Browser (32-bit)
run: cd desktop && C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry run python .\scripts\get-tor.py win32
- name: Install golang (32-bit)
shell: pwsh
run: |
cd ~\Downloads
Invoke-WebRequest -Uri https://go.dev/dl/go1.19.1.windows-386.msi -OutFile go1.19.1.windows-386.msi
msiexec.exe /i go1.19.1.windows-386.msi /quiet /L*V go-install.log
- name: Restore cache - obfs4proxy
uses: actions/cache@v3
with:
path: desktop\onionshare\resources\tor\obfs4proxy.exe
key: ${{ runner.os }}-win32-obfs4proxy-${{ hashFiles('desktop/scripts/build-pt-obfs4proxy.ps1') }}
- name: Build obfs4proxy
shell: pwsh
run: |
if ((Test-Path -Path 'desktop\onionshare\resources\tor\obfs4proxy.exe') -eq $True) {
Write-Output "obfs4proxy already built"
} else {
$env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
cd desktop
.\scripts\build-pt-obfs4proxy.ps1
}
- name: Restore cache - snowflake
uses: actions/cache@v3
with:
path: desktop\onionshare\resources\tor\snowflake-client.exe
key: ${{ runner.os }}-win32-snowflake-${{ hashFiles('desktop/scripts/build-pt-snowflake.ps1') }}
- name: Build snowflake
shell: pwsh
run: |
if ((Test-Path -Path 'desktop\onionshare\resources\tor\snowflake-client.exe') -eq $True) {
Write-Output "snowflake already built"
} else {
$env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
cd desktop
.\scripts\build-pt-snowflake.ps1
}
- name: Restore cache - meek
uses: actions/cache@v3
with:
path: desktop\onionshare\resources\tor\meek-client.exe
key: ${{ runner.os }}-win32-meek-${{ hashFiles('desktop/scripts/build-pt-meek.ps1') }}
- name: Build meek
shell: pwsh
run: |
if ((Test-Path -Path 'desktop\onionshare\resources\tor\meek-client.exe') -eq $True) {
Write-Output "meek already built"
} else {
$env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
cd desktop
.\scripts\build-pt-meek.ps1
}
- name: Build OnionShare
run: |
cd desktop
C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry run python .\setup-freeze.py build
C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry run python .\scripts\build-windows.py cleanup-build
- name: Compress
shell: pwsh
run: |
mv desktop\build\exe.win32-3.9\ ~\onionshare-win32
Compress-Archive -LiteralPath ~\onionshare-win32 -DestinationPath ~\onionshare-win32.zip
- uses: actions/upload-artifact@v3
with:
name: win32-build
path: ~\onionshare-win32.zip
build-mac:
build-mac-intel:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Install Python 3.9.13 (Intel)
- name: Install Python 3.10.9 (universal2)
run: |
curl -L https://www.python.org/ftp/python/3.9.13/python-3.9.13-macosx10.9.pkg --output ~/Downloads/python.pkg
curl -L https://www.python.org/ftp/python/3.10.9/python-3.10.9-macos11.pkg --output ~/Downloads/python.pkg
sudo installer -pkg ~/Downloads/python.pkg -target /
- name: Install poetry
@ -230,7 +134,7 @@ jobs:
- name: Install poetry dependencies
run: |
cd desktop
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry install
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry install
- name: Restore cache - tor
uses: actions/cache@v3
@ -241,7 +145,7 @@ jobs:
- name: Get tor binaries from Tor Browser
run: |
cd desktop
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry run python ./scripts/get-tor.py macos
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./scripts/get-tor.py macos
- name: Restore cache - obfs4proxy
uses: actions/cache@v3
@ -288,22 +192,31 @@ jobs:
./scripts/build-pt-meek.sh
fi
- name: Install cx_Freeze/PySide6 build dependencies
run: |
brew install libiodbc
cd ~/Downloads
curl -O -L https://github.com/PostgresApp/PostgresApp/releases/download/v2.5.12/Postgres-2.5.12-14.dmg
hdiutil attach Postgres-2.5.12-14.dmg
cp -r /Volumes/Postgres-2.5.12-14/Postgres.app /Applications/
hdiutil detach /Volumes/Postgres-2.5.12-14
- name: Build OnionShare
run: |
cd desktop
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry run python ./setup-freeze.py build
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry run python ./setup-freeze.py bdist_mac
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry run python ./scripts/build-macos.py cleanup-build
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./setup-freeze.py build
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./setup-freeze.py bdist_mac
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./scripts/build-macos.py cleanup-build
- name: Compress
run: |
cd desktop/build
tar -czvf ~/onionshare-macos.tar.gz OnionShare.app
tar -czvf ~/onionshare-macos-intel.tar.gz OnionShare.app
- uses: actions/upload-artifact@v3
with:
name: mac-build
path: ~/onionshare-macos.tar.gz
path: ~/onionshare-macos-intel.tar.gz
build-flatpak:
runs-on: ubuntu-latest

2
.gitignore vendored
View File

@ -58,5 +58,7 @@ venv
# other
.vscode
.python-version
onionshare.dist-info
desktop/onionshare/resources/tor
TODO*

View File

@ -69,12 +69,12 @@ cd ..
# get onionshare dependencies
cd pip
./flatpak-pip-generator $(python3 -c 'import toml; print("\n".join(toml.loads(open("../../onionshare/desktop/pyproject.toml").read())["tool"]["poetry"]["dependencies"]))' |grep -vi onionshare_cli |grep -vi python | grep -vi pyside2 | grep -vi cx_freeze |tr "\n" " ")
./flatpak-pip-generator $(python3 -c 'import toml; print("\n".join(toml.loads(open("../../onionshare/desktop/pyproject.toml").read())["tool"]["poetry"]["dependencies"]))' |grep -vi onionshare_cli |grep -vi python | grep -vi pyside6 | grep -vi cx_freeze |tr "\n" " ")
cd ..
# convert to yaml
./flatpak-json2yaml.py -o onionshare-cli.yml poetry/generated-poetry-sources.json
./flatpak-json2yaml.py -o onionshare.yml pip/python3-qrcode.json
./flatpak-json2yaml.py -o onionshare.yml pip/python3-modules.json
```
Now, merge `onionshare-cli.yml` and `onionshare.yml` into the Flatpak manifest.
@ -150,6 +150,32 @@ This will create:
### macOS release
In order to make a universal2 binary, you must run this one a Mac with Apple Silicon. To keep a clean environment, you can use VM.
Set up the VM like this:
- Install [Homebrew](https://brew.sh/)
- `brew install create-dmg libiodbc`
- Install the latest Python 3.10 from https://www.python.org/downloads/
- Install ARM64 version of Go from https://go.dev/dl/
- Install "Postgres.app with PostgreSQL 14 (Universal)" from https://postgresapp.com/downloads.html (required for cx_Freeze build step)
```sh
cd desktop
python3 -m pip install poetry
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry install
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./scripts/get-tor.py macos
./scripts/build-pt-obfs4proxy.sh
./scripts/build-pt-snowflake.sh
./scripts/build-pt-meek.sh
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./setup-freeze.py build
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./setup-freeze.py bdist_mac
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./scripts/build-macos.py cleanup-build
cd build
tar -czvf ~/onionshare-macos-universal2.tar.gz OnionShare.app
```
Set up the packaging environment:
- Install create-dmg: `brew install create-dmg`

View File

@ -1,2 +1,2 @@
# Enable built-in meek-azure bridge
Bridge meek_lite 192.0.2.2:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com
Bridge meek_lite 192.0.2.18:80 BE776A53492E1E044A26F17306E1BC46A55A1625 url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com

View File

@ -6,10 +6,7 @@ Bridge obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=
Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0
Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0
Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1
Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1
Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0
Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0
Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0
Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0
Bridge obfs4 [2a0c:4d80:42:702::1]:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0

View File

@ -1,2 +1,3 @@
# Enable built-in snowflake bridge
Bridge snowflake 192.0.2.3:1 2B280B23E1107BB62ABFC40DDCC8824814F80A72
Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ front=cdn.sstatic.net ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn
Bridge snowflake 192.0.2.4:80 8838024498816A039FCBBAB14E6F40A0843051FA fingerprint=8838024498816A039FCBBAB14E6F40A0843051FA url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ front=cdn.sstatic.net ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.net:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn

1605
cli/poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@ classifiers = [
]
[tool.poetry.dependencies]
python = "^3.7"
python = ">=3.8,<3.11"
click = "*"
flask = "2.0.3"
flask-socketio = "5.3.1"
@ -40,5 +40,5 @@ pytest = ">=7.2.0"
onionshare-cli = 'onionshare_cli:main'
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

View File

@ -151,7 +151,7 @@ class TestGetPlatform:
class TestGetTorPaths:
@pytest.mark.skipif(sys.platform != "Darwin", reason="requires MacOS")
@pytest.mark.skipif(sys.platform != "darwin", reason="requires MacOS")
def test_get_tor_paths_darwin(
self, platform_darwin, common_obj, sys_frozen, sys_meipass
):

View File

@ -120,7 +120,7 @@ class TestSettings:
settings_obj.set("socks_port", "NON_INTEGER")
assert settings_obj._settings["socks_port"] == 9050
@pytest.mark.skipif(sys.platform != "Darwin", reason="requires Darwin")
@pytest.mark.skipif(sys.platform != "darwin", reason="requires Darwin")
def test_filename_darwin(self, monkeypatch, platform_darwin):
obj = settings.Settings(common.Common())
assert obj.filename == os.path.expanduser(

View File

@ -9,7 +9,7 @@ git clone https://github.com/onionshare/onionshare.git
cd onionshare/desktop
```
Make sure you have Python 3 installed. If you're using Windows or macOS, install version 3.9.13 [from python.org](https://www.python.org/downloads/release/python-3913/). For Windows, make sure to check the box to add python to the path on the first page of the installer.
Make sure you have Python 3 installed. If you're using Windows or macOS, install the latest version of 3.10 [from python.org](https://www.python.org/downloads/). For Windows, make sure to check the box to add python to the path on the first page of the installer.
Make sure you have [poetry](https://python-poetry.org/) installed:
@ -29,9 +29,9 @@ poetry install
**Linux users:** In Ubuntu 20.04 you need the `libxcb-xinerama0` package installed.
**Windows users:** Download and install 7-Zip from https://7-zip.org/download.html. [Add](https://medium.com/@kevinmarkvi/how-to-add-executables-to-your-path-in-windows-5ffa4ce61a53) `C:\Program Files (x86)\7-Zip` to your path.
**Windows users:** Download and install 7-Zip (x64) from https://7-zip.org/download.html. [Add](https://medium.com/@kevinmarkvi/how-to-add-executables-to-your-path-in-windows-5ffa4ce61a53) `C:\Program Files\7-Zip` to your path.
Download Tor Browser and extract the binaries for your platform. The platform must be `win32`, `win64`, `macos`, or `linux64`.
Download Tor Browser and extract the binaries for your platform. The platform must be `win64`, `macos`, or `linux64`.
```sh
poetry run python ./scripts/get-tor.py [platform]

View File

@ -26,10 +26,10 @@ import signal
import json
import psutil
import getpass
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from PySide2.QtCore import Slot, Qt
from PySide2.QtGui import QPalette, QColor
from PySide6.QtCore import Slot, Qt
from PySide6.QtGui import QPalette, QColor
from onionshare_cli.common import Common
from onionshare_cli.settings import Settings
@ -47,7 +47,6 @@ class Application(QtWidgets.QApplication):
def __init__(self, common):
if common.platform == "Linux" or common.platform == "BSD":
self.setAttribute(QtCore.Qt.AA_X11InitThreads, True)
self.setDesktopFileName("org.onionshare.OnionShare")
self.setOrganizationDomain("org.onionshare.OnionShare")
self.setOrganizationName("OnionShare")
@ -267,4 +266,4 @@ def main():
qtapp.aboutToQuit.connect(shutdown)
# All done
sys.exit(qtapp.exec_())
sys.exit(qtapp.exec())

View File

@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import os
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.censorship import (
CensorshipCircumvention,

View File

@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import shutil
from pkg_resources import resource_filename
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from . import strings
from onionshare_cli.onion import (
@ -602,7 +602,7 @@ class ToggleCheckbox(QtWidgets.QCheckBox):
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtCore.Qt.NoPen)
opt = QtWidgets.QStyleOptionButton()
opt.init(self)
opt.initFrom(self)
self.initStyleOption(opt)
s = self.style()
s.drawControl(QtWidgets.QStyle.CE_CheckBox, opt, painter, self)

View File

@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import time
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from . import strings
from .widgets import Alert
@ -119,7 +119,7 @@ class MainWindow(QtWidgets.QMainWindow):
)
)
)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_H)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL | QtCore.Qt.Key_H)
self.settings_button.setShortcut(sequence)
self.settings_button.setAccessibleName(strings._("gui_settings_window_title"))
self.settings_button.clicked.connect(self.open_settings)
@ -191,7 +191,7 @@ class MainWindow(QtWidgets.QMainWindow):
a.addButton(settings_button, QtWidgets.QMessageBox.AcceptRole)
a.addButton(quit_button, QtWidgets.QMessageBox.RejectRole)
a.setDefaultButton(settings_button)
a.exec_()
a.exec()
if a.clickedButton() == settings_button:
# Open settings
@ -255,7 +255,7 @@ class MainWindow(QtWidgets.QMainWindow):
if self.tabs.are_tabs_active():
# Open the warning dialog
self.common.log("MainWindow", "closeEvent, opening warning dialog")
self.close_dialog.exec_()
self.close_dialog.exec()
# Close
if self.close_dialog.clickedButton() == self.close_dialog.accept_button:
@ -303,7 +303,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.onion_cleanup_thread.finished.connect(alert.accept)
self.onion_cleanup_thread.start()
alert.exec_()
alert.exec()
if alert.clickedButton() == quit_early_button:
self.common.log("MainWindow", "cleanup", "quitting early")
if self.onion_cleanup_thread.isRunning():

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
import requests
import os
import base64

View File

@ -1,4 +1,4 @@
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.mode_settings import ModeSettings

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
import platform
import datetime
from onionshare_cli.settings import Settings

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore, QtWidgets
from PySide6 import QtCore, QtWidgets
from onionshare_cli.common import AutoStopTimer

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.web import Web

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import os
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from ... import strings
from ...widgets import Alert, AddFileDialog
@ -434,7 +434,7 @@ class FileSelection(QtWidgets.QVBoxLayout):
Add button clicked.
"""
file_dialog = AddFileDialog(self.common, caption=strings._("gui_choose_items"))
if file_dialog.exec_() == QtWidgets.QDialog.Accepted:
if file_dialog.exec() == QtWidgets.QDialog.Accepted:
self.common.log("FileSelection", "add", file_dialog.selectedFiles())
for filename in file_dialog.selectedFiles():
self.file_list.add_file(filename)

View File

@ -22,7 +22,7 @@ import time
import subprocess
import os
from datetime import datetime
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from ... import strings
from ...widgets import Alert

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore, QtWidgets
from PySide6 import QtCore, QtWidgets
from ... import strings

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import os
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.web import Web

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import os
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.common import Common
from onionshare_cli.web import Web

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore
from PySide6 import QtCore
class CompressThread(QtCore.QThread):

View File

@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.common import Common
from onionshare_cli.web import Web

View File

@ -18,8 +18,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import textwrap
from PySide2 import QtCore, QtWidgets, QtGui
from PySide2.QtCore import Qt
from PySide6 import QtCore, QtWidgets, QtGui
from PySide6.QtCore import Qt
from .. import strings
from ..widgets import Alert

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import queue
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.onionshare import OnionShare
from onionshare_cli.web import Web
@ -45,7 +45,7 @@ class NewTabButton(QtWidgets.QPushButton):
self.setFixedSize(280, 280)
# Keyboard shortcut, using the first letter of the mode
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL + shortcut)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL | shortcut)
self.setShortcut(sequence)
self.setAccessibleName(title)
@ -652,7 +652,7 @@ class Tab(QtWidgets.QWidget):
# Open the warning dialog
self.common.log("Tab", "close_tab, opening warning dialog")
self.close_dialog.setText(dialog_text)
self.close_dialog.exec_()
self.close_dialog.exec()
# Close
if self.close_dialog.clickedButton() == self.close_dialog.accept_button:

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.mode_settings import ModeSettings
@ -55,7 +55,7 @@ class TabWidget(QtWidgets.QTabWidget):
# Define the new tab button
self.new_tab_button = QtWidgets.QPushButton("+", parent=self)
self.new_tab_button.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_T)
self.new_tab_button.setShortcut(QtCore.Qt.CTRL | QtCore.Qt.Key_T)
self.new_tab_button.setFlat(True)
self.new_tab_button.setFixedSize(40, 30)
self.new_tab_button.clicked.connect(self.new_tab_clicked)
@ -196,8 +196,8 @@ class TabWidget(QtWidgets.QTabWidget):
index = self.addTab(tab, strings._("gui_new_tab"))
self.setCurrentIndex(index)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_X)
close_shortcut = QtWidgets.QShortcut(sequence, tab)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL | QtCore.Qt.Key_X)
close_shortcut = QtGui.QShortcut(sequence, tab)
close_shortcut.activated.connect(lambda: self.close_tab(index))
tab.init(mode_settings)
@ -249,8 +249,8 @@ class TabWidget(QtWidgets.QTabWidget):
from_autoconnect=from_autoconnect,
)
settings_tab.close_this_tab.connect(self.close_settings_tab)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_X)
close_shortcut = QtWidgets.QShortcut(sequence, settings_tab)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL | QtCore.Qt.Key_X)
close_shortcut = QtGui.QShortcut(sequence, settings_tab)
close_shortcut.activated.connect(self.close_settings_tab)
self.tor_settings_tab = settings_tab.tor_settings_tab
self.tor_settings_tab.tor_is_connected.connect(self.tor_is_connected)

View File

@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import time
import json
import os
from PySide2 import QtCore
from PySide6 import QtCore
from onionshare_cli.onion import (
TorErrorInvalidSetting,

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import time
from PySide2 import QtCore, QtWidgets
from PySide6 import QtCore, QtWidgets
from onionshare_cli.onion import (
BundledTorCanceled,

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
import sys
import platform
import os
@ -579,7 +579,7 @@ class TorSettingsTab(QtWidgets.QWidget):
moat_dialog = MoatDialog(self.common, self.meek)
moat_dialog.got_bridges.connect(self.bridge_moat_got_bridges)
moat_dialog.exec_()
moat_dialog.exec()
def bridge_moat_got_bridges(self, bridges):
"""

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore
from PySide6 import QtCore
import datetime
import re
import socks

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PySide2 import QtCore, QtWidgets, QtGui
from PySide6 import QtCore, QtWidgets, QtGui
import qrcode
from . import strings
@ -52,7 +52,7 @@ class Alert(QtWidgets.QMessageBox):
self.setStandardButtons(buttons)
if autostart:
self.exec_()
self.exec()
class AddFileDialog(QtWidgets.QFileDialog):
@ -71,10 +71,10 @@ class AddFileDialog(QtWidgets.QFileDialog):
self.common = common
self.common.log("AddFileDialog", "__init__")
self.setOption(self.DontUseNativeDialog, True)
self.setOption(self.ReadOnly, True)
self.setOption(self.ShowDirsOnly, False)
self.setFileMode(self.ExistingFiles)
self.setOption(self.Option.DontUseNativeDialog, True)
self.setOption(self.Option.ReadOnly, True)
self.setOption(self.Option.ShowDirsOnly, False)
self.setFileMode(self.FileMode.ExistingFiles)
tree_view = self.findChild(QtWidgets.QTreeView)
tree_view.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
list_view = self.findChild(QtWidgets.QListView, "listView")
@ -101,7 +101,7 @@ class Image(qrcode.image.base.BaseImage):
A custom Image class, for use with the QR Code pixmap.
"""
def __init__(self, border, width, box_size):
def __init__(self, border, width, box_size, *args, **kwargs):
self.border = border
self.width = width
self.box_size = box_size
@ -153,4 +153,4 @@ class QRCodeDialog(QtWidgets.QDialog):
layout.addWidget(self.qr_label_title)
layout.addWidget(self.qr_label)
self.exec_()
self.exec()

2361
desktop/poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,11 +6,12 @@ authors = ["Micah Lee <micah@micahflee.com>"]
license = "GPLv3+"
[tool.poetry.dependencies]
python = ">=3.7,<3.11"
python = ">=3.8,<3.11"
onionshare_cli = {path = "../cli", develop = true}
PySide2 = "5.15.2.1"
PySide6 = "6.4.0"
qrcode = "*"
werkzeug = "~2.0.3"
python-gnupg = "^0.5.0"
[tool.poetry.dev-dependencies]
click = "*"
@ -19,6 +20,7 @@ pytest = ">=7.2.0"
pytest-faulthandler = "*"
pytest-qt = ">=4.2.0"
cx_freeze = "*"
importlib-metadata = "*"
[build-system]
requires = ["poetry-core>=1.0.0"]

View File

@ -63,7 +63,7 @@ def main():
@main.command()
def cleanup_build():
"""Delete unused PySide2 stuff to save space"""
"""Delete unused PySide6 stuff to save space"""
app_path = get_app_path()
before_size = get_size(app_path)
@ -74,24 +74,18 @@ def cleanup_build():
"QtQuickParticles",
"QtRemoteObjects",
"Qt3DInput",
"QtPdfWidgets",
"QtScriptTools",
"QtNetworkAuth",
"QtDataVisualization",
"QtWebEngineCore",
"Qt3DQuickRender",
"Qt3DQuickExtras",
"QtQuick3DRender",
"QtDesigner",
"QtNfc",
"QtQuick3DAssetImport",
"QtBodymovin",
"QtWebEngineWidgets",
"QtQuickWidgets",
"Qt3DQuickInput",
"Qt3DQuickScene2D",
"QtUiPlugin",
"QtPdf",
"Qt3DRender",
"QtQuick3DRuntimeRender",
"QtHelp",
@ -100,13 +94,10 @@ def cleanup_build():
"QtWebSockets",
"QtQuick3DUtils",
"QtQuickTemplates2",
"QtScript",
"QtPositioningQuick",
"Qt3DCore",
"QtLocation",
"QtXml",
"QtSerialPort",
"QtWebView",
"QtQuick",
"QtScxml",
"QtQml",
@ -115,9 +106,7 @@ def cleanup_build():
"QtMultimedia",
"QtQmlWorkerScript",
"QtVirtualKeyboard",
"QtPurchasing",
"QtOpenGL",
"QtWebEngine",
"Qt3DQuick",
"QtTest",
"QtPositioning",
@ -127,7 +116,6 @@ def cleanup_build():
"QtQuickShapes",
"QtQuickTest",
"QtNetwork",
"QtXmlPatterns",
"QtSvg",
"QtDesignerComponents",
"QtMultimediaWidgets",
@ -135,27 +123,58 @@ def cleanup_build():
"Qt3DQuickAnimation",
"QtSensors",
"Qt3DAnimation",
"QtRepParser",
"QtTextToSpeech",
"QtGamepad",
"QtSerialBus",
"QtSql",
"QtConcurrent"
"QtConcurrent",
"QtChartsQml",
"QtDataVisualizationQml",
"QtLabsAnimation",
"QtLabsFolderListModel",
"QtLabsQmlModels",
"QtLabsSettings",
"QtLabsSharedImage",
"QtLabsWavefrontMesh",
"QtOpenGLWidgets",
"QtQmlCore",
"QtQmlLocalStorage",
"QtQmlXmlListModel",
"QtQuick3DAssetUtils",
"QtQuick3DEffects",
"QtQuick3DGlslParser",
"QtQuick3DHelpers",
"QtQuick3DIblBaker",
"QtQuick3DParticleEffects",
"QtQuick3DParticles",
"QtQuickControls2Impl",
"QtQuickDialogs2",
"QtQuickDialogs2QuickImpl",
"QtQuickDialogs2Utils",
"QtQuickLayouts",
"QtQuickTimeline",
"QtRemoteObjectsQml",
"QtScxmlQml",
"QtSensorsQuick",
"QtShaderTools",
"QtStateMachine",
"QtStateMachineQml",
"QtSvgWidgets",
"QtUiTools",
"QtWebEngineQuick",
"QtWebEngineQuickDelegatesQml"
]:
shutil.rmtree(
f"{app_path}/Contents/MacOS/lib/PySide2/Qt/lib/{framework}.framework"
f"{app_path}/Contents/MacOS/lib/PySide6/Qt/lib/{framework}.framework"
)
print(
f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/Qt/lib/{framework}.framework"
f"Deleted: {app_path}/Contents/MacOS/lib/PySide6/Qt/lib/{framework}.framework"
)
try:
os.remove(f"{app_path}/Contents/MacOS/lib/PySide2/{framework}.abi3.so")
print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/{framework}.abi3.so")
os.remove(f"{app_path}/Contents/MacOS/lib/PySide6/{framework}.abi3.so")
print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide6/{framework}.abi3.so")
except FileNotFoundError:
pass
try:
os.remove(f"{app_path}/Contents/MacOS/lib/PySide2/{framework}.pyi")
print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/{framework}.pyi")
os.remove(f"{app_path}/Contents/MacOS/lib/PySide6/{framework}.pyi")
print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide6/{framework}.pyi")
except FileNotFoundError:
pass
@ -176,28 +195,31 @@ def cleanup_build():
# Move frameworks from Resources/lib into Frameworks
os.makedirs(f"{app_path}/Contents/Frameworks", exist_ok=True)
for framework_filename in glob.glob(
f"{app_path}/Contents/Resources/lib/PySide2/Qt/lib/Qt*.framework"
f"{app_path}/Contents/Resources/lib/PySide6/Qt/lib/Qt*.framework"
):
basename = os.path.basename(framework_filename)
os.rename(framework_filename, f"{app_path}/Contents/Frameworks/{basename}")
run(
["ln", "-s", f"../../../../../Frameworks/{basename}"],
cwd=f"{app_path}/Contents/Resources/lib/PySide2/Qt/lib",
cwd=f"{app_path}/Contents/Resources/lib/PySide6/Qt/lib",
)
if os.path.exists(f"{app_path}/Contents/Frameworks/{basename}/Resources"):
if not os.path.exists(f"{app_path}/Contents/Frameworks/{basename}/Versions/A/Resources"):
os.rename(
f"{app_path}/Contents/Frameworks/{basename}/Resources",
f"{app_path}/Contents/Frameworks/{basename}/Versions/5/Resources",
f"{app_path}/Contents/Frameworks/{basename}/Versions/A/Resources",
)
else:
shutil.rmtree(f"{app_path}/Contents/Frameworks/{basename}/Resources")
run(
["ln", "-s", "Versions/5/Resources"],
["ln", "-s", "Versions/A/Resources"],
cwd=f"{app_path}/Contents/Frameworks/{basename}",
)
try:
run(
["ln", "-s", "5", "Current"],
["ln", "-s", "A", "Current"],
cwd=f"{app_path}/Contents/Frameworks/{basename}/Versions",
)
except:
@ -205,27 +227,49 @@ def cleanup_build():
# Move Qt plugins
os.rename(
f"{app_path}/Contents/Resources/lib/PySide2/Qt/plugins",
f"{app_path}/Contents/Resources/lib/PySide6/Qt/plugins",
f"{app_path}/Contents/Frameworks/plugins",
)
run(
["ln", "-s", "../../../../Frameworks/plugins"],
cwd=f"{app_path}/Contents/Resources/lib/PySide2/Qt",
cwd=f"{app_path}/Contents/Resources/lib/PySide6/Qt",
)
print("> Delete more unused PySide2 stuff to save space")
print("> Delete more unused PySide6 stuff to save space")
for filename in [
f"{app_path}/Contents/Resources/lib/PySide2/Designer.app",
f"{app_path}/Contents/Resources/lib/PySide2/examples",
f"{app_path}/Contents/Resources/lib/PySide2/glue",
f"{app_path}/Contents/Resources/lib/PySide2/include",
f"{app_path}/Contents/Resources/lib/PySide2/pyside2-lupdate",
f"{app_path}/Contents/Resources/lib/PySide2/rcc",
f"{app_path}/Contents/Resources/lib/PySide2/uic",
f"{app_path}/Contents/Resources/lib/PySide2/libpyside2.abi3.5.15.dylib",
f"{app_path}/Contents/Resources/lib/PySide2/Qt/qml",
f"{app_path}/Contents/Resources/lib/shiboken2/libshiboken2.abi3.5.15.dylib",
f"{app_path}/Contents/Resources/lib/shiboken2/docs",
f"{app_path}/Contents/Resources/lib/PySide6/Designer.app",
f"{app_path}/Contents/Resources/lib/PySide6/examples",
f"{app_path}/Contents/Resources/lib/PySide6/glue",
f"{app_path}/Contents/Resources/lib/PySide6/include",
f"{app_path}/Contents/Resources/lib/PySide6/lupdate",
f"{app_path}/Contents/Resources/lib/PySide6/libpyside6.abi3.6.4.dylib",
f"{app_path}/Contents/Resources/lib/PySide6/Qt/qml",
f"{app_path}/Contents/Resources/lib/shiboken6/libshiboken6.abi3.6.4.dylib",
f"{app_path}/Contents/Resources/lib/PySide6/Assistant.app",
f"{app_path}/Contents/Resources/lib/PySide6/Linguist.app",
f"{app_path}/Contents/Resources/lib/PySide6/libpyside6qml.abi3.6.4.dylib",
f"{app_path}/Contents/Resources/lib/PySide6/lrelease",
f"{app_path}/Contents/Resources/lib/PySide6/qmlformat",
f"{app_path}/Contents/Resources/lib/PySide6/qmllint",
f"{app_path}/Contents/Resources/lib/PySide6/qmlls",
f"{app_path}/Contents/MacOS/QtBluetooth",
f"{app_path}/Contents/MacOS/QtConcurrent",
f"{app_path}/Contents/MacOS/QtDesigner",
f"{app_path}/Contents/MacOS/QtNetworkAuth",
f"{app_path}/Contents/MacOS/QtNfc",
f"{app_path}/Contents/MacOS/QtOpenGL",
f"{app_path}/Contents/MacOS/QtOpenGLWidgets",
f"{app_path}/Contents/MacOS/QtPositioning",
f"{app_path}/Contents/MacOS/QtQuick3D",
f"{app_path}/Contents/MacOS/QtQuick3DRuntimeRender",
f"{app_path}/Contents/MacOS/QtQuick3DUtils",
f"{app_path}/Contents/MacOS/QtShaderTools",
f"{app_path}/Contents/MacOS/QtStateMachine",
f"{app_path}/Contents/MacOS/QtSvgWidgets",
f"{app_path}/Contents/MacOS/QtWebChannel",
f"{app_path}/Contents/MacOS/QtWebEngineCore",
f"{app_path}/Contents/MacOS/QtWebEngineQuick",
f"{app_path}/Contents/MacOS/QtXml",
]:
if os.path.isfile(filename) or os.path.islink(filename):
os.remove(filename)
@ -250,11 +294,10 @@ def codesign(app_path):
glob.glob(f"{app_path}/Contents/Resources/lib/**/*.so", recursive=True),
glob.glob(f"{app_path}/Contents/Resources/lib/**/*.dylib", recursive=True),
[
f"{app_path}/Contents/Frameworks/QtCore.framework/Versions/5/QtCore",
f"{app_path}/Contents/Frameworks/QtDBus.framework/Versions/5/QtDBus",
f"{app_path}/Contents/Frameworks/QtGui.framework/Versions/5/QtGui",
f"{app_path}/Contents/Frameworks/QtMacExtras.framework/Versions/5/QtMacExtras",
f"{app_path}/Contents/Frameworks/QtWidgets.framework/Versions/5/QtWidgets",
f"{app_path}/Contents/Frameworks/QtCore.framework/Versions/A/QtCore",
f"{app_path}/Contents/Frameworks/QtDBus.framework/Versions/A/QtDBus",
f"{app_path}/Contents/Frameworks/QtGui.framework/Versions/A/QtGui",
f"{app_path}/Contents/Frameworks/QtWidgets.framework/Versions/A/QtWidgets",
f"{app_path}/Contents/Resources/lib/Python",
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/meek-client",
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/obfs4proxy",

View File

@ -1,9 +1,23 @@
#!/bin/bash
MEEK_TAG=v0.37.0
OS=$(uname -s)
mkdir -p ./build/meek
cd ./build/meek
git clone https://git.torproject.org/pluggable-transports/meek.git
git clone https://git.torproject.org/pluggable-transports/meek.git || echo "already cloned"
cd meek
git checkout $MEEK_TAG
go build -o ../../../onionshare/resources/tor/meek-client ./meek-client
if [ "$OS" == "Darwin" ]; then
if [[ $(uname -m) == 'arm64' ]]; then
go build -o ../../../onionshare/resources/tor/meek-client-arm64 ./meek-client
GOOS=darwin GOARCH=amd64 go build -o ../../../onionshare/resources/tor/meek-client-amd64 ./meek-client
lipo -create -output ../../../onionshare/resources/tor/meek-client ../../../onionshare/resources/tor/meek-client-arm64 ../../../onionshare/resources/tor/meek-client-amd64
rm ../../../onionshare/resources/tor/meek-client-arm64 ../../../onionshare/resources/tor/meek-client-amd64
elif [[ $(uname -m) == 'x86_64' ]]; then
go build -o ../../../onionshare/resources/tor/meek-client ./meek-client
fi
else
go build -o ../../../onionshare/resources/tor/meek-client ./meek-client
fi

View File

@ -1,9 +1,22 @@
#!/bin/bash
OBFS4PROXY_TAG=obfs4proxy-0.0.14
OS=$(uname -s)
mkdir -p ./build/obfs4proxy
cd ./build/obfs4proxy
git clone https://gitlab.com/yawning/obfs4 || echo "already cloned"
cd obfs4
git checkout $OBFS4PROXY_TAG
go build -o ../../../onionshare/resources/tor/obfs4proxy ./obfs4proxy
if [ "$OS" == "Darwin" ]; then
if [[ $(uname -m) == 'arm64' ]]; then
go build -o ../../../onionshare/resources/tor/obfs4proxy-arm64 ./obfs4proxy
GOOS=darwin GOARCH=amd64 go build -o ../../../onionshare/resources/tor/obfs4proxy-amd64 ./obfs4proxy
lipo -create -output ../../../onionshare/resources/tor/obfs4proxy ../../../onionshare/resources/tor/obfs4proxy-arm64 ../../../onionshare/resources/tor/obfs4proxy-amd64
rm ../../../onionshare/resources/tor/obfs4proxy-arm64 ../../../onionshare/resources/tor/obfs4proxy-amd64
elif [[ $(uname -m) == 'x86_64' ]]; then
go build -o ../../../onionshare/resources/tor/obfs4proxy ./obfs4proxy
fi
else
go build -o ../../../onionshare/resources/tor/obfs4proxy ./obfs4proxy
fi

View File

@ -1,9 +1,22 @@
#!/bin/bash
SNOWFLAKE_TAG=v2.3.1
OS=$(uname -s)
mkdir -p ./build/snowflake
cd ./build/snowflake
git clone https://git.torproject.org/pluggable-transports/snowflake.git
git clone https://git.torproject.org/pluggable-transports/snowflake.git || echo "already cloned"
cd snowflake
git checkout $SNOWFLAKE_TAG
go build -o ../../../onionshare/resources/tor/snowflake-client ./client
if [ "$OS" == "Darwin" ]; then
if [[ $(uname -m) == 'arm64' ]]; then
go build -o ../../../onionshare/resources/tor/snowflake-client-arm64 ./client
GOOS=darwin GOARCH=amd64 go build -o ../../../onionshare/resources/tor/snowflake-client-amd64 ./client
lipo -create -output ../../../onionshare/resources/tor/snowflake-client ../../../onionshare/resources/tor/snowflake-client-arm64 ../../../onionshare/resources/tor/snowflake-client-amd64
rm ../../../onionshare/resources/tor/snowflake-client-arm64 ../../../onionshare/resources/tor/snowflake-client-amd64
elif [[ $(uname -m) == 'x86_64' ]]; then
go build -o ../../../onionshare/resources/tor/snowflake-client ./client
fi
else
go build -o ../../../onionshare/resources/tor/snowflake-client ./client
fi

View File

@ -8,6 +8,7 @@ import shutil
import subprocess
import uuid
import xml.etree.ElementTree as ET
from glob import glob
root = os.path.dirname(
os.path.dirname(
@ -17,14 +18,6 @@ root = os.path.dirname(
desktop_dir = os.path.join(root, "desktop")
def get_build_path():
if "64 bit" in sys.version:
python_arch = "win-amd64"
else:
python_arch = "win32"
return os.path.join(desktop_dir, "build", f"exe.{python_arch}-3.9")
def get_size(dir):
size = 0
for path, dirs, files in os.walk(dir):
@ -327,244 +320,58 @@ def main():
@main.command()
def cleanup_build():
"""Delete unused PySide2 stuff to save space"""
build_path = get_build_path()
"""Delete unused PySide6 stuff to save space"""
build_path = os.path.join(desktop_dir, "build", "exe.win-amd64-3.10")
before_size = get_size(build_path)
for dirname in ["examples", "qml"]:
shutil.rmtree(os.path.join(build_path, "lib", "PySide2", dirname))
for filename in [
"lconvert.exe",
"linguist.exe",
"lrelease.exe",
"lupdate.exe",
"plugins/assetimporters/assimp.dll",
"plugins/assetimporters/uip.dll",
"plugins/audio/qtaudio_wasapi.dll",
"plugins/audio/qtaudio_windows.dll",
"plugins/bearer/qgenericbearer.dll",
"plugins/canbus/qtpassthrucanbus.dll",
"plugins/canbus/qtpeakcanbus.dll",
"plugins/canbus/qtsysteccanbus.dll",
"plugins/canbus/qttinycanbus.dll",
"plugins/canbus/qtvectorcanbus.dll",
"plugins/canbus/qtvirtualcanbus.dll",
"plugins/gamepads/xinputgamepad.dll",
"plugins/generic/qtuiotouchplugin.dll",
"plugins/geometryloaders/defaultgeometryloader.dll",
"plugins/geometryloaders/gltfgeometryloader.dll",
"plugins/geoservices/qtgeoservices_esri.dll",
"plugins/geoservices/qtgeoservices_itemsoverlay.dll",
"plugins/geoservices/qtgeoservices_mapbox.dll",
"plugins/geoservices/qtgeoservices_nokia.dll",
"plugins/geoservices/qtgeoservices_osm.dll",
"plugins/mediaservice/dsengine.dll",
"plugins/mediaservice/qtmedia_audioengine.dll",
"plugins/mediaservice/wmfengine.dll",
"plugins/platforminputcontexts/qtvirtualkeyboardplugin.dll",
"plugins/platforms/qdirect2d.dll",
"plugins/platforms/qoffscreen.dll",
"plugins/platforms/qwebgl.dll",
"plugins/platformthemes/qxdgdesktopportal.dll",
"plugins/playlistformats/qtmultimedia_m3u.dll",
"plugins/position/qtposition_positionpoll.dll",
"plugins/position/qtposition_serialnmea.dll",
"plugins/position/qtposition_winrt.dll",
"plugins/printsupport/windowsprintersupport.dll",
"plugins/qmltooling/qmldbg_debugger.dll",
"plugins/qmltooling/qmldbg_inspector.dll",
"plugins/qmltooling/qmldbg_local.dll",
"plugins/qmltooling/qmldbg_messages.dll",
"plugins/qmltooling/qmldbg_native.dll",
"plugins/qmltooling/qmldbg_nativedebugger.dll",
"plugins/qmltooling/qmldbg_preview.dll",
"plugins/qmltooling/qmldbg_profiler.dll",
"plugins/qmltooling/qmldbg_quickprofiler.dll",
"plugins/qmltooling/qmldbg_server.dll",
"plugins/qmltooling/qmldbg_tcp.dll",
"plugins/renderers/openglrenderer.dll",
"plugins/renderplugins/scene2d.dll",
"plugins/scenegraph/qsgd3d12backend.dll",
"plugins/sceneparsers/gltfsceneexport.dll",
"plugins/sceneparsers/gltfsceneimport.dll",
"plugins/sensorgestures/qtsensorgestures_plugin.dll",
"plugins/sensorgestures/qtsensorgestures_shakeplugin.dll",
"plugins/sensors/qtsensors_generic.dll",
"plugins/sqldrivers/qsqlite.dll",
"plugins/sqldrivers/qsqlodbc.dll",
"plugins/sqldrivers/qsqlpsql.dll",
"plugins/styles/qwindowsvistastyle.dll",
"plugins/texttospeech/qtexttospeech_sapi.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_hangul.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_openwnn.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_pinyin.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_tcime.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_thai.dll",
"plugins/webview/qtwebview_webengine.dll",
"pyside2-lupdate.exe",
"Qt3DAnimation.pyd",
"Qt3DAnimation.pyi",
"Qt3DCore.pyd",
"Qt3DCore.pyi",
"Qt3DExtras.pyd",
"Qt3DExtras.pyi",
"Qt3DInput.pyd",
"Qt3DInput.pyi",
"Qt3DLogic.pyd",
"Qt3DLogic.pyi",
"Qt3DRender.pyd",
"Qt3DRender.pyi",
"Qt53DAnimation.dll",
"Qt53DCore.dll",
"Qt53DExtras.dll",
"Qt53DInput.dll",
"Qt53DLogic.dll",
"Qt53DQuick.dll",
"Qt53DQuickAnimation.dll",
"Qt53DQuickExtras.dll",
"Qt53DQuickInput.dll",
"Qt53DQuickRender.dll",
"Qt53DQuickScene2D.dll",
"Qt53DRender.dll",
"Qt5Bluetooth.dll",
"Qt5Bodymovin.dll",
"Qt5Charts.dll",
"Qt5Concurrent.dll",
"Qt5DataVisualization.dll",
"Qt5DBus.dll",
"Qt5Designer.dll",
"Qt5DesignerComponents.dll",
"Qt5Gamepad.dll",
"Qt5Help.dll",
"Qt5Location.dll",
"Qt5Multimedia.dll",
"Qt5MultimediaQuick.dll",
"Qt5MultimediaWidgets.dll",
"Qt5Nfc.dll",
"Qt5OpenGL.dll",
"Qt5Pdf.dll",
"Qt5PdfWidgets.dll",
"Qt5Positioning.dll",
"Qt5PositioningQuick.dll",
"Qt5PrintSupport.dll",
"Qt5Purchasing.dll",
"Qt5Quick.dll",
"Qt5Quick3D.dll",
"Qt5Quick3DAssetImport.dll",
"Qt5Quick3DRender.dll",
"Qt5Quick3DRuntimeRender.dll",
"Qt5Quick3DUtils.dll",
"Qt5QuickControls2.dll",
"Qt5QuickParticles.dll",
"Qt5QuickShapes.dll",
"Qt5QuickTemplates2.dll",
"Qt5QuickTest.dll",
"Qt5QuickWidgets.dll",
"Qt5RemoteObjects.dll",
"Qt5Script.dll",
"Qt5ScriptTools.dll",
"Qt5Scxml.dll",
"Qt5Sensors.dll",
"Qt5SerialBus.dll",
"Qt5SerialPort.dll",
"Qt5Sql.dll",
"Qt5Svg.dll",
"Qt5Test.dll",
"Qt5TextToSpeech.dll",
"Qt5VirtualKeyboard.dll",
"Qt5WebChannel.dll",
"Qt5WebEngine.dll",
"Qt5WebEngineCore.dll",
"Qt5WebEngineWidgets.dll",
"Qt5WebSockets.dll",
"Qt5WebView.dll",
"Qt5Xml.dll",
"Qt5XmlPatterns.dll",
"QtAxContainer.pyd",
"QtAxContainer.pyi",
"QtCharts.pyd",
"QtCharts.pyi",
"QtConcurrent.pyd",
"QtConcurrent.pyi",
"QtDataVisualization.pyd",
"QtDataVisualization.pyi",
"qtdiag.exe",
"QtHelp.pyd",
"QtHelp.pyi",
"QtLocation.pyd",
"QtLocation.pyi",
"QtMultimedia.pyd",
"QtMultimedia.pyi",
"QtMultimediaWidgets.pyd",
"QtMultimediaWidgets.pyi",
"QtNetwork.pyd",
"QtNetwork.pyi",
"QtOpenGL.pyd",
"QtOpenGL.pyi",
"QtOpenGLFunctions.pyd",
"QtOpenGLFunctions.pyi",
"QtPositioning.pyd",
"QtPositioning.pyi",
"QtPrintSupport.pyd",
"QtPrintSupport.pyi",
"QtQml.pyd",
"QtQml.pyi",
"QtQuick.pyd",
"QtQuick.pyi",
"QtQuickControls2.pyd",
"QtQuickControls2.pyi",
"QtQuickWidgets.pyd",
"QtQuickWidgets.pyi",
"QtRemoteObjects.pyd",
"QtRemoteObjects.pyi",
"QtScript.pyd",
"QtScript.pyi",
"QtScriptTools.pyd",
"QtScriptTools.pyi",
"QtScxml.pyd",
"QtScxml.pyi",
"QtSensors.pyd",
"QtSensors.pyi",
"QtSerialPort.pyd",
"QtSerialPort.pyi",
"QtSql.pyd",
"QtSql.pyi",
"QtSvg.pyd",
"QtSvg.pyi",
"QtTest.pyd",
"QtTest.pyi",
"QtTextToSpeech.pyd",
"QtTextToSpeech.pyi",
"QtUiTools.pyd",
"QtUiTools.pyi",
"QtWebChannel.pyd",
"QtWebChannel.pyi",
"QtWebEngine.pyd",
"QtWebEngine.pyi",
"QtWebEngineCore.pyd",
"QtWebEngineCore.pyi",
"QtWebEngineProcess.exe",
"QtWebEngineWidgets.pyd",
"QtWebEngineWidgets.pyi",
"QtWebSockets.pyd",
"QtWebSockets.pyi",
"QtWinExtras.pyd",
"QtWinExtras.pyi",
"QtXml.pyd",
"QtXml.pyi",
"QtXmlPatterns.pyd",
"QtXmlPatterns.pyi",
"rcc.exe",
"uic.exe",
shutil.rmtree(os.path.join(build_path, "lib", "PySide6", dirname))
for dirname in [
"assetimporters",
"designer",
"generic",
"geometryloaders",
"platforminputcontexts",
"position",
"qmltooling",
"renderers",
"renderplugins",
"sceneparsers",
"scxmldatamodel",
"sensors",
"sqldrivers",
"styles",
]:
os.remove(
os.path.join(
build_path,
"lib",
"PySide2",
filename.replace("/", "\\"),
)
)
shutil.rmtree(os.path.join(build_path, "lib", "PySide6", "plugins", dirname))
for filename in (
glob(os.path.join(build_path, "lib", "PySide6", "*.exe"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt3D*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt63D*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Bluetooth.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Charts*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Concurrent.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6DataVisualization*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Bus.dll"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Designer*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Help.dll"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Labs*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Multimedia*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Nfc.dll"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6OpenGL*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Qml*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Quick*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6RemoteObjects*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Scxml*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Sensors*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6SerialPort.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6ShaderTools.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Sql.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6StateMachine*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Test.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6VirtualKeyboard.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Web*"))
):
os.remove(filename)
after_size = get_size(build_path)
freed_bytes = before_size - after_size
@ -573,18 +380,13 @@ def cleanup_build():
@main.command()
@click.argument("win32_path")
@click.argument("win64_path")
def codesign(win32_path, win64_path):
@click.argument("path")
def codesign(path):
"""Sign Windows binaries before packaging"""
paths = [win32_path, win64_path]
for path in paths:
if not os.path.isdir(path):
click.echo("Invalid build path")
return
for path in paths:
sign(os.path.join(path, "onionshare.exe"))
sign(os.path.join(path, "onionshare-cli.exe"))
sign(
@ -620,9 +422,8 @@ def codesign(win32_path, win64_path):
@main.command()
@click.argument("win32_path")
@click.argument("win64_path")
def package(win32_path, win64_path):
@click.argument("path")
def package(path):
"""Build the MSI package"""
version_filename = os.path.join(
root, "cli", "onionshare_cli", "resources", "version.txt"
@ -631,12 +432,7 @@ def package(win32_path, win64_path):
version = f.read().strip()
msi_package(
win32_path,
os.path.join(desktop_dir, "dist", f"OnionShare-win32-{version}.msi"),
"12b9695c-965b-4be0-bc33-21274e809576",
)
msi_package(
win64_path,
path,
os.path.join(desktop_dir, "dist", f"OnionShare-win64-{version}.msi"),
"ed7f9243-3528-4b4a-b85c-9943982e75eb",
)

View File

@ -8,30 +8,13 @@ import shutil
import subprocess
import requests
import click
import tempfile
import gnupg
torbrowser_version = "12.0"
expected_win32_sha256 = (
"a9cc0f0af2ce8ca0d7a27d65c7efa37f6419cfc793fa80371e7db73d44b4cc02"
torbrowser_latest_url = (
"https://aus1.torproject.org/torbrowser/update_3/release/downloads.json"
)
expected_win64_sha256 = (
"f496cc0219c8b73f1f100124d6514bad55f503ff76202747f23620a6677e83c2"
)
expected_macos_sha256 = (
"11c8360187356e6c0837612a320f1a117303fc449602c9fd73f4faf9f9bbcfc9"
)
expected_linux64_sha256 = (
"850ce601d815bac63e4f5937646d2b497173be28b27b30a7526ebb946a459874"
)
win32_filename = f"torbrowser-install-{torbrowser_version}_ALL.exe"
win32_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/{win32_filename}"
win64_filename = f"torbrowser-install-win64-{torbrowser_version}_ALL.exe"
win64_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/{win64_filename}"
macos_filename = f"TorBrowser-{torbrowser_version}-macos_ALL.dmg"
macos_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/{macos_filename}"
linux64_filename = f"tor-browser-linux64-{torbrowser_version}_ALL.tar.xz"
linux64_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/{linux64_filename}"
tor_dev_fingerprint = "EF6E286DDA85EA2A4BA7DE684E2C6E8793298290"
# Common paths
root_path = os.path.dirname(
@ -40,27 +23,25 @@ root_path = os.path.dirname(
working_path = os.path.join(root_path, "build", "tor")
def get_tor_windows(platform):
if platform == "win32":
win_url = win32_url
win_filename = win32_filename
expected_win_sha256 = expected_win32_sha256
bin_filenames = [
"tor.exe"
]
elif platform == "win64":
win_url = win64_url
win_filename = win64_filename
expected_win_sha256 = expected_win64_sha256
bin_filenames = [
"tor.exe"
]
else:
click.echo("invalid platform")
return
def get_latest_tor_version_urls(platform):
r = requests.get(torbrowser_latest_url)
if r.status_code != 200 or platform not in r.json()["downloads"]:
print("Tor browser latest version url not working")
sys.exit(-1)
platform_url = r.json()["downloads"][platform]["ALL"]["binary"]
platform_sig_url = r.json()["downloads"][platform]["ALL"]["sig"]
platform_filename = platform_url.split("/")[-1]
return platform_url, platform_filename, platform_sig_url
def get_tor_windows(gpg, torkey, win_url, win_filename, expected_win_sig):
bin_filenames = ["tor.exe"]
# Build paths
win_path = os.path.join(working_path, win_filename)
win_sig_path = os.path.join(working_path, f"{win_filename}.asc")
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
# Make sure the working folder exists
@ -72,19 +53,22 @@ def get_tor_windows(platform):
print("Downloading {}".format(win_url))
r = requests.get(win_url)
open(win_path, "wb").write(r.content)
win_sha256 = hashlib.sha256(r.content).hexdigest()
else:
print("Already downloaded: {}".format(win_path))
win_data = open(win_path, "rb").read()
win_sha256 = hashlib.sha256(win_data).hexdigest()
# Compare the hash
if win_sha256 != expected_win_sha256:
print("ERROR! The sha256 doesn't match:")
print("expected: {}".format(expected_win32_sha256))
print(" actual: {}".format(win_sha256))
# Make sure Tor Browser signature is downloaded
if not os.path.exists(win_sig_path):
print("Downloading {}".format(expected_win_sig))
r = requests.get(expected_win_sig)
open(win_sig_path, "wb").write(r.content)
# Verify the signature
sig_stream = open(win_sig_path, "rb")
verified = gpg.verify_file(sig_stream, win_path)
if not verified.valid or verified.pubkey_fingerprint != tor_dev_fingerprint:
print("ERROR! The tarball verification with the signature failed!")
sys.exit(-1)
print("Tor Browser verification successful!")
# Extract the bits we need from the exe
subprocess.Popen(
[
@ -126,12 +110,13 @@ def get_tor_windows(platform):
update_tor_bridges()
def get_tor_macos():
def get_tor_macos(gpg, torkey, macos_url, macos_filename, expected_macos_sig):
# Build paths
dmg_tor_path = os.path.join(
"/Volumes", "Tor Browser", "Tor Browser.app", "Contents"
)
dmg_path = os.path.join(working_path, macos_filename)
dmg_sig_path = os.path.join(working_path, f"{macos_filename}.asc")
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
if not os.path.exists(dist_path):
os.makedirs(dist_path, exist_ok=True)
@ -145,18 +130,22 @@ def get_tor_macos():
print("Downloading {}".format(macos_url))
r = requests.get(macos_url)
open(dmg_path, "wb").write(r.content)
dmg_sha256 = hashlib.sha256(r.content).hexdigest()
else:
dmg_data = open(dmg_path, "rb").read()
dmg_sha256 = hashlib.sha256(dmg_data).hexdigest()
# Compare the hash
if dmg_sha256 != expected_macos_sha256:
print("ERROR! The sha256 doesn't match:")
print("expected: {}".format(expected_macos_sha256))
print(" actual: {}".format(dmg_sha256))
# Make sure the signature is downloaded
if not os.path.exists(dmg_sig_path):
print("Downloading {}".format(expected_macos_sig))
r = requests.get(expected_macos_sig)
open(dmg_sig_path, "wb").write(r.content)
# Verify the signature
sig_stream = open(dmg_sig_path, "rb")
verified = gpg.verify_file(sig_stream, dmg_path)
if not verified.valid or verified.pubkey_fingerprint != tor_dev_fingerprint:
print("ERROR! The tarball verification with the signature failed!")
sys.exit(-1)
print("Tor Browser verification successful!")
# Mount the dmg, copy data to the working path
subprocess.call(["hdiutil", "attach", dmg_path])
@ -186,9 +175,10 @@ def get_tor_macos():
update_tor_bridges()
def get_tor_linux64():
def get_tor_linux64(gpg, torkey, linux64_url, linux64_filename, expected_linux64_sig):
# Build paths
tarball_path = os.path.join(working_path, linux64_filename)
tarball_sig_path = os.path.join(working_path, f"{linux64_filename}.asc")
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
# Make sure dirs exist
@ -203,25 +193,29 @@ def get_tor_linux64():
print("Downloading {}".format(linux64_url))
r = requests.get(linux64_url)
open(tarball_path, "wb").write(r.content)
tarball_sha256 = hashlib.sha256(r.content).hexdigest()
else:
tarball_data = open(tarball_path, "rb").read()
tarball_sha256 = hashlib.sha256(tarball_data).hexdigest()
# Compare the hash
if tarball_sha256 != expected_linux64_sha256:
print("ERROR! The sha256 doesn't match:")
print("expected: {}".format(expected_linux64_sha256))
print(" actual: {}".format(tarball_sha256))
# Make sure the signature file is downloaded
if not os.path.exists(tarball_sig_path):
print("Downloading {}".format(expected_linux64_sig))
r = requests.get(expected_linux64_sig)
open(tarball_sig_path, "wb").write(r.content)
# Verify signature
sig_stream = open(tarball_sig_path, "rb")
verified = gpg.verify_file(sig_stream, tarball_path)
if not verified.valid or verified.pubkey_fingerprint != tor_dev_fingerprint:
print("ERROR! The tarball verification with the signature failed!")
sys.exit(-1)
print("Tor Browser verification successful!")
# Delete extracted tarball, if it's there
shutil.rmtree(os.path.join(working_path, "tor-browser_en-US"), ignore_errors=True)
shutil.rmtree(os.path.join(working_path, "tor-browser"), ignore_errors=True)
# Extract the tarball
subprocess.call(["tar", "-xvf", tarball_path], cwd=working_path)
tarball_tor_path = os.path.join(
working_path, "tor-browser_en-US", "Browser", "TorBrowser"
working_path, "tor-browser", "Browser", "TorBrowser"
)
# Copy into dist
@ -321,17 +315,29 @@ def main(platform):
click.echo(f"platform must be one of: {valid_platforms}")
return
(
platform_url,
platform_filename,
expected_platform_sig,
) = get_latest_tor_version_urls(platform)
tmpdir = tempfile.TemporaryDirectory()
gpg = gnupg.GPG(gnupghome=tmpdir.name)
torkey = gpg.import_keys_file(os.path.join(root_path, "scripts", "kounek7zrdx745qydx6p59t9mqjpuhdf"))
print(f"Imported Tor GPG key: {torkey.fingerprints}")
if platform == "win32":
get_tor_windows(platform)
get_tor_windows(gpg, torkey, platform_url, platform_filename, expected_platform_sig)
elif platform == "win64":
get_tor_windows(platform)
get_tor_windows(gpg, torkey, platform_url, platform_filename, expected_platform_sig)
elif platform == "macos":
get_tor_macos()
get_tor_macos(gpg, torkey, platform_url, platform_filename, expected_platform_sig)
elif platform == "linux64":
get_tor_linux64()
get_tor_linux64(gpg, torkey, platform_url, platform_filename, expected_platform_sig)
else:
click.echo("invalid platform")
tmpdir.cleanup()
if __name__ == "__main__":
main()

Binary file not shown.

View File

@ -0,0 +1,43 @@
#!/usr/bin/env python3
import os, subprocess, sys
def main(argv):
if len(argv) != 2:
print("Usage: check-arch.py PATH_TO_APP", file = sys.stderr)
sys.exit(-1)
universal = []
silicon = []
intel = []
for d in os.walk(argv[1]):
ap = os.path.join(os.path.abspath('.'),d[0])
for f in os.listdir(ap):
fl = os.path.join(ap,f)
if os.path.isfile(fl):
a = subprocess.run(['file',fl], stdout = subprocess.PIPE)
b = a.stdout.decode('utf-8')
if 'binary' in b or 'executable' in b or 'library' in b:
arm64, x86 = False, False
if 'arm64' in b:
arm64 = True
if 'x86_64' in b:
x86 = True
if arm64 and x86:
universal += [fl]
elif arm64:
silicon += [fl]
elif x86:
intel += [fl]
with open('macos-check-arch.log', 'w') as fout:
fout.write('-*- Universal -*-\n')
for p in universal:
fout.write(p+'\n')
fout.write('\n-*- Silicon -*-\n')
for p in silicon:
fout.write(p+'\n')
fout.write('\n-*- Intel -*-\n')
for p in intel:
fout.write(p+'\n')
if __name__ == '__main__':
main(sys.argv)

View File

@ -26,85 +26,6 @@ import cx_Freeze
from cx_Freeze import setup, Executable
from setuptools import find_packages
# There's an obscure cx_Freeze bug that I'm hitting that's preventing the macOS
# package from getting built. This is some monkeypatching to fix it.
if platform.system() == "Darwin" or platform.system() == "Linux":
import importlib_metadata
import pathlib
from pathlib import Path
from tempfile import TemporaryDirectory
class CustomPackagePath(pathlib.PurePosixPath):
def __init__(self, filename):
self.long_filename = str(filename)
self.short_filename = "/".join(filename.as_posix().split("/")[-2:])
super(CustomPackagePath, self).__init__()
def read_text(self, encoding="utf-8"):
with self.locate().open(encoding=encoding) as stream:
return stream.read()
def read_binary(self):
with self.locate().open("rb") as stream:
return stream.read()
def locate(self):
return Path(self.long_filename)
def as_posix(self):
return self.short_filename
class DistributionCache(importlib_metadata.PathDistribution):
_cachedir = TemporaryDirectory(prefix="cxfreeze-")
@staticmethod
def at(path):
return DistributionCache(Path(path))
at.__doc__ = importlib_metadata.PathDistribution.at.__doc__
@classmethod
def from_name(cls, name):
distribution = super().from_name(name)
temp_dir = Path(cls._cachedir.name)
dist_dir = None
files = distribution.files or []
prep = importlib_metadata.Prepared(distribution.name)
normalized = prep.normalized
legacy_normalized = prep.legacy_normalized
for file in files:
# patch: the onionshare and onionshare_cli files are using absolute paths, which break everything
if name in ["onionshare", "onionshare_cli"]:
if ".dist-info" not in file.as_posix():
continue
file = CustomPackagePath(file)
if (
not file.match(f"{name}-*.dist-info/*")
and not file.match(f"{distribution.name}-*.dist-info/*")
and not file.match(f"{normalized}-*.dist-info/*")
and not file.match(f"{legacy_normalized}-*.dist-info/*")
):
continue
src_path = file.locate()
if not src_path.exists():
continue
dst_path = temp_dir / file.as_posix()
if dist_dir is None:
dist_dir = dst_path.parent
dist_dir.mkdir(exist_ok=True)
shutil.copy2(src_path, dst_path)
if dist_dir is None:
raise importlib_metadata.PackageNotFoundError(name)
return cls.at(dist_dir)
from_name.__doc__ = importlib_metadata.PathDistribution.from_name.__doc__
cx_Freeze.module.DistributionCache = DistributionCache
# Discover the version
with open(os.path.join("..", "cli", "onionshare_cli", "resources", "version.txt")) as f:
version = f.read().strip()
@ -123,20 +44,20 @@ if platform.system() == "Windows":
exec_icon = os.path.join("onionshare", "resources", "onionshare.ico")
elif platform.system() == "Darwin":
import PySide2
import shiboken2
import PySide6
import shiboken6
include_msvcr = False
gui_base = None
exec_icon = None
include_files += [
(
os.path.join(PySide2.__path__[0], "libpyside2.abi3.5.15.dylib"),
"libpyside2.abi3.5.15.dylib",
os.path.join(PySide6.__path__[0], "libpyside6.abi3.6.4.dylib"),
"libpyside6.abi3.6.4.dylib",
),
(
os.path.join(shiboken2.__path__[0], "libshiboken2.abi3.5.15.dylib"),
"libshiboken2.abi3.5.15.dylib",
os.path.join(shiboken6.__path__[0], "libshiboken6.abi3.6.4.dylib"),
"libshiboken6.abi3.6.4.dylib",
),
]
@ -170,53 +91,53 @@ setup(
"jinja2.ext",
"onionshare",
"onionshare_cli",
"PySide2",
"PySide2.QtCore",
"PySide2.QtGui",
"PySide2.QtWidgets",
"PySide6",
"PySide6.QtCore",
"PySide6.QtGui",
"PySide6.QtWidgets",
],
"excludes": [
"test",
"tkinter",
"PySide2.Qt3DAnimation",
"PySide2.Qt3DCore",
"PySide2.Qt3DExtras",
"PySide2.Qt3DInput",
"PySide2.Qt3DLogic",
"PySide2.Qt3DRender",
"PySide2.QtCharts",
"PySide2.QtConcurrent",
"PySide2.QtDataVisualization",
"PySide2.QtHelp",
"PySide2.QtLocation",
"PySide2.QtMultimedia",
"PySide2.QtMultimediaWidgets",
"PySide2.QtNetwork",
"PySide2.QtOpenGL",
"PySide2.QtOpenGLFunctions",
"PySide2.QtPositioning",
"PySide2.QtPrintSupport",
"PySide2.QtQml",
"PySide2.QtQuick",
"PySide2.QtQuickControls2",
"PySide2.QtQuickWidgets",
"PySide2.QtRemoteObjects",
"PySide2.QtScript",
"PySide2.QtScriptTools",
"PySide2.QtScxml",
"PySide2.QtSensors",
"PySide2.QtSerialPort",
"PySide2.QtSql",
"PySide2.QtTest",
"PySide2.QtTextToSpeech",
"PySide2.QtUiTools",
"PySide2.QtWebChannel",
"PySide2.QtWebEngine",
"PySide2.QtWebEngineCore",
"PySide2.QtWebEngineWidgets",
"PySide2.QtWebSockets",
"PySide2.QtXml",
"PySide2.QtXmlPatterns",
"PySide6.Qt3DAnimation",
"PySide6.Qt3DCore",
"PySide6.Qt3DExtras",
"PySide6.Qt3DInput",
"PySide6.Qt3DLogic",
"PySide6.Qt3DRender",
"PySide6.QtCharts",
"PySide6.QtConcurrent",
"PySide6.QtDataVisualization",
"PySide6.QtHelp",
"PySide6.QtLocation",
"PySide6.QtMultimedia",
"PySide6.QtMultimediaWidgets",
"PySide6.QtNetwork",
"PySide6.QtOpenGL",
"PySide6.QtOpenGLFunctions",
"PySide6.QtPositioning",
"PySide6.QtPrintSupport",
"PySide6.QtQml",
"PySide6.QtQuick",
"PySide6.QtQuickControls2",
"PySide6.QtQuickWidgets",
"PySide6.QtRemoteObjects",
"PySide6.QtScript",
"PySide6.QtScriptTools",
"PySide6.QtScxml",
"PySide6.QtSensors",
"PySide6.QtSerialPort",
"PySide6.QtSql",
"PySide6.QtTest",
"PySide6.QtTextToSpeech",
"PySide6.QtUiTools",
"PySide6.QtWebChannel",
"PySide6.QtWebEngine",
"PySide6.QtWebEngineCore",
"PySide6.QtWebEngineWidgets",
"PySide6.QtWebSockets",
"PySide6.QtXml",
"PySide6.QtXmlPatterns",
],
"include_files": include_files,
"include_msvcr": include_msvcr,

View File

@ -2,7 +2,7 @@ import sys
import os
from datetime import datetime, timedelta
from PySide2 import QtTest
from PySide6 import QtTest
# Force tests to look for resources in the source code tree
@ -19,7 +19,7 @@ def qWait(t, qtapp):
qtapp.processEvents()
# Monkeypatch qWait, because PySide2 doesn't have it
# Monkeypatch qWait, although PySide6 has it
# https://stackoverflow.com/questions/17960159/qwait-analogue-in-pyside
QtTest.QTest.qWait = qWait

View File

@ -7,7 +7,7 @@ import secrets
import platform
import sys
from PySide2 import QtCore, QtTest, QtWidgets
from PySide6 import QtCore, QtTest, QtWidgets
from onionshare_cli.common import Common

View File

@ -1,6 +1,6 @@
import requests
from PySide2 import QtTest
from PySide6 import QtTest
from .gui_base_test import GuiBaseTest

View File

@ -6,7 +6,7 @@ import shutil
import sys
from datetime import datetime, timedelta
from PySide2 import QtCore, QtTest
from PySide6 import QtCore, QtTest
from .gui_base_test import GuiBaseTest

View File

@ -3,7 +3,7 @@ import requests
import tempfile
import zipfile
from PySide2 import QtCore, QtTest
from PySide6 import QtCore, QtTest
from .gui_base_test import GuiBaseTest

View File

@ -1,6 +1,6 @@
import os
from PySide2 import QtCore, QtTest, QtWidgets
from PySide6 import QtCore, QtTest, QtWidgets
from .gui_base_test import GuiBaseTest

View File

@ -1,6 +1,6 @@
import requests
from PySide2 import QtTest
from PySide6 import QtTest
from .gui_base_test import GuiBaseTest

View File

@ -2,11 +2,11 @@
app-id: org.onionshare.OnionShare
command: onionshare
runtime: org.kde.Platform
runtime-version: "5.15-21.08"
runtime-version: "6.4"
sdk: org.kde.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.golang
- org.freedesktop.Sdk.Extension.llvm12
- org.freedesktop.Sdk.Extension.llvm15
separate-locales: false
finish-args:
- "--device=dri"
@ -22,33 +22,37 @@ cleanup:
- "/go"
- "/bin/scripts"
modules:
- name: pyside2
buildsystem: cmake-ninja
builddir: true
build-options:
prepend-path: /usr/lib/sdk/llvm12/bin
prepend-ld-library-path: /usr/lib/sdk/llvm12/lib
config-opts:
- -DCMAKE_BUILD_TYPE=Release
- -DBUILD_TESTS=OFF
cleanup:
- /bin
- name: pyside6
buildsystem: simple
build-commands: []
modules:
- name: pyside6-essentials
only-arches:
- x86_64
buildsystem: simple
build-commands:
- pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}"
--prefix=${FLATPAK_DEST} "pyside6-essentials" --no-build-isolation
sources:
- type: archive
sha256: f61210ae24e6882d5d0ca0059229e5dc4f35e2bca92dd6caf96c0f41943a8294
url: https://download.qt.io/official_releases/QtForPython/pyside2/PySide2-5.15.7-src/pyside-setup-opensource-src-5.15.7.tar.xz
- type: shell
commands:
- mkdir -p /app/include/qt5tmp && cp -R /usr/include/Qt* /app/include/qt5tmp # https://bugreports.qt.io/browse/PYSIDE-787
- sed -i 's|\(--include-paths=\)|\1/app/include/qt5tmp:|' sources/pyside2/cmake/Macros/PySideModules.cmake
- sed -i s/'<private\/qaccessiblequickview_p.h>'/'\"private\/qaccessiblequickview_p.h\"'/ /app/include/qt5tmp/QtQuickWidgets/qaccessiblequickwidget.h
- mkdir -p /app/include/qt5tmp/QtQuickWidgets/private && cp /app/include/qt5tmp/QtQuick/5.15.7/QtQuick/private/qaccessiblequickview_p.h /app/include/qt5tmp/QtQuickWidgets/private/qaccessiblequickview_p.h
- type: file
url: https://files.pythonhosted.org/packages/e5/96/f43cdcb397f8a8cff6991ef8109385cc5ad9b0ad78c6dc2988b3b776fe49/PySide6_Essentials-6.4.2-cp37-abi3-manylinux_2_28_x86_64.whl
sha256: 8c3d37cca6e27f6da12b50b20e741d593ccc857bdcdb82d97f8f7c8bfe53639a
modules:
- name: shiboken6
buildsystem: simple
build-commands:
- pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}"
--prefix=${FLATPAK_DEST} "shiboken6" --no-build-isolation
sources:
- type: file
url: https://files.pythonhosted.org/packages/24/f6/f1fe9220a616789a1c6b1b73670d8b1dec882ac730a8b534f963b3f26182/shiboken6-6.4.2-cp37-abi3-manylinux_2_28_x86_64.whl
sha256: 0616c1a12d1e51e680595b3940b986275c1df952a751416a0730a59e5b90105f
- name: tor
buildsystem: autotools
sources:
- type: archive
sha256: 3b5d969712c467851bd028f314343ef15a97ea457191e93ffa97310b05b9e395
url: https://dist.torproject.org/tor-0.4.7.12.tar.gz
sha256: d39d38598208f4d6201d7edc6ad573b3a898a932a5c68d3074016a9525519b22
url: https://dist.torproject.org/tor-0.4.7.9.tar.gz
modules:
- name: libevent
buildsystem: autotools
@ -279,7 +283,7 @@ modules:
dest: src/github.com/xtaci/kcp-go
- type: git
url: https://github.com/xtaci/smux
commit: '09e2c01560df5aaaed50e48e77547858e2623498'
commit: "09e2c01560df5aaaed50e48e77547858e2623498"
dest: src/github.com/xtaci/smux
- type: git
url: https://github.com/klauspost/cpuid
@ -308,6 +312,10 @@ modules:
# - type: git
# url: https://github.com/onionshare/onionshare.git
# tag: v2.6
modules:
- name: python3-modules
buildsystem: simple
build-commands: []
modules:
- name: python3-qrcode
buildsystem: simple
@ -316,8 +324,26 @@ modules:
--prefix=${FLATPAK_DEST} "qrcode" --no-build-isolation
sources:
- type: file
url: https://files.pythonhosted.org/packages/94/9f/31f33cdf3cf8f98e64c42582fb82f39ca718264df61957f28b0bbb09b134/qrcode-7.3.1.tar.gz
sha256: 375a6ff240ca9bd41adc070428b5dfc1dcfbb0f2507f1ac848f6cded38956578
url: https://files.pythonhosted.org/packages/3e/b9/3766cc361d93edb2ce81e2e1f87dd98f314d7d513877a342d31b30741680/pypng-0.20220715.0-py3-none-any.whl
sha256: 4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c
- type: file
url: https://files.pythonhosted.org/packages/24/79/aaf0c1c7214f2632badb2771d770b1500d3d7cbdf2590ae62e721ec50584/qrcode-7.4.2-py3-none-any.whl
sha256: 581dca7a029bcb2deef5d01068e39093e80ef00b4a61098a2182eac59d01643a
- type: file
url: https://files.pythonhosted.org/packages/0b/8e/f1a0a5a76cfef77e1eb6004cb49e5f8d72634da638420b9ea492ce8305e8/typing_extensions-4.4.0-py3-none-any.whl
sha256: 16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e
- name: python3-werkzeug
buildsystem: simple
build-commands:
- pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}"
--prefix=${FLATPAK_DEST} "werkzeug" --no-build-isolation
sources:
- type: file
url: https://files.pythonhosted.org/packages/95/7e/68018b70268fb4a2a605e2be44ab7b4dd7ce7808adae6c5ef32e34f4b55a/MarkupSafe-2.1.2.tar.gz
sha256: abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d
- type: file
url: https://files.pythonhosted.org/packages/c8/27/be6ddbcf60115305205de79c29004a0c6bc53cec814f733467b1bb89386d/Werkzeug-2.2.2-py3-none-any.whl
sha256: f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5
- name: onionshare-cli
buildsystem: simple
build-commands:
@ -333,49 +359,42 @@ modules:
buildsystem: simple
build-commands:
- pip3 install --no-index --find-links="file://${PWD}" --prefix=${FLATPAK_DEST}
wheel Cython
- pip3 install --no-index --find-links="file://${PWD}" --prefix=${FLATPAK_DEST}
atomicwrites attrs bidict certifi cffi charset-normalizer click colorama
dnspython eventlet Flask Flask-SocketIO gevent gevent-websocket greenlet idna
importlib-metadata iniconfig itsdangerous Jinja2 MarkupSafe packaging pluggy psutil
py pycparser PyNaCl pyparsing PySocks pytest python-engineio python-socketio requests
setuptools six stem tomli typing-extensions Unidecode urllib3 Werkzeug zipp
- pip3 install --no-index --find-links="file://${PWD}" --prefix=${FLATPAK_DEST}
zope.event zope.interface
attrs bidict certifi cffi charset-normalizer click colorama dnspython eventlet
exceptiongroup flask flask-socketio gevent gevent-websocket greenlet idna iniconfig
itsdangerous jinja2 markupsafe packaging pluggy psutil pycparser pynacl pysocks
pytest python-engineio python-socketio requests setuptools six stem tomli unidecode
urllib3 werkzeug zope-event zope-interface setuptools wheel Cython
sources:
- type: file
url: https://files.pythonhosted.org/packages/87/c6/53da25344e3e3a9c01095a89f16dbcda021c609ddb42dd6d7c0528236fb2/atomicwrites-1.4.1.tar.gz
sha256: 81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11
url: https://files.pythonhosted.org/packages/fb/6e/6f83bf616d2becdf333a1640f1d463fef3150e2e926b7010cb0f81c95e88/attrs-22.2.0-py3-none-any.whl
sha256: 29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836
- type: file
url: https://files.pythonhosted.org/packages/f2/bc/d817287d1aa01878af07c19505fafd1165cd6a119e9d0821ca1d1c20312d/attrs-22.1.0-py2.py3-none-any.whl
sha256: 86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c
url: https://files.pythonhosted.org/packages/b5/82/ce0b6380f35f49d3fe687979a324c342cfa3588380232f3801db9dd62f9e/bidict-0.22.1-py3-none-any.whl
sha256: 6ef212238eb884b664f28da76f33f1d28b260f665fc737b413b287d5487d1e7b
- type: file
url: https://files.pythonhosted.org/packages/f1/04/ac51cac8d2b792a8de216c775248a371bf1da25f11d919f3528975288e21/bidict-0.21.4-py3-none-any.whl
sha256: 3ac67daa353ecf853a1df9d3e924f005e729227a60a8dbada31a4c31aba7f654
- type: file
url: https://files.pythonhosted.org/packages/1d/38/fa96a426e0c0e68aabc68e896584b83ad1eec779265a028e156ce509630e/certifi-2022.9.24-py3-none-any.whl
sha256: 90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382
url: https://files.pythonhosted.org/packages/71/4c/3db2b8021bd6f2f0ceb0e088d6b2d49147671f25832fb17970e9b583d742/certifi-2022.12.7-py3-none-any.whl
sha256: 4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18
- type: file
url: https://files.pythonhosted.org/packages/2b/a8/050ab4f0c3d4c1b8aaa805f70e26e84d0e27004907c5b8ecc1d31815f92a/cffi-1.15.1.tar.gz
sha256: d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9
- type: file
url: https://files.pythonhosted.org/packages/06/b3/24afc8868eba069a7f03650ac750a778862dc34941a4bebeb58706715726/charset_normalizer-2.0.12-py3-none-any.whl
sha256: 6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df
url: https://files.pythonhosted.org/packages/68/2b/02e9d6a98ddb73fa238d559a9edcc30b247b8dc4ee848b6184c936e99dc0/charset_normalizer-3.0.1-py3-none-any.whl
sha256: 7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24
- type: file
url: https://files.pythonhosted.org/packages/4a/a8/0b2ced25639fb20cc1c9784de90a8c25f9504a7f18cd8b5397bd61696d7d/click-8.0.4-py3-none-any.whl
sha256: 6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1
url: https://files.pythonhosted.org/packages/c2/f1/df59e28c642d583f7dacffb1e0965d0e00b218e0186d7858ac5233dce840/click-8.1.3-py3-none-any.whl
sha256: bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48
- type: file
url: https://files.pythonhosted.org/packages/77/8b/7550e87b2d308a1b711725dfaddc19c695f8c5fa413c640b2be01662f4e6/colorama-0.4.5-py2.py3-none-any.whl
sha256: 854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da
# - type: file
# url: https://files.pythonhosted.org/packages/fe/ca/75fac5856ab5cfa51bbbcefa250182e50441074fdc3f803f6e76451fab43/dataclasses-0.8-py3-none-any.whl
# sha256: 0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf
url: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
sha256: 4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
- type: file
url: https://files.pythonhosted.org/packages/9b/ed/28fb14146c7033ba0e89decd92a4fa16b0b69b84471e2deab3cc4337cc35/dnspython-2.2.1-py3-none-any.whl
sha256: a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f
url: https://files.pythonhosted.org/packages/12/86/d305e87555430ff4630d729420d97dece3b16efcbf2b7d7e974d11b0d86c/dnspython-2.3.0-py3-none-any.whl
sha256: 89141536394f909066cabd112e3e1a37e4e654db00a25308b0f130bc3152eb46
- type: file
url: https://files.pythonhosted.org/packages/20/c0/b8796b6b965f9804b72baccc64b621241736cad7d5f6028ca7bcd0543b8f/eventlet-0.33.1-py2.py3-none-any.whl
sha256: a085922698e5029f820cf311a648ac324d73cec0e4792877609d978a4b5bbf31
url: https://files.pythonhosted.org/packages/90/97/928b89de2e23cc67136eccccf1c122adf74ffdb65bbf7d2964b937cedd4f/eventlet-0.33.3-py2.py3-none-any.whl
sha256: e43b9ae05ba4bb477a10307699c9aff7ff86121b2640f9184d29059f5a687df8
- type: file
url: https://files.pythonhosted.org/packages/e8/14/9c6a7e5f12294ccd6975a45e02899ed25468cd7c2c86f3d9725f387f9f5f/exceptiongroup-1.1.0-py3-none-any.whl
sha256: 327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e
- type: file
url: https://files.pythonhosted.org/packages/cd/77/59df23681f4fd19b7cbbb5e92484d46ad587554f5d490f33ef907e456132/Flask-2.0.3-py3-none-any.whl
sha256: 59da8a3170004800a2837844bfa84d49b022550616070f7cb1a659682b2e7c9f
@ -383,71 +402,62 @@ modules:
url: https://files.pythonhosted.org/packages/a0/39/6899b61349cbcb19e84c948fbc8fc216c20d113e0e1ea996cf8fe5d50ee5/Flask_SocketIO-5.3.1-py3-none-any.whl
sha256: ff0c721f20bff1e2cfba77948727a8db48f187e89a72fe50c34478ce6efb3353
- type: file
url: https://files.pythonhosted.org/packages/c8/18/631398e45c109987f2d8e57f3adda161cc5ff2bd8738ca830c3a2dd41a85/gevent-21.12.0.tar.gz
sha256: f48b64578c367b91fa793bf8eaaaf4995cb93c8bc45860e473bf868070ad094e
url: https://files.pythonhosted.org/packages/9f/4a/e9e57cb9495f0c7943b1d5965c4bdd0d78bc4a433a7c96ee034b16c01520/gevent-22.10.2.tar.gz
sha256: 1ca01da176ee37b3527a2702f7d40dbc9ffb8cfc7be5a03bfa4f9eec45e55c46
- type: file
url: https://files.pythonhosted.org/packages/7b/84/2dc373eb6493e00c884cc11e6c059ec97abae2678d42f06bf780570b0193/gevent_websocket-0.10.1-py3-none-any.whl
sha256: 17b67d91282f8f4c973eba0551183fc84f56f1c90c8f6b6b30256f31f66f5242
- type: file
url: https://files.pythonhosted.org/packages/a0/d5/70772b3693f086a362f122516225a43fe4f1182e17158c81ba1ab271ab9b/greenlet-1.1.3.tar.gz
sha256: bcb6c6dd1d6be6d38d6db283747d07fda089ff8c559a835236560a4410340455
url: https://files.pythonhosted.org/packages/1e/1e/632e55a04d732c8184201238d911207682b119c35cecbb9a573a6c566731/greenlet-2.0.2.tar.gz
sha256: e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0
- type: file
url: https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl
sha256: 90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
- type: file
url: https://files.pythonhosted.org/packages/a0/a1/b153a0a4caf7a7e3f15c2cd56c7702e2cf3d89b1b359d1f1c5e59d68f4ce/importlib_metadata-4.8.3-py3-none-any.whl
sha256: 65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e
url: https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl
sha256: b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
- type: file
url: https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl
sha256: 011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3
url: https://files.pythonhosted.org/packages/68/5f/447e04e828f47465eeab35b5d408b7ebaaaee207f48b7136c5a7267a30ae/itsdangerous-2.1.2-py3-none-any.whl
sha256: 2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44
- type: file
url: https://files.pythonhosted.org/packages/9c/96/26f935afba9cd6140216da5add223a0c465b99d0f112b68a4ca426441019/itsdangerous-2.0.1-py3-none-any.whl
sha256: 5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c
url: https://files.pythonhosted.org/packages/bc/c3/f068337a370801f372f2f8f6bad74a5c140f6fda3d9de154052708dd3c65/Jinja2-3.1.2-py3-none-any.whl
sha256: 6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
- type: file
url: https://files.pythonhosted.org/packages/20/9a/e5d9ec41927401e41aea8af6d16e78b5e612bca4699d417f646a9610a076/Jinja2-3.0.3-py3-none-any.whl
sha256: 077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8
url: https://files.pythonhosted.org/packages/95/7e/68018b70268fb4a2a605e2be44ab7b4dd7ce7808adae6c5ef32e34f4b55a/MarkupSafe-2.1.2.tar.gz
sha256: abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d
- type: file
url: https://files.pythonhosted.org/packages/bf/10/ff66fea6d1788c458663a84d88787bae15d45daa16f6b3ef33322a51fc7e/MarkupSafe-2.0.1.tar.gz
sha256: 594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a
- type: file
url: https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl
sha256: ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522
url: https://files.pythonhosted.org/packages/ed/35/a31aed2993e398f6b09a790a181a7927eb14610ee8bbf02dc14d31677f1c/packaging-23.0-py3-none-any.whl
sha256: 714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2
- type: file
url: https://files.pythonhosted.org/packages/9e/01/f38e2ff29715251cf25532b9082a1589ab7e4f571ced434f98d0139336dc/pluggy-1.0.0-py2.py3-none-any.whl
sha256: 74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3
- type: file
url: https://files.pythonhosted.org/packages/8f/57/828ac1f70badc691a716e77bfae258ef5db76bb7830109bf4bcf882de020/psutil-5.9.2.tar.gz
sha256: feb861a10b6c3bb00701063b37e4afc754f8217f0f09c42280586bd6ac712b5c
- type: file
url: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl
sha256: 607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378
url: https://files.pythonhosted.org/packages/3d/7d/d05864a69e452f003c0d77e728e155a89a2a26b09e64860ddd70ad64fb26/psutil-5.9.4.tar.gz
sha256: 3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62
- type: file
url: https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl
sha256: 8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9
- type: file
url: https://files.pythonhosted.org/packages/a7/22/27582568be639dfe22ddb3902225f91f2f17ceff88ce80e4db396c8986da/PyNaCl-1.5.0.tar.gz
sha256: 8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba
- type: file
url: https://files.pythonhosted.org/packages/80/c1/23fd82ad3121656b585351aba6c19761926bb0db2ebed9e4ff09a43a3fcc/pyparsing-3.0.7-py3-none-any.whl
sha256: a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484
- type: file
url: https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl
sha256: 2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5
- type: file
url: https://files.pythonhosted.org/packages/38/93/c7c0bd1e932b287fb948eb9ce5a3d6307c9fc619db1e199f8c8bc5dad95f/pytest-7.0.1-py3-none-any.whl
sha256: 9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db
url: https://files.pythonhosted.org/packages/cc/02/8f59bf194c9a1ceac6330850715e9ec11e21e2408a30a596c65d54cf4d2a/pytest-7.2.1-py3-none-any.whl
sha256: c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5
- type: file
url: https://files.pythonhosted.org/packages/45/ba/aa28ea42cbe8a133004f1cfe799bbd11d56f24c6fb588feea4d1dffeb148/python_engineio-4.3.4-py3-none-any.whl
sha256: 7454314a529bba20e745928601ffeaf101c1b5aca9a6c4e48ad397803d10ea0c
- type: file
url: https://files.pythonhosted.org/packages/d3/b0/862b095d2c6e7892c7be2056efe02d4faea62ee35b3ed10b905fdfa3d74a/python_socketio-5.7.1-py3-none-any.whl
sha256: 86ee93591c1e781d339d9a61940e62fd6cbc838390653b52a7bcc4f7ce89fe47
url: https://files.pythonhosted.org/packages/5c/27/3a215e5fc16e371fa8e9bca75d37e120d05c8dd5030905b6657ae8c96d13/python_socketio-5.7.2-py3-none-any.whl
sha256: d9a9f047e6fdd306c852fbac36516f4b495c2096f8ad9ceb8803b8e5ff5622e3
- type: file
url: https://files.pythonhosted.org/packages/2d/61/08076519c80041bc0ffa1a8af0cbd3bf3e2b62af10435d269a9d0f40564d/requests-2.27.1-py2.py3-none-any.whl
sha256: f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d
url: https://files.pythonhosted.org/packages/d2/f4/274d1dbe96b41cf4e0efb70cbced278ffd61b5c7bb70338b62af94ccb25b/requests-2.28.2-py3-none-any.whl
sha256: 64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa
- type: file
url: https://files.pythonhosted.org/packages/b0/3a/88b210db68e56854d0bcf4b38e165e03be377e13907746f825790f3df5bf/setuptools-59.6.0-py3-none-any.whl
sha256: 4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e
url: https://files.pythonhosted.org/packages/c8/24/157fed9a57108b3e1b6ccd86e95823327f231ef12464b0eca13650eb33ac/setuptools-67.1.0-py3-none-any.whl
sha256: a7687c12b444eaac951ea87a9627c4f904ac757e7abdc5aac32833234af90378
- type: file
url: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
sha256: 8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
@ -455,32 +465,29 @@ modules:
url: https://files.pythonhosted.org/packages/b2/66/c5515de764bffae1347e671819711268da5c02bfab8406223526822fe5f6/stem-1.8.1.tar.gz
sha256: 81d43a7c668ba9d7bc1103b2e7a911e9d148294b373d27a59ae8da79ef7a3e2f
- type: file
url: https://files.pythonhosted.org/packages/05/e4/74f9440db36734d7ba83c574c1e7024009ce849208a41f90e94a134dc6d1/tomli-1.2.3-py3-none-any.whl
sha256: e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c
- type: file
url: https://files.pythonhosted.org/packages/45/6b/44f7f8f1e110027cf88956b59f2fad776cca7e1704396d043f89effd3a0e/typing_extensions-4.1.1-py3-none-any.whl
sha256: 21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2
url: https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl
sha256: 939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc
- type: file
url: https://files.pythonhosted.org/packages/be/ea/90e14e807da5a39e5b16789acacd48d63ca3e4f23dfa964a840eeadebb13/Unidecode-1.3.6-py3-none-any.whl
sha256: 547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be
- type: file
url: https://files.pythonhosted.org/packages/6f/de/5be2e3eed8426f871b170663333a0f627fc2924cc386cd41be065e7ea870/urllib3-1.26.12-py2.py3-none-any.whl
sha256: b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997
url: https://files.pythonhosted.org/packages/fe/ca/466766e20b767ddb9b951202542310cba37ea5f2d792dae7589f1741af58/urllib3-1.26.14-py2.py3-none-any.whl
sha256: 75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1
- type: file
url: https://files.pythonhosted.org/packages/f4/f3/22afbdb20cc4654b10c98043414a14057cd27fdba9d4ae61cea596000ba2/Werkzeug-2.0.3-py3-none-any.whl
sha256: 1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8
- type: file
url: https://files.pythonhosted.org/packages/bd/df/d4a4974a3e3957fd1c1fa3082366d7fff6e428ddb55f074bf64876f8e8ad/zipp-3.6.0-py3-none-any.whl
sha256: 9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc
url: https://files.pythonhosted.org/packages/8b/a8/3ab9648dc08d2ab7543145ec174a2d982d08fb996d50d9a4d3e057da7132/zope.event-4.6-py2.py3-none-any.whl
sha256: 73d9e3ef750cca14816a9c322c7250b0d7c9dbc337df5d1b807ff8d3d0b9e97c
- type: file
url: https://files.pythonhosted.org/packages/9e/85/b45408c64f3b888976f1d5b37eed8d746b8d5729a66a49ec846fda27d371/zope.event-4.5.0-py2.py3-none-any.whl
sha256: 2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42
url: https://files.pythonhosted.org/packages/38/6f/fbfb7dde38be7e5644bb342c4c7cdc444cd5e2ffbd70d091263b3858a8cb/zope.interface-5.5.2.tar.gz
sha256: bfee1f3ff62143819499e348f5b8a7f3aa0259f9aca5e0ddae7391d059dce671
- type: file
url: https://files.pythonhosted.org/packages/ae/58/e0877f58daa69126a5fb325d6df92b20b77431cd281e189c5ec42b722f58/zope.interface-5.4.0.tar.gz
sha256: 5dba5f530fec3f0988d83b78cc591b58c0b6eb8431a85edd1569a0539a8a5a0e
url: https://files.pythonhosted.org/packages/5f/36/7374297692bb9dbd7569a0f84887c7e5e314c41d5d9518cb76fbb130620d/setuptools-67.2.0.tar.gz
sha256: b440ee5f7e607bb8c9de15259dba2583dd41a38879a7abc1d43a71c59524da48
- type: file
url: https://files.pythonhosted.org/packages/27/d6/003e593296a85fd6ed616ed962795b2f87709c3eee2bca4f6d0fe55c6d00/wheel-0.37.1-py2.py3-none-any.whl
sha256: 4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a
url: https://files.pythonhosted.org/packages/a2/b8/6a06ff0f13a00fc3c3e7d222a995526cbca26c1ad107691b6b1badbbabf1/wheel-0.38.4.tar.gz
sha256: 965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac
- type: file
url: https://files.pythonhosted.org/packages/2e/a7/f20fa91d9de799f8e19bacf225bc993b8a53b5fc6f41ffa20d64f0850579/Cython-3.0.0a11.tar.gz
sha256: e4672491fb31546b9abb63677f638e738085dc9321398170956ef6fbfc0e1726