From c6450bd0faccfab8cadf3a6a4bc93bdc584848da Mon Sep 17 00:00:00 2001 From: Taufiq Widi Nugroho Date: Fri, 8 Jul 2022 10:04:58 +0700 Subject: [PATCH 1/7] add 1 second delay before looping through the rows --- lazy-connect | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lazy-connect b/lazy-connect index 81b40b0..fe7d312 100755 --- a/lazy-connect +++ b/lazy-connect @@ -170,8 +170,8 @@ function _lazy_connect_mojave() { tell application "System Events" tell process "System Preferences" tell window 1 + delay 1 repeat with r in rows of table 1 of scroll area 1 - if (value of attribute "AXValue" of static text 1 of r as string) is equal to "$osx_vpn_name" then select r end if From 57af7cca8a5bbf33baa610da8b980c0b9e519309 Mon Sep 17 00:00:00 2001 From: Taufiq Widi Nugroho Date: Wed, 18 Jan 2023 19:12:12 +0700 Subject: [PATCH 2/7] add support for mac os ventura --- lazy-connect | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/lazy-connect b/lazy-connect index fe7d312..1202c64 100755 --- a/lazy-connect +++ b/lazy-connect @@ -206,6 +206,95 @@ function _lazy_connect_mojave() { EOF } +function _lazy_connect_ventura(){ + vpn_name=$1 + osx_vpn_name="${vpn_name/Connect /}" + + _lazy_connect_get_totp $2 + local autofill=$3 + + if [ -z "$password" ]; then + case $TOTP_MODE in + oathtool) + echo "Error: Unable to generate otp using oathtool." + return 1 + ;; + yubikey) + echo "Error: No YubiKey found." + return 1 + ;; + esac + elif [ "$autofill" == "false" ]; then + echo -n "$password" | pbcopy + fi + + osascript -l JavaScript > /dev/null <<-EOF + function connectVpn(vpnName, password, autofill) { + // Reveal System Settings + Application("System Settings").reveal() + const settings = Application("System Events").applicationProcesses.byName("System Settings") + + // Focus on it + settings.frontmost = true + + // Wait for System Settings window appearing + delay(0.5) + + // Reveal VPN panel + settings.menuBars[0].menuBarItems["View"].menus["View"].menuItems["VPN"].click() + + // Wait for panel switching + delay(0.5) + + // check the Speak item under the pointer checkbox + const areas = settings.windows[0].groups[0].splitterGroups[0].groups[1].groups[0].scrollAreas[0] + let idx = -1 + for (let i = 0; i< areas.groups.length; i++) { + let g = areas.groups[i] + try { + g.checkboxes[vpnName].value() + idx = i + } catch(error) { + // ignore the error + } + } + + if (idx > -1) { + const checkbox = areas.groups[idx].checkboxes[vpnName] + const button = areas.groups[idx].buttons[0] + if (button !== null) { + button.click() + } + + delay(0.5) + + const sectionArea = settings.windows[0].sheets[0].groups[0].splitterGroups[0].groups[0] + const dialogArea = settings.windows[0].sheets[0].groups[0].splitterGroups[0].groups[1] + const authArea = dialogArea.scrollAreas[0].groups[2] + + const passwordField = authArea.textFields[1] + const lastPass = passwordField.value() + if (lastPass === password) { + const cancelButton = dialogArea.buttons[1] + okButton.click() + } else { + passwordField.focused = true + passwordField.value = password + const okButton = dialogArea.buttons[2] + okButton.click() + } + delay(0.5) + if (checkbox.value() === 0) { + checkbox.click() + } + } + + settings.quit() + } + connectVpn("$osx_vpn_name", "$password", "$autofill") +EOF +} + version_lte() { [ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ] } @@ -261,11 +350,14 @@ function lazy-connect() { fzf --height=10 --ansi --reverse --query "$*" --select-1) mac_version=$(sw_vers -productVersion) + is_less_than_ventura=$(version_lt $mac_version 13.0 && echo "yes" || echo "no") is_less_than_mojave=$(version_lt $mac_version 10.14 && echo "yes" || echo "no") if [ $is_less_than_mojave = "yes" ]; then [ -z "$vpn_name" ] || _lazy_connect "$vpn_name" "$secret" "$autofill" - else + elif [ $is_less_than_ventura = "yes" ]; then [ -z "$vpn_name" ] || _lazy_connect_mojave "$vpn_name" "$secret" "$autofill" + else + [ -z "$vpn_name" ] || _lazy_connect_ventura "$vpn_name" "$secret" "$autofill" fi } From 4bebe3a35032ad4fee6d9d543bc3b4fa28be76bc Mon Sep 17 00:00:00 2001 From: Taufiq Widi Nugroho Date: Wed, 18 Jan 2023 19:23:48 +0700 Subject: [PATCH 3/7] fix quit settings --- lazy-connect | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lazy-connect b/lazy-connect index 1202c64..e5146bb 100755 --- a/lazy-connect +++ b/lazy-connect @@ -231,7 +231,8 @@ function _lazy_connect_ventura(){ osascript -l JavaScript > /dev/null <<-EOF function connectVpn(vpnName, password, autofill) { // Reveal System Settings - Application("System Settings").reveal() + const app = Application("System Settings") + app.reveal() const settings = Application("System Events").applicationProcesses.byName("System Settings") // Focus on it @@ -289,7 +290,7 @@ function _lazy_connect_ventura(){ } } - settings.quit() + app.quit() } connectVpn("$osx_vpn_name", "$password", "$autofill") EOF From c594fece22ebe4f236b9c75c9fde9955d8d82ace Mon Sep 17 00:00:00 2001 From: Taufiq Widi Nugroho Date: Wed, 18 Jan 2023 19:36:17 +0700 Subject: [PATCH 4/7] fix typo --- lazy-connect | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lazy-connect b/lazy-connect index e5146bb..2c15315 100755 --- a/lazy-connect +++ b/lazy-connect @@ -277,7 +277,7 @@ function _lazy_connect_ventura(){ const lastPass = passwordField.value() if (lastPass === password) { const cancelButton = dialogArea.buttons[1] - okButton.click() + cancelButton.click() } else { passwordField.focused = true passwordField.value = password From f510e4332c8db3a47a9b87544f8b81f5e595cecb Mon Sep 17 00:00:00 2001 From: Taufiq Widi Nugroho Date: Thu, 19 Jan 2023 12:43:17 +0700 Subject: [PATCH 5/7] refactor the logic --- lazy-connect | 65 +++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/lazy-connect b/lazy-connect index 2c15315..c509f3b 100755 --- a/lazy-connect +++ b/lazy-connect @@ -229,6 +229,17 @@ function _lazy_connect_ventura(){ fi osascript -l JavaScript > /dev/null <<-EOF + function findGroupIndex(vpnName, areas) { + let idx = -1 + for (let i = 0; i< areas.groups.length; i++) { + let g = areas.groups[i] + if (g.staticTexts[0].value() === vpnName) { + idx = i + break + } + } + return idx + } function connectVpn(vpnName, password, autofill) { // Reveal System Settings const app = Application("System Settings") @@ -247,21 +258,12 @@ function _lazy_connect_ventura(){ // Wait for panel switching delay(0.5) - // check the Speak item under the pointer checkbox + // check the vpn name const areas = settings.windows[0].groups[0].splitterGroups[0].groups[1].groups[0].scrollAreas[0] - let idx = -1 - for (let i = 0; i< areas.groups.length; i++) { - let g = areas.groups[i] - try { - g.checkboxes[vpnName].value() - idx = i - } catch(error) { - // ignore the error - } - } + let idx = findGroupIndex(vpnName, areas) - if (idx > -1) { - const checkbox = areas.groups[idx].checkboxes[vpnName] + let checkbox = areas.groups[idx].checkboxes[0] + if (idx > -1 && checkbox.value() === 0) { const button = areas.groups[idx].buttons[0] if (button !== null) { button.click() @@ -269,27 +271,32 @@ function _lazy_connect_ventura(){ delay(0.5) - const sectionArea = settings.windows[0].sheets[0].groups[0].splitterGroups[0].groups[0] - const dialogArea = settings.windows[0].sheets[0].groups[0].splitterGroups[0].groups[1] + const sheet = settings.windows[0].sheets[0] + const dialogArea = sheet.groups[0].splitterGroups[0].groups[1] const authArea = dialogArea.scrollAreas[0].groups[2] - + const passwordField = authArea.textFields[1] - const lastPass = passwordField.value() - if (lastPass === password) { - const cancelButton = dialogArea.buttons[1] - cancelButton.click() - } else { - passwordField.focused = true - passwordField.value = password - const okButton = dialogArea.buttons[2] - okButton.click() + passwordField.focused = true + passwordField.value = password + passwordField.focused = false + + try { + let ok = dialogArea.buttons[2] + if (ok.enabled()) { + ok.click() + } else { + throw "Could not OK" + } + } catch (e) { + let cancel = dialogArea.buttons[1] + if (cancel.enabled()) { + cancel.click() + } } + delay(0.5) - if (checkbox.value() === 0) { - checkbox.click() - } + checkbox.click() } - app.quit() } connectVpn("$osx_vpn_name", "$password", "$autofill") From ef713cc78c71ae74f1290dc1ab290785c51fedb7 Mon Sep 17 00:00:00 2001 From: Taufiq Widi Nugroho Date: Thu, 31 Aug 2023 13:35:52 +0700 Subject: [PATCH 6/7] fix: address https://github.com/thecasualcoder/lazy-connect/pull/32\#issuecomment-1678274731 --- lazy-connect | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lazy-connect b/lazy-connect index c509f3b..0dc638b 100755 --- a/lazy-connect +++ b/lazy-connect @@ -280,6 +280,9 @@ function _lazy_connect_ventura(){ passwordField.value = password passwordField.focused = false + const userField = authArea.textFields[0] + userField.focused = true + try { let ok = dialogArea.buttons[2] if (ok.enabled()) { From 2a47f0acd79915bb55b8ede6e82db8a27c215f45 Mon Sep 17 00:00:00 2001 From: tavvfiq Date: Fri, 1 Dec 2023 23:09:37 +0700 Subject: [PATCH 7/7] fix: add support for sonoma --- lazy-connect | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/lazy-connect b/lazy-connect index 0dc638b..7da62a3 100755 --- a/lazy-connect +++ b/lazy-connect @@ -306,6 +306,80 @@ function _lazy_connect_ventura(){ EOF } +function _lazy_connect_sonoma(){ + vpn_name=$1 + osx_vpn_name="${vpn_name/Connect /}" + + _lazy_connect_get_totp $2 + local autofill=$3 + + if [ -z "$password" ]; then + case $TOTP_MODE in + oathtool) + echo "Error: Unable to generate otp using oathtool." + return 1 + ;; + yubikey) + echo "Error: No YubiKey found." + return 1 + ;; + esac + elif [ "$autofill" == "false" ]; then + echo -n "$password" | pbcopy + fi + + osascript -l JavaScript > /dev/null <<-EOF + function findSwitch(vpnName, areas) { + let idx = -1 + for (let i = 0; i< areas.staticTexts.length; i++) { + let text = areas.staticTexts[i] + if (text.value() == vpnName) { + idx = i + break + } + } + return idx/2 + } + function connectVpn(vpnName, password, autofill) { + // Reveal System Settings + const app = Application("System Settings") + app.reveal() + const settings = Application("System Events").applicationProcesses.byName("System Settings") + + // Focus on it + settings.frontmost = true + + // Wait for System Settings window appearing + delay(0.5) + + // Reveal VPN panel + settings.menuBars[0].menuBarItems["View"].menus["View"].menuItems["VPN"].click() + + // Wait for panel switching + delay(0.5) + + // check the vpn name + const areas = settings.windows[0].groups[0].splitterGroups[0].groups[1].groups[0].scrollAreas[0].groups[0] + let idx = findSwitch(vpnName, areas) + let s = areas.checkboxes[idx] + s.click() + delay(1) + const notif = Application("System Events").applicationProcesses.byName("UserNotificationCenter") + if (notif !== undefined && notif !== null) { + const w = notif.windows[0] + if (w !== undefined && w !== null) { + const passwordField = w.textFields[0] + passwordField.value = password + const okButton = w.buttons[1] + okButton.click() + } + } + app.quit() + } + connectVpn("$osx_vpn_name", "$password", "$autofill") +EOF +} + version_lte() { [ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ] } @@ -361,14 +435,17 @@ function lazy-connect() { fzf --height=10 --ansi --reverse --query "$*" --select-1) mac_version=$(sw_vers -productVersion) + is_less_than_sonoma=$(version_lt $mac_version 14.0 && echo "yes" || echo "no") is_less_than_ventura=$(version_lt $mac_version 13.0 && echo "yes" || echo "no") is_less_than_mojave=$(version_lt $mac_version 10.14 && echo "yes" || echo "no") if [ $is_less_than_mojave = "yes" ]; then [ -z "$vpn_name" ] || _lazy_connect "$vpn_name" "$secret" "$autofill" elif [ $is_less_than_ventura = "yes" ]; then [ -z "$vpn_name" ] || _lazy_connect_mojave "$vpn_name" "$secret" "$autofill" - else + elif [ $is_less_than_sonoma = "yes" ]; then [ -z "$vpn_name" ] || _lazy_connect_ventura "$vpn_name" "$secret" "$autofill" + else + [ -z "$vpn_name" ] || _lazy_connect_sonoma "$vpn_name" "$secret" "$autofill" fi }