diff --git a/.editorconfig b/.editorconfig index 9d08a1a..b200914 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,6 @@ indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true + +[Makefile] +indent_style = tab diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8b858af..c4372fa 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,4 +1,4 @@ -name: Build GPGUI +name: Build on: push: paths-ignore: @@ -8,6 +8,7 @@ on: - .devcontainer branches: - main + - dev tags: - latest - v*.*.* @@ -22,287 +23,244 @@ jobs: id: set-matrix run: | if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - echo "matrix=[\"amd64\", \"arm64\"]" >> $GITHUB_OUTPUT + echo "matrix=[\"ubuntu-latest\", \"arm64\"]" >> $GITHUB_OUTPUT else - echo "matrix=[\"amd64\"]" >> $GITHUB_OUTPUT + echo "matrix=[\"ubuntu-latest\"]" >> $GITHUB_OUTPUT fi - build-fe: + tarball: runs-on: ubuntu-latest + needs: [setup-matrix] steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui + - uses: pnpm/action-setup@v2 + with: + version: 8 + - name: Prepare workspace + run: rm -rf source && mkdir source + - name: Checkout GlobalProtect-openconnect + uses: actions/checkout@v3 + with: + token: ${{ secrets.GH_PAT }} + repository: yuezk/GlobalProtect-openconnect + path: source/gp + - name: Create tarball + run: | + cd source/gp + make tarball + - name: Upload tarball + uses: actions/upload-artifact@v3 + with: + name: artifact-source + if-no-files-found: error + path: | + source/gp/.build/tarball/*.tar.gz - - name: Install Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - - - uses: pnpm/action-setup@v2 - with: - version: 8 - - - name: Install dependencies - run: | - cd app - pnpm install - - name: Build - run: | - cd app - pnpm run build - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: gpgui-fe - path: app/dist - - build-tauri-amd64: - needs: [build-fe] - runs-on: ubuntu-latest - steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui - - - name: Checkout gp repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/GlobalProtect-openconnect - path: gp - - - name: Download gpgui-fe artifact - uses: actions/download-artifact@v3 - with: - name: gpgui-fe - path: gpgui/app/dist - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Build Tauri in Docker - run: | - docker run \ - --rm \ - -v $(pwd):/${{ github.workspace }} \ - -w ${{ github.workspace }} \ - -e CI=true \ - yuezk/gpdev:main \ - "./gpgui/scripts/build.sh" - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: artifact-amd64-tauri - path: | - gpgui/.tmp/artifact - - build-tauri-arm64: - if: startsWith(github.ref, 'refs/tags/') - needs: [build-fe] - runs-on: self-hosted - steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui - - - name: Checkout gp repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/GlobalProtect-openconnect - path: gp - - - name: Download gpgui-fe artifact - uses: actions/download-artifact@v3 - with: - name: gpgui-fe - path: gpgui/app/dist - - name: Build Tauri - run: | - ./gpgui/scripts/build.sh - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: artifact-arm64-tauri - path: | - gpgui/.tmp/artifact - - package-tarball: - needs: [build-tauri-amd64, build-tauri-arm64] - runs-on: ubuntu-latest - steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui - - - name: Download artifact-amd64-tauri - uses: actions/download-artifact@v3 - with: - name: artifact-amd64-tauri - path: gpgui/.tmp/artifact - - - name: Download artifact-arm64-tauri - uses: actions/download-artifact@v3 - with: - name: artifact-arm64-tauri - path: gpgui/.tmp/artifact - - - name: Create tarball - run: | - ./gpgui/scripts/build-tarball.sh - - - name: Upload tarball - uses: actions/upload-artifact@v3 - with: - name: artifact-tarball - path: | - gpgui/.tmp/tarball/*.tar.gz - - package-rpm: - needs: [setup-matrix, package-tarball] - runs-on: ubuntu-latest + build-deb: + needs: + - setup-matrix + - tarball strategy: matrix: - arch: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui + - name: Prepare workspace + run: rm -rf build-deb && mkdir build-deb + - name: Download tarball + uses: actions/download-artifact@v3 + with: + name: artifact-source + path: build-deb + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build DEB package in Docker + run: | + docker run --rm -v $(pwd)/build-deb:/deb yuezk/gpdev:deb-builder + - name: Install DEB package in Docker + run: | + docker run --rm -v $(pwd)/build-deb:/deb yuezk/gpdev:deb-builder \ + bash -c "sudo dpkg -i /deb/*.deb; gpclient --version; gpservice --version; gpauth --version; gpgui-helper --version;" + - name: Upload DEB package + uses: actions/upload-artifact@v3 + with: + name: artifact-deb-${{ matrix.os }} + if-no-files-found: error + path: | + build-deb/*.deb - - name: Download package tarball - uses: actions/download-artifact@v3 - with: - name: artifact-tarball - path: gpgui/.tmp/artifact - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: ${{ matrix.arch }} - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Create RPM package - run: | - docker run \ - --rm \ - -v $(pwd):/${{ github.workspace }} \ - -w ${{ github.workspace }} \ - --platform linux/${{ matrix.arch }} \ - yuezk/gpdev:rpm-builder \ - "./gpgui/scripts/build-rpm.sh" - - - name: Upload rpm artifacts - uses: actions/upload-artifact@v3 - with: - name: artifact-${{ matrix.arch }}-rpm - path: | - gpgui/.tmp/artifact/*.rpm - - package-pkgbuild: - needs: [setup-matrix, build-tauri-amd64, build-tauri-arm64] - runs-on: ubuntu-latest + build-rpm: + needs: + - setup-matrix + - tarball strategy: matrix: - arch: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui + - name: Prepare workspace + run: rm -rf build-rpm && mkdir build-rpm + - name: Download tarball + uses: actions/download-artifact@v3 + with: + name: artifact-source + path: build-rpm + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build RPM package in Docker + run: | + docker run --rm -v $(pwd)/build-rpm:/rpm yuezk/gpdev:rpm-builder + - name: Install RPM package in Docker + run: | + docker run --rm -v $(pwd)/build-rpm:/rpm yuezk/gpdev:rpm-builder \ + bash -c "sudo rpm -i /rpm/*.$(uname -m).rpm; gpclient --version; gpservice --version; gpauth --version; gpgui-helper --version;" + - name: Upload RPM package + uses: actions/upload-artifact@v3 + with: + name: artifact-rpm-${{ matrix.os }} + if-no-files-found: error + path: | + build-rpm/*.rpm - - name: Download artifact-${{ matrix.arch }} - uses: actions/download-artifact@v3 - with: - name: artifact-${{ matrix.arch }}-tauri - path: gpgui/.tmp/artifact + build-pkgbuild: + needs: + - setup-matrix + - tarball + strategy: + matrix: + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} + steps: + - name: Prepare workspace + run: rm -rf build-pkgbuild && mkdir build-pkgbuild + - name: Download tarball + uses: actions/download-artifact@v3 + with: + name: artifact-source + path: build-pkgbuild + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build PKGBUILD package in Docker + run: | + docker run --rm -v $(pwd)/build-pkgbuild:/pkgbuild yuezk/gpdev:pkgbuild + - name: Install PKGBUILD package in Docker + run: | + docker run --rm -v $(pwd)/build-pkgbuild:/pkgbuild yuezk/gpdev:pkgbuild \ + bash -c "sudo pacman -U --noconfirm /pkgbuild/*.pkg.tar.zst; gpclient --version; gpservice --version; gpauth --version; gpgui-helper --version;" + - name: Upload PKGBUILD package + uses: actions/upload-artifact@v3 + with: + name: artifact-pkgbuild-${{ matrix.os }} + if-no-files-found: error + path: | + build-pkgbuild/*.pkg.tar.zst - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: ${{ matrix.arch }} + build-binary: + needs: + - setup-matrix + - tarball + strategy: + matrix: + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} + steps: + - name: Prepare workspace + run: rm -rf build-binary && mkdir build-binary + - name: Download tarball + uses: actions/download-artifact@v3 + with: + name: artifact-source + path: build-binary + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build binary in Docker + run: | + docker run --rm -v $(pwd)/build-binary:/binary yuezk/gpdev:binary-builder + - name: Install binary in Docker + run: | + cd build-binary + tar -xJf ./*.bin.tar.xz + docker run --rm -v $(pwd):/binary yuezk/gpdev:binary-builder \ + bash -c "cd /binary/globalprotect-openconnect*/ && sudo make install && gpclient --version && gpservice --version && gpauth --version && gpgui-helper --version;" + - name: Upload binary + uses: actions/upload-artifact@v3 + with: + name: artifact-binary-${{ matrix.os }} + if-no-files-found: error + path: | + build-binary/*.bin.tar.xz + build-binary/*.bin.tar.xz.sha256 - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Generate PKGBUILD - run: | - export CI_ARCH=${{ matrix.arch }} - ./gpgui/scripts/generate-pkgbuild.sh - - - name: Build PKGBUILD package - run: | - # Build package - docker run \ - --rm \ - -v $(pwd)/gpgui/.tmp/pkgbuild:/pkgbuild \ - --platform linux/${{ matrix.arch }} \ - yuezk/gpdev:pkgbuild - - - name: Upload pkgbuild artifacts - uses: actions/upload-artifact@v3 - with: - name: artifact-${{ matrix.arch }}-pkgbuild - path: | - gpgui/.tmp/pkgbuild/*.pkg.tar.zst + build-gpgui: + needs: + - setup-matrix + strategy: + matrix: + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} + steps: + - uses: pnpm/action-setup@v2 + with: + version: 8 + - name: Prepare workspace + run: rm -rf gpgui-source && mkdir gpgui-source + - name: Checkout GlobalProtect-openconnect + uses: actions/checkout@v3 + with: + token: ${{ secrets.GH_PAT }} + repository: yuezk/GlobalProtect-openconnect + path: gpgui-source/gp + - name: Checkout gpgui + uses: actions/checkout@v3 + with: + token: ${{ secrets.GH_PAT }} + repository: yuezk/gpgui + path: gpgui-source/gpgui + - name: Tarball + run: | + cd gpgui-source + tar -czf gpgui.tar.gz gpgui gp + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build gpgui in Docker + run: | + docker run --rm -v $(pwd)/gpgui-source:/gpgui yuezk/gpdev:gpgui-builder + - name: Install gpgui in Docker + run: | + cd gpgui-source + tar -xJf *.bin.tar.xz + docker run --rm -v $(pwd):/gpgui yuezk/gpdev:gpgui-builder \ + bash -c "cd /gpgui/gpgui_*/ && ./gpgui --version" + - name: Upload gpgui + uses: actions/upload-artifact@v3 + with: + name: artifact-gpgui-${{ matrix.os }} + if-no-files-found: error + path: | + gpgui-source/*.bin.tar.xz + gpgui-source/*.bin.tar.xz.sha256 gh-release: if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest needs: - - package-rpm - - package-pkgbuild + - build-deb + - build-rpm + - build-pkgbuild + - build-binary + - build-gpgui steps: - - name: Download artifact - uses: actions/download-artifact@v3 - with: - path: artifact - # pattern: artifact-* - # merge-multiple: true - - # - name: Generate checksum - # uses: jmgilman/actions-generate-checksum@v1 - # with: - # output: checksums.txt - # patterns: | - # artifact/* - - - name: Create GH release - uses: softprops/action-gh-release@v1 - with: - token: ${{ secrets.GH_PAT }} - prerelease: ${{ contains(github.ref, 'latest') }} - fail_on_unmatched_files: true - files: | - artifact/artifact-*/* + - name: Prepare workspace + run: rm -rf build-artifact && mkdir build-artifact + - name: Download all artifacts + uses: actions/download-artifact@v3 + with: + path: build-artifact + - name: Create GH release + uses: softprops/action-gh-release@v1 + with: + token: ${{ secrets.GH_PAT }} + prerelease: ${{ contains(github.ref, 'latest') }} + fail_on_unmatched_files: true + files: | + build-artifact/artifact-*/* diff --git a/.gitignore b/.gitignore index 20282f4..498e6c8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,8 @@ /target .pnpm-store .env +.vendor +*.tar.xz + +.cargo +.build diff --git a/Cargo.lock b/Cargo.lock index f85ac8b..6529415 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -903,19 +903,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "downloader" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05213e96f184578b5f70105d4d0a644a168e99e12d7bea0b200c15d67b5c182" -dependencies = [ - "futures", - "rand 0.8.5", - "reqwest", - "thiserror", - "tokio", -] - [[package]] name = "dtoa" version = "1.0.9" @@ -1514,7 +1501,6 @@ dependencies = [ "anyhow", "clap", "compile-time", - "downloader", "env_logger", "futures-util", "gpapi", @@ -1541,8 +1527,10 @@ dependencies = [ "openconnect", "serde", "serde_json", + "tar", "tokio", "tokio-util", + "xz2", ] [[package]] @@ -2212,6 +2200,17 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "mac" version = "0.1.1" @@ -5138,6 +5137,15 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + [[package]] name = "zeroize" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index 17124e7..9d158c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ resolver = "2" members = ["crates/*", "apps/gpclient", "apps/gpservice", "apps/gpauth", "apps/gpgui-helper/src-tauri"] [workspace.package] +rust-version = "1.70" version = "2.0.0" authors = ["Kevin Yue "] homepage = "https://github.com/yuezk/GlobalProtect-openconnect" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..78a0f80 --- /dev/null +++ b/Makefile @@ -0,0 +1,234 @@ +OFFLINE ?= 0 +BUILD_FE ?= 1 +CARGO ?= cargo + +VERSION = $(shell $(CARGO) metadata --no-deps --format-version 1 | jq -r '.packages[0].version') +REVISION ?= 1 +PPA_REVISION ?= 1 +PKG_NAME = globalprotect-openconnect +PKG = $(PKG_NAME)-$(VERSION) +SERIES ?= $(shell lsb_release -cs) +PUBLISH ?= 0 + +export DEBEMAIL = k3vinyue@gmail.com +export DEBFULLNAME = Kevin Yue + +CARGO_BUILD_ARGS = --release + +ifeq ($(OFFLINE), 1) + CARGO_BUILD_ARGS += --frozen +endif + +default: build + +version: + @echo $(VERSION) + +clean-tarball: + rm -rf .build/tarball + rm -rf .vendor + rm -rf vendor.tar.xz + rm -rf .cargo + +# Create a tarball, include the cargo dependencies if OFFLINE is set to 1 +tarball: clean-tarball + if [ $(BUILD_FE) -eq 1 ]; then \ + cd apps/gpgui-helper && pnpm install && pnpm build; \ + fi + + # Remove node_modules to reduce the tarball size + rm -rf apps/gpgui-helper/node_modules + + mkdir -p .cargo + mkdir -p .build/tarball + + # If OFFLINE is set to 1, vendor all cargo dependencies + if [ $(OFFLINE) -eq 1 ]; then \ + $(CARGO) vendor .vendor > .cargo/config.toml; \ + tar -cJf vendor.tar.xz .vendor; \ + fi + + tar --exclude .vendor --exclude target --transform 's,^,${PKG}/,' -czf .build/tarball/${PKG}.tar.gz * .cargo + +build: build-fe build-rs + +# Install and build the frontend +# If OFFLINE is set to 1, skip it +build-fe: + if [ $(OFFLINE) -eq 1 ] || [ $(BUILD_FE) -eq 0 ]; then \ + echo "Skipping frontend build (OFFLINE=1 or BUILD_FE=0)"; \ + else \ + cd apps/gpgui-helper && pnpm install && pnpm build; \ + fi + + if [ ! -d apps/gpgui-helper/dist ]; then \ + echo "Error: frontend build failed"; \ + exit 1; \ + fi + +build-rs: + if [ $(OFFLINE) -eq 1 ]; then \ + tar -xJf vendor.tar.xz; \ + fi + + $(CARGO) build $(CARGO_BUILD_ARGS) -p gpclient -p gpservice -p gpauth + $(CARGO) build $(CARGO_BUILD_ARGS) -p gpgui-helper --features "tauri/custom-protocol" + +clean: + $(CARGO) clean + rm -rf .build + rm -rf .vendor + rm -rf apps/gpgui-helper/node_modules + +install: + @echo "Installing $(PKG_NAME)..." + + install -Dm755 target/release/gpclient $(DESTDIR)/usr/bin/gpclient + install -Dm755 target/release/gpauth $(DESTDIR)/usr/bin/gpauth + install -Dm755 target/release/gpservice $(DESTDIR)/usr/bin/gpservice + install -Dm755 target/release/gpgui-helper $(DESTDIR)/usr/bin/gpgui-helper + + install -Dm644 packaging/files/usr/share/applications/gpgui.desktop $(DESTDIR)/usr/share/applications/gpgui.desktop + install -Dm644 packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg + install -Dm644 packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png + install -Dm644 packaging/files/usr/share/icons/hicolor/128x128/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/128x128/apps/gpgui.png + install -Dm644 packaging/files/usr/share/icons/hicolor/256x256@2/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/256x256@2/apps/gpgui.png + install -Dm644 packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy $(DESTDIR)/usr/share/polkit-1/actions/com.yuezk.gpgui.policy + +uninstall: + @echo "Uninstalling $(PKG_NAME)..." + + rm -f $(DESTDIR)/usr/bin/gpclient + rm -f $(DESTDIR)/usr/bin/gpauth + rm -f $(DESTDIR)/usr/bin/gpservice + rm -f $(DESTDIR)/usr/bin/gpgui-helper + rm -f $(DESTDIR)/usr/bin/gpgui + + rm -f $(DESTDIR)/usr/share/applications/gpgui.desktop + rm -f $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg + rm -f $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/icons/hicolor/128x128/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/icons/hicolor/256x256@2/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/polkit-1/actions/com.yuezk.gpgui.policy + +clean-debian: + rm -rf .build/deb + +# Generate the debian package structure, without the changelog +init-debian: clean-debian tarball + mkdir -p .build/deb + cp .build/tarball/${PKG}.tar.gz .build/deb + + tar -xzf .build/deb/${PKG}.tar.gz -C .build/deb + cd .build/deb/${PKG} && debmake + + cp -f packaging/deb/control.in .build/deb/$(PKG)/debian/control + cp -f packaging/deb/rules .build/deb/$(PKG)/debian/rules + + sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/deb/$(PKG)/debian/rules + + rm -f .build/deb/$(PKG)/debian/changelog + +deb: init-debian + # Remove the rust build depdency from the control file + sed -i "s/@RUST@//g" .build/deb/$(PKG)/debian/control + + cd .build/deb/$(PKG) && dch --create --distribution unstable --package $(PKG_NAME) --newversion $(VERSION)-$(REVISION) "Bugfix and improvements." + + cd .build/deb/$(PKG) && debuild --preserve-env -e PATH -us -uc -b + +check-ppa: + if [ $(OFFLINE) -eq 0 ]; then \ + echo "Error: ppa build requires offline mode (OFFLINE=1)"; \ + fi + +# Usage: make ppa SERIES=focal OFFLINE=1 PUBLISH=1 +ppa: check-ppa init-debian + cd .build/deb/${PKG} + + sed -i "s/@RUST@/rust-all(>=1.70)/g" debian/control + + $(eval SERIES_VER = $(shell distro-info --series $(SERIES) -r | cut -d' ' -f1)) + @echo "Building for $(SERIES) $(SERIES_VER)" + + dch --create --distribution $(SERIES) --package $(PKG_NAME) --newversion $(VERSION)-$(REVISION)ppa$(PPA_REVISION)~ubuntu$(SERIES_VER) "Bugfix and improvements." + + echo "y" | debuild -e PATH -S -sa -k"$(GPG_KEY_ID)" -p"gpg --batch --passphrase $(GPG_KEY_PASS) --pinentry-mode loopback" + + if [ $(PUBLISH) -eq 1 ]; then \ + dput ppa:yuezk/globalprotect-openconnect ../*.changes; \ + else + echo "Skipping ppa publish (PUBLISH=0)" + fi + +clean-rpm: + rm -rf .build/rpm + +# Generate RPM sepc file +init-rpm: clean-rpm + mkdir -p .build/rpm + + cp packaging/rpm/globalprotect-openconnect.spec.in .build/rpm/globalprotect-openconnect.spec + cp packaging/rpm/globalprotect-openconnect.changes.in .build/rpm/globalprotect-openconnect.changes + + sed -i "s/@VERSION@/$(VERSION)/g" .build/rpm/globalprotect-openconnect.spec + sed -i "s/@REVISION@/$(REVISION)/g" .build/rpm/globalprotect-openconnect.spec + sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/rpm/globalprotect-openconnect.spec + sed -i "s/@DATE@/$(shell date "+%a %b %d %Y")/g" .build/rpm/globalprotect-openconnect.spec + + sed -i "s/@VERSION@/$(VERSION)/g" .build/rpm/globalprotect-openconnect.changes + sed -i "s/@DATE@/$(shell LC_ALL=en.US date -u "+%a %b %e %T %Z %Y")/g" .build/rpm/globalprotect-openconnect.changes + +rpm: init-rpm tarball + rm -rf $(HOME)/rpmbuild + rpmdev-setuptree + + cp .build/tarball/${PKG}.tar.gz $(HOME)/rpmbuild/SOURCES/${PKG_NAME}.tar.gz + rpmbuild -ba .build/rpm/globalprotect-openconnect.spec + + # Copy RPM package from build directory + cp $(HOME)/rpmbuild/RPMS/$(shell uname -m)/$(PKG_NAME)*.rpm .build/rpm + + # Copy the SRPM only for x86_64. + if [ "$(shell uname -m)" = "x86_64" ]; then \ + cp $(HOME)/rpmbuild/SRPMS/$(PKG_NAME)*.rpm .build/rpm; \ + fi + +clean-pkgbuild: + rm -rf .build/pkgbuild + +init-pkgbuild: clean-pkgbuild tarball + mkdir -p .build/pkgbuild + + cp .build/tarball/${PKG}.tar.gz .build/pkgbuild + cp packaging/pkgbuild/PKGBUILD.in .build/pkgbuild/PKGBUILD + + sed -i "s/@PKG_NAME@/$(PKG_NAME)/g" .build/pkgbuild/PKGBUILD + sed -i "s/@VERSION@/$(VERSION)/g" .build/pkgbuild/PKGBUILD + sed -i "s/@REVISION@/$(REVISION)/g" .build/pkgbuild/PKGBUILD + sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/pkgbuild/PKGBUILD + +pkgbuild: init-pkgbuild + cd .build/pkgbuild && makepkg -s --noconfirm + +clean-binary: + rm -rf .build/binary + +binary: clean-binary tarball + mkdir -p .build/binary + + cp .build/tarball/${PKG}.tar.gz .build/binary + tar -xzf .build/binary/${PKG}.tar.gz -C .build/binary + + mkdir -p .build/binary/$(PKG_NAME)_$(VERSION)/artifacts + + make -C .build/binary/${PKG} build OFFLINE=$(OFFLINE) BUILD_FE=0 + make -C .build/binary/${PKG} install DESTDIR=$(PWD)/.build/binary/$(PKG_NAME)_$(VERSION)/artifacts + + cp packaging/binary/Makefile.in .build/binary/$(PKG_NAME)_$(VERSION)/Makefile + + # Create a tarball for the binary package + tar -cJf .build/binary/$(PKG_NAME)_$(VERSION)_$(shell uname -m).bin.tar.xz -C .build/binary $(PKG_NAME)_$(VERSION) + + # Generate sha256sum + cd .build/binary && sha256sum $(PKG_NAME)_$(VERSION)_$(shell uname -m).bin.tar.xz | cut -d' ' -f1 > $(PKG_NAME)_$(VERSION)_$(shell uname -m).bin.tar.xz.sha256 diff --git a/apps/gpgui-helper/.gitignore b/apps/gpgui-helper/.gitignore index a547bf3..f52de67 100644 --- a/apps/gpgui-helper/.gitignore +++ b/apps/gpgui-helper/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +.vite diff --git a/apps/gpgui-helper/src-tauri/Cargo.toml b/apps/gpgui-helper/src-tauri/Cargo.toml index 839e1f6..51d972c 100644 --- a/apps/gpgui-helper/src-tauri/Cargo.toml +++ b/apps/gpgui-helper/src-tauri/Cargo.toml @@ -18,7 +18,6 @@ clap.workspace = true compile-time.workspace = true env_logger.workspace = true futures-util.workspace = true -downloader = "0.2" tempfile.workspace = true reqwest = { workspace = true, features = ["stream"] } diff --git a/apps/gpgui-helper/src-tauri/src/updater.rs b/apps/gpgui-helper/src-tauri/src/updater.rs index 83275c3..ec479a5 100644 --- a/apps/gpgui-helper/src-tauri/src/updater.rs +++ b/apps/gpgui-helper/src-tauri/src/updater.rs @@ -80,12 +80,20 @@ impl GuiUpdater { pub async fn update(&self) { info!("Update GUI, version: {}", self.version); - #[cfg(target_arch = "x86_64")] - let arch = "amd64"; - #[cfg(target_arch = "aarch64")] - let arch = "arm64"; + #[cfg(debug_assertions)] + let release_tag = "latest"; + #[cfg(not(debug_assertions))] + let release_tag = format!("v{}", self.version); - let file_url = format!("https://github.com/yuezk/GlobalProtect-openconnect/releases/download/v{}/gpgui-linux-{}", self.version, arch); + #[cfg(target_arch = "x86_64")] + let arch = "x86_64"; + #[cfg(target_arch = "aarch64")] + let arch = "aarch64"; + + let file_url = format!( + "https://github.com/yuezk/GlobalProtect-openconnect/releases/download/{}/gpgui_{}_{}.bin.tar.xz", + release_tag, self.version, arch + ); let checksum_url = format!("{}.sha256", file_url); info!("Downloading file: {}", file_url); diff --git a/apps/gpservice/Cargo.toml b/apps/gpservice/Cargo.toml index 5a38524..4212f43 100644 --- a/apps/gpservice/Cargo.toml +++ b/apps/gpservice/Cargo.toml @@ -18,3 +18,5 @@ serde_json.workspace = true env_logger.workspace = true log.workspace = true compile-time.workspace = true +xz2 = "0.1" +tar = "0.4" diff --git a/apps/gpservice/src/handlers.rs b/apps/gpservice/src/handlers.rs index 1b2fa72..643eeb0 100644 --- a/apps/gpservice/src/handlers.rs +++ b/apps/gpservice/src/handlers.rs @@ -1,4 +1,12 @@ -use std::{borrow::Cow, fs::Permissions, ops::ControlFlow, os::unix::fs::PermissionsExt, path::PathBuf, sync::Arc}; +use std::{ + borrow::Cow, + fs::{File, Permissions}, + io::BufReader, + ops::ControlFlow, + os::unix::fs::PermissionsExt, + path::PathBuf, + sync::Arc, +}; use anyhow::bail; use axum::{ @@ -17,7 +25,9 @@ use gpapi::{ GP_GUI_BINARY, }; use log::{info, warn}; +use tar::Archive; use tokio::fs; +use xz2::read::XzDecoder; use crate::ws_server::WsServerContext; @@ -60,6 +70,7 @@ pub async fn update_gui(State(ctx): State>, body: Bytes) -> Ok(()) } +// Unpack GPGUI archive, gpgui_2.0.0_{arch}.bin.tar.xz and install it async fn install_gui(src: &str) -> anyhow::Result<()> { let path = PathBuf::from(GP_GUI_BINARY); let Some(dir) = path.parent() else { @@ -68,8 +79,27 @@ async fn install_gui(src: &str) -> anyhow::Result<()> { fs::create_dir_all(dir).await?; - // Copy the file to the final location and make it executable - fs::copy(src, GP_GUI_BINARY).await?; + // Unpack the archive + info!("Unpacking GUI archive"); + let tar = XzDecoder::new(BufReader::new(File::open(src)?)); + let mut ar = Archive::new(tar); + + for entry in ar.entries()? { + let mut entry = entry?; + let path = entry.path()?; + + if let Some(name) = path.file_name() { + let name = name.to_string_lossy(); + + if name == "gpgui" { + let mut file = File::create(GP_GUI_BINARY)?; + std::io::copy(&mut entry, &mut file)?; + break; + } + } + } + + // Make the binary executable fs::set_permissions(GP_GUI_BINARY, Permissions::from_mode(0o755)).await?; Ok(()) diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..b1bda96 --- /dev/null +++ b/changelog.md @@ -0,0 +1,9 @@ +# Changelog + +## 2.0.0 - 2024-02-05 + +- Refactor using Tauri +- Support HIP report +- Support pass vpn-slice command +- Do not error when the region field is empty +- Update the auth window icon diff --git a/packaging/binary/Makefile.in b/packaging/binary/Makefile.in new file mode 100644 index 0000000..96b7faa --- /dev/null +++ b/packaging/binary/Makefile.in @@ -0,0 +1,30 @@ +install: + @echo "===> Installing..." + + install -Dm755 artifacts/usr/bin/gpclient $(DESTDIR)/usr/bin/gpclient + install -Dm755 artifacts/usr/bin/gpservice $(DESTDIR)/usr/bin/gpservice + install -Dm755 artifacts/usr/bin/gpauth $(DESTDIR)/usr/bin/gpauth + install -Dm755 artifacts/usr/bin/gpgui-helper $(DESTDIR)/usr/bin/gpgui-helper + + install -Dm644 artifacts/usr/share/applications/gpgui.desktop $(DESTDIR)/usr/share/applications/gpgui.desktop + install -Dm644 artifacts/usr/share/icons/hicolor/scalable/apps/gpgui.svg $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg + install -Dm644 artifacts/usr/share/icons/hicolor/32x32/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png + install -Dm644 artifacts/usr/share/icons/hicolor/128x128/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/128x128/apps/gpgui.png + install -Dm644 artifacts/usr/share/icons/hicolor/256x256@2/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/256x256@2/apps/gpgui.png + install -Dm644 artifacts/usr/share/polkit-1/actions/com.yuezk.gpgui.policy $(DESTDIR)/usr/share/polkit-1/actions/com.yuezk.gpgui.policy + +uninstall: + @echo "===> Uninstalling from $(DESTDIR)..." + + rm -f $(DESTDIR)/usr/bin/gpclient + rm -f $(DESTDIR)/usr/bin/gpservice + rm -f $(DESTDIR)/usr/bin/gpauth + rm -f $(DESTDIR)/usr/bin/gpgui-helper + rm -f $(DESTDIR)/usr/bin/gpgui + + rm -f $(DESTDIR)/usr/share/applications/gpgui.desktop + rm -f $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg + rm -f $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/icons/hicolor/128x128/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/icons/hicolor/256x256@2/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/polkit-1/actions/com.yuezk.gpgui.policy diff --git a/packaging/deb/control.in b/packaging/deb/control.in new file mode 100644 index 0000000..c789fb9 --- /dev/null +++ b/packaging/deb/control.in @@ -0,0 +1,14 @@ +Source: globalprotect-openconnect +Section: net +Priority: optional +Maintainer: Kevin Yue +Standards-Version: 4.1.4 +Build-Depends: debhelper (>= 9), pkg-config, jq (>= 1), make (>= 4), openconnect (>= 8.20), libxml2, libsecret-1-0, libayatana-appindicator3-1, libwebkit2gtk-4.0-37, libgtk-3-0, gnome-keyring, @RUST@ +Homepage: https://github.com/yuezk/GlobalProtect-openconnect + +Package: globalprotect-openconnect +Architecture: any +Multi-Arch: foreign +Depends: ${misc:Depends}, ${shlibs:Depends}, openconnect (>=8.20), libxml2, libsecret-1-0, libayatana-appindicator3-1, gnome-keyring +Description: A GUI for GlobalProtect VPN + A GUI for GlobalProtect VPN, based on OpenConnect, supports the SSO authentication method. diff --git a/packaging/deb/rules b/packaging/deb/rules new file mode 100755 index 0000000..ca3f834 --- /dev/null +++ b/packaging/deb/rules @@ -0,0 +1,6 @@ +#!/usr/bin/make -f + +export OFFLINE = @OFFLINE@ BUILD_FE=0 + +%: + dh $@ diff --git a/packaging/files/usr/share/applications/gpgui.desktop b/packaging/files/usr/share/applications/gpgui.desktop new file mode 100644 index 0000000..8ad6418 --- /dev/null +++ b/packaging/files/usr/share/applications/gpgui.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] + +Type=Application +Name=GlobalProtect Openconnect VPN Client +Comment=A GUI for GlobalProtect VPN +GenericName=GlobalProtect VPN Client +Categories=Network;Dialup; +Exec=/usr/bin/gpclient launch-gui %u +MimeType=x-scheme-handler/globalprotectcallback; +Icon=gpgui +Keywords=GlobalProtect;Openconnect;SAML;connection;VPN; diff --git a/packaging/files/usr/share/icons/hicolor/128x128/apps/gpgui.png b/packaging/files/usr/share/icons/hicolor/128x128/apps/gpgui.png new file mode 100644 index 0000000..d7e9730 Binary files /dev/null and b/packaging/files/usr/share/icons/hicolor/128x128/apps/gpgui.png differ diff --git a/packaging/files/usr/share/icons/hicolor/256x256@2/apps/gpgui.png b/packaging/files/usr/share/icons/hicolor/256x256@2/apps/gpgui.png new file mode 100644 index 0000000..301c18a Binary files /dev/null and b/packaging/files/usr/share/icons/hicolor/256x256@2/apps/gpgui.png differ diff --git a/packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png b/packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png new file mode 100644 index 0000000..a29d98a Binary files /dev/null and b/packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png differ diff --git a/packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg b/packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg new file mode 100644 index 0000000..bccc611 --- /dev/null +++ b/packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg @@ -0,0 +1,99 @@ + + + +image/svg+xml + + + + + + + + \ No newline at end of file diff --git a/packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy b/packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy new file mode 100644 index 0000000..8c8af09 --- /dev/null +++ b/packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy @@ -0,0 +1,18 @@ + + + + The GlobalProtect-openconnect Project + https://github.com/yuezk/GlobalProtect-openconnect + gpgui + + Run GPService as root + Authentication is required to run the GPService as root + + auth_admin + auth_admin + yes + + /usr/bin/gpservice + true + + diff --git a/packaging/pkgbuild/PKGBUILD.in b/packaging/pkgbuild/PKGBUILD.in new file mode 100644 index 0000000..a238afb --- /dev/null +++ b/packaging/pkgbuild/PKGBUILD.in @@ -0,0 +1,35 @@ +# Maintainer: Keinv Yue + +_pkgname=@PKG_NAME@ +pkgname=${_pkgname} +pkgver="@VERSION@" +pkgrel=@REVISION@ +pkgdesc="A GUI for GlobalProtect VPN, based on OpenConnect, supports the SSO authentication method." +arch=('x86_64' 'aarch64') +url="https://github.com/yuezk/GlobalProtect-openconnect" +license=('GPL3') +makedepends=('make' 'pkg-config' 'rust' 'cargo' 'jq' 'webkit2gtk' 'curl' 'wget' 'file' 'openssl' 'appmenu-gtk-module' 'gtk3' 'libappindicator-gtk3' 'librsvg' 'libvips' 'libayatana-appindicator' 'openconnect' 'libsecret') +depends=('openconnect>=8.20' webkit2gtk libappindicator-gtk3 libayatana-appindicator libsecret libxml2) +optdepends=('wmctrl: for window management') + +provides=('globalprotect-openconnect' 'gpclient' 'gpservice' 'gpauth' 'gpgui') + +source=("${_pkgname}-${pkgver}.tar.gz") +sha256sums=('SKIP') + +options=('!strip') + +build() { + cd "$pkgname-$pkgver" + + # Must unset the CFLAGS, otherwise the build fails + unset CFLAGS + + make build OFFLINE=@OFFLINE@ BUILD_FE=0 +} + +package() { + cd "$pkgname-$pkgver" + + make install DESTDIR="$pkgdir" +} diff --git a/packaging/rpm/globalprotect-openconnect.changes.in b/packaging/rpm/globalprotect-openconnect.changes.in new file mode 100644 index 0000000..3d9280d --- /dev/null +++ b/packaging/rpm/globalprotect-openconnect.changes.in @@ -0,0 +1,5 @@ +------------------------------------------------------------------- +@DATE@ - k3vinyue@gmail.com - @VERSION@ + +- Update to @VERSION@ + * Bugfix and improvements. diff --git a/packaging/rpm/globalprotect-openconnect.spec.in b/packaging/rpm/globalprotect-openconnect.spec.in new file mode 100644 index 0000000..7314944 --- /dev/null +++ b/packaging/rpm/globalprotect-openconnect.spec.in @@ -0,0 +1,72 @@ +Name: globalprotect-openconnect +Version: @VERSION@ +Release: @REVISION@ +Summary: A GlobalProtect VPN client powered by OpenConnect +Group: Productivity/Networking/PPP + +License: GPL-3.0 +URL: https://github.com/yuezk/GlobalProtect-openconnect +Source: %{name}.tar.gz + +BuildRequires: make +BuildRequires: rust +BuildRequires: cargo +BuildRequires: jq +BuildRequires: pkg-config +BuildRequires: openconnect-devel +BuildRequires: openssl-devel +BuildRequires: curl +BuildRequires: wget +BuildRequires: file + +BuildRequires: (webkit2gtk4.0-devel or webkit2gtk3-soup2-devel) +BuildRequires: (libappindicator-gtk3-devel or libappindicator3-1) +BuildRequires: (librsvg2-devel or librsvg-devel) + +Requires: openconnect >= 8.20, (libayatana-appindicator or libappindicator-gtk3) +Conflicts: globalprotect-openconnect-snapshot + +%global debug_package %{nil} + +%description +A GUI for GlobalProtect VPN, based on OpenConnect, supports the SSO authentication method. + +%prep +%setup + +%build +# The injected RUSTFLAGS could fail the build +unset RUSTFLAGS +make build OFFLINE=@OFFLINE@ BUILD_FE=0 + +%install +%make_install + +%files +%defattr(-,root,root) +%{_bindir}/gpclient +%{_bindir}/gpservice +%{_bindir}/gpauth +%{_bindir}/gpgui-helper +%{_datadir}/applications/gpgui.desktop +%{_datadir}/icons/hicolor/32x32/apps/gpgui.png +%{_datadir}/icons/hicolor/128x128/apps/gpgui.png +%{_datadir}/icons/hicolor/256x256@2/apps/gpgui.png +%{_datadir}/icons/hicolor/scalable/apps/gpgui.svg +%{_datadir}/polkit-1/actions/com.yuezk.gpgui.policy + +%dir %{_datadir}/icons/hicolor +%dir %{_datadir}/icons/hicolor/32x32 +%dir %{_datadir}/icons/hicolor/32x32/apps +%dir %{_datadir}/icons/hicolor/128x128 +%dir %{_datadir}/icons/hicolor/128x128/apps +%dir %{_datadir}/icons/hicolor/256x256@2 +%dir %{_datadir}/icons/hicolor/256x256@2/apps +%dir %{_datadir}/icons/hicolor/scalable +%dir %{_datadir}/icons/hicolor/scalable/apps +%dir %{_datadir}/polkit-1 +%dir %{_datadir}/polkit-1/actions + +%changelog +* @DATE@ Kevin Yue - @VERSION@ +- Bugfix and improvements