mirror of
				https://github.com/yuezk/GlobalProtect-openconnect.git
				synced 2025-05-20 07:26:58 -04:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			dev
			...
			gpauth_win
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 3175d1083a | 
							
								
								
									
										10
									
								
								.github/workflows/build.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/build.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -152,13 +152,11 @@ 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 \ | ||||||
| @@ -207,16 +205,12 @@ 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 \ |         docker run --pull=always --rm -v $(pwd)/gpgui-source:/gpgui yuezk/gpdev:gpgui-builder-tauri2 | ||||||
|           -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 \ |         docker run --pull=always --rm -v $(pwd):/gpgui yuezk/gpdev:gpgui-builder-tauri2 \ | ||||||
|           -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 | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/release.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/release.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -112,14 +112,12 @@ jobs: | |||||||
|       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 | ||||||
|   | |||||||
							
								
								
									
										457
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										457
									
								
								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.4" | version = "2.4.3" | ||||||
| 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" | ||||||
|   | |||||||
							
								
								
									
										193
									
								
								apps/gpgui-helper/dist/assets/main-CQPVXkdn.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								apps/gpgui-helper/dist/assets/main-CQPVXkdn.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										228
									
								
								apps/gpgui-helper/dist/assets/main-sEPcTvJX.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										228
									
								
								apps/gpgui-helper/dist/assets/main-sEPcTvJX.js
									
									
									
									
										vendored
									
									
								
							
										
											
												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-sEPcTvJX.js"></script> |     <script type="module" crossorigin src="/assets/main-CQPVXkdn.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.4.3", |     "@mui/icons-material": "^6.3.0", | ||||||
|     "@mui/material": "^6.4.3", |     "@mui/material": "^6.3.0", | ||||||
|     "@tauri-apps/api": "^2.2.0", |     "@tauri-apps/api": "^2.1.1", | ||||||
|     "react": "^19.0.0", |     "react": "^19.0.0", | ||||||
|     "react-dom": "^19.0.0" |     "react-dom": "^19.0.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@tauri-apps/cli": "^2.2.7", |     "@tauri-apps/cli": "^2.1.0", | ||||||
|     "@types/node": "^22.13.1", |     "@types/node": "^22.10.2", | ||||||
|     "@types/react": "^19.0.8", |     "@types/react": "^19.0.2", | ||||||
|     "@types/react-dom": "^19.0.3", |     "@types/react-dom": "^19.0.2", | ||||||
|     "@typescript-eslint/eslint-plugin": "^8.23.0", |     "@typescript-eslint/eslint-plugin": "^8.18.2", | ||||||
|     "@typescript-eslint/parser": "^8.23.0", |     "@typescript-eslint/parser": "^8.18.2", | ||||||
|     "@vitejs/plugin-react": "^4.3.4", |     "@vitejs/plugin-react": "^4.3.4", | ||||||
|     "eslint": "^9.20.0", |     "eslint": "^9.17.0", | ||||||
|     "eslint-config-prettier": "^9.1.0", |     "eslint-config-prettier": "^9.1.0", | ||||||
|     "eslint-plugin-react": "^7.37.4", |     "eslint-plugin-react": "^7.37.3", | ||||||
|     "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.3", |     "typescript": "^5.7.2", | ||||||
|     "vite": "^6.1.0" |     "vite": "^6.0.5" | ||||||
|   }, |   }, | ||||||
|   "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,10 +1,5 @@ | |||||||
| # 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. | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ regex = { workspace = true, optional = true } | |||||||
| tokio-util = { workspace = true, optional = true } | tokio-util = { workspace = true, optional = true } | ||||||
| html-escape = { version = "0.2.13", optional = true } | html-escape = { version = "0.2.13", optional = true } | ||||||
|  |  | ||||||
| [target.'cfg(not(target_os = "macos"))'.dependencies] | [target.'cfg(not(any(target_os="macos", target_os="windows")))'.dependencies] | ||||||
| webkit2gtk = { version = "2", optional = true } | webkit2gtk = { version = "2", optional = true } | ||||||
|  |  | ||||||
| [target.'cfg(target_os="macos")'.dependencies] | [target.'cfg(target_os="macos")'.dependencies] | ||||||
| @@ -37,6 +37,12 @@ objc2 = { version = "0.5", optional = true } | |||||||
| objc2-foundation = { version = "0.2", optional = true } | objc2-foundation = { version = "0.2", optional = true } | ||||||
| objc2-web-kit = { version = "0.2", optional = true } | objc2-web-kit = { version = "0.2", optional = true } | ||||||
|  |  | ||||||
|  | [target.'cfg(target_os="windows")'.dependencies] | ||||||
|  | webview2-com = { version = "0.34", optional = true } | ||||||
|  | windows-core = { version = "0.58", optional = true } | ||||||
|  | windows = { version = "0.58", optional = true } | ||||||
|  | serde_json = { workspace = true, optional = true } | ||||||
|  |  | ||||||
| [features] | [features] | ||||||
| browser-auth = [ | browser-auth = [ | ||||||
|   "dep:webbrowser", |   "dep:webbrowser", | ||||||
| @@ -56,4 +62,8 @@ webview-auth = [ | |||||||
|   "dep:objc2", |   "dep:objc2", | ||||||
|   "dep:objc2-foundation", |   "dep:objc2-foundation", | ||||||
|   "dep:objc2-web-kit", |   "dep:objc2-web-kit", | ||||||
|  |   "dep:webview2-com", | ||||||
|  |   "dep:windows-core", | ||||||
|  |   "dep:windows", | ||||||
|  |   "dep:serde_json", | ||||||
| ] | ] | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| use std::{env::temp_dir, fs, os::unix::fs::PermissionsExt}; | use std::{env::temp_dir, fs}; | ||||||
|  |  | ||||||
| use gpapi::{auth::SamlAuthData, GP_CALLBACK_PORT_FILENAME}; | use gpapi::{auth::SamlAuthData, GP_CALLBACK_PORT_FILENAME}; | ||||||
| use log::info; | use log::info; | ||||||
| @@ -96,7 +96,11 @@ async fn wait_auth_data() -> anyhow::Result<SamlAuthData> { | |||||||
|  |  | ||||||
|   // Write the port to a file |   // Write the port to a file | ||||||
|   fs::write(&port_file, port.to_string())?; |   fs::write(&port_file, port.to_string())?; | ||||||
|  |   #[cfg(unix)] | ||||||
|  |   { | ||||||
|  |     use os::unix::fs::PermissionsExt; | ||||||
|     fs::set_permissions(&port_file, fs::Permissions::from_mode(0o600))?; |     fs::set_permissions(&port_file, fs::Permissions::from_mode(0o600))?; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Remove the previous log file |   // Remove the previous log file | ||||||
|   let callback_log = temp_dir().join("gpcallback.log"); |   let callback_log = temp_dir().join("gpcallback.log"); | ||||||
|   | |||||||
| @@ -1,8 +1,9 @@ | |||||||
| mod auth_messenger; | mod auth_messenger; | ||||||
| mod webview_auth; | mod webview_auth; | ||||||
|  |  | ||||||
| #[cfg_attr(not(target_os = "macos"), path = "webview/unix.rs")] | #[cfg_attr(not(any(target_os = "macos", target_os = "windows")), path = "webview/unix.rs")] | ||||||
| #[cfg_attr(target_os = "macos", path = "webview/macos.rs")] | #[cfg_attr(target_os = "macos", path = "webview/macos.rs")] | ||||||
|  | #[cfg_attr(windows, path = "webview/windows.rs")] | ||||||
| mod platform_impl; | mod platform_impl; | ||||||
|  |  | ||||||
| pub use webview_auth::WebviewAuthenticator; | pub use webview_auth::WebviewAuthenticator; | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ pub(crate) enum AuthDataLocation { | |||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub(crate) enum AuthError { | pub(crate) enum AuthError { | ||||||
|   /// Failed to load page due to TLS error |   /// Failed to load page due to TLS error | ||||||
|   #[cfg(not(target_os = "macos"))] |   #[cfg(not(any(target_os = "macos", target_os = "windows")))] | ||||||
|   TlsError, |   TlsError, | ||||||
|   /// 1. Found auth data in headers/body but it's invalid |   /// 1. Found auth data in headers/body but it's invalid | ||||||
|   /// 2. Loaded an empty page, failed to load page. etc. |   /// 2. Loaded an empty page, failed to load page. etc. | ||||||
|   | |||||||
| @@ -115,7 +115,7 @@ impl<'a> WebviewAuthenticator<'a> { | |||||||
|       match auth_messenger.subscribe().await? { |       match auth_messenger.subscribe().await? { | ||||||
|         AuthEvent::Close => bail!("Authentication cancelled"), |         AuthEvent::Close => bail!("Authentication cancelled"), | ||||||
|         AuthEvent::RaiseWindow => self.raise_window(&auth_window), |         AuthEvent::RaiseWindow => self.raise_window(&auth_window), | ||||||
|         #[cfg(not(target_os = "macos"))] |         #[cfg(not(any(target_os = "macos", target_os = "windows")))] | ||||||
|         AuthEvent::Error(AuthError::TlsError) => bail!(gpapi::error::PortalError::TlsError), |         AuthEvent::Error(AuthError::TlsError) => bail!(gpapi::error::PortalError::TlsError), | ||||||
|         AuthEvent::Error(AuthError::NotFound(location)) => { |         AuthEvent::Error(AuthError::NotFound(location)) => { | ||||||
|           info!( |           info!( | ||||||
| @@ -261,10 +261,10 @@ impl<'a> WebviewAuthenticator<'a> { | |||||||
|  |  | ||||||
|     info!("Raising auth window..."); |     info!("Raising auth window..."); | ||||||
|  |  | ||||||
|     #[cfg(target_os = "macos")] |     #[cfg(any(target_os = "macos", target_os = "windows"))] | ||||||
|     let result = auth_window.show(); |     let result = auth_window.show(); | ||||||
|  |  | ||||||
|     #[cfg(not(target_os = "macos"))] |     #[cfg(not(any(target_os = "macos", target_os = "windows")))] | ||||||
|     let result = { |     let result = { | ||||||
|       use gpapi::utils::window::WindowExt; |       use gpapi::utils::window::WindowExt; | ||||||
|       auth_window.raise() |       auth_window.raise() | ||||||
|   | |||||||
							
								
								
									
										142
									
								
								crates/auth/src/webview/windows.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								crates/auth/src/webview/windows.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | |||||||
|  | use log::warn; | ||||||
|  | use tauri::webview::PlatformWebview; | ||||||
|  | use webview2_com::{ | ||||||
|  |   pwstr_from_str, take_pwstr, ExecuteScriptCompletedHandler, | ||||||
|  |   Microsoft::Web::WebView2::Win32::{ | ||||||
|  |     ICoreWebView2WebResourceResponseView, ICoreWebView2_14, ICoreWebView2_2, | ||||||
|  |     COREWEBVIEW2_SERVER_CERTIFICATE_ERROR_ACTION_ALWAYS_ALLOW, | ||||||
|  |   }, | ||||||
|  |   ServerCertificateErrorDetectedEventHandler, WebResourceResponseReceivedEventHandler, | ||||||
|  | }; | ||||||
|  | use windows_core::{Interface, PWSTR}; | ||||||
|  |  | ||||||
|  | use super::{ | ||||||
|  |   auth_messenger::AuthError, | ||||||
|  |   webview_auth::{GetHeader, PlatformWebviewExt}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | impl PlatformWebviewExt for PlatformWebview { | ||||||
|  |   fn ignore_tls_errors(&self) -> anyhow::Result<()> { | ||||||
|  |     unsafe { | ||||||
|  |       let wv = self.controller().CoreWebView2()?.cast::<ICoreWebView2_14>()?; | ||||||
|  |       let handler = ServerCertificateErrorDetectedEventHandler::create(Box::new(|_, e| { | ||||||
|  |         if let Some(e) = e { | ||||||
|  |           let _ = e.SetAction(COREWEBVIEW2_SERVER_CERTIFICATE_ERROR_ACTION_ALWAYS_ALLOW); | ||||||
|  |         } | ||||||
|  |         Ok(()) | ||||||
|  |       })); | ||||||
|  |  | ||||||
|  |       wv.add_ServerCertificateErrorDetected(&handler, &mut Default::default())?; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Ok(()) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   fn load_url(&self, url: &str) -> anyhow::Result<()> { | ||||||
|  |     let url = pwstr_from_str(url); | ||||||
|  |  | ||||||
|  |     unsafe { self.controller().CoreWebView2()?.Navigate(url)? } | ||||||
|  |  | ||||||
|  |     Ok(()) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   fn load_html(&self, html: &str) -> anyhow::Result<()> { | ||||||
|  |     let html = pwstr_from_str(html); | ||||||
|  |  | ||||||
|  |     unsafe { self.controller().CoreWebView2()?.NavigateToString(html)? } | ||||||
|  |  | ||||||
|  |     Ok(()) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   fn get_html(&self, callback: Box<dyn Fn(anyhow::Result<String>) + 'static>) { | ||||||
|  |     unsafe { | ||||||
|  |       match self.controller().CoreWebView2() { | ||||||
|  |         Ok(wv) => { | ||||||
|  |           let js = "document.documentElement.outerHTML"; | ||||||
|  |           let js = pwstr_from_str(js); | ||||||
|  |  | ||||||
|  |           let handler = ExecuteScriptCompletedHandler::create(Box::new(move |err, html| { | ||||||
|  |             if let Err(err) = err { | ||||||
|  |               callback(Err(anyhow::anyhow!(err))); | ||||||
|  |               return Ok(()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // The returned HTML is JSON.stringify'd string, so we need to parse it | ||||||
|  |             let res = match serde_json::from_str(&html) { | ||||||
|  |               Ok(Some(html)) => Ok(html), | ||||||
|  |               Ok(None) => Err(anyhow::anyhow!("No HTML returned")), | ||||||
|  |               Err(err) => Err(anyhow::anyhow!(err)), | ||||||
|  |             }; | ||||||
|  |             callback(res); | ||||||
|  |  | ||||||
|  |             Ok(()) | ||||||
|  |           })); | ||||||
|  |  | ||||||
|  |           if let Err(err) = wv.ExecuteScript(js, &handler) { | ||||||
|  |             warn!("Failed to execute script: {}", err); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         Err(err) => callback(Err(anyhow::anyhow!(err))), | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl GetHeader for ICoreWebView2WebResourceResponseView { | ||||||
|  |   fn get_header(&self, key: &str) -> Option<String> { | ||||||
|  |     unsafe { | ||||||
|  |       let headers = self.Headers().ok()?; | ||||||
|  |       let key = pwstr_from_str(key); | ||||||
|  |  | ||||||
|  |       let mut contains = Default::default(); | ||||||
|  |       headers.Contains(key, &mut contains).ok()?; | ||||||
|  |  | ||||||
|  |       if contains.as_bool() { | ||||||
|  |         let mut value = PWSTR::null(); | ||||||
|  |         headers.GetHeader(key, &mut value).ok()?; | ||||||
|  |         let value = take_pwstr(value); | ||||||
|  |  | ||||||
|  |         Some(value) | ||||||
|  |       } else { | ||||||
|  |         None | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub trait PlatformWebviewOnResponse { | ||||||
|  |   fn on_response( | ||||||
|  |     &self, | ||||||
|  |     callback: Box<dyn Fn(anyhow::Result<ICoreWebView2WebResourceResponseView, AuthError>) + 'static>, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl PlatformWebviewOnResponse for PlatformWebview { | ||||||
|  |   fn on_response( | ||||||
|  |     &self, | ||||||
|  |     callback: Box<dyn Fn(anyhow::Result<ICoreWebView2WebResourceResponseView, AuthError>) + 'static>, | ||||||
|  |   ) { | ||||||
|  |     unsafe { | ||||||
|  |       let _ = self | ||||||
|  |         .controller() | ||||||
|  |         .CoreWebView2() | ||||||
|  |         .and_then(|wv| wv.cast::<ICoreWebView2_2>()) | ||||||
|  |         .map(|wv| { | ||||||
|  |           let handler = WebResourceResponseReceivedEventHandler::create(Box::new(move |_, e| { | ||||||
|  |             let Some(e) = e else { | ||||||
|  |               return Ok(()); | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             match e.Response() { | ||||||
|  |               Ok(res) => callback(Ok(res)), | ||||||
|  |               Err(err) => warn!("Failed to get response: {}", err), | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             Ok(()) | ||||||
|  |           })); | ||||||
|  |  | ||||||
|  |           let _ = wv.add_WebResourceResponseReceived(&handler, &mut Default::default()); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -27,7 +27,7 @@ chacha20poly1305 = { version = "0.10", features = ["std"] } | |||||||
| redact-engine.workspace = true | redact-engine.workspace = true | ||||||
| url.workspace = true | url.workspace = true | ||||||
| regex.workspace = true | regex.workspace = true | ||||||
| uzers.workspace = true |  | ||||||
| serde_urlencoded.workspace = true | serde_urlencoded.workspace = true | ||||||
| md5.workspace = true | md5.workspace = true | ||||||
| sha256.workspace = true | sha256.workspace = true | ||||||
| @@ -39,8 +39,8 @@ 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] | [target.'cfg(target_family="unix")'.dependencies] | ||||||
| gtk = "0.18" | uzers.workspace = true | ||||||
|  |  | ||||||
| [features] | [features] | ||||||
| tauri = ["dep:tauri"] | tauri = ["dep:tauri"] | ||||||
|   | |||||||
| @@ -104,7 +104,7 @@ impl SamlAuthData { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     let auth_data = decode_to_string(auth_data).map_err(|e| { |     let auth_data = decode_to_string(auth_data).map_err(|e| { | ||||||
|       warn!("Failed to decode SAML auth data: {}", e); |       warn!("Failed to decode SAML auth data: {}", auth_data); | ||||||
|       AuthDataParseError::Invalid(anyhow::anyhow!(e)) |       AuthDataParseError::Invalid(anyhow::anyhow!(e)) | ||||||
|     })?; |     })?; | ||||||
|     let auth_data = Self::from_html(&auth_data)?; |     let auth_data = Self::from_html(&auth_data)?; | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| mod login; | mod login; | ||||||
| mod parse_gateways; | mod parse_gateways; | ||||||
|  |  | ||||||
|  | #[cfg(unix)] | ||||||
| pub mod hip; | pub mod hip; | ||||||
|  |  | ||||||
| pub use login::*; | pub use login::*; | ||||||
|   | |||||||
| @@ -4,7 +4,10 @@ pub mod error; | |||||||
| pub mod gateway; | pub mod gateway; | ||||||
| pub mod gp_params; | pub mod gp_params; | ||||||
| pub mod portal; | pub mod portal; | ||||||
|  |  | ||||||
|  | #[cfg(unix)] | ||||||
| pub mod process; | pub mod process; | ||||||
|  |  | ||||||
| pub mod service; | pub mod service; | ||||||
| pub mod utils; | pub mod utils; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
| pub(crate) mod command_traits; | pub(crate) mod command_traits; | ||||||
|  |  | ||||||
| pub(crate) mod gui_helper_launcher; | pub(crate) mod gui_helper_launcher; | ||||||
|  |  | ||||||
| pub mod auth_launcher; | pub mod auth_launcher; | ||||||
| pub mod gui_launcher; | pub mod gui_launcher; | ||||||
| pub mod hip_launcher; | pub mod hip_launcher; | ||||||
| pub mod service_launcher; | pub mod service_launcher; | ||||||
|  |  | ||||||
|  | #[cfg(unix)] | ||||||
| pub mod users; | pub mod users; | ||||||
|   | |||||||
| @@ -41,6 +41,12 @@ 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"); | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ pub mod lock_file; | |||||||
| pub mod openssl; | pub mod openssl; | ||||||
| pub mod redact; | pub mod redact; | ||||||
| pub mod request; | pub mod request; | ||||||
| #[cfg(feature = "tauri")] | #[cfg(all(feature = "tauri", not(any(target_os = "macos", target_os = "windows"))))] | ||||||
| pub mod window; | pub mod window; | ||||||
|  |  | ||||||
| mod shutdown_signal; | mod shutdown_signal; | ||||||
|   | |||||||
| @@ -6,15 +6,21 @@ pub async fn shutdown_signal() { | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   #[cfg(unix)] |   #[cfg(unix)] | ||||||
|  |   { | ||||||
|     let terminate = async { |     let terminate = async { | ||||||
|       signal::unix::signal(signal::unix::SignalKind::terminate()) |       signal::unix::signal(signal::unix::SignalKind::terminate()) | ||||||
|         .expect("failed to install signal handler") |         .expect("failed to install signal handler") | ||||||
|         .recv() |         .recv() | ||||||
|         .await; |         .await; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     tokio::select! { |     tokio::select! { | ||||||
|         _ = ctrl_c => {}, |         _ = ctrl_c => {}, | ||||||
|         _ = terminate => {}, |         _ = terminate => {}, | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   #[cfg(not(unix))] | ||||||
|  |   { | ||||||
|  |     ctrl_c.await; | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,49 +1,26 @@ | |||||||
|  | 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<()> { | ||||||
|     self.show()?; |     raise_window(self) | ||||||
|     Ok(()) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   #[cfg(not(any(target_os = "macos", target_os = "windows")))] |  | ||||||
|   fn raise(&self) -> anyhow::Result<()> { |  | ||||||
|     unix::raise_window(self) |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(not(any(target_os = "macos", target_os = "windows")))] |  | ||||||
| mod unix { |  | ||||||
|   use std::{process::ExitStatus, time::Duration}; |  | ||||||
|  |  | ||||||
|   use anyhow::bail; |  | ||||||
|   use gtk::{ |  | ||||||
|     glib::Cast, |  | ||||||
|     traits::{EventBoxExt, GtkWindowExt, WidgetExt}, |  | ||||||
|     EventBox, |  | ||||||
|   }; |  | ||||||
|   use log::info; |  | ||||||
|   use tauri::WebviewWindow; |  | ||||||
|   use tokio::process::Command; |  | ||||||
|  |  | ||||||
| pub fn raise_window(win: &WebviewWindow) -> anyhow::Result<()> { | pub fn raise_window(win: &WebviewWindow) -> anyhow::Result<()> { | ||||||
|   let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland"; |   let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland"; | ||||||
|  |  | ||||||
|   if is_wayland { |   if is_wayland { | ||||||
|       let gtk_win = win.gtk_window()?; |     win.hide()?; | ||||||
|       if let Some(header) = gtk_win.titlebar() { |     win.show()?; | ||||||
|         let _ = header.downcast::<EventBox>().map(|event_box| { |  | ||||||
|           event_box.set_above_child(false); |  | ||||||
|         }); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       gtk_win.hide(); |  | ||||||
|       gtk_win.show_all(); |  | ||||||
|   } else { |   } else { | ||||||
|     if !win.is_visible()? { |     if !win.is_visible()? { | ||||||
|       win.show()?; |       win.show()?; | ||||||
| @@ -56,7 +33,7 @@ mod unix { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|     // Calling window.show() on window object will cause the menu to be shown. |   // Calling window.show() on Windows will cause the menu to be shown. | ||||||
|   // We need to hide it again. |   // We need to hide it again. | ||||||
|   win.hide_menu()?; |   win.hide_menu()?; | ||||||
|  |  | ||||||
| @@ -94,4 +71,3 @@ mod unix { | |||||||
|  |  | ||||||
|   Ok(exit_status) |   Ok(exit_status) | ||||||
| } | } | ||||||
| } |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user