wifi-wand 2.16.1 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +9 -7
- data/RELEASE_NOTES.md +10 -0
- data/integration-tests/wifi-wand/models/mac_os_model_spec.rb +1 -1
- data/lib/wifi-wand/command_line_interface.rb +0 -25
- data/lib/wifi-wand/models/mac_os_model.rb +14 -136
- data/lib/wifi-wand/version.rb +1 -1
- data/swift/AvailableWifiNetworkLister.swift +5 -7
- data/swift/WifiNetworkDisconecter.swift +4 -0
- metadata +2 -3
- data/lib/wifi-wand/models/model_validator.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71b05a8e0debe969871ce1c44e2a5497458b970f7cf6d666d2035448636f194b
|
4
|
+
data.tar.gz: 3decf9e34a5aaca2b0d1de7ccb91a93138b002d755c648d0975ca0164a48624d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57fa874a6588a7a03862a2397f172374a3203e27fb0694623a6385a1743d195e1899393705cb6ef2133448e402fdf09a8fd4cebb19dfd67fa16d367addaa9a99
|
7
|
+
data.tar.gz: 37b6a84124163b57e1a6922f7703dac69bb8ebcddf6c3ac5d4e056404b4a224b27f1a98505f09c798586df6e0a8cd6a6564664775f48742dd28d90d8dbf6f00a
|
data/README.md
CHANGED
@@ -32,7 +32,7 @@ $ wifi-wand -h
|
|
32
32
|
Command Line Switches: [wifi-wand version 2.14.0 at https://github.com/keithrbennett/wifiwand]
|
33
33
|
|
34
34
|
-o {i,j,k,p,y} - outputs data in inspect, JSON, pretty JSON, puts, or YAML format when not in shell mode
|
35
|
-
-p
|
35
|
+
-p wifi_interface_name - override automatic detection of interface name with this name
|
36
36
|
-s - run in shell mode
|
37
37
|
-v - verbose mode (prints OS commands and their outputs)
|
38
38
|
|
@@ -44,17 +44,18 @@ co[nnect] network-name - turns wifi on, connects to network-name
|
|
44
44
|
cy[cle] - turns wifi off, then on, preserving network selection
|
45
45
|
d[isconnect] - disconnects from current network, does not turn off wifi
|
46
46
|
f[orget] name1 [..name_n] - removes network-name(s) from the preferred networks list
|
47
|
+
in interactive mode, can be a single array of names, e.g. returned by `pref_nets`
|
47
48
|
h[elp] - prints this help
|
48
49
|
i[nfo] - a hash of wifi-related information
|
49
|
-
|
50
|
-
|
50
|
+
na[meservers] - nameservers: 'show' or no arg to show, 'clear' to clear,
|
51
|
+
or IP addresses to set, e.g. '9.9.9.9 8.8.8.8'
|
51
52
|
ne[twork_name] - name (SSID) of currently connected network
|
52
53
|
on - turns wifi on
|
53
54
|
of[f] - turns wifi off
|
54
55
|
pa[ssword] network-name - password for preferred network-name
|
55
56
|
pr[ef_nets] - preferred (saved) networks
|
56
57
|
q[uit] - exits this program (interactive shell mode only) (see also 'x')
|
57
|
-
ro[pen] - open resource ('ipl' (IP Location), 'ipw' (What is My IP), 'spe' (Speed Test), 'this' (wifi-wand home page))
|
58
|
+
ro[pen] - open resource ('cap' (Portal Logins), 'ipl' (IP Location), 'ipw' (What is My IP), 'libre' (LibreSpeed), 'spe' (Speed Test), 'this' (wifi-wand home page))
|
58
59
|
t[ill] - returns when the desired Internet connection state is true. Options:
|
59
60
|
1) 'on'/:on, 'off'/:off, 'conn'/:conn, or 'disc'/:disc
|
60
61
|
2) wait interval between tests, in seconds (optional, defaults to 0.5 seconds)
|
@@ -203,7 +204,6 @@ constants or instance variables if you want to create variables in your shell.
|
|
203
204
|
```
|
204
205
|
wifi-wand i # prints out wifi info
|
205
206
|
wifi-wand a # prints out names of available networks
|
206
|
-
wifi-wand lsa # prints available networks detailed information
|
207
207
|
wifi-wand pr # prints preferred networks
|
208
208
|
wifi-wand cy # cycles the wifi off and on
|
209
209
|
wifi-wand co a-network a-password # connects to a network requiring a password
|
@@ -366,12 +366,14 @@ The following tasks were restored by using `networksetup`:
|
|
366
366
|
* determining whether or not wifi is on
|
367
367
|
* the name of the currently connected network
|
368
368
|
|
369
|
-
The only remaining issue is that we were getting some extended information from airport for each available network.
|
369
|
+
The only remaining issue is that we were getting some extended information from airport for each available network. This extended information has now been removed in version 2.17.0.
|
370
|
+
|
371
|
+
In addition, the extended information about the available networks (`ls_avail_nets`) has been removed in version 2.17.0.
|
370
372
|
|
371
373
|
|
372
374
|
### License
|
373
375
|
|
374
|
-
|
376
|
+
Apache 2 License (see LICENSE.txt)
|
375
377
|
|
376
378
|
### Logo
|
377
379
|
|
data/RELEASE_NOTES.md
CHANGED
@@ -1,7 +1,17 @@
|
|
1
|
+
## v2.17.0
|
2
|
+
|
3
|
+
* Remove all remaining uses of the 'airport' command.
|
4
|
+
* Remove 'available_network_info' command which required the 'airport' command.
|
5
|
+
* Remove extended information in the 'info' command output, which required the 'airport' command.
|
6
|
+
* Remove unused ModelValidator class.
|
7
|
+
* In README, update license reference and make other edits.
|
8
|
+
|
9
|
+
|
1
10
|
## v2.16.1
|
2
11
|
|
3
12
|
* Fix airport deprecations' removal of listing all networks and disconnecting from a network by using Swift scripts.
|
4
13
|
|
14
|
+
|
5
15
|
## v2.16.0 (2024-04)
|
6
16
|
|
7
17
|
* Handle deprecation of the `airport` command starting at Mac OS 14.4.
|
@@ -73,7 +73,6 @@ f[orget] name1 [..name_n] - removes network-name(s) from the preferred networks
|
|
73
73
|
in interactive mode, can be a single array of names, e.g. returned by `pref_nets`
|
74
74
|
h[elp] - prints this help
|
75
75
|
i[nfo] - a hash of wifi-related information
|
76
|
-
l[s_avail_nets] - details about available networks, in descending order of signal strength
|
77
76
|
na[meservers] - nameservers: 'show' or no arg to show, 'clear' to clear,
|
78
77
|
or IP addresses to set, e.g. '9.9.9.9 8.8.8.8'
|
79
78
|
ne[twork_name] - name (SSID) of currently connected network
|
@@ -203,7 +202,6 @@ When in interactive shell mode:
|
|
203
202
|
end
|
204
203
|
|
205
204
|
|
206
|
-
|
207
205
|
def quit
|
208
206
|
if interactive_mode
|
209
207
|
exit(0)
|
@@ -272,29 +270,6 @@ When in interactive shell mode:
|
|
272
270
|
end
|
273
271
|
end
|
274
272
|
|
275
|
-
|
276
|
-
def cmd_l
|
277
|
-
info = model.available_network_info
|
278
|
-
|
279
|
-
if interactive_mode
|
280
|
-
info
|
281
|
-
else
|
282
|
-
output = ''
|
283
|
-
unless model.wifi_on?
|
284
|
-
output << "Wifi is off, cannot see available networks."
|
285
|
-
else
|
286
|
-
if post_processor
|
287
|
-
output = post_processor.(info)
|
288
|
-
else
|
289
|
-
output << "\nAccess points listed in descending order of signal strength (RSSI):\n\n"
|
290
|
-
output << fancy_string(info)
|
291
|
-
end
|
292
|
-
end
|
293
|
-
puts output
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
|
298
273
|
# Performs nameserver functionality.
|
299
274
|
# @param subcommand 'get' or no arg to get, 'clear' to clear, and an array of IP addresses to set
|
300
275
|
def cmd_na(*args)
|
@@ -10,49 +10,11 @@ module WifiWand
|
|
10
10
|
|
11
11
|
class MacOsModel < BaseModel
|
12
12
|
|
13
|
-
DEFAULT_AIRPORT_FILESPEC = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport'
|
14
|
-
|
15
|
-
attr_reader :airport_deprecated, :mac_os_version_major, :mac_os_version_minor, :mac_os_version_string
|
16
|
-
|
17
13
|
# Takes an OpenStruct containing options such as verbose mode and interface name.
|
18
14
|
def initialize(options = OpenStruct.new)
|
19
15
|
super
|
20
|
-
populate_mac_os_version
|
21
|
-
@airport_deprecated = @mac_os_version_major > 14 || (@mac_os_version_major == 14 && @mac_os_version_minor >= 4)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Provides Mac OS major and minor version numbers
|
25
|
-
def populate_mac_os_version
|
26
|
-
@mac_os_version_string = `sw_vers --productVersion`.chomp
|
27
|
-
@mac_os_version_major, @mac_os_version_minor = mac_os_version_string.split('.').map(&:to_i)
|
28
|
-
[@mac_os_version_major, @mac_os_version_minor]
|
29
|
-
end
|
30
|
-
|
31
|
-
def airport_deprecated_message
|
32
|
-
<<~MESSAGE
|
33
|
-
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
34
|
-
This method requires the airport utility which is no longer functional in Mac OS >= 14.4.
|
35
|
-
You are running Mac OS version #{mac_os_version_string}.
|
36
|
-
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
37
|
-
MESSAGE
|
38
|
-
end
|
39
|
-
|
40
|
-
# Although at this time the airport command utility is predictable,
|
41
|
-
# allow putting it elsewhere in the path for overriding and easier fix
|
42
|
-
# if that location should change.
|
43
|
-
def airport_command
|
44
|
-
airport_in_path = `which airport`.chomp
|
45
|
-
|
46
|
-
return airport_in_path unless airport_in_path.empty?
|
47
|
-
|
48
|
-
return DEFAULT_AIRPORT_FILESPEC if File.exist?(DEFAULT_AIRPORT_FILESPEC)
|
49
|
-
|
50
|
-
raise Error.new("Airport command not found.") unless airport_deprecated
|
51
|
-
|
52
|
-
nil # no error, no data
|
53
16
|
end
|
54
17
|
|
55
|
-
|
56
18
|
# Identifies the (first) wireless network hardware interface in the system, e.g. en0 or en1
|
57
19
|
# This may not detect wifi ports with nonstandard names, such as USB wifi devices.
|
58
20
|
def detect_wifi_interface
|
@@ -78,97 +40,6 @@ class MacOsModel < BaseModel
|
|
78
40
|
end
|
79
41
|
end
|
80
42
|
|
81
|
-
|
82
|
-
# Returns data pertaining to available wireless networks.
|
83
|
-
# For some reason, this often returns no results, so I've put the operation in a loop.
|
84
|
-
# I was unable to detect a sort strategy in the airport utility's output, so I sort
|
85
|
-
# the lines alphabetically, to show duplicates and for easier lookup.
|
86
|
-
#
|
87
|
-
# Sample Output:
|
88
|
-
#
|
89
|
-
# => ["SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group)",
|
90
|
-
# "ByCO-U00tRzUzMEg 64:6c:b2:db:f3:0c -56 6 Y -- NONE",
|
91
|
-
# "Chancery 0a:18:d6:0b:b9:c3 -82 11 Y -- NONE",
|
92
|
-
# "Chancery 2a:a4:3c:03:33:99 -59 60,+1 Y -- NONE",
|
93
|
-
# "DIRECT-sq-BRAVIA 02:71:cc:87:4a:8c -76 6 Y -- WPA2(PSK/AES/AES) ", #
|
94
|
-
def available_network_info
|
95
|
-
|
96
|
-
raise RuntimeError, airport_deprecated_message if airport_deprecated
|
97
|
-
|
98
|
-
return nil unless wifi_on? # no need to try
|
99
|
-
command = "#{airport_command} -s | iconv -f macroman -t utf-8"
|
100
|
-
max_attempts = 50
|
101
|
-
|
102
|
-
reformat_line = ->(line) do
|
103
|
-
ssid = line[0..31].strip
|
104
|
-
"%-32.32s%s" % [ssid, line[32..-1]]
|
105
|
-
end
|
106
|
-
|
107
|
-
signal_strength = ->(line) { (line[50..54] || '').to_i }
|
108
|
-
|
109
|
-
sort_in_place_by_signal_strength = ->(lines) do
|
110
|
-
lines.sort! { |x,y| signal_strength.(y) <=> signal_strength.(x) }
|
111
|
-
end
|
112
|
-
|
113
|
-
process_tabular_data = ->(output) do
|
114
|
-
lines = output.split("\n")
|
115
|
-
header_line = lines[0]
|
116
|
-
data_lines = lines[1..-1]
|
117
|
-
data_lines.map! do |line|
|
118
|
-
# Reformat the line so that the name is left instead of right justified
|
119
|
-
reformat_line.(line)
|
120
|
-
end
|
121
|
-
sort_in_place_by_signal_strength.(data_lines)
|
122
|
-
[reformat_line.(header_line)] + data_lines
|
123
|
-
end
|
124
|
-
|
125
|
-
output = try_os_command_until(command, ->(output) do
|
126
|
-
! ([nil, ''].include?(output))
|
127
|
-
end)
|
128
|
-
|
129
|
-
if output
|
130
|
-
process_tabular_data.(output)
|
131
|
-
else
|
132
|
-
raise Error.new("Unable to get available network information after #{max_attempts} attempts.")
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
|
137
|
-
# The Mac OS airport utility (at
|
138
|
-
# /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport)
|
139
|
-
# outputs the network names right padded with spaces so there is no way to differentiate a
|
140
|
-
# network name *with* leading space(s) from one without:
|
141
|
-
#
|
142
|
-
# SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group)
|
143
|
-
# ngHub_319442NL0293C 04:a1:51:58:5b:05 -65 11 Y US WPA2(PSK/AES/AES)
|
144
|
-
# NETGEAR89_2GEXT 9c:3d:cf:11:69:b4 -67 8 Y US NONE
|
145
|
-
#
|
146
|
-
# To remedy this, they offer a "-x" option that outputs the information in (pseudo) XML.
|
147
|
-
# This XML has 'dict' elements that contain many elements. The SSID can be found in the
|
148
|
-
# XML element <string> which immediately follows an XML element whose text is "SSID_STR".
|
149
|
-
# Unfortunately, since there is no way to connect the two other than their physical location,
|
150
|
-
# the key is rather useless for XML parsing.
|
151
|
-
#
|
152
|
-
# I tried extracting the arrays of keys and strings, and finding the string element
|
153
|
-
# at the same position in the string array as the 'SSID_STR' was in the keys array.
|
154
|
-
# However, not all keys had string elements, so the index in the key array was the wrong index.
|
155
|
-
# Here is an excerpt from the XML output:
|
156
|
-
#
|
157
|
-
# <key>RSSI</key>
|
158
|
-
# <integer>-91</integer>
|
159
|
-
# <key>SSID</key>
|
160
|
-
# <data>
|
161
|
-
# TkVUR0VBUjY1
|
162
|
-
# </data>
|
163
|
-
# <key>SSID_STR</key>
|
164
|
-
# <string>NETGEAR65</string>
|
165
|
-
#
|
166
|
-
# The kludge I came up with was that the ssid was always the 2nd value in the <string> element
|
167
|
-
# array, so that's what is used here.
|
168
|
-
#
|
169
|
-
# But now even that approach has been superseded by the XPath approach now used.
|
170
|
-
#
|
171
|
-
# REXML is used here to avoid the need for the user to install Nokogiri.
|
172
43
|
def available_network_names
|
173
44
|
return nil unless wifi_on? # no need to try
|
174
45
|
|
@@ -331,13 +202,6 @@ class MacOsModel < BaseModel
|
|
331
202
|
'timestamp' => Time.now,
|
332
203
|
}
|
333
204
|
|
334
|
-
unless airport_deprecated
|
335
|
-
more_output = run_os_command(airport_command + " -I")
|
336
|
-
more_info = colon_output_to_hash(more_output)
|
337
|
-
info.merge!(more_info)
|
338
|
-
info.delete('AirPort') # will be here if off, but info is already in wifi_on key
|
339
|
-
end
|
340
|
-
|
341
205
|
if info['internet_on'] && (! need_hotspot_login)
|
342
206
|
begin
|
343
207
|
info['public_ip'] = public_ip_address_info
|
@@ -430,7 +294,21 @@ class MacOsModel < BaseModel
|
|
430
294
|
output.split("\n")
|
431
295
|
end
|
432
296
|
|
297
|
+
def ensure_swift_and_corewlan_present
|
298
|
+
unless swift_and_corewlan_present?
|
299
|
+
raise RuntimeError, <<~MESSAGE
|
300
|
+
Swift and/or CoreWLAN are not present and are needed by this task.
|
301
|
+
This can be fixed by installing XCode.
|
302
|
+
MESSAGE
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def swift_and_corewlan_present?
|
307
|
+
system("swift -e 'import CoreWLAN' >/dev/null 2>&1")
|
308
|
+
end
|
309
|
+
|
433
310
|
def run_swift_command(basename)
|
311
|
+
ensure_swift_and_corewlan_present
|
434
312
|
swift_filespec = File.join(
|
435
313
|
File.dirname(__FILE__), "../../../swift/#{basename}.swift"
|
436
314
|
)
|
data/lib/wifi-wand/version.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#!/usr/bin/env swift
|
2
|
+
|
1
3
|
import Foundation
|
2
4
|
import CoreWLAN
|
3
5
|
|
@@ -11,10 +13,9 @@ class NetworkScanner {
|
|
11
13
|
return nil
|
12
14
|
}
|
13
15
|
self.currentInterface = defaultInterface
|
14
|
-
self.scanForNetworks()
|
15
16
|
}
|
16
17
|
|
17
|
-
func
|
18
|
+
func available_networks() {
|
18
19
|
do {
|
19
20
|
let networks = try currentInterface.scanForNetworks(withName: nil)
|
20
21
|
for network in networks {
|
@@ -23,10 +24,7 @@ class NetworkScanner {
|
|
23
24
|
} catch let error as NSError {
|
24
25
|
print("Error: \(error.localizedDescription)")
|
25
26
|
}
|
26
|
-
}
|
27
|
+
}
|
27
28
|
}
|
28
29
|
|
29
|
-
|
30
|
-
if NetworkScanner() != nil {
|
31
|
-
// The list of available networks will be printed
|
32
|
-
}
|
30
|
+
NetworkScanner()?.available_networks()
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wifi-wand
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keith Bennett
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|
@@ -134,7 +134,6 @@ files:
|
|
134
134
|
- lib/wifi-wand/models/base_model.rb
|
135
135
|
- lib/wifi-wand/models/helpers/command_output_formatter.rb
|
136
136
|
- lib/wifi-wand/models/mac_os_model.rb
|
137
|
-
- lib/wifi-wand/models/model_validator.rb
|
138
137
|
- lib/wifi-wand/operating_systems.rb
|
139
138
|
- lib/wifi-wand/os/base_os.rb
|
140
139
|
- lib/wifi-wand/os/imaginary_os.rb
|
@@ -1,60 +0,0 @@
|
|
1
|
-
module WifiWand
|
2
|
-
|
3
|
-
class ModelValidator
|
4
|
-
|
5
|
-
BASE_MODEL_ESSENTIAL_METHODS = [
|
6
|
-
:connect,
|
7
|
-
:connected_to?,
|
8
|
-
:connected_to_internet?,
|
9
|
-
:cycle_network,
|
10
|
-
:preferred_network_password,
|
11
|
-
:public_ip_address_info,
|
12
|
-
:random_mac_address,
|
13
|
-
:remove_preferred_networks,
|
14
|
-
:run_os_command,
|
15
|
-
:till,
|
16
|
-
:try_os_command_until,
|
17
|
-
:verbose_mode,
|
18
|
-
:verbose_mode=,
|
19
|
-
:wifi_interface,
|
20
|
-
:wifi_interface=
|
21
|
-
]
|
22
|
-
|
23
|
-
|
24
|
-
BASE_MODEL_NONESSENTIAL_METHODS = [
|
25
|
-
]
|
26
|
-
|
27
|
-
|
28
|
-
MAC_OS_MODEL_ESSENTIAL_METHODS = [
|
29
|
-
:airport_command,
|
30
|
-
:available_network_info,
|
31
|
-
:available_network_names,
|
32
|
-
:connected_network_name,
|
33
|
-
:detect_wifi_interface,
|
34
|
-
:disconnect,
|
35
|
-
:ip_address,
|
36
|
-
:is_wifi_interface?,
|
37
|
-
:mac_address,
|
38
|
-
:nameservers_using_networksetup,
|
39
|
-
:nameservers_using_resolv_conf,
|
40
|
-
:nameservers_using_scutil,
|
41
|
-
:open_resource,
|
42
|
-
:os_level_connect,
|
43
|
-
:os_level_preferred_network_password,
|
44
|
-
:preferred_networks,
|
45
|
-
:remove_preferred_network,
|
46
|
-
:set_nameservers,
|
47
|
-
:wifi_info,
|
48
|
-
:wifi_off,
|
49
|
-
:wifi_on,
|
50
|
-
:wifi_on?
|
51
|
-
]
|
52
|
-
|
53
|
-
MAC_OS_MODEL_ESSENTIAL_METHODS = [
|
54
|
-
]
|
55
|
-
|
56
|
-
ALL_MODEL_METHODS = BASE_MODEL_ESSENTIAL_METHODS + MAC_OS_MODEL_ESSENTIAL_METHODS
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|