mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-05-20 07:26:58 -04:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ea9819d161 | ||
|
dc9480fd71 | ||
|
fa2849a080 | ||
|
c70c7ee5b9 | ||
|
fe3d3df662 | ||
|
2f90b73683 | ||
|
5186e80c6f |
73
.github/workflows/build.yaml
vendored
73
.github/workflows/build.yaml
vendored
@@ -44,7 +44,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: 9
|
version: 9
|
||||||
- name: Prepare workspace
|
- name: Prepare workspace
|
||||||
run: rm -rf source && mkdir source
|
run: rm -rf source && mkdir -p source/artifacts
|
||||||
|
|
||||||
- name: Checkout GlobalProtect-openconnect
|
- name: Checkout GlobalProtect-openconnect
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -52,6 +53,7 @@ jobs:
|
|||||||
repository: yuezk/GlobalProtect-openconnect
|
repository: yuezk/GlobalProtect-openconnect
|
||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
path: source/gp
|
path: source/gp
|
||||||
|
|
||||||
- name: Create tarball
|
- name: Create tarball
|
||||||
run: |
|
run: |
|
||||||
cd source/gp
|
cd source/gp
|
||||||
@@ -60,13 +62,69 @@ jobs:
|
|||||||
touch SNAPSHOT
|
touch SNAPSHOT
|
||||||
fi
|
fi
|
||||||
make tarball
|
make tarball
|
||||||
|
|
||||||
|
mv -v .build/tarball/*.tar.gz ../artifacts/
|
||||||
|
|
||||||
|
- name: Generate RPM spec file
|
||||||
|
env:
|
||||||
|
RELEASE_TAG: ${{ github.ref == 'refs/heads/dev' && 'snapshot' || github.ref_name }}
|
||||||
|
run: |
|
||||||
|
cd source/gp
|
||||||
|
|
||||||
|
make init-rpm \
|
||||||
|
REVISION='1%{?dist}' \
|
||||||
|
RPM_SOURCE=https://github.com/yuezk/GlobalProtect-openconnect/releases/download/${RELEASE_TAG}/%{name}-%{version}.tar.gz
|
||||||
|
|
||||||
|
mv -v .build/rpm/*.spec ../artifacts/
|
||||||
|
|
||||||
- name: Upload tarball
|
- name: Upload tarball
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifact-source
|
name: artifact-source
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
path: |
|
path: |
|
||||||
source/gp/.build/tarball/*.tar.gz
|
source/artifacts/*
|
||||||
|
|
||||||
|
tarball-offline:
|
||||||
|
if: ${{ github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- tarball
|
||||||
|
steps:
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
|
- name: Prepare workspace
|
||||||
|
run: rm -rf source-offline && mkdir source-offline
|
||||||
|
|
||||||
|
- name: Download tarball
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: artifact-source
|
||||||
|
path: source-offline
|
||||||
|
|
||||||
|
- name: Create offline tarball
|
||||||
|
run: |
|
||||||
|
cd source-offline
|
||||||
|
|
||||||
|
offline_tarball=$(basename *.tar.gz .tar.gz).offline.tar.gz
|
||||||
|
|
||||||
|
# Extract the tarball
|
||||||
|
tar -xzf *.tar.gz
|
||||||
|
|
||||||
|
cd */
|
||||||
|
make tarball OFFLINE=1
|
||||||
|
|
||||||
|
# Rename the tarball to .offline.tar.gz
|
||||||
|
mv -v .build/tarball/*.tar.gz ../$offline_tarball
|
||||||
|
|
||||||
|
- name: Upload offline tarball
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
path: source-offline/*.offline.tar.gz
|
||||||
|
name: artifact-source-offline
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
build-gp:
|
build-gp:
|
||||||
needs:
|
needs:
|
||||||
@@ -94,11 +152,13 @@ jobs:
|
|||||||
- name: Build ${{ matrix.package }} package in Docker
|
- name: Build ${{ matrix.package }} package in Docker
|
||||||
run: |
|
run: |
|
||||||
docker run --pull=always --rm \
|
docker run --pull=always --rm \
|
||||||
|
-e COREPACK_INTEGRITY_KEYS=0 \
|
||||||
-v $(pwd)/build-gp-${{ matrix.package }}:/${{ matrix.package }} \
|
-v $(pwd)/build-gp-${{ matrix.package }}:/${{ matrix.package }} \
|
||||||
yuezk/gpdev:${{ matrix.package }}-builder-tauri2
|
yuezk/gpdev:${{ matrix.package }}-builder-tauri2
|
||||||
- name: Install ${{ matrix.package }} package in Docker
|
- name: Install ${{ matrix.package }} package in Docker
|
||||||
run: |
|
run: |
|
||||||
docker run --pull=always --rm \
|
docker run --pull=always --rm \
|
||||||
|
-e COREPACK_INTEGRITY_KEYS=0 \
|
||||||
-e GPGUI_INSTALLED=0 \
|
-e GPGUI_INSTALLED=0 \
|
||||||
-v $(pwd)/build-gp-${{ matrix.package }}:/${{ matrix.package }} \
|
-v $(pwd)/build-gp-${{ matrix.package }}:/${{ matrix.package }} \
|
||||||
yuezk/gpdev:${{ matrix.package }}-builder-tauri2 \
|
yuezk/gpdev:${{ matrix.package }}-builder-tauri2 \
|
||||||
@@ -147,12 +207,16 @@ jobs:
|
|||||||
run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
|
run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
|
||||||
- name: Build gpgui in Docker
|
- name: Build gpgui in Docker
|
||||||
run: |
|
run: |
|
||||||
docker run --pull=always --rm -v $(pwd)/gpgui-source:/gpgui yuezk/gpdev:gpgui-builder-tauri2
|
docker run --pull=always --rm \
|
||||||
|
-e COREPACK_INTEGRITY_KEYS=0 \
|
||||||
|
-v $(pwd)/gpgui-source:/gpgui yuezk/gpdev:gpgui-builder-tauri2
|
||||||
- name: Install gpgui in Docker
|
- name: Install gpgui in Docker
|
||||||
run: |
|
run: |
|
||||||
cd gpgui-source
|
cd gpgui-source
|
||||||
tar -xJf *.bin.tar.xz
|
tar -xJf *.bin.tar.xz
|
||||||
docker run --pull=always --rm -v $(pwd):/gpgui yuezk/gpdev:gpgui-builder-tauri2 \
|
docker run --pull=always --rm \
|
||||||
|
-e COREPACK_INTEGRITY_KEYS=0 \
|
||||||
|
-v $(pwd):/gpgui yuezk/gpdev:gpgui-builder-tauri2 \
|
||||||
bash -c "cd /gpgui/gpgui_*/ && ./gpgui --version"
|
bash -c "cd /gpgui/gpgui_*/ && ./gpgui --version"
|
||||||
- name: Upload gpgui
|
- name: Upload gpgui
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -168,6 +232,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- tarball
|
- tarball
|
||||||
|
- tarball-offline
|
||||||
- build-gp
|
- build-gp
|
||||||
- build-gpgui
|
- build-gpgui
|
||||||
|
|
||||||
|
33
.github/workflows/publish.yaml
vendored
33
.github/workflows/publish.yaml
vendored
@@ -52,22 +52,26 @@ jobs:
|
|||||||
version: 9
|
version: 9
|
||||||
- name: Prepare workspace
|
- name: Prepare workspace
|
||||||
run: rm -rf publish-ppa && mkdir publish-ppa
|
run: rm -rf publish-ppa && mkdir publish-ppa
|
||||||
- name: Download ${{ inputs.tag }} source code
|
- name: Download ${{ inputs.tag }} offline source code
|
||||||
uses: robinraju/release-downloader@v1.9
|
env:
|
||||||
with:
|
GH_TOKEN: ${{ secrets.GH_PAT }}
|
||||||
token: ${{ secrets.GH_PAT }}
|
run: |
|
||||||
tag: ${{ inputs.tag }}
|
gh -R yuezk/GlobalProtect-openconnect \
|
||||||
fileName: globalprotect-openconnect-*.tar.gz
|
release download ${{ inputs.tag }} \
|
||||||
tarBall: false
|
--pattern '*.offline.tar.gz' \
|
||||||
zipBall: false
|
--dir publish-ppa
|
||||||
out-file-path: publish-ppa
|
- name: Patch the source code
|
||||||
- name: Make the offline tarball
|
|
||||||
run: |
|
run: |
|
||||||
cd publish-ppa
|
cd publish-ppa
|
||||||
tar -xf globalprotect-openconnect-*.tar.gz
|
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
make tarball OFFLINE=1
|
# Rename the source tarball without the offline suffix
|
||||||
|
mv -v *.tar.gz $(basename *.tar.gz .offline.tar.gz).tar.gz
|
||||||
|
|
||||||
|
# Extract the source tarball
|
||||||
|
tar -xzf *.tar.gz
|
||||||
|
|
||||||
|
# Prepare the debian directory with custom files
|
||||||
|
cd globalprotect-openconnect-*/
|
||||||
|
|
||||||
# Prepare the debian directory with custom files
|
# Prepare the debian directory with custom files
|
||||||
mkdir -p .build/debian
|
mkdir -p .build/debian
|
||||||
@@ -78,7 +82,6 @@ jobs:
|
|||||||
cp -v packaging/deb/postrm .build/debian/postrm
|
cp -v packaging/deb/postrm .build/debian/postrm
|
||||||
|
|
||||||
sed -i "s/@RUST@/cargo-1.80/g" .build/debian/control
|
sed -i "s/@RUST@/cargo-1.80/g" .build/debian/control
|
||||||
|
|
||||||
sed -i "s/@OFFLINE@/1/g" .build/debian/rules
|
sed -i "s/@OFFLINE@/1/g" .build/debian/rules
|
||||||
sed -i "s/@BUILD_GUI@/1/g" .build/debian/rules
|
sed -i "s/@BUILD_GUI@/1/g" .build/debian/rules
|
||||||
sed -i "s/@RUST_VERSION@/1.80/g" .build/debian/rules
|
sed -i "s/@RUST_VERSION@/1.80/g" .build/debian/rules
|
||||||
@@ -89,7 +92,7 @@ jobs:
|
|||||||
repository: "yuezk/globalprotect-openconnect"
|
repository: "yuezk/globalprotect-openconnect"
|
||||||
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
||||||
gpg_passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
|
gpg_passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
|
||||||
tarball: publish-ppa/globalprotect-openconnect-*/.build/tarball/*.tar.gz
|
tarball: publish-ppa/globalprotect-openconnect-*.tar.gz
|
||||||
debian_dir: publish-ppa/globalprotect-openconnect-*/.build/debian
|
debian_dir: publish-ppa/globalprotect-openconnect-*/.build/debian
|
||||||
deb_email: "k3vinyue@gmail.com"
|
deb_email: "k3vinyue@gmail.com"
|
||||||
deb_fullname: "Kevin Yue"
|
deb_fullname: "Kevin Yue"
|
||||||
|
19
.github/workflows/release.yaml
vendored
19
.github/workflows/release.yaml
vendored
@@ -96,27 +96,30 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Prepare workspace
|
- name: Prepare workspace
|
||||||
run: rm -rf build-${{ matrix.package }} && mkdir -p build-${{ matrix.package }}
|
run: rm -rf build-${{ matrix.package }} && mkdir -p build-${{ matrix.package }}
|
||||||
|
|
||||||
- name: Download ${{ inputs.tag }} source code
|
- name: Download ${{ inputs.tag }} source code
|
||||||
uses: robinraju/release-downloader@v1.9
|
env:
|
||||||
with:
|
GH_TOKEN: ${{ secrets.GH_PAT }}
|
||||||
token: ${{ secrets.GH_PAT }}
|
run: |
|
||||||
tag: ${{ inputs.tag }}
|
gh -R yuezk/GlobalProtect-openconnect \
|
||||||
fileName: globalprotect-openconnect-*.tar.gz
|
release download ${{ inputs.tag }} \
|
||||||
tarBall: false
|
--pattern '*[^offline].tar.gz' \
|
||||||
zipBall: false
|
--dir build-${{ matrix.package }}
|
||||||
out-file-path: build-${{ matrix.package }}
|
|
||||||
- name: Docker Login
|
- name: Docker Login
|
||||||
run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
|
run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
|
||||||
- name: Build ${{ matrix.package }} package in Docker
|
- name: Build ${{ matrix.package }} package in Docker
|
||||||
run: |
|
run: |
|
||||||
docker run --pull=always --rm \
|
docker run --pull=always --rm \
|
||||||
-v $(pwd)/build-${{ matrix.package }}:/${{ matrix.package }} \
|
-v $(pwd)/build-${{ matrix.package }}:/${{ matrix.package }} \
|
||||||
|
-e COREPACK_INTEGRITY_KEYS=0 \
|
||||||
-e INCLUDE_GUI=1 \
|
-e INCLUDE_GUI=1 \
|
||||||
yuezk/gpdev:${{ matrix.package }}-builder-tauri2
|
yuezk/gpdev:${{ matrix.package }}-builder-tauri2
|
||||||
|
|
||||||
- name: Install ${{ matrix.package }} package in Docker
|
- name: Install ${{ matrix.package }} package in Docker
|
||||||
run: |
|
run: |
|
||||||
docker run --pull=always --rm \
|
docker run --pull=always --rm \
|
||||||
|
-e COREPACK_INTEGRITY_KEYS=0 \
|
||||||
-v $(pwd)/build-${{ matrix.package }}:/${{ matrix.package }} \
|
-v $(pwd)/build-${{ matrix.package }}:/${{ matrix.package }} \
|
||||||
yuezk/gpdev:${{ matrix.package }}-builder-tauri2 \
|
yuezk/gpdev:${{ matrix.package }}-builder-tauri2 \
|
||||||
bash install.sh
|
bash install.sh
|
||||||
|
453
Cargo.lock
generated
453
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ members = [
|
|||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
rust-version = "1.80"
|
rust-version = "1.80"
|
||||||
version = "2.4.3"
|
version = "2.4.4"
|
||||||
authors = ["Kevin Yue <k3vinyue@gmail.com>"]
|
authors = ["Kevin Yue <k3vinyue@gmail.com>"]
|
||||||
homepage = "https://github.com/yuezk/GlobalProtect-openconnect"
|
homepage = "https://github.com/yuezk/GlobalProtect-openconnect"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
3
Makefile
3
Makefile
@@ -8,6 +8,8 @@ RUST_VERSION = 1.80
|
|||||||
|
|
||||||
VERSION = $(shell $(CARGO) metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
|
VERSION = $(shell $(CARGO) metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
|
||||||
REVISION ?= 1
|
REVISION ?= 1
|
||||||
|
RPM_SOURCE ?= %{name}.tar.gz
|
||||||
|
|
||||||
PPA_REVISION ?= 1
|
PPA_REVISION ?= 1
|
||||||
PKG_NAME = globalprotect-openconnect
|
PKG_NAME = globalprotect-openconnect
|
||||||
PKG = $(PKG_NAME)-$(VERSION)
|
PKG = $(PKG_NAME)-$(VERSION)
|
||||||
@@ -234,6 +236,7 @@ init-rpm: clean-rpm
|
|||||||
|
|
||||||
sed -i "s/@VERSION@/$(VERSION)/g" .build/rpm/globalprotect-openconnect.spec
|
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/@REVISION@/$(REVISION)/g" .build/rpm/globalprotect-openconnect.spec
|
||||||
|
sed -i "s|@SOURCE@|$(RPM_SOURCE)|g" .build/rpm/globalprotect-openconnect.spec
|
||||||
sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/rpm/globalprotect-openconnect.spec
|
sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/rpm/globalprotect-openconnect.spec
|
||||||
sed -i "s/@DATE@/$(shell LC_ALL=en.US date "+%a %b %d %Y")/g" .build/rpm/globalprotect-openconnect.spec
|
sed -i "s/@DATE@/$(shell LC_ALL=en.US date "+%a %b %d %Y")/g" .build/rpm/globalprotect-openconnect.spec
|
||||||
|
|
||||||
|
@@ -70,7 +70,7 @@ The GUI version is also available after you installed it. You can launch it from
|
|||||||
|
|
||||||
### Debian/Ubuntu based distributions
|
### Debian/Ubuntu based distributions
|
||||||
|
|
||||||
#### Install from PPA (Ubuntu > 18.04)
|
#### Install from PPA
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo add-apt-repository ppa:yuezk/globalprotect-openconnect
|
sudo add-apt-repository ppa:yuezk/globalprotect-openconnect
|
||||||
@@ -81,10 +81,6 @@ sudo apt-get install globalprotect-openconnect
|
|||||||
>
|
>
|
||||||
> For Linux Mint, you might need to import the GPG key with: `sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7937C393082992E5D6E4A60453FC26B43838D761` if you encountered an error `gpg: keyserver receive failed: General error`.
|
> For Linux Mint, you might need to import the GPG key with: `sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7937C393082992E5D6E4A60453FC26B43838D761` if you encountered an error `gpg: keyserver receive failed: General error`.
|
||||||
|
|
||||||
#### **Ubuntu 18.04**
|
|
||||||
|
|
||||||
The latest package is not available in the PPA, but you still needs to add the `ppa:yuezk/globalprotect-openconnect` repo beforehand to use the required `openconnect` package. Then you can follow the [Install from deb package](#install-from-deb-package) section to install the latest package.
|
|
||||||
|
|
||||||
#### Install from deb package
|
#### Install from deb package
|
||||||
|
|
||||||
Download the latest deb package from [releases](https://github.com/yuezk/GlobalProtect-openconnect/releases) page. Then install it with `apt`:
|
Download the latest deb package from [releases](https://github.com/yuezk/GlobalProtect-openconnect/releases) page. Then install it with `apt`:
|
||||||
@@ -145,7 +141,7 @@ It is available via `guru` and `lamdness` overlays.
|
|||||||
```bash
|
```bash
|
||||||
sudo eselect repository enable guru
|
sudo eselect repository enable guru
|
||||||
sudo emerge -r guru sync
|
sudo emerge -r guru sync
|
||||||
sudo emerge -av net-vpn/globalprotect-openconnect
|
sudo emerge -av net-vpn/GlobalProtect-openconnect
|
||||||
```
|
```
|
||||||
|
|
||||||
### Other distributions
|
### Other distributions
|
||||||
|
@@ -1,17 +1,21 @@
|
|||||||
use std::{env::temp_dir, fs::File};
|
use std::{env::temp_dir, fs::File, str::FromStr};
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use gpapi::{
|
use gpapi::{
|
||||||
clap::{handle_error, Args, InfoLevelVerbosity},
|
clap::{handle_error, Args, InfoLevelVerbosity},
|
||||||
utils::openssl,
|
utils::openssl,
|
||||||
};
|
};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use sysinfo::{Pid, System};
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
use tokio::fs;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
connect::{ConnectArgs, ConnectHandler},
|
connect::{ConnectArgs, ConnectHandler},
|
||||||
disconnect::{DisconnectArgs, DisconnectHandler},
|
disconnect::{DisconnectArgs, DisconnectHandler},
|
||||||
launch_gui::{LaunchGuiArgs, LaunchGuiHandler},
|
launch_gui::{LaunchGuiArgs, LaunchGuiHandler},
|
||||||
|
GP_CLIENT_LOCK_FILE,
|
||||||
};
|
};
|
||||||
|
|
||||||
const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), " (", compile_time::date_str!(), ")");
|
const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), " (", compile_time::date_str!(), ")");
|
||||||
@@ -77,6 +81,25 @@ impl Args for Cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Cli {
|
impl Cli {
|
||||||
|
async fn is_running(&self) -> bool {
|
||||||
|
let Ok(c) = fs::read_to_string(GP_CLIENT_LOCK_FILE).await else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(pid) = Pid::from_str(c.trim()) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let s = System::new_all();
|
||||||
|
let Some(p) = s.process(pid) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
p.exe()
|
||||||
|
.map(|exe| exe.to_string_lossy().contains("gpclient"))
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
fn fix_openssl(&self) -> anyhow::Result<Option<NamedTempFile>> {
|
fn fix_openssl(&self) -> anyhow::Result<Option<NamedTempFile>> {
|
||||||
if self.fix_openssl {
|
if self.fix_openssl {
|
||||||
let file = openssl::fix_openssl_env()?;
|
let file = openssl::fix_openssl_env()?;
|
||||||
@@ -87,6 +110,11 @@ impl Cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&self) -> anyhow::Result<()> {
|
async fn run(&self) -> anyhow::Result<()> {
|
||||||
|
// check if an instance is running
|
||||||
|
if self.is_running().await {
|
||||||
|
bail!("Another instance of the client is already running");
|
||||||
|
}
|
||||||
|
|
||||||
// The temp file will be dropped automatically when the file handle is dropped
|
// The temp file will be dropped automatically when the file handle is dropped
|
||||||
// So, declare it here to ensure it's not dropped
|
// So, declare it here to ensure it's not dropped
|
||||||
let _file = self.fix_openssl()?;
|
let _file = self.fix_openssl()?;
|
||||||
|
193
apps/gpgui-helper/dist/assets/main-CQPVXkdn.js
vendored
193
apps/gpgui-helper/dist/assets/main-CQPVXkdn.js
vendored
File diff suppressed because one or more lines are too long
228
apps/gpgui-helper/dist/assets/main-sEPcTvJX.js
vendored
Normal file
228
apps/gpgui-helper/dist/assets/main-sEPcTvJX.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
apps/gpgui-helper/dist/index.html
vendored
2
apps/gpgui-helper/dist/index.html
vendored
@@ -5,7 +5,7 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>GlobalProtect</title>
|
<title>GlobalProtect</title>
|
||||||
<script type="module" crossorigin src="/assets/main-CQPVXkdn.js"></script>
|
<script type="module" crossorigin src="/assets/main-sEPcTvJX.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/main-B3YRsHQ2.css">
|
<link rel="stylesheet" crossorigin href="/assets/main-B3YRsHQ2.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@@ -11,27 +11,27 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@mui/icons-material": "^6.3.0",
|
"@mui/icons-material": "^6.4.3",
|
||||||
"@mui/material": "^6.3.0",
|
"@mui/material": "^6.4.3",
|
||||||
"@tauri-apps/api": "^2.1.1",
|
"@tauri-apps/api": "^2.2.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^2.1.0",
|
"@tauri-apps/cli": "^2.2.7",
|
||||||
"@types/node": "^22.10.2",
|
"@types/node": "^22.13.1",
|
||||||
"@types/react": "^19.0.2",
|
"@types/react": "^19.0.8",
|
||||||
"@types/react-dom": "^19.0.2",
|
"@types/react-dom": "^19.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.18.2",
|
"@typescript-eslint/eslint-plugin": "^8.23.0",
|
||||||
"@typescript-eslint/parser": "^8.18.2",
|
"@typescript-eslint/parser": "^8.23.0",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"eslint": "^9.17.0",
|
"eslint": "^9.20.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-react": "^7.37.3",
|
"eslint-plugin-react": "^7.37.4",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0",
|
"eslint-plugin-react-hooks": "^5.1.0",
|
||||||
"prettier": "3.4.2",
|
"prettier": "3.4.2",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.7.3",
|
||||||
"vite": "^6.0.5"
|
"vite": "^6.1.0"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.15.1"
|
"packageManager": "pnpm@9.15.1"
|
||||||
}
|
}
|
||||||
|
1412
apps/gpgui-helper/pnpm-lock.yaml
generated
1412
apps/gpgui-helper/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2.4.4 - 2025-02-09
|
||||||
|
|
||||||
|
- GUI: fix multiple tray icons issue (fix [#464](https://github.com/yuezk/GlobalProtect-openconnect/issues/464))
|
||||||
|
- CLI: check the cli running state before running the `gpclient` command (fix [#447](https://github.com/yuezk/GlobalProtect-openconnect/issues/447))
|
||||||
|
|
||||||
## 2.4.3 - 2025-01-21
|
## 2.4.3 - 2025-01-21
|
||||||
|
|
||||||
- Do not use static default value for `--os-version` option.
|
- Do not use static default value for `--os-version` option.
|
||||||
|
@@ -39,6 +39,9 @@ clap-verbosity-flag = { workspace = true, optional = true }
|
|||||||
env_logger = { workspace = true, optional = true }
|
env_logger = { workspace = true, optional = true }
|
||||||
log-reload = { version = "0.1", optional = true }
|
log-reload = { version = "0.1", optional = true }
|
||||||
|
|
||||||
|
[target.'cfg(not(any(target_os="macos", target_os="windows")))'.dependencies]
|
||||||
|
gtk = "0.18"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
tauri = ["dep:tauri"]
|
tauri = ["dep:tauri"]
|
||||||
clap = ["dep:clap", "dep:clap-verbosity-flag"]
|
clap = ["dep:clap", "dep:clap-verbosity-flag"]
|
||||||
|
@@ -41,12 +41,6 @@ pub fn patch_gui_runtime_env(hidpi: bool) {
|
|||||||
// This is to avoid blank screen on some systems
|
// This is to avoid blank screen on some systems
|
||||||
std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1");
|
std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1");
|
||||||
|
|
||||||
// Workaround for https://github.com/tauri-apps/tao/issues/929
|
|
||||||
let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland";
|
|
||||||
if is_wayland {
|
|
||||||
env::set_var("GDK_BACKEND", "x11");
|
|
||||||
}
|
|
||||||
|
|
||||||
if hidpi {
|
if hidpi {
|
||||||
info!("Setting GDK_SCALE=2 and GDK_DPI_SCALE=0.5");
|
info!("Setting GDK_SCALE=2 and GDK_DPI_SCALE=0.5");
|
||||||
std::env::set_var("GDK_SCALE", "2");
|
std::env::set_var("GDK_SCALE", "2");
|
||||||
|
@@ -1,73 +1,97 @@
|
|||||||
use std::{process::ExitStatus, time::Duration};
|
|
||||||
|
|
||||||
use anyhow::bail;
|
|
||||||
use log::info;
|
|
||||||
use tauri::WebviewWindow;
|
use tauri::WebviewWindow;
|
||||||
use tokio::process::Command;
|
|
||||||
|
|
||||||
pub trait WindowExt {
|
pub trait WindowExt {
|
||||||
fn raise(&self) -> anyhow::Result<()>;
|
fn raise(&self) -> anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowExt for WebviewWindow {
|
impl WindowExt for WebviewWindow {
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||||
fn raise(&self) -> anyhow::Result<()> {
|
fn raise(&self) -> anyhow::Result<()> {
|
||||||
raise_window(self)
|
self.show()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||||
|
fn raise(&self) -> anyhow::Result<()> {
|
||||||
|
unix::raise_window(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raise_window(win: &WebviewWindow) -> anyhow::Result<()> {
|
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||||
let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland";
|
mod unix {
|
||||||
|
use std::{process::ExitStatus, time::Duration};
|
||||||
|
|
||||||
if is_wayland {
|
use anyhow::bail;
|
||||||
win.hide()?;
|
use gtk::{
|
||||||
win.show()?;
|
glib::Cast,
|
||||||
} else {
|
traits::{EventBoxExt, GtkWindowExt, WidgetExt},
|
||||||
if !win.is_visible()? {
|
EventBox,
|
||||||
win.show()?;
|
};
|
||||||
}
|
use log::info;
|
||||||
let title = win.title()?;
|
use tauri::WebviewWindow;
|
||||||
tokio::spawn(async move {
|
use tokio::process::Command;
|
||||||
if let Err(err) = wmctrl_raise_window(&title).await {
|
|
||||||
info!("Window not raised: {}", err);
|
pub fn raise_window(win: &WebviewWindow) -> anyhow::Result<()> {
|
||||||
|
let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland";
|
||||||
|
|
||||||
|
if is_wayland {
|
||||||
|
let gtk_win = win.gtk_window()?;
|
||||||
|
if let Some(header) = gtk_win.titlebar() {
|
||||||
|
let _ = header.downcast::<EventBox>().map(|event_box| {
|
||||||
|
event_box.set_above_child(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calling window.show() on Windows will cause the menu to be shown.
|
gtk_win.hide();
|
||||||
// We need to hide it again.
|
gtk_win.show_all();
|
||||||
win.hide_menu()?;
|
} else {
|
||||||
|
if !win.is_visible()? {
|
||||||
Ok(())
|
win.show()?;
|
||||||
}
|
|
||||||
|
|
||||||
async fn wmctrl_raise_window(title: &str) -> anyhow::Result<()> {
|
|
||||||
let mut counter = 0;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if let Ok(exit_status) = wmctrl_try_raise_window(title).await {
|
|
||||||
if exit_status.success() {
|
|
||||||
info!("Window raised after {} attempts", counter + 1);
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
let title = win.title()?;
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(err) = wmctrl_raise_window(&title).await {
|
||||||
|
info!("Window not raised: {}", err);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if counter >= 10 {
|
// Calling window.show() on window object will cause the menu to be shown.
|
||||||
bail!("Failed to raise window: {}", title)
|
// We need to hide it again.
|
||||||
}
|
win.hide_menu()?;
|
||||||
|
|
||||||
counter += 1;
|
Ok(())
|
||||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
}
|
||||||
|
|
||||||
|
async fn wmctrl_raise_window(title: &str) -> anyhow::Result<()> {
|
||||||
|
let mut counter = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Ok(exit_status) = wmctrl_try_raise_window(title).await {
|
||||||
|
if exit_status.success() {
|
||||||
|
info!("Window raised after {} attempts", counter + 1);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if counter >= 10 {
|
||||||
|
bail!("Failed to raise window: {}", title)
|
||||||
|
}
|
||||||
|
|
||||||
|
counter += 1;
|
||||||
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn wmctrl_try_raise_window(title: &str) -> anyhow::Result<ExitStatus> {
|
||||||
|
let exit_status = Command::new("wmctrl")
|
||||||
|
.arg("-F")
|
||||||
|
.arg("-a")
|
||||||
|
.arg(title)
|
||||||
|
.spawn()?
|
||||||
|
.wait()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(exit_status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn wmctrl_try_raise_window(title: &str) -> anyhow::Result<ExitStatus> {
|
|
||||||
let exit_status = Command::new("wmctrl")
|
|
||||||
.arg("-F")
|
|
||||||
.arg("-a")
|
|
||||||
.arg(title)
|
|
||||||
.spawn()?
|
|
||||||
.wait()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(exit_status)
|
|
||||||
}
|
|
||||||
|
@@ -6,7 +6,7 @@ Group: Productivity/Networking/PPP
|
|||||||
|
|
||||||
License: GPL-3.0
|
License: GPL-3.0
|
||||||
URL: https://github.com/yuezk/GlobalProtect-openconnect
|
URL: https://github.com/yuezk/GlobalProtect-openconnect
|
||||||
Source: %{name}.tar.gz
|
Source: @SOURCE@
|
||||||
|
|
||||||
BuildRequires: make
|
BuildRequires: make
|
||||||
BuildRequires: rust
|
BuildRequires: rust
|
||||||
|
@@ -28,7 +28,7 @@ release_snapshot() {
|
|||||||
|
|
||||||
echo "Uploading new assets..."
|
echo "Uploading new assets..."
|
||||||
gh -R "$REPO" release upload "$TAG" \
|
gh -R "$REPO" release upload "$TAG" \
|
||||||
"$PROJECT_DIR"/.build/artifacts/artifact-source/* \
|
"$PROJECT_DIR"/.build/artifacts/artifact-source*/* \
|
||||||
"$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/*
|
"$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/*
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ release_tag() {
|
|||||||
gh -R "$REPO" release create $TAG \
|
gh -R "$REPO" release create $TAG \
|
||||||
--title "$TAG" \
|
--title "$TAG" \
|
||||||
--notes "$RELEASE_NOTES" \
|
--notes "$RELEASE_NOTES" \
|
||||||
"$PROJECT_DIR"/.build/artifacts/artifact-source/* \
|
"$PROJECT_DIR"/.build/artifacts/artifact-source*/* \
|
||||||
"$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/*
|
"$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user