mirror of
https://github.com/onionshare/onionshare.git
synced 2025-01-10 03:37:28 -03:00
commit
b7ec0cd902
30 changed files with 1537 additions and 1123 deletions
|
@ -1,60 +1,437 @@
|
|||
version: 2
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
win: circleci/windows@4.0.0
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
test:
|
||||
ci:
|
||||
jobs:
|
||||
- test-cli
|
||||
- test-gui
|
||||
- build-win64:
|
||||
requires:
|
||||
- test-cli
|
||||
- test-gui
|
||||
- build-win32:
|
||||
requires:
|
||||
- test-cli
|
||||
- test-gui
|
||||
- build-macos:
|
||||
requires:
|
||||
- test-cli
|
||||
- test-gui
|
||||
|
||||
jobs:
|
||||
test-cli:
|
||||
docker:
|
||||
- image: cimg/python:3.9
|
||||
|
||||
working_directory: ~/repo
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install tor obfs4proxy
|
||||
pip install poetry
|
||||
cd ~/repo/cli
|
||||
- restore_cache:
|
||||
key: test-cli-poetry-deps-{{ .Environment.CACHE_VERSION }}-{{ checksum "~/project/cli/poetry.lock" }}
|
||||
- run:
|
||||
name: Install poetry dependencies
|
||||
command: |
|
||||
cd ~/project/cli
|
||||
poetry install
|
||||
|
||||
- save_cache:
|
||||
key: test-cli-poetry-deps-{{ .Environment.CACHE_VERSION }}-{{ checksum "~/project/cli/poetry.lock" }}
|
||||
paths:
|
||||
- /home/circleci/.cache/pypoetry/virtualenvs
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
cd ~/repo/cli
|
||||
cd ~/project/cli
|
||||
poetry run pytest -v ./tests
|
||||
poetry run onionshare-cli --local-only ./tests --auto-stop-timer 2
|
||||
poetry run onionshare-cli --local-only --receive --auto-stop-timer 2
|
||||
poetry run onionshare-cli --local-only --website ../docs --auto-stop-timer 2
|
||||
poetry run onionshare-cli --local-only --chat --auto-stop-timer 2
|
||||
|
||||
|
||||
test-gui:
|
||||
docker:
|
||||
- image: cimg/python:3.9
|
||||
|
||||
working_directory: ~/repo
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y tor obfs4proxy gcc python3-dev python3-pyside2.qtcore python3-pyside2.qtwidgets python3-pyside2.qtgui
|
||||
sudo apt-get install -y xvfb x11-utils libxkbcommon-x11-0 libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev libxcb-render-util0 libxcb-icccm4 libxcb-keysyms1 libxcb-image0
|
||||
cd ~/repo/desktop
|
||||
- restore_cache:
|
||||
key: test-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Install poetry dependencies
|
||||
command: |
|
||||
cd ~/project/desktop
|
||||
poetry install
|
||||
|
||||
- save_cache:
|
||||
key: test-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- /home/circleci/.cache/pypoetry/virtualenvs
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
cd ~/repo/desktop
|
||||
cd ~/project/desktop
|
||||
QT_DEBUG_PLUGINS=1 xvfb-run poetry run pytest -v ./tests/test_gui_*.py
|
||||
|
||||
build-win64:
|
||||
executor:
|
||||
name: win/default
|
||||
shell: powershell.exe
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- run:
|
||||
name: Install Python 3.9.13 (64-bit)
|
||||
command: |
|
||||
cd ~\Downloads
|
||||
Invoke-WebRequest -Uri https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe -OutFile python-3.9.13-amd64.exe
|
||||
.\python-3.9.13-amd64.exe /quiet InstallAllUsers=1 TargetDir=C:\Python39
|
||||
while($true) {
|
||||
if ((Test-Path -Path C:\Python39\python.exe) -eq $True) {
|
||||
Write-Output "Python is installed"
|
||||
break
|
||||
} else {
|
||||
Write-Output "Waiting for Python to finish installing ..."
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
}
|
||||
|
||||
- run:
|
||||
name: Install poetry
|
||||
command: C:\Python39\python -m pip install poetry
|
||||
|
||||
# - restore_cache:
|
||||
# key: build-win64-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Install poetry dependencies
|
||||
command: |
|
||||
cd C:\Users\circleci\project\desktop
|
||||
C:\Python39\scripts\poetry install
|
||||
# - save_cache:
|
||||
# key: build-win64-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
|
||||
# paths:
|
||||
# - C:\Users\circleci\AppData\Local\pypoetry\Cache\virtualenvs
|
||||
|
||||
- restore_cache:
|
||||
key: get-tor-win64-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Get tor binaries from Tor Browser (64-bit)
|
||||
command: |
|
||||
cd desktop
|
||||
C:\Python39\Scripts\poetry run python .\scripts\get-tor.py win64
|
||||
- save_cache:
|
||||
key: get-tor-win64-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- C:\Users\circleci\project\desktop\build\tor
|
||||
|
||||
- restore_cache:
|
||||
key: build-win64-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build obfs4proxy
|
||||
command: |
|
||||
if ((Test-Path -Path 'C:\Users\circleci\project\desktop\onionshare\resources\tor\obfs4proxy.exe') -eq $True) {
|
||||
Write-Output "obfs4proxy already built"
|
||||
} else {
|
||||
cd C:\Users\circleci\project\desktop
|
||||
.\scripts\build-pt-obfs4proxy.ps1
|
||||
}
|
||||
- save_cache:
|
||||
key: build-win64-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- C:\Users\circleci\project\desktop\onionshare\resources\tor\obfs4proxy.exe
|
||||
|
||||
- restore_cache:
|
||||
key: build-win64-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build snowflake-client
|
||||
command: |
|
||||
if ((Test-Path -Path 'C:\Users\circleci\project\desktop\onionshare\resources\tor\snowflake-client.exe') -eq $True) {
|
||||
Write-Output "snowflake already built"
|
||||
} else {
|
||||
cd C:\Users\circleci\project\desktop
|
||||
.\scripts\build-pt-snowflake.ps1
|
||||
}
|
||||
- save_cache:
|
||||
key: build-win64-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- C:\Users\circleci\project\desktop\onionshare\resources\tor\snowflake-client.exe
|
||||
|
||||
- restore_cache:
|
||||
key: build-win64-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build meek-client
|
||||
command: |
|
||||
if ((Test-Path -Path 'C:\Users\circleci\project\desktop\onionshare\resources\tor\meek-client.exe') -eq $True) {
|
||||
Write-Output "snowflake already built"
|
||||
} else {
|
||||
cd C:\Users\circleci\project\desktop
|
||||
.\scripts\build-pt-meek.ps1
|
||||
}
|
||||
- save_cache:
|
||||
key: build-win64-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- C:\Users\circleci\project\desktop\onionshare\resources\tor\meek-client.exe
|
||||
|
||||
- run:
|
||||
name: Build OnionShare
|
||||
command: |
|
||||
cd ~\project\desktop
|
||||
C:\Python39\Scripts\poetry run python .\setup-freeze.py build
|
||||
C:\Python39\Scripts\poetry run python .\scripts\build-windows.py cleanup-build
|
||||
|
||||
- run:
|
||||
name: Compress
|
||||
command: |
|
||||
mv ~\project\desktop\build\exe.win-amd64-3.9\ ~\onionshare-win64
|
||||
Compress-Archive -LiteralPath ~\onionshare-win64 -DestinationPath ~\onionshare-win64.zip
|
||||
|
||||
- store_artifacts:
|
||||
path: ~\onionshare-win64.zip
|
||||
|
||||
build-win32:
|
||||
executor:
|
||||
name: win/default
|
||||
shell: powershell.exe
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- run:
|
||||
name: Install Python 3.9.13 (32-bit)
|
||||
command: |
|
||||
cd ~\Downloads
|
||||
Invoke-WebRequest -Uri https://www.python.org/ftp/python/3.9.13/python-3.9.13.exe -OutFile python-3.9.13.exe
|
||||
.\python-3.9.13.exe /quiet InstallAllUsers=1 TargetDir=C:\Python39
|
||||
while($true) {
|
||||
if ((Test-Path -Path C:\Python39\python.exe) -eq $True) {
|
||||
Write-Output "Python is installed"
|
||||
break
|
||||
} else {
|
||||
Write-Output "Waiting for Python to finish installing ..."
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
}
|
||||
|
||||
- run:
|
||||
name: Install poetry
|
||||
command: C:\Python39\python -m pip install poetry
|
||||
|
||||
# - restore_cache:
|
||||
# key: build-win32-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Install poetry dependencies
|
||||
command: |
|
||||
cd ~\project\desktop
|
||||
C:\Python39\Scripts\poetry install
|
||||
# - save_cache:
|
||||
# key: build-win32-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
|
||||
# paths:
|
||||
# - C:\Users\circleci\AppData\Local\pypoetry\Cache\virtualenvs
|
||||
|
||||
- restore_cache:
|
||||
key: get-tor-win32-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Get tor binaries from Tor Browser (32-bit)
|
||||
command: |
|
||||
cd desktop
|
||||
C:\Python39\Scripts\poetry run python .\scripts\get-tor.py win32
|
||||
- save_cache:
|
||||
key: get-tor-win32-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- C:\Users\circleci\project\desktop\build\tor
|
||||
|
||||
- run:
|
||||
name: Install golang (32-bit)
|
||||
command: |
|
||||
cd ~\Downloads
|
||||
Invoke-WebRequest -Uri https://go.dev/dl/go1.18.windows-386.msi -OutFile go1.18.windows-386.msi
|
||||
msiexec.exe /i go1.18.windows-386.msi /quiet /L*V go-install.log
|
||||
|
||||
- restore_cache:
|
||||
key: build-win32-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build obfs4proxy
|
||||
command: |
|
||||
if ((Test-Path -Path C:\Users\circleci\project\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 C:\Users\circleci\project\desktop
|
||||
.\scripts\build-pt-obfs4proxy.ps1
|
||||
}
|
||||
- save_cache:
|
||||
key: build-win32-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- C:\Users\circleci\project\desktop\onionshare\resources\tor\obfs4proxy.exe
|
||||
|
||||
- restore_cache:
|
||||
key: build-win32-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build snowflake-client
|
||||
command: |
|
||||
if ((Test-Path -Path C:\Users\circleci\project\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 C:\Users\circleci\project\desktop
|
||||
.\scripts\build-pt-snowflake.ps1
|
||||
}
|
||||
- save_cache:
|
||||
key: build-win32-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- C:\Users\circleci\project\desktop\onionshare\resources\tor\snowflake-client.exe
|
||||
|
||||
- restore_cache:
|
||||
key: build-win32-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build meek-client
|
||||
command: |
|
||||
if ((Test-Path -Path C:\Users\circleci\project\desktop\onionshare\resources\tor\meek-client.exe) -eq $True) {
|
||||
Write-Output "snowflake already built"
|
||||
} else {
|
||||
$env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
|
||||
cd C:\Users\circleci\project\desktop
|
||||
.\scripts\build-pt-meek.ps1
|
||||
}
|
||||
- save_cache:
|
||||
key: build-win32-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.ps1" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- C:\Users\circleci\project\desktop\onionshare\resources\tor\meek-client.exe
|
||||
|
||||
- run:
|
||||
name: Build OnionShare
|
||||
command: |
|
||||
cd ~\project\desktop
|
||||
C:\Python39\Scripts\poetry run python .\setup-freeze.py build
|
||||
C:\Python39\Scripts\poetry run python .\scripts\build-windows.py cleanup-build
|
||||
|
||||
- run:
|
||||
name: Compress
|
||||
command: |
|
||||
mv ~\project\desktop\build\exe.win32-3.9\ ~\onionshare-win32
|
||||
Compress-Archive -LiteralPath ~\onionshare-win32 -DestinationPath ~\onionshare-win32.zip
|
||||
|
||||
- store_artifacts:
|
||||
path: ~\onionshare-win32.zip
|
||||
|
||||
build-macos:
|
||||
macos:
|
||||
xcode: 12.5.1
|
||||
environment:
|
||||
BINARY_DIR: /Users/distiller/bin
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install Go 1.18.3
|
||||
command: |
|
||||
curl -L https://go.dev/dl/go1.18.3.darwin-amd64.pkg --output ~/Downloads/go.pkg
|
||||
sudo installer -pkg ~/Downloads/go.pkg -target /
|
||||
|
||||
- run:
|
||||
name: Install Python 3.9.13
|
||||
command: |
|
||||
curl -L https://www.python.org/ftp/python/3.9.13/python-3.9.13-macosx10.9.pkg --output ~/Downloads/python.pkg
|
||||
sudo installer -pkg ~/Downloads/python.pkg -target /
|
||||
|
||||
- run:
|
||||
name: Install poetry
|
||||
command: |
|
||||
pip3 install poetry
|
||||
ln -s /Library/Frameworks/Python.framework/Versions/3.9/bin/poetry /usr/local/bin
|
||||
|
||||
- restore_cache:
|
||||
key: build-macos-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Install poetry dependencies
|
||||
command: |
|
||||
cd ~/project/desktop
|
||||
poetry install
|
||||
- save_cache:
|
||||
key: build-macos-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- /Users/distiller/Library/Caches/pypoetry/virtualenvs
|
||||
|
||||
- restore_cache:
|
||||
key: get-tor-macos-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Get tor binaries from Tor Browser
|
||||
command: |
|
||||
cd desktop
|
||||
poetry run python ./scripts/get-tor.py macos
|
||||
- save_cache:
|
||||
key: get-tor-macos-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- ~/project/desktop/build/tor
|
||||
|
||||
- restore_cache:
|
||||
key: build-macos-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.sh" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build obfs4proxy
|
||||
command: |
|
||||
if [[ -f "/Users/distiller/project/desktop/onionshare/resources/tor/obfs4proxy" ]]; then
|
||||
echo "obfs4proxy already built"
|
||||
else
|
||||
cd /Users/distiller/project/desktop
|
||||
./scripts/build-pt-obfs4proxy.sh
|
||||
fi
|
||||
- save_cache:
|
||||
key: build-macos-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.sh" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- /Users/distiller/project/desktop/onionshare/resources/tor/obfs4proxy
|
||||
|
||||
- restore_cache:
|
||||
key: build-macos-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.sh" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build snowflake
|
||||
command: |
|
||||
if [[ -f "/Users/distiller/project/desktop/onionshare/resources/tor/snowflake-client" ]]; then
|
||||
echo "snowflake already built"
|
||||
else
|
||||
cd /Users/distiller/project/desktop
|
||||
./scripts/build-pt-snowflake.sh
|
||||
fi
|
||||
- save_cache:
|
||||
key: build-macos-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.sh" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- ~/project/desktop/onionshare/resources/tor/snowflake-client
|
||||
|
||||
- restore_cache:
|
||||
key: build-macos-meek-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.sh" }}-{{ .Environment.CACHE_VERSION }}
|
||||
- run:
|
||||
name: Build meek
|
||||
command: |
|
||||
if [[ -f "/Users/distiller/project/desktop/onionshare/resources/tor/meek-client" ]]; then
|
||||
echo "meek already built"
|
||||
else
|
||||
cd /Users/distiller/project/desktop
|
||||
./scripts/build-pt-meek.sh
|
||||
fi
|
||||
- save_cache:
|
||||
key: build-macos-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.sh" }}-{{ .Environment.CACHE_VERSION }}
|
||||
paths:
|
||||
- ~/project/desktop/onionshare/resources/tor/meek-client
|
||||
|
||||
- run:
|
||||
name: Build OnionShare
|
||||
command: |
|
||||
cd ~/project/desktop
|
||||
poetry run python ./setup-freeze.py build
|
||||
poetry run python ./setup-freeze.py bdist_mac
|
||||
poetry run python ./scripts/build-macos.py cleanup-build
|
||||
|
||||
- run:
|
||||
name: Compress
|
||||
command: |
|
||||
cd ~/project/desktop/build
|
||||
tar -czvf ~/onionshare-macos.tar.gz OnionShare.app
|
||||
|
||||
- store_artifacts:
|
||||
path: ~/onionshare-macos.tar.gz
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# OnionShare Changelog
|
||||
|
||||
## 2.6
|
||||
|
||||
* TODO
|
||||
|
||||
## 2.5
|
||||
|
||||
* Security fix: Sanitize the path parameter in History item widget to be plain text
|
||||
|
|
54
RELEASE.md
54
RELEASE.md
|
@ -16,12 +16,6 @@ Before making a release, you must update the version in these places:
|
|||
|
||||
If you update `flask-socketio`, ensure that you also update the [socket.io.min.js](https://github.com/micahflee/onionshare/blob/develop/cli/onionshare_cli/resources/static/js/socket.io.min.js) file to a version that is [supported](https://flask-socketio.readthedocs.io/en/latest/#version-compatibility) by the updated version of `flask-socketio`.
|
||||
|
||||
Use tor binaries from the latest Tor Browser:
|
||||
|
||||
- [ ] `desktop/scripts/get-tor-linux.py`
|
||||
- [ ] `desktop/scripts/get-tor-osx.py`
|
||||
- [ ] `desktop/scripts/get-tor-windows.py`
|
||||
|
||||
Update the documentation:
|
||||
|
||||
- [ ] Update all of the documentation in `docs` to cover new features, including taking new screenshots if necessary
|
||||
|
@ -100,37 +94,61 @@ snapcraft upload --release=stable onionshare_${VERSION}_amd64.snap
|
|||
|
||||
## Windows
|
||||
|
||||
Set up the development environment described in desktop `README.md`.
|
||||
Set up the packaging environment:
|
||||
|
||||
- To get `signtool.exe`, install the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk) and add `C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86` to your path.
|
||||
- Install the [Windows SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/) and add `C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64` to your path (to get `signtool.exe`).
|
||||
- Go to https://dotnet.microsoft.com/download/dotnet-framework and download and install .NET Framework 3.5 SP1 Runtime. I downloaded `dotnetfx35.exe`.
|
||||
- Go to https://wixtoolset.org/releases/ and download and install WiX toolset. I downloaded `wix311.exe`. Add `C:\Program Files (x86)\WiX Toolset v3.11\bin` to the path.
|
||||
|
||||
Run the Windows build script:
|
||||
CircleCI will build the binaries. Find the CircleCI jobs `build-win32` and `build-win64`, switch to the artifacts tab, and download:
|
||||
|
||||
- `onionshare-win32.zip`
|
||||
- `onionshare-win64.zip`
|
||||
|
||||
Extract these files, change to the `desktop` folder, and run:
|
||||
|
||||
```
|
||||
poetry run python .\package\build-windows.py
|
||||
poetry run python .\scripts\build-windows.py codesign [onionshare_win32_path] [onionshare_win64_path]
|
||||
poetry run python .\scripts\build-windows.py package [onionshare_win32_path] [onionshare_win64_path]
|
||||
```
|
||||
|
||||
This will create `desktop/dist/OnionShare-$VERSION.msi`, signed.
|
||||
This will create:
|
||||
|
||||
- `desktop/dist/OnionShare-win32-$VERSION.msi`
|
||||
- `desktop/dist/OnionShare-win64-$VERSION.msi`
|
||||
|
||||
## macOS
|
||||
|
||||
Set up the development environment described in `README.md`.
|
||||
Set up the packaging environment:
|
||||
|
||||
Then build an executable, make it a macOS app bundle, and package it in a dmg:
|
||||
- Install create-dmg: `brew install create-dmg`
|
||||
|
||||
CircleCI will build the binaries. Find the CircleCI job `build-macos`, switch to the artifacts tab, and download:
|
||||
|
||||
- `onionshare-macos.zip`
|
||||
|
||||
Extract these files, change to the `desktop` folder, and run:
|
||||
|
||||
```sh
|
||||
poetry run ./package/build-mac.py
|
||||
poetry run python ./scripts/build-macos.py codesign [app_path]
|
||||
poetry run python ./scripts/build-macos.py package [app_path]
|
||||
```
|
||||
|
||||
The will create `dist/OnionShare-$VERSION.dmg`.
|
||||
|
||||
Now, notarize the release. You must have an app-specific Apple ID password saved in the login keychain called `onionshare-notarize`.
|
||||
Now, notarize the release.
|
||||
|
||||
- Notarize it: `xcrun altool --notarize-app --primary-bundle-id "com.micahflee.onionshare" -u "micah@micahflee.com" -p "@keychain:onionshare-notarize" --file dist/OnionShare-$VERSION.dmg`
|
||||
- Wait for it to get approved, check status with: `xcrun altool --notarization-history 0 -u "micah@micahflee.com" -p "@keychain:onionshare-notarize"`
|
||||
- After it's approved, staple the ticket: `xcrun stapler staple dist/OnionShare-$VERSION.dmg`
|
||||
```sh
|
||||
export APPLE_PASSWORD="changeme" # app-specific Apple ID password
|
||||
export VERSION=$(cat ../cli/onionshare_cli/resources/version.txt)
|
||||
|
||||
# Notarize it
|
||||
xcrun altool --notarize-app --primary-bundle-id "com.micahflee.onionshare" -u "micah@micahflee.com" -p "$APPLE_PASSWORD" --file dist/OnionShare-$VERSION.dmg
|
||||
# Wait for it to get approved, ceck status with
|
||||
xcrun altool --notarization-history 0 -u "micah@micahflee.com" -p "$APPLE_PASSWORD"
|
||||
# After it's approved, staple the ticket
|
||||
xcrun stapler staple dist/OnionShare-$VERSION.dmg
|
||||
```
|
||||
|
||||
This will create `desktop/dist/OnionShare-$VERSION.dmg`, signed and notarized.
|
||||
|
||||
|
|
|
@ -332,21 +332,27 @@ class Common:
|
|||
# In Windows, the Tor binaries are in the onionshare package, not the onionshare_cli package
|
||||
base_path = self.get_resource_path("tor")
|
||||
base_path = base_path.replace("onionshare_cli", "onionshare")
|
||||
tor_path = os.path.join(base_path, "Tor", "tor.exe")
|
||||
tor_path = os.path.join(base_path, "tor.exe")
|
||||
|
||||
# If tor.exe isn't there, mayber we're running from the source tree
|
||||
if not os.path.exists(tor_path):
|
||||
self.log(
|
||||
"Common", "get_tor_paths", f"Cannot find tor.exe at {tor_path}"
|
||||
)
|
||||
base_path = os.path.join(os.getcwd(), "onionshare", "resources", "tor")
|
||||
|
||||
tor_path = os.path.join(base_path, "Tor", "tor.exe")
|
||||
tor_path = os.path.join(base_path, "tor.exe")
|
||||
if not os.path.exists(tor_path):
|
||||
self.log(
|
||||
"Common", "get_tor_paths", f"Cannot find tor.exe at {tor_path}"
|
||||
)
|
||||
raise CannotFindTor()
|
||||
|
||||
obfs4proxy_file_path = os.path.join(base_path, "Tor", "obfs4proxy.exe")
|
||||
snowflake_file_path = os.path.join(base_path, "Tor", "snowflake-client.exe")
|
||||
meek_client_file_path = os.path.join(base_path, "Tor", "meek-client.exe")
|
||||
tor_geo_ip_file_path = os.path.join(base_path, "Data", "Tor", "geoip")
|
||||
tor_geo_ipv6_file_path = os.path.join(base_path, "Data", "Tor", "geoip6")
|
||||
obfs4proxy_file_path = os.path.join(base_path, "obfs4proxy.exe")
|
||||
snowflake_file_path = os.path.join(base_path, "snowflake-client.exe")
|
||||
meek_client_file_path = os.path.join(base_path, "meek-client.exe")
|
||||
tor_geo_ip_file_path = os.path.join(base_path, "geoip")
|
||||
tor_geo_ipv6_file_path = os.path.join(base_path, "geoip6")
|
||||
|
||||
elif self.platform == "Darwin":
|
||||
# Let's see if we have tor binaries in the onionshare GUI package
|
||||
|
@ -499,7 +505,7 @@ class Common:
|
|||
if valid_bridges:
|
||||
return valid_bridges
|
||||
else:
|
||||
return False
|
||||
return False
|
||||
|
||||
def is_flatpak(self):
|
||||
"""
|
||||
|
@ -513,7 +519,6 @@ class Common:
|
|||
"""
|
||||
return os.environ.get("SNAP_INSTANCE_NAME") == "onionshare"
|
||||
|
||||
|
||||
@staticmethod
|
||||
def random_string(num_bytes, output_len=None):
|
||||
"""
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.5
|
||||
2.6.dev1
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "onionshare_cli"
|
||||
version = "2.5"
|
||||
version = "2.6"
|
||||
description = "OnionShare lets you securely and anonymously send and receive files. It works by starting a web server, making it accessible as a Tor onion service, and generating an unguessable web address so others can download files from you, or upload files to you. It does _not_ require setting up a separate server or using a third party file-sharing service."
|
||||
authors = ["Micah Lee <micah@micahflee.com>"]
|
||||
license = "GPLv3+"
|
||||
|
|
|
@ -9,62 +9,54 @@ 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.9 [from python.org](https://www.python.org/downloads/release/python-3912/). For Windows, make sure to install the 32-bit (x86) version, and 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 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 [poetry installed](https://python-poetry.org/docs/#installation), and then install the dependencies:
|
||||
Make sure you have [poetry](https://python-poetry.org/) installed:
|
||||
|
||||
```
|
||||
pip3 install poetry
|
||||
```
|
||||
|
||||
And install the poetry dependencies:
|
||||
|
||||
```sh
|
||||
poetry install
|
||||
```
|
||||
|
||||
In Windows, you may need to install [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/), making sure to check "Desktop development with C++", before `poetry install` will work properly.
|
||||
**Windows users:** You may need to install [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/), making sure to check "Desktop development with C++", before `poetry install` will work properly.
|
||||
|
||||
### Install platform-specific dependencies
|
||||
### Get Tor
|
||||
|
||||
#### Linux
|
||||
**Linux users:** In Ubuntu 20.04 you need the `libxcb-xinerama0` package installed.
|
||||
|
||||
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.
|
||||
|
||||
Download Tor Browser and extract the binaries:
|
||||
Download Tor Browser and extract the binaries for your platform. The platform must be `win32`, `win64`, `macos`, or `linux64`.
|
||||
|
||||
```sh
|
||||
poetry run ./scripts/get-tor-linux.py
|
||||
```
|
||||
|
||||
#### macOS
|
||||
|
||||
Download Tor Browser and extract the binaries:
|
||||
|
||||
```sh
|
||||
poetry run ./scripts/get-tor-osx.py
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
These instructions include adding folders to the path in Windows. To do this, go to Start and type "advanced system settings", and open "View advanced system settings" in the Control Panel. Click Environment Variables. Under "System variables" double-click on Path. From there you can add and remove folders that are available in the PATH.
|
||||
|
||||
Download and install 7-Zip from https://7-zip.org/download.html. I downloaded `7z1900.exe`. Add `C:\Program Files (x86)\7-Zip` to your path.
|
||||
|
||||
Download Tor Browser and extract the binaries:
|
||||
|
||||
```sh
|
||||
poetry run python scripts\get-tor-windows.py
|
||||
poetry run python ./scripts/get-tor.py [platform]
|
||||
```
|
||||
|
||||
### Compile dependencies
|
||||
|
||||
Install Go. The simplest way to make sure everything works is to install Go by following [these instructions](https://golang.org/doc/install). (In Windows, make sure to install the 32-bit version of Go, such as `go1.17.5.windows-386.msi`.)
|
||||
Install Go. The simplest way to make sure everything works is to install Go by following [these instructions](https://golang.org/doc/install).
|
||||
|
||||
Download and compile `meek-client`:
|
||||
Compile pluggable transports:
|
||||
|
||||
```sh
|
||||
./scripts/build-meek-client.py
|
||||
```
|
||||
|
||||
Or in Windows:
|
||||
**Windows users, in PowerShell:**
|
||||
|
||||
```powershell
|
||||
python .\scripts\build-meek-client.py
|
||||
.\scripts\build-pt-obfs4proxy.ps1
|
||||
.\scripts\build-pt-snowflake.ps1
|
||||
.\scripts\build-pt-meek.ps1
|
||||
```
|
||||
|
||||
**macOS and Linux users:**
|
||||
|
||||
```sh
|
||||
./scripts/build-pt-obfs4proxy.sh
|
||||
./scripts/build-pt-snowflake.sh
|
||||
./scripts/build-pt-meek.sh
|
||||
```
|
||||
|
||||
### Running OnionShare from the source code tree
|
||||
|
|
|
@ -507,12 +507,12 @@ class GuiCommon:
|
|||
|
||||
if self.common.platform == "Windows":
|
||||
base_path = self.get_resource_path("tor")
|
||||
tor_path = os.path.join(base_path, "Tor", "tor.exe")
|
||||
obfs4proxy_file_path = os.path.join(base_path, "Tor", "obfs4proxy.exe")
|
||||
snowflake_file_path = os.path.join(base_path, "Tor", "snowflake-client.exe")
|
||||
meek_client_file_path = os.path.join(base_path, "Tor", "meek-client.exe")
|
||||
tor_geo_ip_file_path = os.path.join(base_path, "Data", "Tor", "geoip")
|
||||
tor_geo_ipv6_file_path = os.path.join(base_path, "Data", "Tor", "geoip6")
|
||||
tor_path = os.path.join(base_path, "tor.exe")
|
||||
obfs4proxy_file_path = os.path.join(base_path, "obfs4proxy.exe")
|
||||
snowflake_file_path = os.path.join(base_path, "snowflake-client.exe")
|
||||
meek_client_file_path = os.path.join(base_path, "meek-client.exe")
|
||||
tor_geo_ip_file_path = os.path.join(base_path, "geoip")
|
||||
tor_geo_ipv6_file_path = os.path.join(base_path, "geoip6")
|
||||
elif self.common.platform == "Darwin":
|
||||
base_path = self.get_resource_path("tor")
|
||||
tor_path = os.path.join(base_path, "tor")
|
||||
|
@ -613,7 +613,9 @@ class ToggleCheckbox(QtWidgets.QCheckBox):
|
|||
x = (
|
||||
rect.width() - rect.x() - self.w + 20
|
||||
) # 20 is the padding between text and toggle
|
||||
y = self.height() / 2 - self.h / 2 + 16 # 16 is the padding top for the checkbox
|
||||
y = (
|
||||
self.height() / 2 - self.h / 2 + 16
|
||||
) # 16 is the padding top for the checkbox
|
||||
self.toggleRect = QtCore.QRect(x, y, self.w, self.h)
|
||||
painter.setBrush(QtGui.QColor(self.bg_color))
|
||||
painter.drawRoundedRect(x, y, self.w, self.h, self.h / 2, self.h / 2)
|
||||
|
|
|
@ -24,6 +24,6 @@
|
|||
<update_contact>micah@micahflee.com</update_contact>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release type="development" date="2022-01-17" version="2.5" />
|
||||
<release type="development" date="2022-06-19" version="2.6" />
|
||||
</releases>
|
||||
</component>
|
||||
|
|
|
@ -1,308 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import inspect
|
||||
import subprocess
|
||||
import shutil
|
||||
import itertools
|
||||
import glob
|
||||
|
||||
root = os.path.dirname(
|
||||
os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def run(cmd, cwd=None, error_ok=False):
|
||||
print(f"{cmd} # cwd={cwd}")
|
||||
subprocess.run(cmd, cwd=cwd, check=True)
|
||||
|
||||
|
||||
def get_size(dir):
|
||||
size = 0
|
||||
for path, dirs, files in os.walk(dir):
|
||||
for f in files:
|
||||
fp = os.path.join(path, f)
|
||||
size += os.path.getsize(fp)
|
||||
return size
|
||||
|
||||
|
||||
def codesign(path, entitlements, identity):
|
||||
run(
|
||||
[
|
||||
"codesign",
|
||||
"--sign",
|
||||
identity,
|
||||
"--entitlements",
|
||||
str(entitlements),
|
||||
"--timestamp",
|
||||
"--deep",
|
||||
"--force",
|
||||
"--options",
|
||||
"runtime,library",
|
||||
str(path),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
desktop_dir = f"{root}/desktop"
|
||||
app_dir = f"{desktop_dir}/build/OnionShare.app"
|
||||
|
||||
print("○ Clean up from last build")
|
||||
if os.path.exists(f"{desktop_dir}/build"):
|
||||
shutil.rmtree(f"{desktop_dir}/build")
|
||||
if os.path.exists(f"{desktop_dir}/dist"):
|
||||
shutil.rmtree(f"{desktop_dir}/dist")
|
||||
|
||||
print("○ Building binaries")
|
||||
run(
|
||||
[
|
||||
shutil.which("python"),
|
||||
"setup-freeze.py",
|
||||
"bdist_mac",
|
||||
],
|
||||
desktop_dir,
|
||||
)
|
||||
before_size = get_size(f"{app_dir}")
|
||||
|
||||
print("○ Delete unused Qt Frameworks")
|
||||
for framework in [
|
||||
"Qt3DAnimation",
|
||||
"Qt3DCore",
|
||||
"Qt3DExtras",
|
||||
"Qt3DInput",
|
||||
"Qt3DLogic",
|
||||
"Qt3DQuick",
|
||||
"Qt3DQuickAnimation",
|
||||
"Qt3DQuickExtras",
|
||||
"Qt3DQuickInput",
|
||||
"Qt3DQuickRender",
|
||||
"Qt3DQuickScene2D",
|
||||
"Qt3DRender",
|
||||
"QtBluetooth",
|
||||
"QtBodymovin",
|
||||
"QtCharts",
|
||||
"QtConcurrent",
|
||||
"QtDataVisualization",
|
||||
"QtDesigner",
|
||||
"QtDesignerComponents",
|
||||
"QtGamepad",
|
||||
"QtHelp",
|
||||
"QtLocation",
|
||||
"QtMultimedia",
|
||||
"QtMultimediaQuick",
|
||||
"QtMultimediaWidgets",
|
||||
"QtNetwork",
|
||||
"QtNetworkAuth",
|
||||
"QtNfc",
|
||||
"QtOpenGL",
|
||||
"QtPdf",
|
||||
"QtPdfWidgets",
|
||||
"QtPositioning",
|
||||
"QtPositioningQuick",
|
||||
"QtPrintSupport",
|
||||
"QtPurchasing",
|
||||
"QtQml",
|
||||
"QtQmlModels",
|
||||
"QtQmlWorkerScript",
|
||||
"QtQuick",
|
||||
"QtQuick3D",
|
||||
"QtQuick3DAssetImport",
|
||||
"QtQuick3DRender",
|
||||
"QtQuick3DRuntimeRender",
|
||||
"QtQuick3DUtils",
|
||||
"QtQuickControls2",
|
||||
"QtQuickParticles",
|
||||
"QtQuickShapes",
|
||||
"QtQuickTemplates2",
|
||||
"QtQuickTest",
|
||||
"QtQuickWidgets",
|
||||
"QtRemoteObjects",
|
||||
"QtRepParser",
|
||||
"QtScript",
|
||||
"QtScriptTools",
|
||||
"QtScxml",
|
||||
"QtSensors",
|
||||
"QtSerialBus",
|
||||
"QtSerialPort",
|
||||
"QtSql",
|
||||
"QtSvg",
|
||||
"QtTest",
|
||||
"QtTextToSpeech",
|
||||
"QtUiPlugin",
|
||||
"QtVirtualKeyboard",
|
||||
"QtWebChannel",
|
||||
"QtWebEngine",
|
||||
"QtWebEngineCore",
|
||||
"QtWebEngineWidgets",
|
||||
"QtWebSockets",
|
||||
"QtWebView",
|
||||
"QtXml",
|
||||
"QtXmlPatterns",
|
||||
]:
|
||||
shutil.rmtree(
|
||||
f"{app_dir}/Contents/MacOS/lib/PySide2/Qt/lib/{framework}.framework"
|
||||
)
|
||||
try:
|
||||
os.remove(
|
||||
f"{app_dir}/Contents/MacOS/lib/PySide2/{framework}.abi3.so"
|
||||
)
|
||||
os.remove(
|
||||
f"{app_dir}/Contents/MacOS/lib/PySide2/{framework}.pyi"
|
||||
)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
print("○ Move files around so Apple will notarize")
|
||||
# https://github.com/marcelotduarte/cx_Freeze/issues/594
|
||||
# https://gist.github.com/TechnicalPirate/259a9c24878fcad948452cb148af2a2c#file-custom_bdist_mac-py-L415
|
||||
|
||||
# Move lib from MacOS into Resources
|
||||
os.rename(
|
||||
f"{app_dir}/Contents/MacOS/lib",
|
||||
f"{app_dir}/Contents/Resources/lib",
|
||||
)
|
||||
run(
|
||||
["ln", "-s", "../Resources/lib"],
|
||||
cwd=f"{app_dir}/Contents/MacOS",
|
||||
)
|
||||
|
||||
# Move frameworks from Resources/lib into Frameworks
|
||||
os.makedirs(f"{app_dir}/Contents/Frameworks", exist_ok=True)
|
||||
for framework_filename in glob.glob(
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/Qt/lib/Qt*.framework"
|
||||
):
|
||||
basename = os.path.basename(framework_filename)
|
||||
|
||||
os.rename(framework_filename, f"{app_dir}/Contents/Frameworks/{basename}")
|
||||
run(
|
||||
["ln", "-s", f"../../../../../Frameworks/{basename}"],
|
||||
cwd=f"{app_dir}/Contents/Resources/lib/PySide2/Qt/lib",
|
||||
)
|
||||
if os.path.exists(f"{app_dir}/Contents/Frameworks/{basename}/Resources"):
|
||||
os.rename(
|
||||
f"{app_dir}/Contents/Frameworks/{basename}/Resources",
|
||||
f"{app_dir}/Contents/Frameworks/{basename}/Versions/5/Resources"
|
||||
)
|
||||
run(
|
||||
["ln", "-s", "Versions/5/Resources"],
|
||||
cwd=f"{app_dir}/Contents/Frameworks/{basename}",
|
||||
)
|
||||
|
||||
run(
|
||||
["ln", "-s", "5", "Current"],
|
||||
cwd=f"{app_dir}/Contents/Frameworks/{basename}/Versions",
|
||||
)
|
||||
|
||||
# Move Qt plugins
|
||||
os.rename(
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/Qt/plugins",
|
||||
f"{app_dir}/Contents/Frameworks/plugins",
|
||||
)
|
||||
run(
|
||||
["ln", "-s", "../../../../Frameworks/plugins"],
|
||||
cwd=f"{app_dir}/Contents/Resources/lib/PySide2/Qt",
|
||||
)
|
||||
|
||||
print("○ Delete more unused PySide2 stuff to save space")
|
||||
for filename in [
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/Designer.app",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/examples",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/glue",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/include",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/pyside2-lupdate",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/Qt/qml",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/libpyside2.abi3.5.15.dylib",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/Qt/lib/QtRepParser.framework",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/Qt/lib/QtUiPlugin.framework",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/Qt/lib/QtWebEngineCore.framework/Helpers",
|
||||
f"{app_dir}/Contents/Resources/lib/shiboken2/libshiboken2.abi3.5.15.dylib",
|
||||
f"{app_dir}/Contents/Resources/lib/shiboken2/docs",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/rcc",
|
||||
f"{app_dir}/Contents/Resources/lib/PySide2/uic",
|
||||
]:
|
||||
if os.path.isdir(filename):
|
||||
shutil.rmtree(filename)
|
||||
elif os.path.isfile(filename):
|
||||
os.remove(filename)
|
||||
else:
|
||||
print(f"Cannot delete, filename not found: {filename}")
|
||||
|
||||
after_size = get_size(f"{app_dir}")
|
||||
freed_bytes = before_size - after_size
|
||||
freed_mb = int(freed_bytes / 1024 / 1024)
|
||||
print(f"○ Freed {freed_mb} mb")
|
||||
|
||||
print("○ Sign app bundle")
|
||||
identity_name_application = "Developer ID Application: Micah Lee (N9B95FDWH4)"
|
||||
entitlements_plist_path = f"{desktop_dir}/package/Entitlements.plist"
|
||||
|
||||
for path in itertools.chain(
|
||||
glob.glob(f"{app_dir}/Contents/Resources/lib/**/*.so", recursive=True),
|
||||
glob.glob(f"{app_dir}/Contents/Resources/lib/**/*.dylib", recursive=True),
|
||||
[
|
||||
f"{app_dir}/Contents/Frameworks/QtCore.framework/Versions/5/QtCore",
|
||||
f"{app_dir}/Contents/Frameworks/QtDBus.framework/Versions/5/QtDBus",
|
||||
f"{app_dir}/Contents/Frameworks/QtGui.framework/Versions/5/QtGui",
|
||||
f"{app_dir}/Contents/Frameworks/QtMacExtras.framework/Versions/5/QtMacExtras",
|
||||
f"{app_dir}/Contents/Frameworks/QtWidgets.framework/Versions/5/QtWidgets",
|
||||
f"{app_dir}/Contents/Resources/lib/Python",
|
||||
f"{app_dir}/Contents/Resources/lib/onionshare/resources/tor/meek-client",
|
||||
f"{app_dir}/Contents/Resources/lib/onionshare/resources/tor/obfs4proxy",
|
||||
f"{app_dir}/Contents/Resources/lib/onionshare/resources/tor/snowflake-client",
|
||||
f"{app_dir}/Contents/Resources/lib/onionshare/resources/tor/tor",
|
||||
f"{app_dir}/Contents/Resources/lib/onionshare/resources/tor/libevent-2.1.7.dylib",
|
||||
f"{app_dir}/Contents/MacOS/onionshare",
|
||||
f"{app_dir}/Contents/MacOS/onionshare-cli",
|
||||
f"{app_dir}",
|
||||
],
|
||||
):
|
||||
codesign(path, entitlements_plist_path, identity_name_application)
|
||||
|
||||
print(f"○ Signed app bundle: {app_dir}")
|
||||
|
||||
if not os.path.exists("/usr/local/bin/create-dmg"):
|
||||
print("○ Error: create-dmg is not installed")
|
||||
return
|
||||
|
||||
print("○ Create DMG")
|
||||
version_filename = f"{root}/cli/onionshare_cli/resources/version.txt"
|
||||
with open(version_filename) as f:
|
||||
version = f.read().strip()
|
||||
|
||||
os.makedirs(f"{desktop_dir}/dist", exist_ok=True)
|
||||
dmg_path = f"{desktop_dir}/dist/OnionShare-{version}.dmg"
|
||||
run(
|
||||
[
|
||||
"create-dmg",
|
||||
"--volname",
|
||||
"OnionShare",
|
||||
"--volicon",
|
||||
f"{desktop_dir}/onionshare/resources/onionshare.icns",
|
||||
"--window-size",
|
||||
"400",
|
||||
"200",
|
||||
"--icon-size",
|
||||
"100",
|
||||
"--icon",
|
||||
"OnionShare.app",
|
||||
"100",
|
||||
"70",
|
||||
"--hide-extension",
|
||||
"OnionShare.app",
|
||||
"--app-drop-link",
|
||||
"300",
|
||||
"70",
|
||||
dmg_path,
|
||||
f"{app_dir}",
|
||||
"--identity",
|
||||
identity_name_application,
|
||||
]
|
||||
)
|
||||
|
||||
print(f"○ Finished building DMG: {dmg_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
68
desktop/poetry.lock
generated
68
desktop/poetry.lock
generated
|
@ -62,7 +62,7 @@ python-versions = "*"
|
|||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2022.5.18.1"
|
||||
version = "2022.6.15"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -104,7 +104,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
|||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
description = "Cross-platform colored terminal text."
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -112,18 +112,24 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|||
|
||||
[[package]]
|
||||
name = "cx-freeze"
|
||||
version = "6.10"
|
||||
version = "6.11.0"
|
||||
description = "Create standalone executables from Python scripts"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
cx-logging = {version = ">=3.0", markers = "sys_platform == \"win32\""}
|
||||
cx-logging = {version = ">=3.0", markers = "sys_platform == \"win32\" and python_version < \"3.10\""}
|
||||
importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""}
|
||||
lief = {version = ">=0.11.5", markers = "sys_platform == \"win32\" and python_version < \"3.10\""}
|
||||
lief = {version = ">=0.11.5", markers = "sys_platform == \"win32\""}
|
||||
packaging = ">=21.0"
|
||||
patchelf = {version = ">=0.12", markers = "sys_platform == \"linux\""}
|
||||
|
||||
[package.extras]
|
||||
dev = ["bump2version (>=1.0.1)", "pre-commit (>=2.17.0)", "pylint (>=2.13.0)", "cibuildwheel (==2.6.0)"]
|
||||
doc = ["sphinx (==4.5.0)", "sphinx-rtd-theme (==1.0.0)"]
|
||||
test = ["nose (==1.3.7)", "pygments (==2.11.2)", "pytest (>=7.0.1)", "pytest-cov (==3.0.0)", "pytest-mock (>=3.6.1)", "pytest-timeout (>=1.4.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "cx-logging"
|
||||
version = "3.0"
|
||||
|
@ -323,7 +329,7 @@ python-versions = "*"
|
|||
|
||||
[[package]]
|
||||
name = "onionshare-cli"
|
||||
version = "2.5"
|
||||
version = "2.6"
|
||||
description = "OnionShare lets you securely and anonymously send and receive files. It works by starting a web server, making it accessible as a Tor onion service, and generating an unguessable web address so others can download files from you, or upload files to you. It does _not_ require setting up a separate server or using a third party file-sharing service."
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -353,7 +359,7 @@ url = "../cli"
|
|||
name = "packaging"
|
||||
version = "21.3"
|
||||
description = "Core utilities for Python packages"
|
||||
category = "dev"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
|
@ -452,7 +458,7 @@ tests = ["pytest (>=3.2.1,!=3.3.0)", "hypothesis (>=3.27.0)"]
|
|||
name = "pyparsing"
|
||||
version = "3.0.7"
|
||||
description = "Python parsing module"
|
||||
category = "dev"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
|
@ -706,7 +712,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
|
|||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = ">=3.6.2,<3.11"
|
||||
content-hash = "60276ce053d95d34415d8bee002e2c39f410ad5c97f2d1948e7ddbdc5da9cc56"
|
||||
content-hash = "80aa2819ec2d5e4dd5acb42f178c196776e05fb7efa5d1b99e5c2626c2208cd9"
|
||||
|
||||
[metadata.files]
|
||||
atomicwrites = [
|
||||
|
@ -750,8 +756,8 @@ cepa = [
|
|||
{file = "cepa-1.8.3.tar.gz", hash = "sha256:1dc6f0b324d37a2ed2ca274648ece8fd2c96a1d2f440f58c0ca17afd4b5ede7a"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2022.5.18.1-py3-none-any.whl", hash = "sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a"},
|
||||
{file = "certifi-2022.5.18.1.tar.gz", hash = "sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7"},
|
||||
{file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"},
|
||||
{file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"},
|
||||
]
|
||||
cffi = [
|
||||
{file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"},
|
||||
|
@ -814,21 +820,35 @@ click = [
|
|||
{file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"},
|
||||
]
|
||||
colorama = [
|
||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||
{file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
|
||||
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
|
||||
]
|
||||
cx-freeze = [
|
||||
{file = "cx_Freeze-6.10-cp310-cp310-win32.whl", hash = "sha256:770e911f70b48e4f309a47e02aaa7e1f6dc659fd1c486f3eebe5c9e9fe70aec2"},
|
||||
{file = "cx_Freeze-6.10-cp310-cp310-win_amd64.whl", hash = "sha256:8d936a872c124c2e2a40da2e898e4fa0d225a165ab606217f75136c14ee8e673"},
|
||||
{file = "cx_Freeze-6.10-cp36-cp36m-win32.whl", hash = "sha256:2be07ffce2dba23618cf736476df6f9837d9887c85f4f92fb3fbfcd090de041a"},
|
||||
{file = "cx_Freeze-6.10-cp36-cp36m-win_amd64.whl", hash = "sha256:59b4cb77f5c82613efbec03815b952a6fe73d4a1805bb370d57a8a1130a181ca"},
|
||||
{file = "cx_Freeze-6.10-cp37-cp37m-win32.whl", hash = "sha256:f03928cbcf8282e688dc1f9fa421044c24f5b7492a7b0fe7f45d5cc6f24c1ebf"},
|
||||
{file = "cx_Freeze-6.10-cp37-cp37m-win_amd64.whl", hash = "sha256:9c4b491affd10065bcdd20dc0ab5239f787affe6d61857811a937ed266faa213"},
|
||||
{file = "cx_Freeze-6.10-cp38-cp38-win32.whl", hash = "sha256:1438db6d59be86e8483ea2bf2ff2f81374ca63d8a1d3a84706173cc1b98dd46f"},
|
||||
{file = "cx_Freeze-6.10-cp38-cp38-win_amd64.whl", hash = "sha256:ec752333fa2e40347902730662785da0ec4576cec976552784a6f60a7a07b45d"},
|
||||
{file = "cx_Freeze-6.10-cp39-cp39-win32.whl", hash = "sha256:08a537681dcd1bcde9742584e91d86ef001fe798386f2834a904652d5b2a468a"},
|
||||
{file = "cx_Freeze-6.10-cp39-cp39-win_amd64.whl", hash = "sha256:a4d2cb00eec6bc72a419370b5b0b5d0f3adf4d8417eb89228981d470cf4c6af6"},
|
||||
{file = "cx_Freeze-6.10.tar.gz", hash = "sha256:e5b71bf57b9881ac142fbebeae2c8b0d3294b56f6e48ab64032321e3b1a2ba27"},
|
||||
{file = "cx_Freeze-6.11.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0fa63ae171ee34dd644331ad9cba0e1627036a11ef23b0ce8569229e4546762f"},
|
||||
{file = "cx_Freeze-6.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8274f4d1c696e6e824f98423b4afa618db4eadecb554d2948c364cb524e46bde"},
|
||||
{file = "cx_Freeze-6.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1897bb479e9ad1d5ff339eb2f59009f618e4651e33f1dd695500b36c29045c75"},
|
||||
{file = "cx_Freeze-6.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9a3f3d7934b93f1a73579f4b19fc7ee37556bee46768e6e8c54ac0d469a8918"},
|
||||
{file = "cx_Freeze-6.11.0-cp310-cp310-win32.whl", hash = "sha256:dfbb70832ecb461798d8d19ca110c1c2f8a622475d22ec49c143a8abf19339b0"},
|
||||
{file = "cx_Freeze-6.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:09ccf1c96354d11f694f1a9f6887b069d40fcf853b1b819d2308747d62efebb7"},
|
||||
{file = "cx_Freeze-6.11.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44cb609f7849176e06fe12bb52459de31a3b68fc1d72279e9b081f18c9276c7a"},
|
||||
{file = "cx_Freeze-6.11.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:986e666a8473e699f2a4ba689cfa017a4955ed79a56e2093df55af8ca3bff56f"},
|
||||
{file = "cx_Freeze-6.11.0-cp36-cp36m-win32.whl", hash = "sha256:07428f54a17cb6e8a889030a357edb6398c1c90b998564b90399e028f538930b"},
|
||||
{file = "cx_Freeze-6.11.0-cp36-cp36m-win_amd64.whl", hash = "sha256:83bb02fa03e0c52fdb078b064cb1c17cf6c0410bd74e768ade10d1708c324b74"},
|
||||
{file = "cx_Freeze-6.11.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:630d0d0d3bcdc69df9af0cc02d84a9ab4f9305bc74513058e30042bfc379dd20"},
|
||||
{file = "cx_Freeze-6.11.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea2f4f5bea120f88d53ca32a71ccf1b6758dc82ed468f944338ed8535eec550e"},
|
||||
{file = "cx_Freeze-6.11.0-cp37-cp37m-win32.whl", hash = "sha256:70835e9d6475fb9a7f207d74bd0f3be1bd2d59b6cd09941e032ae512e7fdedee"},
|
||||
{file = "cx_Freeze-6.11.0-cp37-cp37m-win_amd64.whl", hash = "sha256:0c141cba6f9e9e9923b1cfbbb0cb44655848bf50c57249d8058fe388c18116f3"},
|
||||
{file = "cx_Freeze-6.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:04453a2de82f81356be1c183ee0ab2fbf024791451970dbdde4f9f1bf6301b6a"},
|
||||
{file = "cx_Freeze-6.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4324f1abf6e0d0a017e9fabb0f3805acd08f5b3b7eb059395e08e7ff2b6e9b83"},
|
||||
{file = "cx_Freeze-6.11.0-cp38-cp38-win32.whl", hash = "sha256:81cacbc22c0f3be8e3807b9690c73eb682b16e5a2358f6bd213af6bf88402061"},
|
||||
{file = "cx_Freeze-6.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:c2315a1634108fc94398bef3ef63435d53c8ecd1cbcce9e05c4bcca61a833d62"},
|
||||
{file = "cx_Freeze-6.11.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f4da77d44b910d4b18fbe95a487ddc081ebe5cd4f35971b496c1fff0420cf495"},
|
||||
{file = "cx_Freeze-6.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:868837ca628fe9501c317e475f68d04f442f98e6174cb77b7ec413061e3613d7"},
|
||||
{file = "cx_Freeze-6.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b92dda05bd7d5c1a2632de837ea738d73070af6effc035a016ab820ee1ec51a"},
|
||||
{file = "cx_Freeze-6.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:920e6ff71b7fe1dd77d7a01b7de04a7856ba4803964ce2acab1962d2212a2746"},
|
||||
{file = "cx_Freeze-6.11.0-cp39-cp39-win32.whl", hash = "sha256:81a6a56b8ad83635a441eb0049cff65993c53fcf7c46f49b4cf31998facb24d6"},
|
||||
{file = "cx_Freeze-6.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:ee81a20340f830182fba3e42b32a0fb1e455324d6d6c3f6c3b3020d619e04c2d"},
|
||||
{file = "cx_Freeze-6.11.0.tar.gz", hash = "sha256:c461fc3a33cbdfc2b6bbdd02cb0ea048d496e9e33067489cae778d929379bee8"},
|
||||
]
|
||||
cx-logging = [
|
||||
{file = "cx_Logging-3.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9fcd297e5c51470521c47eff0f86ba844aeca6be97e13c3e2114ebdf03fa3c96"},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "onionshare"
|
||||
version = "2.5"
|
||||
version = "2.6"
|
||||
description = "OnionShare lets you securely and anonymously send and receive files. It works by starting a web server, making it accessible as a Tor onion service, and generating an unguessable web address so others can download files from you, or upload files to you. It does _not_ require setting up a separate server or using a third party file-sharing service."
|
||||
authors = ["Micah Lee <micah@micahflee.com>"]
|
||||
license = "GPLv3+"
|
||||
|
@ -13,6 +13,7 @@ qrcode = "*"
|
|||
cx_freeze = "*"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
click = "*"
|
||||
black = "*"
|
||||
pytest = "*"
|
||||
pytest-faulthandler = "*"
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
OnionShare | https://onionshare.org/
|
||||
|
||||
Copyright (C) 2014-2022 Micah Lee, et al. <micah@micahflee.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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 os
|
||||
import requests
|
||||
|
||||
|
||||
class UpdateTorBridges:
|
||||
"""
|
||||
Update the built-in Tor Bridges in OnionShare's torrc templates.
|
||||
"""
|
||||
|
||||
def __init__(self, root_path):
|
||||
self.root_path = root_path
|
||||
torrc_template_dir = os.path.join(
|
||||
self.root_path, os.pardir, "cli/onionshare_cli/resources"
|
||||
)
|
||||
endpoint = "https://bridges.torproject.org/moat/circumvention/builtin"
|
||||
r = requests.post(
|
||||
endpoint,
|
||||
headers={"Content-Type": "application/vnd.api+json"},
|
||||
)
|
||||
if r.status_code != 200:
|
||||
print(
|
||||
f"There was a problem fetching the latest built-in bridges: status_code={r.status_code}"
|
||||
)
|
||||
return False
|
||||
|
||||
result = r.json()
|
||||
|
||||
if "errors" in result:
|
||||
print(
|
||||
f"There was a problem fetching the latest built-in bridges: errors={result['errors']}"
|
||||
)
|
||||
return False
|
||||
|
||||
for bridge_type in ["meek-azure", "obfs4", "snowflake"]:
|
||||
if result[bridge_type]:
|
||||
if bridge_type == "meek-azure":
|
||||
torrc_template_extension = "meek_lite_azure"
|
||||
else:
|
||||
torrc_template_extension = bridge_type
|
||||
torrc_template = os.path.join(
|
||||
self.root_path,
|
||||
torrc_template_dir,
|
||||
f"torrc_template-{torrc_template_extension}",
|
||||
)
|
||||
|
||||
with open(torrc_template, "w") as f:
|
||||
f.write(f"# Enable built-in {bridge_type} bridge\n")
|
||||
bridges = result[bridge_type]
|
||||
# Sorts the bridges numerically by IP, since they come back in
|
||||
# random order from the API each time, and create noisy git diff.
|
||||
bridges.sort(key=lambda s: s.split()[1])
|
||||
for item in bridges:
|
||||
f.write(f"Bridge {item}\n")
|
321
desktop/scripts/build-macos.py
Normal file
321
desktop/scripts/build-macos.py
Normal file
|
@ -0,0 +1,321 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import inspect
|
||||
import click
|
||||
import subprocess
|
||||
import shutil
|
||||
import glob
|
||||
import itertools
|
||||
|
||||
root = os.path.dirname(
|
||||
os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
)
|
||||
)
|
||||
desktop_dir = os.path.join(root, "desktop")
|
||||
|
||||
identity_name_application = "Developer ID Application: Micah Lee (N9B95FDWH4)"
|
||||
entitlements_plist_path = f"{desktop_dir}/package/Entitlements.plist"
|
||||
|
||||
|
||||
def get_app_path():
|
||||
return os.path.join(desktop_dir, "build", "OnionShare.app")
|
||||
|
||||
|
||||
def run(cmd, cwd=None, error_ok=False):
|
||||
print(f"{cmd} # cwd={cwd}")
|
||||
subprocess.run(cmd, cwd=cwd, check=True)
|
||||
|
||||
|
||||
def get_size(dir):
|
||||
size = 0
|
||||
for path, dirs, files in os.walk(dir):
|
||||
for f in files:
|
||||
fp = os.path.join(path, f)
|
||||
size += os.path.getsize(fp)
|
||||
return size
|
||||
|
||||
|
||||
def sign(path, entitlements, identity):
|
||||
run(
|
||||
[
|
||||
"codesign",
|
||||
"--sign",
|
||||
identity,
|
||||
"--entitlements",
|
||||
str(entitlements),
|
||||
"--timestamp",
|
||||
"--deep",
|
||||
"--force",
|
||||
"--options",
|
||||
"runtime,library",
|
||||
str(path),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@click.group()
|
||||
def main():
|
||||
"""
|
||||
macOS build tasks
|
||||
"""
|
||||
|
||||
|
||||
@main.command()
|
||||
def cleanup_build():
|
||||
"""Delete unused PySide2 stuff to save space"""
|
||||
app_path = get_app_path()
|
||||
before_size = get_size(app_path)
|
||||
|
||||
print("> Delete unused Qt Frameworks")
|
||||
for framework in [
|
||||
"QtMultimediaQuick",
|
||||
"QtQuickControls2",
|
||||
"QtQuickParticles",
|
||||
"QtRemoteObjects",
|
||||
"Qt3DInput",
|
||||
"QtPdfWidgets",
|
||||
"QtScriptTools",
|
||||
"QtNetworkAuth",
|
||||
"QtDataVisualization",
|
||||
"QtWebEngineCore",
|
||||
"Qt3DQuickRender",
|
||||
"Qt3DQuickExtras",
|
||||
"QtQuick3DRender",
|
||||
"QtDesigner",
|
||||
"QtNfc",
|
||||
"QtQuick3DAssetImport",
|
||||
"QtBodymovin",
|
||||
"QtWebEngineWidgets",
|
||||
"QtQuickWidgets",
|
||||
"Qt3DQuickInput",
|
||||
"Qt3DQuickScene2D",
|
||||
"QtUiPlugin",
|
||||
"QtPdf",
|
||||
"Qt3DRender",
|
||||
"QtQuick3DRuntimeRender",
|
||||
"QtHelp",
|
||||
"QtPrintSupport",
|
||||
"QtCharts",
|
||||
"QtWebSockets",
|
||||
"QtQuick3DUtils",
|
||||
"QtQuickTemplates2",
|
||||
"QtScript",
|
||||
"QtPositioningQuick",
|
||||
"Qt3DCore",
|
||||
"QtLocation",
|
||||
"QtXml",
|
||||
"QtSerialPort",
|
||||
"QtWebView",
|
||||
"QtQuick",
|
||||
"QtScxml",
|
||||
"QtQml",
|
||||
"Qt3DExtras",
|
||||
"QtWebChannel",
|
||||
"QtMultimedia",
|
||||
"QtQmlWorkerScript",
|
||||
"QtVirtualKeyboard",
|
||||
"QtPurchasing",
|
||||
"QtOpenGL",
|
||||
"QtWebEngine",
|
||||
"Qt3DQuick",
|
||||
"QtTest",
|
||||
"QtPositioning",
|
||||
"QtBluetooth",
|
||||
"QtQuick3D",
|
||||
"Qt3DLogic",
|
||||
"QtQuickShapes",
|
||||
"QtQuickTest",
|
||||
"QtNetwork",
|
||||
"QtXmlPatterns",
|
||||
"QtSvg",
|
||||
"QtDesignerComponents",
|
||||
"QtMultimediaWidgets",
|
||||
"QtQmlModels",
|
||||
"Qt3DQuickAnimation",
|
||||
"QtSensors",
|
||||
"Qt3DAnimation",
|
||||
"QtRepParser",
|
||||
"QtTextToSpeech",
|
||||
"QtGamepad",
|
||||
"QtSerialBus",
|
||||
"QtSql",
|
||||
"QtConcurrent"
|
||||
]:
|
||||
shutil.rmtree(
|
||||
f"{app_path}/Contents/MacOS/lib/PySide2/Qt/lib/{framework}.framework"
|
||||
)
|
||||
print(
|
||||
f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/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")
|
||||
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")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
print("> Move files around so Apple will notarize")
|
||||
# https://github.com/marcelotduarte/cx_Freeze/issues/594
|
||||
# https://gist.github.com/TechnicalPirate/259a9c24878fcad948452cb148af2a2c#file-custom_bdist_mac-py-L415
|
||||
|
||||
# Move lib from MacOS into Resources
|
||||
os.rename(
|
||||
f"{app_path}/Contents/MacOS/lib",
|
||||
f"{app_path}/Contents/Resources/lib",
|
||||
)
|
||||
run(
|
||||
["ln", "-s", "../Resources/lib"],
|
||||
cwd=f"{app_path}/Contents/MacOS",
|
||||
)
|
||||
|
||||
# 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"
|
||||
):
|
||||
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",
|
||||
)
|
||||
if os.path.exists(f"{app_path}/Contents/Frameworks/{basename}/Resources"):
|
||||
os.rename(
|
||||
f"{app_path}/Contents/Frameworks/{basename}/Resources",
|
||||
f"{app_path}/Contents/Frameworks/{basename}/Versions/5/Resources",
|
||||
)
|
||||
run(
|
||||
["ln", "-s", "Versions/5/Resources"],
|
||||
cwd=f"{app_path}/Contents/Frameworks/{basename}",
|
||||
)
|
||||
|
||||
try:
|
||||
run(
|
||||
["ln", "-s", "5", "Current"],
|
||||
cwd=f"{app_path}/Contents/Frameworks/{basename}/Versions",
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Move Qt plugins
|
||||
os.rename(
|
||||
f"{app_path}/Contents/Resources/lib/PySide2/Qt/plugins",
|
||||
f"{app_path}/Contents/Frameworks/plugins",
|
||||
)
|
||||
run(
|
||||
["ln", "-s", "../../../../Frameworks/plugins"],
|
||||
cwd=f"{app_path}/Contents/Resources/lib/PySide2/Qt",
|
||||
)
|
||||
|
||||
print("> Delete more unused PySide2 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",
|
||||
]:
|
||||
if os.path.isfile(filename) or os.path.islink(filename):
|
||||
os.remove(filename)
|
||||
print(f"Deleted: {filename}")
|
||||
elif os.path.isdir(filename):
|
||||
shutil.rmtree(filename)
|
||||
print(f"Deleted: {filename}")
|
||||
else:
|
||||
print(f"Cannot delete, filename not found: {filename}")
|
||||
|
||||
after_size = get_size(f"{app_path}")
|
||||
freed_bytes = before_size - after_size
|
||||
freed_mb = int(freed_bytes / 1024 / 1024)
|
||||
print(f"> Freed {freed_mb} mb")
|
||||
|
||||
|
||||
@main.command()
|
||||
@click.argument("app_path")
|
||||
def codesign(app_path):
|
||||
"""Sign macOS binaries before packaging"""
|
||||
for path in itertools.chain(
|
||||
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/Resources/lib/Python",
|
||||
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/meek-client",
|
||||
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/obfs4proxy",
|
||||
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/snowflake-client",
|
||||
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/tor",
|
||||
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/libevent-2.1.7.dylib",
|
||||
f"{app_path}/Contents/MacOS/onionshare",
|
||||
f"{app_path}/Contents/MacOS/onionshare-cli",
|
||||
f"{app_path}",
|
||||
],
|
||||
):
|
||||
sign(path, entitlements_plist_path, identity_name_application)
|
||||
|
||||
print(f"> Signed app bundle: {app_path}")
|
||||
|
||||
|
||||
@main.command()
|
||||
@click.argument("app_path")
|
||||
def package(app_path):
|
||||
"""Build the DMG package"""
|
||||
if not os.path.exists("/usr/local/bin/create-dmg"):
|
||||
print("> Error: create-dmg is not installed")
|
||||
return
|
||||
|
||||
print("> Create DMG")
|
||||
version_filename = f"{root}/cli/onionshare_cli/resources/version.txt"
|
||||
with open(version_filename) as f:
|
||||
version = f.read().strip()
|
||||
|
||||
os.makedirs(f"{desktop_dir}/dist", exist_ok=True)
|
||||
dmg_path = f"{desktop_dir}/dist/OnionShare-{version}.dmg"
|
||||
run(
|
||||
[
|
||||
"create-dmg",
|
||||
"--volname",
|
||||
"OnionShare",
|
||||
"--volicon",
|
||||
f"{desktop_dir}/onionshare/resources/onionshare.icns",
|
||||
"--window-size",
|
||||
"400",
|
||||
"200",
|
||||
"--icon-size",
|
||||
"100",
|
||||
"--icon",
|
||||
"OnionShare.app",
|
||||
"100",
|
||||
"70",
|
||||
"--hide-extension",
|
||||
"OnionShare.app",
|
||||
"--app-drop-link",
|
||||
"300",
|
||||
"70",
|
||||
dmg_path,
|
||||
app_path,
|
||||
"--identity",
|
||||
identity_name_application,
|
||||
]
|
||||
)
|
||||
|
||||
print(f"> Finished building DMG: {dmg_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,68 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
OnionShare | https://onionshare.org/
|
||||
|
||||
Copyright (C) 2014-2022 Micah Lee, et al. <micah@micahflee.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
"""
|
||||
This script downloads a pre-built tor binary to bundle with OnionShare.
|
||||
In order to avoid a Mac gnupg dependency, I manually verify the signature
|
||||
and hard-code the sha256 hash.
|
||||
"""
|
||||
import shutil
|
||||
import os
|
||||
import subprocess
|
||||
import inspect
|
||||
import platform
|
||||
|
||||
|
||||
def main():
|
||||
if shutil.which("go") is None:
|
||||
print("Install go: https://golang.org/doc/install")
|
||||
return
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
"go",
|
||||
"install",
|
||||
"git.torproject.org/pluggable-transports/meek.git/meek-client@v0.37.0",
|
||||
]
|
||||
)
|
||||
|
||||
root_path = os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
)
|
||||
if platform.system() == "Windows":
|
||||
dist_path = os.path.join(root_path, "onionshare", "resources", "tor", "Tor")
|
||||
bin_filename = "meek-client.exe"
|
||||
else:
|
||||
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
|
||||
bin_filename = "meek-client"
|
||||
|
||||
bin_path = os.path.join(os.path.expanduser("~"), "go", "bin", bin_filename)
|
||||
shutil.copyfile(
|
||||
os.path.join(bin_path),
|
||||
os.path.join(dist_path, bin_filename),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, bin_filename), 0o755)
|
||||
|
||||
print(f"Installed {bin_filename} in {dist_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
9
desktop/scripts/build-pt-meek.ps1
Normal file
9
desktop/scripts/build-pt-meek.ps1
Normal file
|
@ -0,0 +1,9 @@
|
|||
$env:MEEK_TAG = 'v0.37.0'
|
||||
|
||||
New-Item -ItemType Directory -Force -Path .\build\meek
|
||||
cd .\build\meek
|
||||
git clone https://git.torproject.org/pluggable-transports/meek.git
|
||||
cd meek
|
||||
git checkout $MEEK_TAG
|
||||
go build .\meek-client
|
||||
Move-Item -Path .\meek-client.exe -Destination ..\..\..\onionshare\resources\tor\meek-client.exe
|
9
desktop/scripts/build-pt-meek.sh
Executable file
9
desktop/scripts/build-pt-meek.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
MEEK_TAG=v0.37.0
|
||||
|
||||
mkdir -p ./build/meek
|
||||
cd ./build/meek
|
||||
git clone https://git.torproject.org/pluggable-transports/meek.git
|
||||
cd meek
|
||||
git checkout $MEEK_TAG
|
||||
go build -o ../../../onionshare/resources/tor/meek-client ./meek-client
|
9
desktop/scripts/build-pt-obfs4proxy.ps1
Normal file
9
desktop/scripts/build-pt-obfs4proxy.ps1
Normal file
|
@ -0,0 +1,9 @@
|
|||
$env:OBFS4PROXY_TAG = 'obfs4proxy-0.0.13'
|
||||
|
||||
New-Item -ItemType Directory -Force -Path .\build\obfs4proxy
|
||||
cd .\build\obfs4proxy
|
||||
git clone https://gitlab.com/yawning/obfs4
|
||||
cd obfs4
|
||||
git checkout $OBFS4PROXY_TAG
|
||||
go build .\obfs4proxy
|
||||
Move-Item -Path .\obfs4proxy.exe -Destination ..\..\..\onionshare\resources\tor\obfs4proxy.exe
|
9
desktop/scripts/build-pt-obfs4proxy.sh
Executable file
9
desktop/scripts/build-pt-obfs4proxy.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
OBFS4PROXY_TAG=obfs4proxy-0.0.13
|
||||
|
||||
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
|
9
desktop/scripts/build-pt-snowflake.ps1
Normal file
9
desktop/scripts/build-pt-snowflake.ps1
Normal file
|
@ -0,0 +1,9 @@
|
|||
$env:SNOWFLAKE_TAG = 'v2.2.0'
|
||||
|
||||
New-Item -ItemType Directory -Force -Path .\build\snowflake
|
||||
cd .\build\snowflake
|
||||
git clone https://git.torproject.org/pluggable-transports/snowflake.git
|
||||
cd snowflake
|
||||
git checkout $SNOWFLAKE_TAG
|
||||
go build .\client
|
||||
Move-Item -Path .\client.exe -Destination ..\..\..\onionshare\resources\tor\snowflake-client.exe
|
9
desktop/scripts/build-pt-snowflake.sh
Executable file
9
desktop/scripts/build-pt-snowflake.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
SNOWFLAKE_TAG=v2.2.0
|
||||
|
||||
mkdir -p ./build/snowflake
|
||||
cd ./build/snowflake
|
||||
git clone https://git.torproject.org/pluggable-transports/snowflake.git
|
||||
cd snowflake
|
||||
git checkout $SNOWFLAKE_TAG
|
||||
go build -o ../../../onionshare/resources/tor/snowflake-client ./client
|
|
@ -1,17 +1,37 @@
|
|||
#!/usr/bin/env python3
|
||||
from distutils.command.build import build
|
||||
import sys
|
||||
import os
|
||||
import inspect
|
||||
import subprocess
|
||||
import click
|
||||
import shutil
|
||||
import subprocess
|
||||
import uuid
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
root = os.path.dirname(
|
||||
os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
)
|
||||
)
|
||||
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):
|
||||
for f in files:
|
||||
fp = os.path.join(path, f)
|
||||
size += os.path.getsize(fp)
|
||||
return size
|
||||
|
||||
|
||||
def run(cmd, cwd=None, error_ok=False):
|
||||
|
@ -23,7 +43,8 @@ def run(cmd, cwd=None, error_ok=False):
|
|||
raise subprocess.CalledProcessError(e)
|
||||
|
||||
|
||||
def sign(filename, cwd=None):
|
||||
def sign(filename):
|
||||
click.echo(f"> Signing {filename}")
|
||||
run(
|
||||
[
|
||||
shutil.which("signtool"),
|
||||
|
@ -32,7 +53,7 @@ def sign(filename, cwd=None):
|
|||
"/d",
|
||||
"OnionShare",
|
||||
"/sha1",
|
||||
"bb1d265ab02272e8fc742f149dcf8751cac63f50",
|
||||
"1a0345732140749bdaa03efe8591b2c2a036884c",
|
||||
"/fd",
|
||||
"SHA256",
|
||||
"/td",
|
||||
|
@ -40,20 +61,10 @@ def sign(filename, cwd=None):
|
|||
"/tr",
|
||||
"http://timestamp.digicert.com",
|
||||
filename,
|
||||
],
|
||||
cwd,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def get_size(dir):
|
||||
size = 0
|
||||
for path, dirs, files in os.walk(dir):
|
||||
for f in files:
|
||||
fp = os.path.join(path, f)
|
||||
size += os.path.getsize(fp)
|
||||
return size
|
||||
|
||||
|
||||
def wix_build_data(dirname, dir_prefix, id_, name):
|
||||
data = {
|
||||
"id": id_,
|
||||
|
@ -73,7 +84,7 @@ def wix_build_data(dirname, dir_prefix, id_, name):
|
|||
id_prefix = id_
|
||||
|
||||
# Skip lib/Pyside2/Examples folder
|
||||
if "\\build\\exe.win32-3.9\\lib\\PySide2\\examples" in dirname:
|
||||
if "\\lib\\PySide2\\examples" in dirname:
|
||||
continue
|
||||
|
||||
id_value = f"{id_prefix}{basename.capitalize().replace('-', '_')}"
|
||||
|
@ -159,33 +170,169 @@ def wix_build_components_xml(root, data):
|
|||
return component_ids
|
||||
|
||||
|
||||
def main():
|
||||
desktop_dir = os.path.join(root, "desktop")
|
||||
def msi_package(build_path, msi_path, product_update_code):
|
||||
print(f"> Build the WiX file")
|
||||
version_filename = os.path.join(
|
||||
build_path, "lib", "onionshare_cli", "resources", "version.txt"
|
||||
)
|
||||
with open(version_filename) as f:
|
||||
version = f.read().strip()
|
||||
# change a version like 2.6.dev1 to just 2.6, for cx_Freeze's sake
|
||||
last_digit = version[-1]
|
||||
if version.endswith(f".dev{last_digit}"):
|
||||
version = version[0:-5]
|
||||
|
||||
print("○ Clean up from last build")
|
||||
if os.path.exists(os.path.join(desktop_dir, "build")):
|
||||
shutil.rmtree(os.path.join(desktop_dir, "build"))
|
||||
if os.path.exists(os.path.join(desktop_dir, "dist")):
|
||||
shutil.rmtree(os.path.join(desktop_dir, "dist"))
|
||||
data = {
|
||||
"id": "TARGETDIR",
|
||||
"name": "SourceDir",
|
||||
"dirs": [
|
||||
{
|
||||
"id": "ProgramFilesFolder",
|
||||
"dirs": [],
|
||||
},
|
||||
{
|
||||
"id": "ProgramMenuFolder",
|
||||
"dirs": [],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
print("○ Building binaries")
|
||||
data["dirs"][0]["dirs"].append(
|
||||
wix_build_data(
|
||||
build_path,
|
||||
".",
|
||||
"INSTALLDIR",
|
||||
"OnionShare",
|
||||
)
|
||||
)
|
||||
|
||||
root_el = ET.Element("Wix", xmlns="http://schemas.microsoft.com/wix/2006/wi")
|
||||
product_el = ET.SubElement(
|
||||
root_el,
|
||||
"Product",
|
||||
Name="OnionShare",
|
||||
Manufacturer="Micah Lee, et al.",
|
||||
Id="*",
|
||||
UpgradeCode="$(var.ProductUpgradeCode)",
|
||||
Language="1033",
|
||||
Codepage="1252",
|
||||
Version="$(var.ProductVersion)",
|
||||
)
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"Package",
|
||||
Id="*",
|
||||
Keywords="Installer",
|
||||
Description="OnionShare $(var.ProductVersion) Installer",
|
||||
Manufacturer="Micah Lee, et al.",
|
||||
InstallerVersion="100",
|
||||
Languages="1033",
|
||||
Compressed="yes",
|
||||
SummaryCodepage="1252",
|
||||
)
|
||||
ET.SubElement(product_el, "Media", Id="1", Cabinet="product.cab", EmbedCab="yes")
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"Icon",
|
||||
Id="ProductIcon",
|
||||
SourceFile=os.path.join(
|
||||
desktop_dir, "onionshare", "resources", "onionshare.ico"
|
||||
),
|
||||
)
|
||||
ET.SubElement(product_el, "Property", Id="ARPPRODUCTICON", Value="ProductIcon")
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"Property",
|
||||
Id="ARPHELPLINK",
|
||||
Value="https://docs.onionshare.org",
|
||||
)
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"Property",
|
||||
Id="ARPURLINFOABOUT",
|
||||
Value="https://onionshare.org",
|
||||
)
|
||||
ET.SubElement(product_el, "UIRef", Id="WixUI_Minimal")
|
||||
ET.SubElement(product_el, "UIRef", Id="WixUI_ErrorProgressText")
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"WixVariable",
|
||||
Id="WixUILicenseRtf",
|
||||
Value=os.path.join(desktop_dir, "package", "license.rtf"),
|
||||
)
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"WixVariable",
|
||||
Id="WixUIDialogBmp",
|
||||
Value=os.path.join(desktop_dir, "package", "dialog.bmp"),
|
||||
)
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"MajorUpgrade",
|
||||
AllowSameVersionUpgrades="yes",
|
||||
DowngradeErrorMessage="A newer version of [ProductName] is already installed. If you are sure you want to downgrade, remove the existing installation via Programs and Features.",
|
||||
)
|
||||
|
||||
wix_build_dir_xml(product_el, data)
|
||||
component_ids = wix_build_components_xml(product_el, data)
|
||||
|
||||
feature_el = ET.SubElement(product_el, "Feature", Id="DefaultFeature", Level="1")
|
||||
for component_id in component_ids:
|
||||
ET.SubElement(feature_el, "ComponentRef", Id=component_id)
|
||||
ET.SubElement(feature_el, "ComponentRef", Id="ApplicationShortcuts")
|
||||
|
||||
with open(os.path.join(build_path, "OnionShare.wxs"), "w") as f:
|
||||
f.write('<?xml version="1.0" encoding="windows-1252"?>\n')
|
||||
f.write(f'<?define ProductVersion = "{version}"?>\n')
|
||||
f.write(f'<?define ProductUpgradeCode = "{product_update_code}"?>\n')
|
||||
|
||||
ET.indent(root_el)
|
||||
f.write(ET.tostring(root_el).decode())
|
||||
|
||||
print(f"> Build the MSI")
|
||||
run(
|
||||
[shutil.which("candle.exe"), "OnionShare.wxs"],
|
||||
build_path,
|
||||
)
|
||||
run(
|
||||
[shutil.which("light.exe"), "-ext", "WixUIExtension", "OnionShare.wixobj"],
|
||||
build_path,
|
||||
)
|
||||
|
||||
print(f"> Prepare OnionShare.msi for signing")
|
||||
run(
|
||||
[
|
||||
shutil.which("python"),
|
||||
"setup-freeze.py",
|
||||
"build",
|
||||
shutil.which("insignia.exe"),
|
||||
"-im",
|
||||
os.path.join(build_path, "OnionShare.msi"),
|
||||
],
|
||||
desktop_dir,
|
||||
error_ok=True,
|
||||
)
|
||||
before_size = get_size(os.path.join(desktop_dir, "build", "exe.win32-3.9"))
|
||||
sign(os.path.join(build_path, "OnionShare.msi"))
|
||||
|
||||
print(f"> Final MSI: {msi_path}")
|
||||
os.makedirs(os.path.join(desktop_dir, "dist"), exist_ok=True)
|
||||
os.rename(
|
||||
os.path.join(build_path, "OnionShare.msi"),
|
||||
msi_path,
|
||||
)
|
||||
|
||||
|
||||
@click.group()
|
||||
def main():
|
||||
"""
|
||||
Windows build tasks
|
||||
"""
|
||||
|
||||
|
||||
@main.command()
|
||||
def cleanup_build():
|
||||
"""Delete unused PySide2 stuff to save space"""
|
||||
build_path = get_build_path()
|
||||
before_size = get_size(build_path)
|
||||
|
||||
print("○ Delete unused PySide2 stuff to save space")
|
||||
for dirname in ["examples", "qml"]:
|
||||
shutil.rmtree(
|
||||
os.path.join(
|
||||
desktop_dir, "build", "exe.win32-3.9", "lib", "PySide2", dirname
|
||||
)
|
||||
)
|
||||
shutil.rmtree(os.path.join(build_path, "lib", "PySide2", dirname))
|
||||
for filename in [
|
||||
"lconvert.exe",
|
||||
"linguist.exe",
|
||||
|
@ -412,174 +559,86 @@ def main():
|
|||
]:
|
||||
os.remove(
|
||||
os.path.join(
|
||||
desktop_dir,
|
||||
"build",
|
||||
"exe.win32-3.9",
|
||||
build_path,
|
||||
"lib",
|
||||
"PySide2",
|
||||
filename.replace("/", "\\"),
|
||||
)
|
||||
)
|
||||
|
||||
after_size = get_size(os.path.join(desktop_dir, "build", "exe.win32-3.9"))
|
||||
after_size = get_size(build_path)
|
||||
freed_bytes = before_size - after_size
|
||||
freed_mb = int(freed_bytes / 1024 / 1024)
|
||||
print(f"○ Freed {freed_mb} mb")
|
||||
print(f"Freed {freed_mb} mb")
|
||||
|
||||
print(f"○ Signing onionshare.exe")
|
||||
sign(os.path.join("build", "exe.win32-3.9", "onionshare.exe"), desktop_dir)
|
||||
|
||||
print(f"○ Signing onionshare-cli.exe")
|
||||
sign(os.path.join("build", "exe.win32-3.9", "onionshare-cli.exe"), desktop_dir)
|
||||
@main.command()
|
||||
@click.argument("win32_path")
|
||||
@click.argument("win64_path")
|
||||
def codesign(win32_path, win64_path):
|
||||
"""Sign Windows binaries before packaging"""
|
||||
paths = [win32_path, win64_path]
|
||||
|
||||
print(f"○ Build the WiX file")
|
||||
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(
|
||||
os.path.join(
|
||||
path,
|
||||
"lib",
|
||||
"onionshare",
|
||||
"resources",
|
||||
"tor",
|
||||
"meek-client.exe",
|
||||
)
|
||||
)
|
||||
sign(
|
||||
os.path.join(
|
||||
path,
|
||||
"lib",
|
||||
"onionshare",
|
||||
"resources",
|
||||
"tor",
|
||||
"obfs4proxy.exe",
|
||||
)
|
||||
)
|
||||
sign(
|
||||
os.path.join(
|
||||
path,
|
||||
"lib",
|
||||
"onionshare",
|
||||
"resources",
|
||||
"tor",
|
||||
"snowflake-client.exe",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@main.command()
|
||||
@click.argument("win32_path")
|
||||
@click.argument("win64_path")
|
||||
def package(win32_path, win64_path):
|
||||
"""Build the MSI package"""
|
||||
version_filename = os.path.join(
|
||||
root, "cli", "onionshare_cli", "resources", "version.txt"
|
||||
)
|
||||
with open(version_filename) as f:
|
||||
version = f.read().strip()
|
||||
|
||||
dist_dir = os.path.join(
|
||||
root,
|
||||
"desktop",
|
||||
"build",
|
||||
"exe.win32-3.9",
|
||||
msi_package(
|
||||
win32_path,
|
||||
os.path.join(desktop_dir, "dist", f"OnionShare-win32-{version}.msi"),
|
||||
"12b9695c-965b-4be0-bc33-21274e809576",
|
||||
)
|
||||
|
||||
data = {
|
||||
"id": "TARGETDIR",
|
||||
"name": "SourceDir",
|
||||
"dirs": [
|
||||
{
|
||||
"id": "ProgramFilesFolder",
|
||||
"dirs": [],
|
||||
},
|
||||
{
|
||||
"id": "ProgramMenuFolder",
|
||||
"dirs": [],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
data["dirs"][0]["dirs"].append(
|
||||
wix_build_data(
|
||||
dist_dir,
|
||||
"exe.win32-3.9",
|
||||
"INSTALLDIR",
|
||||
"OnionShare",
|
||||
)
|
||||
)
|
||||
|
||||
root_el = ET.Element("Wix", xmlns="http://schemas.microsoft.com/wix/2006/wi")
|
||||
product_el = ET.SubElement(
|
||||
root_el,
|
||||
"Product",
|
||||
Name="OnionShare",
|
||||
Manufacturer="Micah Lee, et al.",
|
||||
Id="*",
|
||||
UpgradeCode="$(var.ProductUpgradeCode)",
|
||||
Language="1033",
|
||||
Codepage="1252",
|
||||
Version="$(var.ProductVersion)",
|
||||
)
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"Package",
|
||||
Id="*",
|
||||
Keywords="Installer",
|
||||
Description="OnionShare $(var.ProductVersion) Installer",
|
||||
Manufacturer="Micah Lee, et al.",
|
||||
InstallerVersion="100",
|
||||
Languages="1033",
|
||||
Compressed="yes",
|
||||
SummaryCodepage="1252",
|
||||
)
|
||||
ET.SubElement(product_el, "Media", Id="1", Cabinet="product.cab", EmbedCab="yes")
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"Icon",
|
||||
Id="ProductIcon",
|
||||
SourceFile="..\\onionshare\\resources\\onionshare.ico",
|
||||
)
|
||||
ET.SubElement(product_el, "Property", Id="ARPPRODUCTICON", Value="ProductIcon")
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"Property",
|
||||
Id="ARPHELPLINK",
|
||||
Value="https://docs.onionshare.org",
|
||||
)
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"Property",
|
||||
Id="ARPURLINFOABOUT",
|
||||
Value="https://onionshare.org",
|
||||
)
|
||||
ET.SubElement(product_el, "UIRef", Id="WixUI_Minimal")
|
||||
ET.SubElement(product_el, "UIRef", Id="WixUI_ErrorProgressText")
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"WixVariable",
|
||||
Id="WixUILicenseRtf",
|
||||
Value="..\\package\\license.rtf",
|
||||
)
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"WixVariable",
|
||||
Id="WixUIDialogBmp",
|
||||
Value="..\\package\\dialog.bmp",
|
||||
)
|
||||
ET.SubElement(
|
||||
product_el,
|
||||
"MajorUpgrade",
|
||||
AllowSameVersionUpgrades="yes",
|
||||
DowngradeErrorMessage="A newer version of [ProductName] is already installed. If you are sure you want to downgrade, remove the existing installation via Programs and Features.",
|
||||
)
|
||||
|
||||
wix_build_dir_xml(product_el, data)
|
||||
component_ids = wix_build_components_xml(product_el, data)
|
||||
|
||||
feature_el = ET.SubElement(product_el, "Feature", Id="DefaultFeature", Level="1")
|
||||
for component_id in component_ids:
|
||||
ET.SubElement(feature_el, "ComponentRef", Id=component_id)
|
||||
ET.SubElement(feature_el, "ComponentRef", Id="ApplicationShortcuts")
|
||||
|
||||
with open(os.path.join(root, "desktop", "build", "OnionShare.wxs"), "w") as f:
|
||||
f.write('<?xml version="1.0" encoding="windows-1252"?>\n')
|
||||
f.write(f'<?define ProductVersion = "{version}"?>\n')
|
||||
f.write(
|
||||
'<?define ProductUpgradeCode = "12b9695c-965b-4be0-bc33-21274e809576"?>\n'
|
||||
)
|
||||
|
||||
ET.indent(root_el)
|
||||
f.write(ET.tostring(root_el).decode())
|
||||
|
||||
print(f"○ Build the MSI")
|
||||
run(
|
||||
[shutil.which("candle.exe"), "OnionShare.wxs"],
|
||||
os.path.join(desktop_dir, "build"),
|
||||
)
|
||||
run(
|
||||
[shutil.which("light.exe"), "-ext", "WixUIExtension", "OnionShare.wixobj"],
|
||||
os.path.join(desktop_dir, "build"),
|
||||
)
|
||||
|
||||
print(f"○ Prepare OnionShare.msi for signing")
|
||||
run(
|
||||
[
|
||||
shutil.which("insignia.exe"),
|
||||
"-im",
|
||||
os.path.join(desktop_dir, "build", "OnionShare.msi"),
|
||||
],
|
||||
error_ok=True,
|
||||
)
|
||||
sign(os.path.join(desktop_dir, "build", "OnionShare.msi"))
|
||||
|
||||
final_msi_filename = os.path.join(desktop_dir, "dist", f"OnionShare-{version}.msi")
|
||||
print(f"○ Final MSI: {final_msi_filename}")
|
||||
os.makedirs(os.path.join(desktop_dir, "dist"), exist_ok=True)
|
||||
os.rename(
|
||||
os.path.join(desktop_dir, "build", "OnionShare.msi"),
|
||||
final_msi_filename,
|
||||
msi_package(
|
||||
win64_path,
|
||||
os.path.join(desktop_dir, "dist", f"OnionShare-win64-{version}.msi"),
|
||||
"ed7f9243-3528-4b4a-b85c-9943982e75eb",
|
||||
)
|
||||
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
OnionShare | https://onionshare.org/
|
||||
|
||||
Copyright (C) 2014-2022 Micah Lee, et al. <micah@micahflee.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
"""
|
||||
This script downloads a pre-built tor binary to bundle with OnionShare.
|
||||
In order to avoid a Mac gnupg dependency, I manually verify the signature
|
||||
and hard-code the sha256 hash.
|
||||
"""
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import hashlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import requests
|
||||
from bridges import UpdateTorBridges
|
||||
|
||||
|
||||
def main():
|
||||
tarball_url = "https://dist.torproject.org/torbrowser/11.0.13/tor-browser-linux64-11.0.13_en-US.tar.xz"
|
||||
tarball_filename = "tor-browser-linux64-11.0.13_en-US.tar.xz"
|
||||
expected_tarball_sha256 = (
|
||||
"df61fd90b7c1033cbb5856f3d076b5ca19f27e93c1a84741bd83b019dfe7ff0e"
|
||||
)
|
||||
|
||||
# Build paths
|
||||
root_path = os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
)
|
||||
working_path = os.path.join(root_path, "build", "tor")
|
||||
tarball_path = os.path.join(working_path, tarball_filename)
|
||||
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
|
||||
|
||||
# Make sure dirs exist
|
||||
if not os.path.exists(working_path):
|
||||
os.makedirs(working_path, exist_ok=True)
|
||||
|
||||
if not os.path.exists(dist_path):
|
||||
os.makedirs(dist_path, exist_ok=True)
|
||||
|
||||
# Make sure the tarball is downloaded
|
||||
if not os.path.exists(tarball_path):
|
||||
print("Downloading {}".format(tarball_url))
|
||||
r = requests.get(tarball_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_tarball_sha256:
|
||||
print("ERROR! The sha256 doesn't match:")
|
||||
print("expected: {}".format(expected_tarball_sha256))
|
||||
print(" actual: {}".format(tarball_sha256))
|
||||
sys.exit(-1)
|
||||
|
||||
# Delete extracted tarball, if it's there
|
||||
shutil.rmtree(os.path.join(working_path, "tor-browser_en-US"), 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"
|
||||
)
|
||||
|
||||
# Copy into dist
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Data", "Tor", "geoip"),
|
||||
os.path.join(dist_path, "geoip"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Data", "Tor", "geoip6"),
|
||||
os.path.join(dist_path, "geoip6"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "tor"),
|
||||
os.path.join(dist_path, "tor"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "tor"), 0o755)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "libcrypto.so.1.1"),
|
||||
os.path.join(dist_path, "libcrypto.so.1.1"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "libevent-2.1.so.7"),
|
||||
os.path.join(dist_path, "libevent-2.1.so.7"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "libssl.so.1.1"),
|
||||
os.path.join(dist_path, "libssl.so.1.1"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "libstdc++", "libstdc++.so.6"),
|
||||
os.path.join(dist_path, "libstdc++.so.6"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "PluggableTransports", "obfs4proxy"),
|
||||
os.path.join(dist_path, "obfs4proxy"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "obfs4proxy"), 0o755)
|
||||
shutil.copyfile(
|
||||
os.path.join(
|
||||
tarball_tor_path, "Tor", "PluggableTransports", "snowflake-client"
|
||||
),
|
||||
os.path.join(dist_path, "snowflake-client"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "snowflake-client"), 0o755)
|
||||
|
||||
print(f"Tor binaries extracted to: {dist_path}")
|
||||
|
||||
# Fetch the built-in bridges
|
||||
UpdateTorBridges(root_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,123 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
OnionShare | https://onionshare.org/
|
||||
|
||||
Copyright (C) 2014-2022 Micah Lee, et al. <micah@micahflee.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
"""
|
||||
This script downloads a pre-built tor binary to bundle with OnionShare.
|
||||
In order to avoid a Mac gnupg dependency, I manually verify the signature
|
||||
and hard-code the sha256 hash.
|
||||
"""
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import hashlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import requests
|
||||
|
||||
from bridges import UpdateTorBridges
|
||||
|
||||
|
||||
def main():
|
||||
dmg_url = "https://dist.torproject.org/torbrowser/11.0.13/TorBrowser-11.0.13-osx64_en-US.dmg"
|
||||
dmg_filename = "TorBrowser-11.0.13-osx64_en-US.dmg"
|
||||
expected_dmg_sha256 = (
|
||||
"3abd14f3e567a800f279b602dff1d886c2578d002d5e01f0bea6cee24e153c66"
|
||||
)
|
||||
|
||||
# Build paths
|
||||
root_path = os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
)
|
||||
working_path = os.path.join(root_path, "build", "tor")
|
||||
dmg_tor_path = os.path.join(
|
||||
"/Volumes", "Tor Browser", "Tor Browser.app", "Contents"
|
||||
)
|
||||
dmg_path = os.path.join(working_path, dmg_filename)
|
||||
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
|
||||
if not os.path.exists(dist_path):
|
||||
os.makedirs(dist_path, exist_ok=True)
|
||||
|
||||
# Make sure the working folder exists
|
||||
if not os.path.exists(working_path):
|
||||
os.makedirs(working_path)
|
||||
|
||||
# Make sure the zip is downloaded
|
||||
if not os.path.exists(dmg_path):
|
||||
print("Downloading {}".format(dmg_url))
|
||||
r = requests.get(dmg_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_dmg_sha256:
|
||||
print("ERROR! The sha256 doesn't match:")
|
||||
print("expected: {}".format(expected_dmg_sha256))
|
||||
print(" actual: {}".format(dmg_sha256))
|
||||
sys.exit(-1)
|
||||
|
||||
# Mount the dmg, copy data to the working path
|
||||
subprocess.call(["hdiutil", "attach", dmg_path])
|
||||
|
||||
# Copy into dist
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "geoip"),
|
||||
os.path.join(dist_path, "geoip"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "geoip6"),
|
||||
os.path.join(dist_path, "geoip6"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "MacOS", "Tor", "tor.real"),
|
||||
os.path.join(dist_path, "tor"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "tor"), 0o755)
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "MacOS", "Tor", "libevent-2.1.7.dylib"),
|
||||
os.path.join(dist_path, "libevent-2.1.7.dylib"),
|
||||
)
|
||||
# obfs4proxy binary
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "MacOS", "Tor", "PluggableTransports", "obfs4proxy"),
|
||||
os.path.join(dist_path, "obfs4proxy"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "obfs4proxy"), 0o755)
|
||||
# snowflake-client binary
|
||||
shutil.copyfile(
|
||||
os.path.join(
|
||||
dmg_tor_path, "MacOS", "Tor", "PluggableTransports", "snowflake-client"
|
||||
),
|
||||
os.path.join(dist_path, "snowflake-client"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "snowflake-client"), 0o755)
|
||||
|
||||
# Eject dmg
|
||||
subprocess.call(["diskutil", "eject", "/Volumes/Tor Browser"])
|
||||
|
||||
# Fetch the built-in bridges
|
||||
UpdateTorBridges(root_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,108 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
OnionShare | https://onionshare.org/
|
||||
|
||||
Copyright (C) 2014-2022 Micah Lee, et al. <micah@micahflee.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
"""
|
||||
This script downloads a pre-built tor binary to bundle with OnionShare.
|
||||
In order to avoid a Windows gnupg dependency, I manually verify the signature
|
||||
and hard-code the sha256 hash.
|
||||
"""
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import hashlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import requests
|
||||
|
||||
from bridges import UpdateTorBridges
|
||||
|
||||
|
||||
def main():
|
||||
exe_url = "https://dist.torproject.org/torbrowser/11.0.13/torbrowser-install-11.0.13_en-US.exe"
|
||||
exe_filename = "torbrowser-install-11.0.13_en-US.exe"
|
||||
expected_exe_sha256 = (
|
||||
"20dd6c7ec6caed5ec793e351bd025d8cd9819ddbb7a87b11a3b3128e92b7baa4"
|
||||
)
|
||||
# Build paths
|
||||
root_path = os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
)
|
||||
working_path = os.path.join(root_path, "build", "tor")
|
||||
exe_path = os.path.join(working_path, exe_filename)
|
||||
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
|
||||
|
||||
# Make sure the working folder exists
|
||||
if not os.path.exists(working_path):
|
||||
os.makedirs(working_path)
|
||||
|
||||
# Make sure Tor Browser is downloaded
|
||||
if not os.path.exists(exe_path):
|
||||
print("Downloading {}".format(exe_url))
|
||||
r = requests.get(exe_url)
|
||||
open(exe_path, "wb").write(r.content)
|
||||
exe_sha256 = hashlib.sha256(r.content).hexdigest()
|
||||
else:
|
||||
exe_data = open(exe_path, "rb").read()
|
||||
exe_sha256 = hashlib.sha256(exe_data).hexdigest()
|
||||
|
||||
# Compare the hash
|
||||
if exe_sha256 != expected_exe_sha256:
|
||||
print("ERROR! The sha256 doesn't match:")
|
||||
print("expected: {}".format(expected_exe_sha256))
|
||||
print(" actual: {}".format(exe_sha256))
|
||||
sys.exit(-1)
|
||||
|
||||
# Extract the bits we need from the exe
|
||||
subprocess.Popen(
|
||||
[
|
||||
"7z",
|
||||
"e",
|
||||
"-y",
|
||||
exe_path,
|
||||
"Browser\\TorBrowser\\Tor",
|
||||
"-o%s" % os.path.join(working_path, "Tor"),
|
||||
]
|
||||
).wait()
|
||||
subprocess.Popen(
|
||||
[
|
||||
"7z",
|
||||
"e",
|
||||
"-y",
|
||||
exe_path,
|
||||
"Browser\\TorBrowser\\Data\\Tor\\geoip*",
|
||||
"-o%s" % os.path.join(working_path, "Data"),
|
||||
]
|
||||
).wait()
|
||||
|
||||
# Copy into the onionshare resources
|
||||
if os.path.exists(dist_path):
|
||||
shutil.rmtree(dist_path)
|
||||
os.makedirs(dist_path)
|
||||
shutil.copytree(os.path.join(working_path, "Tor"), os.path.join(dist_path, "Tor"))
|
||||
shutil.copytree(
|
||||
os.path.join(working_path, "Data"), os.path.join(dist_path, "Data", "Tor")
|
||||
)
|
||||
|
||||
# Fetch the built-in bridges
|
||||
UpdateTorBridges(root_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
368
desktop/scripts/get-tor.py
Normal file
368
desktop/scripts/get-tor.py
Normal file
|
@ -0,0 +1,368 @@
|
|||
#!/usr/bin/env python3
|
||||
import inspect
|
||||
import os
|
||||
from re import M
|
||||
import sys
|
||||
import hashlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import requests
|
||||
import click
|
||||
|
||||
torbrowser_version = "11.0.14"
|
||||
expected_win32_sha256 = (
|
||||
"c14b979c81310ad039985e047dbb5b8058662bb3105b9022f7b9e0d18a29d0d6"
|
||||
)
|
||||
expected_win64_sha256 = (
|
||||
"ced3de06d089fbbeb8cee309971ac26983aba8eaf948fedce472d40cdd572301"
|
||||
)
|
||||
expected_macos_sha256 = (
|
||||
"558ae5ab188f62feb04c6b2e7f43eae2361e8ec1718e0f4f927801411d911e22"
|
||||
)
|
||||
expected_linux64_sha256 = (
|
||||
"b606924fdf8237e697cf95c229189da5875c190875d729769655c7b67aeb9aa6"
|
||||
)
|
||||
|
||||
win32_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/torbrowser-install-{torbrowser_version}_en-US.exe"
|
||||
win32_filename = f"torbrowser-install-{torbrowser_version}_en-US.exe"
|
||||
win64_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/torbrowser-install-win64-{torbrowser_version}_en-US.exe"
|
||||
win64_filename = f"torbrowser-install-win64-{torbrowser_version}_en-US.exe"
|
||||
macos_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/TorBrowser-{torbrowser_version}-osx64_en-US.dmg"
|
||||
macos_filename = f"TorBrowser-{torbrowser_version}-osx64_en-US.dmg"
|
||||
linux64_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/tor-browser-linux64-{torbrowser_version}_en-US.tar.xz"
|
||||
linux64_filename = f"tor-browser-linux64-{torbrowser_version}_en-US.tar.xz"
|
||||
|
||||
|
||||
# Common paths
|
||||
root_path = os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
)
|
||||
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 = [
|
||||
"libcrypto-1_1.dll",
|
||||
"libevent-2-1-7.dll",
|
||||
"libevent_core-2-1-7.dll",
|
||||
"libevent_extra-2-1-7.dll",
|
||||
"libgcc_s_dw2-1.dll",
|
||||
"libssl-1_1.dll",
|
||||
"libssp-0.dll",
|
||||
"libwinpthread-1.dll",
|
||||
"tor.exe",
|
||||
"zlib1.dll",
|
||||
]
|
||||
elif platform == "win64":
|
||||
win_url = win64_url
|
||||
win_filename = win64_filename
|
||||
expected_win_sha256 = expected_win64_sha256
|
||||
bin_filenames = [
|
||||
"libcrypto-1_1-x64.dll",
|
||||
"libevent-2-1-7.dll",
|
||||
"libevent_core-2-1-7.dll",
|
||||
"libevent_extra-2-1-7.dll",
|
||||
"libgcc_s_seh-1.dll",
|
||||
"libssl-1_1-x64.dll",
|
||||
"libssp-0.dll",
|
||||
"libwinpthread-1.dll",
|
||||
"tor.exe",
|
||||
"zlib1.dll",
|
||||
]
|
||||
else:
|
||||
click.echo("invalid platform")
|
||||
return
|
||||
|
||||
# Build paths
|
||||
win_path = os.path.join(working_path, win_filename)
|
||||
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
|
||||
|
||||
# Make sure the working folder exists
|
||||
if not os.path.exists(working_path):
|
||||
os.makedirs(working_path)
|
||||
|
||||
# Make sure Tor Browser is downloaded
|
||||
if not os.path.exists(win_path):
|
||||
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))
|
||||
sys.exit(-1)
|
||||
|
||||
# Extract the bits we need from the exe
|
||||
subprocess.Popen(
|
||||
[
|
||||
"7z",
|
||||
"e",
|
||||
"-y",
|
||||
win_path,
|
||||
"Browser\\TorBrowser\\Tor",
|
||||
"-o%s" % os.path.join(working_path, "Tor"),
|
||||
]
|
||||
).wait()
|
||||
subprocess.Popen(
|
||||
[
|
||||
"7z",
|
||||
"e",
|
||||
"-y",
|
||||
win_path,
|
||||
"Browser\\TorBrowser\\Data\\Tor\\geoip*",
|
||||
"-o%s" % os.path.join(working_path, "Data"),
|
||||
]
|
||||
).wait()
|
||||
|
||||
# Copy into the onionshare resources
|
||||
if os.path.exists(dist_path):
|
||||
shutil.rmtree(dist_path)
|
||||
os.makedirs(dist_path)
|
||||
for filename in bin_filenames:
|
||||
shutil.copyfile(
|
||||
os.path.join(working_path, "Tor", filename),
|
||||
os.path.join(dist_path, filename),
|
||||
)
|
||||
for filename in ["geoip", "geoip6"]:
|
||||
shutil.copyfile(
|
||||
os.path.join(working_path, "Data", filename),
|
||||
os.path.join(dist_path, filename),
|
||||
)
|
||||
|
||||
# Fetch the built-in bridges
|
||||
update_tor_bridges()
|
||||
|
||||
|
||||
def get_tor_macos():
|
||||
# Build paths
|
||||
dmg_tor_path = os.path.join(
|
||||
"/Volumes", "Tor Browser", "Tor Browser.app", "Contents"
|
||||
)
|
||||
dmg_path = os.path.join(working_path, macos_filename)
|
||||
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
|
||||
if not os.path.exists(dist_path):
|
||||
os.makedirs(dist_path, exist_ok=True)
|
||||
|
||||
# Make sure the working folder exists
|
||||
if not os.path.exists(working_path):
|
||||
os.makedirs(working_path)
|
||||
|
||||
# Make sure the zip is downloaded
|
||||
if not os.path.exists(dmg_path):
|
||||
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))
|
||||
sys.exit(-1)
|
||||
|
||||
# Mount the dmg, copy data to the working path
|
||||
subprocess.call(["hdiutil", "attach", dmg_path])
|
||||
|
||||
# Copy into dist
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "geoip"),
|
||||
os.path.join(dist_path, "geoip"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "geoip6"),
|
||||
os.path.join(dist_path, "geoip6"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "MacOS", "Tor", "tor.real"),
|
||||
os.path.join(dist_path, "tor"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "tor"), 0o755)
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "MacOS", "Tor", "libevent-2.1.7.dylib"),
|
||||
os.path.join(dist_path, "libevent-2.1.7.dylib"),
|
||||
)
|
||||
# obfs4proxy binary
|
||||
shutil.copyfile(
|
||||
os.path.join(dmg_tor_path, "MacOS", "Tor", "PluggableTransports", "obfs4proxy"),
|
||||
os.path.join(dist_path, "obfs4proxy"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "obfs4proxy"), 0o755)
|
||||
# snowflake-client binary
|
||||
shutil.copyfile(
|
||||
os.path.join(
|
||||
dmg_tor_path, "MacOS", "Tor", "PluggableTransports", "snowflake-client"
|
||||
),
|
||||
os.path.join(dist_path, "snowflake-client"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "snowflake-client"), 0o755)
|
||||
|
||||
# Eject dmg
|
||||
subprocess.call(["diskutil", "eject", "/Volumes/Tor Browser"])
|
||||
|
||||
# Fetch the built-in bridges
|
||||
update_tor_bridges()
|
||||
|
||||
|
||||
def get_tor_linux64():
|
||||
# Build paths
|
||||
tarball_path = os.path.join(working_path, linux64_filename)
|
||||
dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
|
||||
|
||||
# Make sure dirs exist
|
||||
if not os.path.exists(working_path):
|
||||
os.makedirs(working_path, exist_ok=True)
|
||||
|
||||
if not os.path.exists(dist_path):
|
||||
os.makedirs(dist_path, exist_ok=True)
|
||||
|
||||
# Make sure the tarball is downloaded
|
||||
if not os.path.exists(tarball_path):
|
||||
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))
|
||||
sys.exit(-1)
|
||||
|
||||
# Delete extracted tarball, if it's there
|
||||
shutil.rmtree(os.path.join(working_path, "tor-browser_en-US"), 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"
|
||||
)
|
||||
|
||||
# Copy into dist
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Data", "Tor", "geoip"),
|
||||
os.path.join(dist_path, "geoip"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Data", "Tor", "geoip6"),
|
||||
os.path.join(dist_path, "geoip6"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "tor"),
|
||||
os.path.join(dist_path, "tor"),
|
||||
)
|
||||
os.chmod(os.path.join(dist_path, "tor"), 0o755)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "libcrypto.so.1.1"),
|
||||
os.path.join(dist_path, "libcrypto.so.1.1"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "libevent-2.1.so.7"),
|
||||
os.path.join(dist_path, "libevent-2.1.so.7"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "libssl.so.1.1"),
|
||||
os.path.join(dist_path, "libssl.so.1.1"),
|
||||
)
|
||||
shutil.copyfile(
|
||||
os.path.join(tarball_tor_path, "Tor", "libstdc++", "libstdc++.so.6"),
|
||||
os.path.join(dist_path, "libstdc++.so.6"),
|
||||
)
|
||||
|
||||
print(f"Tor binaries extracted to: {dist_path}")
|
||||
|
||||
# Fetch the built-in bridges
|
||||
update_tor_bridges()
|
||||
|
||||
|
||||
def update_tor_bridges():
|
||||
"""
|
||||
Update the built-in Tor Bridges in OnionShare's torrc templates.
|
||||
"""
|
||||
torrc_template_dir = os.path.join(
|
||||
root_path, os.pardir, "cli/onionshare_cli/resources"
|
||||
)
|
||||
endpoint = "https://bridges.torproject.org/moat/circumvention/builtin"
|
||||
r = requests.post(
|
||||
endpoint,
|
||||
headers={"Content-Type": "application/vnd.api+json"},
|
||||
)
|
||||
if r.status_code != 200:
|
||||
print(
|
||||
f"There was a problem fetching the latest built-in bridges: status_code={r.status_code}"
|
||||
)
|
||||
return False
|
||||
|
||||
result = r.json()
|
||||
|
||||
if "errors" in result:
|
||||
print(
|
||||
f"There was a problem fetching the latest built-in bridges: errors={result['errors']}"
|
||||
)
|
||||
return False
|
||||
|
||||
for bridge_type in ["meek-azure", "obfs4", "snowflake"]:
|
||||
if result[bridge_type]:
|
||||
if bridge_type == "meek-azure":
|
||||
torrc_template_extension = "meek_lite_azure"
|
||||
else:
|
||||
torrc_template_extension = bridge_type
|
||||
torrc_template = os.path.join(
|
||||
root_path,
|
||||
torrc_template_dir,
|
||||
f"torrc_template-{torrc_template_extension}",
|
||||
)
|
||||
|
||||
with open(torrc_template, "w") as f:
|
||||
f.write(f"# Enable built-in {bridge_type} bridge\n")
|
||||
bridges = result[bridge_type]
|
||||
# Sorts the bridges numerically by IP, since they come back in
|
||||
# random order from the API each time, and create noisy git diff.
|
||||
bridges.sort(key=lambda s: s.split()[1])
|
||||
for item in bridges:
|
||||
f.write(f"Bridge {item}\n")
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("platform")
|
||||
def main(platform):
|
||||
"""
|
||||
Download Tor Browser and extract tor binaries
|
||||
"""
|
||||
valid_platforms = ["win32", "win64", "macos", "linux64"]
|
||||
if platform not in valid_platforms:
|
||||
click.echo(f"platform must be one of: {valid_platforms}")
|
||||
return
|
||||
|
||||
if platform == "win32":
|
||||
get_tor_windows(platform)
|
||||
elif platform == "win64":
|
||||
get_tor_windows(platform)
|
||||
elif platform == "macos":
|
||||
get_tor_macos()
|
||||
elif platform == "linux64":
|
||||
get_tor_linux64()
|
||||
else:
|
||||
click.echo("invalid platform")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -24,6 +24,7 @@ import platform
|
|||
import shutil
|
||||
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.
|
||||
|
@ -107,7 +108,10 @@ if platform.system() == "Darwin" or platform.system() == "Linux":
|
|||
# Discover the version
|
||||
with open(os.path.join("..", "cli", "onionshare_cli", "resources", "version.txt")) as f:
|
||||
version = f.read().strip()
|
||||
|
||||
# change a version like 2.6.dev1 to just 2.6, for cx_Freeze's sake
|
||||
last_digit = version[-1]
|
||||
if version.endswith(f".dev{last_digit}"):
|
||||
version = version[0:-5]
|
||||
|
||||
# Build
|
||||
include_files = [(os.path.join("..", "LICENSE"), "LICENSE")]
|
||||
|
@ -148,6 +152,11 @@ setup(
|
|||
name="onionshare",
|
||||
version=version,
|
||||
description="Securely and anonymously share files, host websites, and chat with friends using the Tor network",
|
||||
packages=find_packages(
|
||||
where=".",
|
||||
include=["onionshare"],
|
||||
exclude=["package", "screenshots", "scripts", "tests"],
|
||||
),
|
||||
options={
|
||||
# build_exe, for Windows and macOS
|
||||
"build_exe": {
|
||||
|
@ -214,7 +223,7 @@ setup(
|
|||
# bdist_mac, making the macOS app bundle
|
||||
"bdist_mac": {
|
||||
"iconfile": os.path.join("onionshare", "resources", "onionshare.icns"),
|
||||
"bundle_name": "OnionShare"
|
||||
"bundle_name": "OnionShare",
|
||||
},
|
||||
},
|
||||
executables=[
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import setuptools
|
||||
|
||||
# The version must be hard-coded because Snapcraft won't have access to ../cli
|
||||
version = "2.5"
|
||||
version = "2.6"
|
||||
|
||||
setuptools.setup(
|
||||
name="onionshare",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
project = "OnionShare"
|
||||
author = copyright = "Micah Lee, et al."
|
||||
version = release = "2.5"
|
||||
version = release = "2.6"
|
||||
|
||||
extensions = ["sphinx_rtd_theme"]
|
||||
templates_path = ["_templates"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: onionshare
|
||||
base: core18
|
||||
version: '2.5'
|
||||
version: "2.6"
|
||||
summary: Securely and anonymously share files, host websites, and chat using Tor
|
||||
description: |
|
||||
OnionShare lets you securely and anonymously send and receive files. It works by starting
|
||||
|
@ -15,7 +15,7 @@ apps:
|
|||
onionshare:
|
||||
common-id: org.onionshare.OnionShare
|
||||
command: onionshare
|
||||
extensions: [ gnome-3-34 ]
|
||||
extensions: [gnome-3-34]
|
||||
plugs:
|
||||
- desktop
|
||||
- home
|
||||
|
|
Loading…
Reference in a new issue