wifi-wand 2.16.1 → 2.17.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|