Merge wicd:master-takahiro into wicd:master
- Git
- lp:wicd
- master-takahiro
- Merge into master
Proposed by
Takahiro Yoshizawa
Status: | Merged |
---|---|
Merged at revision: | db879f94b34f5432e9388e6271468f3e84639b32 |
Proposed branch: | wicd:master-takahiro |
Merge into: | wicd:master |
Diff against target: |
5070 lines (+1944/-796) 27 files modified
AUTHORS (+2/-0) INSTALL (+74/-57) in/init=debian=wicd.in (+1/-1) in/init=plamo=wicd.in (+65/-0) other/wicd.conf (+47/-0) po/ja.po (+2/-2) pyproject.toml (+60/-1) setup.cfg (+0/-25) setup.py (+341/-28) src/wicd/commandline.py (+2/-1) src/wicd/configmanager.py (+3/-2) src/wicd/daemon/__main__.py (+149/-67) src/wicd/daemon/monitor.py (+21/-18) src/wicd/dbus.py (+6/-3) src/wicd/errors.py (+34/-1) src/wicd/frontends/cli.py (+24/-10) src/wicd/frontends/gtk/__main__.py (+210/-91) src/wicd/frontends/gtk/configscript.py (+9/-6) src/wicd/frontends/gtk/gui.py (+75/-57) src/wicd/frontends/gtk/guiutil.py (+29/-19) src/wicd/frontends/gtk/netentry.py (+184/-114) src/wicd/frontends/gtk/prefs.py (+13/-8) src/wicd/frontends/gtk/resources/wicd.ui (+4/-3) src/wicd/logfile.py (+11/-3) src/wicd/misc.py (+66/-12) src/wicd/networking.py (+59/-46) src/wicd/wnettools.py (+453/-221) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Takahiro Yoshizawa | Approve | ||
Review via email:
|
Commit message
Description of the change
Merge Takahiro Yoshizawa's work for Python 3.x compatibility.
To post a comment you must log in.
Revision history for this message

Takahiro Yoshizawa (hanaguro) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/AUTHORS b/AUTHORS |
2 | index a629671..80b34dd 100644 |
3 | --- a/AUTHORS |
4 | +++ b/AUTHORS |
5 | @@ -3,3 +3,5 @@ Adam Blackburn (compwiz18@gmail.com) |
6 | Dan O'Reilly (oreilldf@gmail.com) |
7 | Andrew Psaltis (ampsaltis@gmail.com) |
8 | David Paleino (d.paleino@gmail.com) |
9 | +Andreas Messer (andi@bastelmap.de) |
10 | +Takahiro Yoshizawa (kuro@takahiro.org) |
11 | diff --git a/INSTALL b/INSTALL |
12 | index 5af7ce3..b64166e 100644 |
13 | --- a/INSTALL |
14 | +++ b/INSTALL |
15 | @@ -1,58 +1,75 @@ |
16 | -Installation of Wicd should be done using your distribution package if one |
17 | -exists. If not, the installation is relatively straightforward, but there |
18 | -are a few dependencies: |
19 | - 1. python (>=2.4, <3.0) |
20 | - #2. pygtk (>=2.10) |
21 | - 2. dbus and its glib and python bindings |
22 | - 3. a dhcp client (dhclient, dhcpcd, and pump are supported) |
23 | - 4. wireless-tools (iwlist, iwconfig, etcetera) |
24 | - 5. net-tools (ip, route, etcetera) |
25 | - 6. a graphical sudo application (gksu, kdesu, and ktsuss are supported), |
26 | - while optional, is strongly recommended |
27 | - 7. urwid (if you want to use the curses client - needs version >=0.9.8.3) |
28 | - 8. pm-utils (optional for suspend/resume integration) |
29 | - Wicd supports using versions >=1.2.4 -- earlier versions may work just |
30 | - fine, but they are completely unsupported here. |
31 | - 9. pybabel |
32 | - 10. rfkill |
33 | - 11. python-appindicator if you want the Unity-compatible appindicator notifications |
34 | - |
35 | -Next, configure Wicd for installation. Wicd will, by default, follow the |
36 | -FHS guidelines <http://www.pathname.com/fhs/> (or distribution standards |
37 | -where applicable if we know about them and it's feasible to implement them). |
38 | -You can specify exactly where every non-Python file (and some Python files) |
39 | -in Wicd will be placed. Pass "--help" as an option to the following command |
40 | -for more information, otherwise run it as is to configure Wicd for installation. |
41 | - python setup.py configure |
42 | - |
43 | -Note that setup.py will try to determine if and where to install the autostart |
44 | -desktop file for kde (either kde3 or kde4, but not both) and where to install |
45 | -the sleep hook for pm-utils. |
46 | - |
47 | -If you want native language translations, please remember to run: |
48 | - python setup.py compile_translations |
49 | -before the next step. |
50 | - |
51 | -Finally, do the actual installation. This step will need to be done as |
52 | -root or with sudo in most cases: |
53 | - python setup.py install |
54 | -If you are packaging Wicd, you will almost surely want to use the "--root" |
55 | -option; for example: |
56 | - python setup.py install --root=/package-dir |
57 | - |
58 | -To uninstall, you can use (using root or sudo): |
59 | - python setup.py uninstall |
60 | - |
61 | -You *MUST* run "python setup.py configure" before "python setup.py install" - |
62 | -the "configure" step generates wpath.py from wpath.py.in using the paths |
63 | -specified from the arguments to "python setup.py configure". |
64 | -As noted above in the configure step, "python setup.py configure" will use |
65 | -acceptable defaults, so it is usually not necessary to specify any arguments |
66 | -at all. |
67 | - |
68 | -After installation, especially if Wicd has not been installed before, you |
69 | -will probably need to restart the system message bus (dbus) or reload its |
70 | -configuration. You will also need to make sure the Wicd init script is |
71 | -started at boot. How to do those things is distribution-dependent, so if |
72 | -you're not sure, ask in your distribution's support area(s). |
73 | +INSTALL |
74 | |
75 | +Note: It is generally recommended to install Wicd using your distribution’s package manager if a package is available. If not, follow the instructions below. |
76 | + |
77 | +Requirements |
78 | +1. Python 3.10 or later |
79 | +2. D-Bus with GLib and Python bindings |
80 | +3. A DHCP client: |
81 | + - On Ubuntu 24.04: Must use isc-dhcp-client (provides dhclient). |
82 | + - On Fedora 41: Either dhclient (provided by isc-dhcp-client) or dhcpcd can be used. |
83 | +4. net-tools (provides ifconfig, route, etc.) |
84 | +5. iw |
85 | +6. AyatanaAppIndicator3 bindings: |
86 | + - On Ubuntu 24.04: gir1.2-ayatanaappindicator3-0.1 |
87 | + - On Fedora 41: libayatana-appindicator-gtk3 |
88 | +7. A graphical sudo application (optional but recommended: gksu, kdesu, or ktsuss) |
89 | +8. rfkill (if not already available) |
90 | +9. pip (Python package installer) |
91 | + |
92 | + |
93 | +General Installation Steps |
94 | + |
95 | +1. Install Dependencies |
96 | +Use your distribution’s package manager to install the required dependencies. For example: |
97 | + |
98 | +Ubuntu 24.04: |
99 | + sudo apt install git python3-pip net-tools iw isc-dhcp-client gir1.2-ayatanaappindicator3-0.1 |
100 | + |
101 | +Fedora 41: |
102 | + sudo dnf install git python3-pip net-tools iw libayatana-appindicator-gtk3 |
103 | + |
104 | +(Adjust package names as needed for other distributions.) |
105 | + |
106 | + |
107 | +2. Obtain and Install Wicd from Source |
108 | + git clone https://git.launchpad.net/wicd -b {branch_name} |
109 | + cd wicd |
110 | + |
111 | +For Ubuntu 24.04: |
112 | + sudo pip install . --break-system-packages |
113 | + |
114 | +For Fedora 41 (and most other distributions): |
115 | + sudo pip install . |
116 | + |
117 | + |
118 | +3. Adjust Init/Startup Scripts |
119 | +After installing Wicd, template init files (e.g., SysV init scripts, systemd unit templates) are placed in the `template/init` directory within the source tree. |
120 | +You may need to edit these templates to match your system's paths and conventions. For example, if the scripts reference `/usr/bin` but you installed Wicd into `/usr/local/bin`, update the paths accordingly. Once adjusted, install these scripts in the appropriate locations for your distribution’s init system (e.g., `/etc/init.d` for SysV, `/etc/systemd/system` for systemd). |
121 | + |
122 | + |
123 | +4. Configure D-Bus |
124 | +After installation, create a symbolic link for the D-Bus configuration: |
125 | + sudo ln -s /usr/local/share/dbus-1/system.d/wicd.conf /usr/share/dbus-1/system.d/wicd.conf |
126 | + |
127 | + |
128 | +5. Disable Conflicting Services |
129 | +Wicd can conflict with other network managers. Stop and disable them before using Wicd: |
130 | + sudo systemctl stop NetworkManager.service |
131 | + sudo systemctl disable NetworkManager.service |
132 | + |
133 | + sudo systemctl stop systemd-resolved.service |
134 | + sudo systemctl disable systemd-resolved.service |
135 | + |
136 | +Adjust resolv.conf if necessary: |
137 | + sudo mv /etc/resolv.conf /etc/resolv.conf.backup |
138 | + sudo touch /etc/resolv.conf |
139 | + |
140 | + |
141 | +6. Desktop Environment Integration (Optional) |
142 | +If using wicd-gtk on a GNOME-based desktop (such as Fedora GNOME), install gnome-shell-extension-appindicator and enable the "KStatusNotifierItem/AppIndicator Support" extension. |
143 | + |
144 | + |
145 | +7. Reboot |
146 | +After making these changes, it is recommended to restart your system: |
147 | + sudo reboot |
148 | diff --git a/in/init=debian=wicd.in b/in/init=debian=wicd.in |
149 | index 879695b..2968c99 100755 |
150 | --- a/in/init=debian=wicd.in |
151 | +++ b/in/init=debian=wicd.in |
152 | @@ -19,7 +19,7 @@ PATH=/usr/sbin:/usr/bin:/sbin:/bin |
153 | DESC="Network connection manager" |
154 | NAME=wicd |
155 | RUNDIR=/var/run/$NAME |
156 | -DAEMON=%SBIN%$NAME |
157 | +DAEMON=%BIN%$NAME |
158 | DAEMON_ARGS="" |
159 | PIDFILE=$RUNDIR/wicd.pid |
160 | SCRIPTNAME=%INIT%%INITFILENAME% |
161 | diff --git a/in/init=plamo=wicd.in b/in/init=plamo=wicd.in |
162 | new file mode 100755 |
163 | index 0000000..4f72b51 |
164 | --- /dev/null |
165 | +++ b/in/init=plamo=wicd.in |
166 | @@ -0,0 +1,65 @@ |
167 | +#!/bin/sh |
168 | +######################################################################## |
169 | +# Begin scriptname : wicd |
170 | +# |
171 | +# Description : start/stop wicd |
172 | +# |
173 | +# Authors : KOJIMA |
174 | +# |
175 | +# Version : Plamo-7.0 |
176 | +# |
177 | +# Notes : |
178 | +# |
179 | +######################################################################## |
180 | + |
181 | +### BEGIN INIT INFO |
182 | +# Provides: wicd |
183 | +# Required-Start: dbus |
184 | +# Required-Stop: sendsignals |
185 | +# Default-Start: 2 3 4 5 |
186 | +# Default-Stop: 0 2 6 |
187 | +# Short-Description: starts wicd network manager |
188 | +# Description: Wicd is a wireless and wired network manager for Linux. |
189 | +# X-LFS-Provided-By: |
190 | +### END INIT INFO |
191 | + |
192 | +. /lib/lsb/init-functions |
193 | + |
194 | +WICD=/usr/bin/wicd |
195 | +if [ -x /usr/bin/wicd ]; then |
196 | + WICD=/usr/bin/wicd |
197 | +fi |
198 | + |
199 | +PIDFILE="%PIDFILE%" |
200 | + |
201 | +case "${1}" in |
202 | + start) |
203 | + log_info_msg "Starting wicd network manager" |
204 | + start_daemon $WICD |
205 | + evaluate_retval |
206 | + ;; |
207 | + |
208 | + stop) |
209 | + log_info_msg "Stopping wicd network manager" |
210 | + $WICD -k |
211 | + evaluate_retval |
212 | + if [ -f $PIDFILE ]; then |
213 | + rm -f $PIDFILE |
214 | + fi |
215 | + ;; |
216 | + |
217 | + restart) |
218 | + ${0} stop |
219 | + sleep 1 |
220 | + ${0} start |
221 | + ;; |
222 | + |
223 | + *) |
224 | + echo "Usage: ${0} {start|stop|restart}" |
225 | + exit 1 |
226 | + ;; |
227 | +esac |
228 | + |
229 | +exit 0 |
230 | + |
231 | +# End scriptname |
232 | diff --git a/in/wicd=wpath.py.in b/in/wpath.py.in |
233 | similarity index 100% |
234 | rename from in/wicd=wpath.py.in |
235 | rename to in/wpath.py.in |
236 | diff --git a/other/wicd.conf b/other/wicd.conf |
237 | new file mode 100644 |
238 | index 0000000..598d12e |
239 | --- /dev/null |
240 | +++ b/other/wicd.conf |
241 | @@ -0,0 +1,47 @@ |
242 | +<!-- /etc/dbus-1/system.d/wicd.conf --> |
243 | +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" |
244 | +"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> |
245 | +<busconfig> |
246 | + |
247 | + <policy user="root"> |
248 | + <allow own="org.wicd.daemon"/> |
249 | + <allow send_destination="org.wicd.daemon"/> |
250 | + <allow send_interface="org.wicd.daemon"/> |
251 | + <allow send_destination="org.wicd.daemon.wireless"/> |
252 | + <allow send_interface="org.wicd.daemon.wireless"/> |
253 | + <allow send_destination="org.wicd.daemon.wired"/> |
254 | + <allow send_interface="org.wicd.daemon.wired"/> |
255 | + </policy> |
256 | + |
257 | + <policy context="default"> |
258 | + <deny own="org.wicd.daemon"/> |
259 | + </policy> |
260 | + |
261 | + <!-- This Unix group will have permission to use Wicd's gui --> |
262 | + <policy group="users"> |
263 | + <allow send_destination="org.wicd.daemon"/> |
264 | + <allow send_interface="org.wicd.daemon"/> |
265 | + <allow send_interface="org.freedesktop.DBus.Introspectable"/> |
266 | + <!-- The Introspectable allow shouldn't be needed here, but |
267 | + it seems that a few distributions aren't yet allowing |
268 | + it in their hal configs, and we need it here, so... --> |
269 | + </policy> |
270 | + |
271 | + <!-- Comment the block below if you do not want all users logged in |
272 | + locally to have permission to use wicd-client. This ignores the |
273 | + group based permission model defined above for the "users" |
274 | + group. Note that this only applies if you are using ConsoleKit - |
275 | + if you do not have ConsoleKit installed and in use, then this |
276 | + block makes no difference either way. --> |
277 | + |
278 | + <policy at_console="true"> |
279 | + <allow send_destination="org.wicd.daemon"/> |
280 | + <allow send_interface="org.wicd.daemon"/> |
281 | + <allow send_destination="org.wicd.daemon.wireless"/> |
282 | + <allow send_interface="org.wicd.daemon.wireless"/> |
283 | + <allow send_destination="org.wicd.daemon.wired"/> |
284 | + <allow send_interface="org.wicd.daemon.wired"/> |
285 | + <allow send_interface="org.freedesktop.DBus.Introspectable"/> |
286 | + </policy> |
287 | + |
288 | +</busconfig> |
289 | diff --git a/po/ja.po b/po/ja.po |
290 | index 4af6a37..b8ca798 100644 |
291 | --- a/po/ja.po |
292 | +++ b/po/ja.po |
293 | @@ -519,7 +519,7 @@ msgstr "" |
294 | |
295 | #: curses/configscript_curses.py:57 gtk/configscript.py:129 |
296 | msgid "Post-connection Script" |
297 | -msgstr "切断後にスクリプトを実行する" |
298 | +msgstr "接続後にスクリプトを実行する" |
299 | |
300 | #: curses/configscript_curses.py:59 gtk/configscript.py:132 |
301 | msgid "Post-disconnection Script" |
302 | @@ -527,7 +527,7 @@ msgstr "切断後にスクリプトを実行する" |
303 | |
304 | #: curses/configscript_curses.py:56 gtk/configscript.py:128 |
305 | msgid "Pre-connection Script" |
306 | -msgstr "切断前にスクリプトを実行する" |
307 | +msgstr "接続前にスクリプトを実行する" |
308 | |
309 | #: curses/configscript_curses.py:58 gtk/configscript.py:130 |
310 | msgid "Pre-disconnection Script" |
311 | diff --git a/pyproject.toml b/pyproject.toml |
312 | index 433b209..370f2d9 100644 |
313 | --- a/pyproject.toml |
314 | +++ b/pyproject.toml |
315 | @@ -3,8 +3,67 @@ requires = [ |
316 | "setuptools>45", |
317 | "setuptools_scm", |
318 | "wheel", |
319 | + "babel", |
320 | + "pybabel", |
321 | ] |
322 | build-backend = "setuptools.build_meta" |
323 | |
324 | [tool.setuptools_scm] |
325 | -write_to = "pkg/_version.py" |
326 | \ No newline at end of file |
327 | +write_to = "src/wicd/_version.py" |
328 | + |
329 | +[project] |
330 | +name = "wicd" |
331 | +dynamic = ["version"] |
332 | +description = "A wireless and wired network manager" |
333 | +readme = "README.rst" |
334 | +authors = [ |
335 | +{name = "Tom Van Braeckel", email = "tomvanbraeckel@gmail.com"}, |
336 | +{name = "Adam Blackburn", email = "compwiz18@gmail.com"}, |
337 | +{name = "Dan O'Reilly", email = "oreilldf@gmail.com"}, |
338 | +{name = "Andrew Psaltis", email = "ampsaltis@gmail.com"}, |
339 | +{name = "David Paleino", email = "d.paleino@gmail.com"}, |
340 | +{name = "Andreas Messer", email = "andi@bastelmap.de"}, |
341 | +{name = "Takahiro Yoshizawa", email = "kuro@takahiro.org"}, |
342 | +] |
343 | +license = {file = "LICENSE"} |
344 | +requires-python = ">=3.9" |
345 | +dependencies = [ |
346 | + "python-daemon", |
347 | + "lockfile", |
348 | +] |
349 | + |
350 | +[tool.setuptools] |
351 | +package-dir = {"" = "src"} |
352 | + |
353 | +[project.optional-dependencies] |
354 | +gui = ["notify2"] |
355 | + |
356 | +[project.urls] |
357 | +Homepage = "https://launchpad.net/wicd" |
358 | + |
359 | +[tool.setuptools.data-files] |
360 | +"share/icons/hicolor/16x16/status" = ["images/16x16/status/*"] |
361 | +"share/icons/hicolor/22x22/status" = ["images/22x22/status/*"] |
362 | +"share/icons/hicolor/24x24/status" = ["images/24x24/status/*"] |
363 | +"share/icons/hicolor/32x32/status" = ["images/32x32/status/*"] |
364 | +"share/icons/hicolor/36x36/status" = ["images/36x36/status/*"] |
365 | +"share/icons/hicolor/48x48/status" = ["images/48x48/status/*"] |
366 | +"share/icons/hicolor/48x48/devices" = ["images/48x48/devices/*"] |
367 | +"share/icons/hicolor/scalable/devices" = ["images/scalable/devices/*"] |
368 | +"share/icons/hicolor/original/status" = ["images/original/status/*"] |
369 | +"share/wicd/encryption/templates" = ["encryption/templates/*"] |
370 | +"share/dbus-1/system.d" = ["other/wicd.conf"] |
371 | + |
372 | +[tool.setuptools.package-data] |
373 | +wicd = [ |
374 | + "encryption/templates/*", |
375 | +] |
376 | + |
377 | +[project.scripts] |
378 | +wicd = "wicd.daemon.__main__:main" |
379 | +wicd-gtk = "wicd.frontends.gtk.__main__:main" |
380 | +wicd-cli = "wicd.frontends.cli:main" |
381 | + |
382 | +[project.entry-points."wicd.backends"] |
383 | +external = "wicd.backends.external" |
384 | +ioctl = "wicd.backends.ioctl" |
385 | diff --git a/setup.cfg b/setup.cfg |
386 | index 8a5d1ed..4bd9609 100644 |
387 | --- a/setup.cfg |
388 | +++ b/setup.cfg |
389 | @@ -1,27 +1,2 @@ |
390 | -[metadata] |
391 | -name = wicd |
392 | -version = 1.8.0.dev1 |
393 | - |
394 | -[options] |
395 | -packages = find_namespace: |
396 | -package_dir = |
397 | - =src |
398 | -include_package_data = True |
399 | - |
400 | [install] |
401 | record = install.log |
402 | -[bdist_rpm] |
403 | -group = Productivity/Networking/System |
404 | - |
405 | -[options.packages.find] |
406 | -where = src |
407 | - |
408 | -[options.entry_points] |
409 | -console_scripts = |
410 | - wicd = wicd.daemon.__main__:main |
411 | - wicd-cli = wicd.frontends.cli:main |
412 | - wicd-gtk = wicd.frontends.gtk.__main__:main |
413 | -wicd.backends = |
414 | - external = wicd.backends.external |
415 | - ioctl = wicd.backends.ioctl |
416 | - |
417 | diff --git a/setup.py b/setup.py |
418 | old mode 100755 |
419 | new mode 100644 |
420 | index 510efca..d36e814 |
421 | --- a/setup.py |
422 | +++ b/setup.py |
423 | @@ -5,6 +5,7 @@ |
424 | # Copyright (C) 2007 - 2009 Dan O'Reilly |
425 | # Copyright (C) 2009 Andrew Psaltis |
426 | # Copyright (C) 2021 - 2022 Andreas Messer |
427 | +# Copyright (C) 2024 Takahiro Yoshizawa |
428 | # |
429 | # |
430 | # This program is free software; you can redistribute it and/or modify |
431 | @@ -19,9 +20,18 @@ |
432 | # You should have received a copy of the GNU General Public License |
433 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
434 | # |
435 | -from setuptools import setup, find_packages |
436 | +from setuptools import setup, find_namespace_packages |
437 | from setuptools.command.build_py import build_py |
438 | +from setuptools.command.install import install as _install |
439 | + |
440 | + |
441 | +from setuptools import setup |
442 | +from setuptools.command.build_py import build_py as _build_py |
443 | import os |
444 | +import subprocess |
445 | +import shutil |
446 | +import re |
447 | +from glob import glob |
448 | |
449 | config_file_template = ''' |
450 | import os |
451 | @@ -38,41 +48,344 @@ pidfile_path = rundir_path + "wicd.pid" |
452 | resolvconf_backup_path = rundir_path + "resolv.conf.orig" |
453 | ''' |
454 | |
455 | -class wicd_build_py(build_py): |
456 | + |
457 | +class build_py(_build_py): |
458 | def run(self): |
459 | config_file = os.path.join(self.build_lib, 'wicd', 'config.py') |
460 | - |
461 | + os.makedirs(os.path.dirname(config_file), exist_ok=True) |
462 | with open(config_file, 'wt') as f: |
463 | print('generating ' + config_file) |
464 | - f.write(config_file_template); |
465 | + f.write(config_file_template) |
466 | |
467 | + self.compile_translations() |
468 | + self.process_templates() |
469 | super().run() |
470 | |
471 | -def version_scheme(version): |
472 | - if version.exact: |
473 | - return version.format_with("{tag}") |
474 | - else: |
475 | - return "git" |
476 | + def compile_translations(self): |
477 | + print('Compiling translations...') |
478 | + threshold = 0.8 |
479 | |
480 | -setup( |
481 | - description = "A wireless and wired network manager", |
482 | - long_description = """A complete network connection manager |
483 | -Wicd supports wired and wireless networks, and capable of |
484 | -creating and tracking profiles for both. It has a |
485 | -template-based wireless encryption system, which allows the user |
486 | -to easily add encryption methods used. It ships with some common |
487 | -encryption types, such as WPA and WEP. Wicd will automatically |
488 | -connect at startup to any preferred network within range. |
489 | -""", |
490 | - setup_requires = ['setuptools_scm'], |
491 | - use_scm_version = { |
492 | - "version_scheme" : version_scheme, |
493 | - }, |
494 | + print("Update wicd.pot with new strings") |
495 | + os.system('pybabel extract . -o po/wicd.pot --sort-output') |
496 | + |
497 | + print("Update po-files with new strings from wicd.pot") |
498 | + for pofile in glob('po/*.po'): |
499 | + lang = os.path.splitext(os.path.basename(pofile))[0] |
500 | + os.system(f'pybabel update -N -i po/wicd.pot -d po -D wicd -l {lang}') |
501 | + |
502 | + print('Compile po-files to binary mo') |
503 | + if os.path.exists('translations'): |
504 | + shutil.rmtree('translations/') |
505 | + os.makedirs('translations') |
506 | + |
507 | + oldlang = os.environ.get('LANG', 'C') |
508 | + os.environ['LANG'] = 'C' |
509 | + |
510 | + for pofile in sorted(glob('po/*.po')): |
511 | + lang = os.path.splitext(os.path.basename(pofile))[0] |
512 | + compile_po = False |
513 | + try: |
514 | + result = subprocess.run(['msgfmt', '--statistics', pofile, '-o', '/dev/null'], |
515 | + stderr=subprocess.PIPE, text=True) |
516 | + output = result.stderr.strip() |
517 | + if result.returncode != 0 or not output: |
518 | + print(f"Error processing {pofile}: {result.stderr}") |
519 | + raise ValueError(f"Error processing {pofile}") |
520 | + else: |
521 | + m = re.match( |
522 | + r'^(?:' |
523 | + r'(?:(\d+) translated messages)' |
524 | + r'(?:, )?' |
525 | + r'(?:(\d+) fuzzy translation(?:s)?)?' |
526 | + r'(?:, )?' |
527 | + r'(?:(\d+) untranslated messages?)?' |
528 | + r')\.?$', |
529 | + output |
530 | + ) |
531 | + if m: |
532 | + done = int(m.group(1) or 0) |
533 | + fuzzy = int(m.group(2) or 0) |
534 | + missing = int(m.group(3) or 0) |
535 | + total = done + fuzzy + missing |
536 | + completeness = done / total if total > 0 else 0 |
537 | + if completeness >= threshold: |
538 | + compile_po = True |
539 | + else: |
540 | + print(f'Disabled {lang} ({completeness*100:.1f}% < {threshold*100:.1f}%).') |
541 | + continue |
542 | + except Exception as e: |
543 | + print(f'An error occurred while processing {pofile}: {e}') |
544 | + |
545 | + if compile_po: |
546 | + mo_dir = os.path.join('translations', lang, 'LC_MESSAGES') |
547 | + os.makedirs(mo_dir, exist_ok=True) |
548 | + os.system(f'pybabel compile -D wicd -i {pofile} -l {lang} -d translations/') |
549 | + os.environ['LANG'] = oldlang |
550 | + |
551 | + new_data_files = self.find_mo_files() |
552 | + existing_data_files = self.distribution.data_files or [] |
553 | + self.distribution.data_files = existing_data_files + new_data_files |
554 | + |
555 | + def find_mo_files(self): |
556 | + data_files = [] |
557 | + for root, dirs, files in os.walk('translations'): |
558 | + for file in files: |
559 | + if file.endswith('.mo'): |
560 | + lang = os.path.relpath(root, 'translations').split(os.sep)[0] |
561 | + mo_file = os.path.join(root, file) |
562 | + install_dir = os.path.join('share', 'locale', lang, 'LC_MESSAGES') |
563 | + data_files.append((install_dir, [mo_file])) |
564 | + return data_files |
565 | + |
566 | + def initialize_options(self): |
567 | + super().initialize_options() |
568 | + self.init = '' |
569 | + self.lib = '/usr/lib/wicd/' |
570 | + self.share = '/usr/share/wicd/' |
571 | + self.etc = '/etc/wicd/' |
572 | + self.scripts = self.share + "scripts/" |
573 | + self.encryption = self.share + 'encryption/templates/' |
574 | + self.bin = '/usr/bin/' |
575 | + self.sbin = '/usr/sbin/' |
576 | + self.daemon = self.share + 'daemon' |
577 | + self.backends = self.share + 'backends' |
578 | + self.curses = self.share + 'curses' |
579 | + self.gtk = self.share + 'gtk' |
580 | + self.cli = self.share + 'cli' |
581 | + self.gnome_shell_extensions = '/usr/share/gnome-shell/extensions/' |
582 | + self.icons = '/usr/share/icons/hicolor/' |
583 | + self.pixmaps = '/usr/share/pixmaps/' |
584 | + self.images = '/usr/share/icons/' |
585 | + self.varlib = '/var/lib/wicd/' |
586 | + self.networks = self.varlib + 'configurations/' |
587 | + self.log = '/var/log/wicd/' |
588 | + self.resume = '/etc/acpi/resume.d/' |
589 | + self.suspend = '/etc/acpi/suspend.d/' |
590 | + self.pmutils = '/usr/lib/pm-utils/sleep.d/' |
591 | + self.dbus = '/etc/dbus-1/system.d/' |
592 | + self.dbus_service = '/usr/share/dbus-1/system-services/' |
593 | + self.systemd = '/lib/systemd/system/' |
594 | + self.logrotate = '/etc/logrotate.d/' |
595 | + self.desktop = '/usr/share/applications/' |
596 | + self.translations = '/usr/share/locale/' |
597 | + self.autostart = '/etc/xdg/autostart/' |
598 | + self.docdir = '/usr/share/doc/wicd/' |
599 | + self.mandir = '/usr/share/man/' |
600 | + self.kdedir = '/usr/share/autostart/' |
601 | + self.distro = 'auto' |
602 | + |
603 | + self.no_install_init = False |
604 | + self.no_install_man = False |
605 | + self.no_install_i18n = False |
606 | + self.no_install_i18n_man = False |
607 | + self.no_install_kde = False |
608 | + self.no_install_acpi = False |
609 | + self.no_install_pmutils = False |
610 | + self.no_install_docs = False |
611 | + self.no_install_gtk = False |
612 | + self.no_install_ncurses = False |
613 | + self.no_install_cli = False |
614 | + self.no_install_gnome_shell_extensions = False |
615 | + self.no_use_notifications = False |
616 | + |
617 | + self.initfile = 'init/default/wicd' |
618 | + # ddistro is the detected distro |
619 | + if os.path.exists('/etc/redhat-release'): |
620 | + self.ddistro = 'redhat' |
621 | + elif os.path.exists('/etc/SuSE-release'): |
622 | + self.ddistro = 'suse' |
623 | + elif os.path.exists('/etc/fedora-release'): |
624 | + self.ddistro = 'redhat' |
625 | + elif os.path.exists('/etc/gentoo-release'): |
626 | + self.ddistro = 'gentoo' |
627 | + elif os.path.exists('/etc/debian_version'): |
628 | + self.ddistro = 'debian' |
629 | + elif os.path.exists('/etc/arch-release'): |
630 | + self.ddistro = 'arch' |
631 | + elif os.path.exists('/etc/slackware-version') or \ |
632 | + os.path.exists('/etc/slamd64-version') or \ |
633 | + os.path.exists('/etc/bluewhite64-version'): |
634 | + self.ddistro = 'slackware' |
635 | + elif os.path.exists('/etc/pld-release'): |
636 | + self.ddistro = 'pld' |
637 | + elif os.path.exists('/etc/lunar.release'): |
638 | + self.distro = 'lunar' |
639 | + elif os.path.exists('/etc/plamo-release'): |
640 | + self.ddistro = 'plamo' |
641 | + else: |
642 | + self.ddistro = 'FAIL' |
643 | + #self.no_install_init = True |
644 | + #self.distro_detect_failed = True |
645 | + print('WARNING: Unable to detect the distribution in use. ' + \ |
646 | + 'If you have specified --distro or --init and --initfile, configure will continue. ' + \ |
647 | + 'Please report this warning, along with the name of your ' + \ |
648 | + 'distribution, to the wicd developers.') |
649 | + |
650 | + # Try to get the pm-utils sleep hooks directory from pkg-config and |
651 | + # the kde prefix from kde-config |
652 | + # Don't run these in a shell because it's not needed and because shell |
653 | + # swallows the OSError we would get if {pkg,kde}-config do not exist |
654 | + # If we don't get anything from *-config, or it didn't run properly, |
655 | + # or the path is not a proper absolute path, raise an error |
656 | + try: |
657 | + pmtemp = subprocess.Popen(["pkg-config", "--variable=pm_sleephooks", |
658 | + "pm-utils"], stdout=subprocess.PIPE) |
659 | + returncode = pmtemp.wait() # let it finish, and get the exit code |
660 | + pmutils_candidate = str(pmtemp.stdout.readline().strip()) # read stdout |
661 | + if len(pmutils_candidate) == 0 or returncode != 0 or \ |
662 | + not os.path.isabs(pmutils_candidate): |
663 | + raise ValueError |
664 | + else: |
665 | + self.pmutils = pmutils_candidate |
666 | + except (OSError, ValueError, FileNotFoundError): |
667 | + pass # use our default |
668 | + |
669 | + try: |
670 | + kdetemp = subprocess.Popen(["kde-config","--prefix"], stdout=subprocess.PIPE) |
671 | + returncode = kdetemp.wait() # let it finish, and get the exit code |
672 | + kdedir_candidate = str(kdetemp.stdout.readline().strip()) # read stdout |
673 | + if len(kdedir_candidate) == 0 or returncode != 0 or \ |
674 | + not os.path.isabs(kdedir_candidate): |
675 | + raise ValueError |
676 | + else: |
677 | + self.kdedir = kdedir_candidate + '/share/autostart' |
678 | + except (OSError, ValueError, FileNotFoundError): |
679 | + # If kde-config isn't present, we'll check for kde-4.x |
680 | + try: |
681 | + kde4temp = subprocess.Popen(["kde4-config","--prefix"], stdout=subprocess.PIPE) |
682 | + returncode = kde4temp.wait() # let it finish, and get the exit code |
683 | + kde4dir_candidate = str(kde4temp.stdout.readline().strip()) # read stdout |
684 | + if len(kde4dir_candidate) == 0 or returncode != 0 or \ |
685 | + not os.path.isabs(kde4dir_candidate): |
686 | + raise ValueError |
687 | + else: |
688 | + self.kdedir = kde4dir_candidate + '/share/autostart' |
689 | + except (OSError, ValueError, FileNotFoundError): |
690 | + # If neither kde-config nor kde4-config are not present or |
691 | + # return an error, then we can assume that kde isn't installed |
692 | + # on the user's system |
693 | + self.no_install_kde = True |
694 | + # If the assumption above turns out to be wrong, do this: |
695 | + #pass # use our default |
696 | + |
697 | + self.python = '/usr/bin/python3' |
698 | + self.pidfile = '/var/run/wicd/wicd.pid' |
699 | + self.initfilename = os.path.basename(self.initfile) |
700 | + self.wicdgroup = 'users' |
701 | + self.loggroup = '' |
702 | + self.logperms = '0600' |
703 | + |
704 | + def process_templates(self): |
705 | + # Retrieve version information for curses |
706 | + try: |
707 | + import curses |
708 | + print("curses version: ", curses.version) |
709 | + if isinstance(curses.version, bytes): |
710 | + curses_version = curses.version.decode('utf-8').strip().split()[0].lstrip("b'") |
711 | + else: |
712 | + curses_version = curses.version.split()[0] |
713 | + except (AttributeError, IndexError): |
714 | + curses_version = 'unknown' |
715 | |
716 | - author = "Tom Van Braeckel, Adam Blackburn, Dan O'Reilly, Andrew Psaltis, David Paleino, Andreas Messer", |
717 | - author_email = "tomvanbraeckel@gmail.com, compwiz18@gmail.com, oreilldf@gmail.com, ampsaltis@gmail.com, d.paleino@gmail.com, andi@bastelmap.de", |
718 | - url = "https://launchpad.net/wicd", |
719 | - license = "http://www.gnu.org/licenses/old-licenses/gpl-2.0.html", |
720 | + # Retrieve version information from setuptools. |
721 | + version = self.distribution.get_version() |
722 | |
723 | - cmdclass = { "build_py" : wicd_build_py }, |
724 | + # Retrieve the revision from setup.cfg. |
725 | + revision_num = getattr(self.distribution.metadata, 'revision', '0') |
726 | + |
727 | + # Convert the attributes of self into values. |
728 | + values = {attr.upper(): getattr(self, attr) for attr in dir(self) |
729 | + if not callable(getattr(self, attr)) and not attr.startswith("_")} |
730 | + |
731 | + # Additional placeholder information. |
732 | + values.update({ |
733 | + 'VERSION': version, |
734 | + 'REVISION': revision_num, |
735 | + 'CURSES_REVNO': curses_version, |
736 | + }) |
737 | + |
738 | + print('Processing templates...') |
739 | + in_dir = 'in' |
740 | + |
741 | + for item in os.listdir(in_dir): |
742 | + if item.endswith('.in'): |
743 | + original_name = os.path.join(in_dir, item) |
744 | + final_name = item[:-3].replace('=', '/') |
745 | + |
746 | + if final_name == 'wpath.py': |
747 | + full_path = os.path.join(self.build_lib, 'wicd', final_name) |
748 | + else: |
749 | + full_path = os.path.join('template', final_name) |
750 | + |
751 | + os.makedirs(os.path.dirname(full_path), exist_ok=True) |
752 | + |
753 | + try: |
754 | + with open(original_name, 'r') as infile, open(full_path, 'w') as outfile: |
755 | + for line in infile: |
756 | + for key, value in values.items(): |
757 | + placeholder = f'%{key.upper()}%' |
758 | + line = line.replace(placeholder, str(value)) |
759 | + |
760 | + line = line.replace('%VERSION%', str(version)) |
761 | + line = line.replace('%REVNO%', str(revision_num)) |
762 | + line = line.replace('%CURSES_REVNO%', str(curses_version)) |
763 | + |
764 | + outfile.write(line) |
765 | + |
766 | + shutil.copymode(original_name, full_path) |
767 | + print(f"Processed template: {original_name} -> {full_path}") |
768 | + |
769 | + except FileNotFoundError: |
770 | + print(f"ERROR: Template file {original_name} not found.") |
771 | + except Exception as e: |
772 | + print(f"ERROR: Failed to process {original_name}: {e}") |
773 | + |
774 | +# new_data_files = self.find_templates() |
775 | +# existing_data_files = self.distribution.data_files or [] |
776 | +# self.distribution.data_files = existing_data_files + new_data_files |
777 | + |
778 | +# def find_templates(self): |
779 | +# data_files = [] |
780 | +# if self.ddistro == "redhat": |
781 | +# init = '/etc/rc.d/init.d/' |
782 | +# initfile = 'init/redhat/wicd' |
783 | +# elif self.ddistro == "suse": |
784 | +# init = '/etc/init.d/' |
785 | +# initfile = 'init/suse/wicd' |
786 | +# elif self.ddistro == "gentoo": |
787 | +# init = '/etc/init.d/' |
788 | +# initfile = 'init/gentoo/wicd' |
789 | +# elif self.ddistro == "debian": |
790 | +# init = '/etc/init.d/' |
791 | +# initfile = 'init/debian/wicd' |
792 | +# elif self.ddistro == "arch": |
793 | +# init = '/etc/rc.d/' |
794 | +# initfile = 'init/arch/wicd' |
795 | +# elif self.ddistro == "slackware": |
796 | +# init = '/etc/rc.d/' |
797 | +# initfile = 'init/slackware/rc.wicd' |
798 | +# elif self.ddistro == "pld": |
799 | +# init = '/etc/rc.d/init.d/' |
800 | +# initfile = 'init/pld/wicd' |
801 | +# elif self.ddistro == "lunar": |
802 | +# init='/etc/init.d/' |
803 | +# initfile = 'init/lunar/wicd' |
804 | +# elif self.ddistro == "plamo": |
805 | +# init='/etc/rc.d/init.d/' |
806 | +# initfile = 'init/plamo/wicd' |
807 | +# else: |
808 | +# print("Distro not supported for init script installation.") |
809 | +# init='/etc/rc.d/init.d/' |
810 | +# initfile = 'init/redhat/wicd' |
811 | +# |
812 | +# initfile_path = os.path.join('template', initfile) |
813 | +# data_files.append((init, [initfile_path])) |
814 | +# |
815 | +# return data_files |
816 | + |
817 | + |
818 | +setup( |
819 | + cmdclass={ |
820 | + 'build_py': build_py, |
821 | + }, |
822 | ) |
823 | diff --git a/src/wicd/commandline.py b/src/wicd/commandline.py |
824 | index 02bbb57..f7b1a90 100644 |
825 | --- a/src/wicd/commandline.py |
826 | +++ b/src/wicd/commandline.py |
827 | @@ -4,6 +4,7 @@ |
828 | # wicd commandline handling |
829 | # |
830 | # Copyright (C) 2021 Andreas Messer |
831 | +# Copyright (C) 2024 Takahiro Yoshizawa |
832 | # |
833 | # This program is free software; you can redistribute it and/or modify |
834 | # it under the terms of the GNU General Public License Version 2 as |
835 | @@ -29,7 +30,7 @@ class CommandlineManager(object): |
836 | @classmethod |
837 | def get_args(cls): |
838 | if hasattr(cls, "parser"): |
839 | - cls.args = cls.parser.parse_args() |
840 | + cls.args, unknown = cls.parser.parse_known_args() |
841 | del cls.parser |
842 | |
843 | return cls.args |
844 | diff --git a/src/wicd/configmanager.py b/src/wicd/configmanager.py |
845 | index b5851dd..2699b97 100644 |
846 | --- a/src/wicd/configmanager.py |
847 | +++ b/src/wicd/configmanager.py |
848 | @@ -191,6 +191,7 @@ class ConfigManager(RawConfigParser): |
849 | print("_write_one", to_unicode(section)) |
850 | if not to_unicode(section): |
851 | self.remove_section(to_unicode(section)) |
852 | + os.makedirs(os.path.dirname(self.config_file), exist_ok=True) |
853 | configfile = open(self.config_file, 'w') |
854 | RawConfigParser.write(self, configfile) |
855 | configfile.close() |
856 | @@ -216,7 +217,7 @@ class ConfigManager(RawConfigParser): |
857 | entries in these files override entries in the main file. |
858 | """ |
859 | if os.path.exists(path): |
860 | - RawConfigParser.readfp(self, codecs.open(path, 'r', 'utf-8')) |
861 | + RawConfigParser.read_file(self, codecs.open(path, 'r', 'utf-8')) |
862 | |
863 | path_d = path + ".d" |
864 | files = [] |
865 | @@ -227,7 +228,7 @@ class ConfigManager(RawConfigParser): |
866 | |
867 | for fname in files: |
868 | p = RawConfigParser() |
869 | - p.readfp(codecs.open(fname, 'r', 'utf-8')) |
870 | + p.read_file(codecs.open(fname, 'r', 'utf-8')) |
871 | for section_name in p.sections(): |
872 | # New files override old, so remove first to avoid |
873 | # DuplicateSectionError. |
874 | diff --git a/src/wicd/daemon/__main__.py b/src/wicd/daemon/__main__.py |
875 | index e51c541..71e9bf6 100644 |
876 | --- a/src/wicd/daemon/__main__.py |
877 | +++ b/src/wicd/daemon/__main__.py |
878 | @@ -20,6 +20,7 @@ class WirelessDaemon() -- DBus interface to managed the wireless network. |
879 | # Copyright (C) 2007 - 2009 Byron Hillis |
880 | # Copyright (C) 2009 Andrew Psaltis |
881 | # Copyright (C) 2021 Andreas Messer |
882 | +# Copyright (C) 2024 Takahiro Yoshizawa |
883 | # |
884 | # This program is free software; you can redistribute it and/or modify |
885 | # it under the terms of the GNU General Public License Version 2 as |
886 | @@ -33,9 +34,9 @@ class WirelessDaemon() -- DBus interface to managed the wireless network. |
887 | # You should have received a copy of the GNU General Public License |
888 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
889 | # |
890 | - |
891 | import wicd.log |
892 | import wicd.config |
893 | +import wicd.errors |
894 | import lockfile |
895 | import daemon |
896 | import os |
897 | @@ -47,6 +48,7 @@ import signal |
898 | import atexit |
899 | from subprocess import Popen |
900 | from operator import itemgetter |
901 | +from wicd.dbus import dbus_manager |
902 | |
903 | # DBUS |
904 | from gi.repository import GLib as gobject |
905 | @@ -65,6 +67,11 @@ import wicd.dbus |
906 | |
907 | import wicd.pkg_helpers |
908 | |
909 | +from wicd import wpath |
910 | + |
911 | +redirect_stderr = False |
912 | +redirect_stdout = False |
913 | + |
914 | misc.RenameProcess("wicd") |
915 | |
916 | class WicdDaemon(wicd.dbus.service.Object, wicd.log.LogAble): |
917 | @@ -1013,10 +1020,16 @@ class WirelessDaemon(dbus.service.Object, object): |
918 | self.ReadWirelessNetworkProfile(i) |
919 | self.SendEndScanSignal() |
920 | |
921 | +# @dbus.service.method('org.wicd.daemon.wireless') |
922 | +# def GetIwconfig(self): |
923 | +# """ Calls and returns the output of iwconfig""" |
924 | +# return misc.to_unicode(self.wifi.GetIwconfig()) |
925 | + |
926 | @dbus.service.method('org.wicd.daemon.wireless') |
927 | - def GetIwconfig(self): |
928 | + def GetIwLink(self): |
929 | """ Calls and returns the output of iwconfig""" |
930 | - return misc.to_unicode(self.wifi.GetIwconfig()) |
931 | + return misc.to_unicode(self.wifi.GetIwLink()) |
932 | + |
933 | |
934 | @dbus.service.method('org.wicd.daemon.wireless') |
935 | def GetNumberOfNetworks(self): |
936 | @@ -1029,19 +1042,19 @@ class WirelessDaemon(dbus.service.Object, object): |
937 | return self.wifi.GetBSSID() |
938 | |
939 | @dbus.service.method('org.wicd.daemon.wireless') |
940 | - def GetCurrentBitrate(self, iwconfig): |
941 | + def GetCurrentBitrate(self, iwlink): |
942 | """ Returns the current bitrate for the active network. """ |
943 | - return self.wifi.GetCurrentBitrate(iwconfig) |
944 | + return self.wifi.GetCurrentBitrate(iwlink) |
945 | |
946 | @dbus.service.method('org.wicd.daemon.wireless') |
947 | - def GetOperationalMode(self, iwconfig): |
948 | + def GetOperationalMode(self, iwlink): |
949 | """ Returns the operational mode for the iwconfig parameter """ |
950 | - return misc.to_unicode(self.wifi.GetOperationalMode(iwconfig)) |
951 | + return misc.to_unicode(self.wifi.GetOperationalMode(iwlink)) |
952 | |
953 | - @dbus.service.method('org.wicd.daemon.wireless') |
954 | - def GetAvailableAuthMethods(self, iwlistauth): |
955 | - """ Returns the operational mode for the iwlistauth parameter """ |
956 | - return misc.to_unicode(self.wifi.GetAvailableAuthMethods(iwlistauth)) |
957 | +# @dbus.service.method('org.wicd.daemon.wireless') |
958 | +# def GetAvailableAuthMethods(self, iwlistauth): |
959 | +# """ Returns the operational mode for the iwlistauth parameter """ |
960 | +# return misc.to_unicode(self.wifi.GetAvailableAuthMethods(iwlistauth)) |
961 | |
962 | @dbus.service.method('org.wicd.daemon.wireless') |
963 | def GetAvailableBitrates(self): |
964 | @@ -1066,6 +1079,12 @@ class WirelessDaemon(dbus.service.Object, object): |
965 | self.wifi.CreateAdHocNetwork(essid, channel, ip, enctype, key, encused) |
966 | |
967 | @dbus.service.method('org.wicd.daemon.wireless') |
968 | + def GetMode(self): |
969 | + """ Gets the MAC address for the active network. """ |
970 | + return self.wifi.GetMode() |
971 | + |
972 | + |
973 | + @dbus.service.method('org.wicd.daemon.wireless') |
974 | def GetKillSwitchEnabled(self): |
975 | """ Returns true if kill switch is pressed. """ |
976 | status = self.wifi.GetKillSwitchStatus() |
977 | @@ -1129,33 +1148,33 @@ class WirelessDaemon(dbus.service.Object, object): |
978 | return self.wifi.IsUp() |
979 | |
980 | @dbus.service.method('org.wicd.daemon.wireless') |
981 | - def GetCurrentSignalStrength(self, iwconfig=None): |
982 | + def GetCurrentSignalStrength(self, iwlink=None): |
983 | """ Returns the current signal strength. """ |
984 | try: |
985 | - strength = int(self.wifi.GetSignalStrength(iwconfig)) |
986 | + strength = int(self.wifi.GetSignalStrength(iwlink)) |
987 | except TypeError: |
988 | strength = 0 |
989 | return strength |
990 | |
991 | @dbus.service.method('org.wicd.daemon.wireless') |
992 | - def GetCurrentDBMStrength(self, iwconfig=None): |
993 | + def GetCurrentDBMStrength(self, iwlink=None): |
994 | """ Returns the current dbm signal strength. """ |
995 | try: |
996 | - dbm_strength = int(self.wifi.GetDBMStrength(iwconfig)) |
997 | + dbm_strength = int(self.wifi.GetDBMStrength(iwlink)) |
998 | except: |
999 | dbm_strength = 0 |
1000 | return dbm_strength |
1001 | |
1002 | @dbus.service.method('org.wicd.daemon.wireless') |
1003 | - def GetCurrentNetwork(self, iwconfig=None): |
1004 | + def GetCurrentNetwork(self, iwlink=None): |
1005 | """ Returns the current network. """ |
1006 | - current_network = str(self.wifi.GetCurrentNetwork(iwconfig)) |
1007 | + current_network = str(self.wifi.GetCurrentNetwork(iwlink)) |
1008 | return current_network |
1009 | |
1010 | @dbus.service.method('org.wicd.daemon.wireless') |
1011 | - def GetCurrentNetworkID(self, iwconfig=None): |
1012 | + def GetCurrentNetworkID(self, iwlink=None): |
1013 | """ Returns the id of the current network, or -1 if its not found. """ |
1014 | - currentESSID = self.GetCurrentNetwork(iwconfig) |
1015 | + currentESSID = self.GetCurrentNetwork(iwlink) |
1016 | for x in range(0, len(self.LastScan)): |
1017 | if self.LastScan[x]['essid'] == currentESSID: |
1018 | return x |
1019 | @@ -1351,6 +1370,8 @@ class WirelessDaemon(dbus.service.Object, object): |
1020 | ret.append((section.replace('essid:', ''), 'None')) |
1021 | else: |
1022 | essid = self.config.get(section, 'essid') |
1023 | + if essid is None: |
1024 | + essid = 'None' |
1025 | ret.append((essid, section)) |
1026 | return sorted(ret, key=itemgetter(0)) |
1027 | |
1028 | @@ -1402,6 +1423,13 @@ class WirelessDaemon(dbus.service.Object, object): |
1029 | return |
1030 | print("Unable to autoconnect, you'll have to manually connect") |
1031 | |
1032 | + @dbus.service.method('org.wicd.daemon.wireless') |
1033 | + def SetLastScan(self, key, value): |
1034 | + if self.LastScan: |
1035 | + self.LastScan[key] = value |
1036 | + |
1037 | + |
1038 | + |
1039 | ########################### |
1040 | ###### Wired Daemon ####### |
1041 | ########################### |
1042 | @@ -1695,6 +1723,51 @@ def spawn_monitor(): |
1043 | |
1044 | atexit.register(daemon_killmonitor) |
1045 | |
1046 | +def determine_root(): |
1047 | + if os.getuid() != 0: |
1048 | + print(("Root privileges are required for the daemon to run properly." + |
1049 | + " Exiting.")) |
1050 | + sys.exit(1) |
1051 | + |
1052 | + if not os.path.exists(wpath.networks): |
1053 | + os.makedirs(wpath.networks) |
1054 | + |
1055 | +def check_duplicates(): |
1056 | + if os.path.exists(wpath.pidfile): |
1057 | + print('It seems like the daemon is already running.') |
1058 | + print('If it is not, please remove %s and try again.' % wpath.pidfile) |
1059 | + sys.exit(1) |
1060 | + |
1061 | +def redirect_output(): |
1062 | + global redirect_stderr, redirect_stdout |
1063 | + output = None |
1064 | + group = [""] |
1065 | + if redirect_stderr or redirect_stdout: |
1066 | + logpath = os.path.join(wpath.log, 'wicd.log') |
1067 | + if not os.path.exists(wpath.log): |
1068 | + os.makedirs(wpath.log) |
1069 | + os.chmod(wpath.log, 0o755) |
1070 | + output = ManagedStdio(logpath) |
1071 | + if os.path.exists(logpath): |
1072 | + try: |
1073 | + os.chmod(logpath, int(wpath.log_perms, 8)) |
1074 | + except OSError: |
1075 | + print('unable to chmod log file to %s' % wpath.log_perms) |
1076 | + |
1077 | + try: |
1078 | + if wpath.log_group: |
1079 | + import grp |
1080 | + group = grp.getgrnam(wpath.log_group) |
1081 | + os.chown(logpath, 0, group[2]) |
1082 | + except OSError: |
1083 | + print('unable to chown log file to %s' % group[2]) |
1084 | + |
1085 | + if redirect_stdout: |
1086 | + sys.stdout = output |
1087 | + if redirect_stderr: |
1088 | + sys.stderr= output |
1089 | + |
1090 | + |
1091 | def daemon_main(): |
1092 | print('---------------------------') |
1093 | print('wicd initializing...') |
1094 | @@ -1717,31 +1790,69 @@ def daemon_main(): |
1095 | daemon.DaemonClosing() |
1096 | |
1097 | def run_daemon(): |
1098 | + determine_root() |
1099 | + check_duplicates() |
1100 | + redirect_output() |
1101 | + |
1102 | os.makedirs(wicd.config.rundir_path, exist_ok=True) |
1103 | |
1104 | - context = daemon.DaemonContext( |
1105 | - working_directory = wicd.config.rundir_path, |
1106 | - umask = 0o077, |
1107 | - pidfile = lockfile.FileLock(wicd.config.pidfile_path) |
1108 | - ) |
1109 | + std_out = sys.stdout |
1110 | + std_err = sys.stderr |
1111 | + |
1112 | + try: |
1113 | + with daemon.DaemonContext( |
1114 | + working_directory = wicd.config.rundir_path, |
1115 | + umask = 0o077, |
1116 | + pidfile = lockfile.FileLock(wicd.config.pidfile_path), |
1117 | + stdout = std_out, |
1118 | + stderr = std_err, |
1119 | + signal_map = { |
1120 | + signal.SIGTERM: on_exit, |
1121 | + signal.SIGINT: on_exit, |
1122 | + } |
1123 | + ): |
1124 | + |
1125 | + try: |
1126 | + pid = os.getpid() |
1127 | + with open(wicd.config.pidfile_path, 'w') as pid_file: |
1128 | + pid_file.write(f"{pid}\n") |
1129 | + daemon_main() |
1130 | + except Exception as e: |
1131 | + print(f"Error in daemon: {e}") |
1132 | + |
1133 | + except lockfile.AlreadyLocked: |
1134 | + print("wicd is already running, aborting.", file=sys.stderr) |
1135 | + sys.exit(1) |
1136 | |
1137 | - with context: |
1138 | - daemon_main() |
1139 | + except lockfile.LockFailed as e: |
1140 | + print(f"Error locking pidfile: {e}") |
1141 | |
1142 | def run_foreground(): |
1143 | + determine_root() |
1144 | + check_duplicates() |
1145 | daemon_main() |
1146 | |
1147 | def kill_daemon(): |
1148 | + determine_root() |
1149 | + redirect_output() |
1150 | + |
1151 | try: |
1152 | f = open(wicd.config.pidfile_path) |
1153 | except IOError: |
1154 | - #print >> sys.stderr, "No wicd instance active, aborting." |
1155 | + print("No wicd instance active, aborting.", file=sys.stderr) |
1156 | sys.exit(1) |
1157 | |
1158 | - # connect to dbus, trigger a disconnect, then knock out the daemon |
1159 | - from wicd import dbusmanager |
1160 | - bus = dbusmanager.connect_to_dbus() |
1161 | - dbus_ifaces = dbusmanager.get_dbus_ifaces() |
1162 | +# bus = dbus_manager.connect_to_dbus() |
1163 | +# dbus_ifaces = dbus_manager.get_dbus_ifaces() |
1164 | + try: |
1165 | + dbus_manager.connect() |
1166 | + except wicd.errors.WiCDDaemonNotFound: |
1167 | + pid = int(f.readline()) |
1168 | + f.close() |
1169 | + os.kill(pid, signal.SIGTERM) |
1170 | + return |
1171 | + |
1172 | + dbus_ifaces = dbus_manager.get_dbus_ifaces() |
1173 | dbus_ifaces['daemon'].Disconnect() |
1174 | pid = int(f.readline()) |
1175 | f.close() |
1176 | @@ -1775,45 +1886,16 @@ def main(): |
1177 | parser.add_argument('-o', '--no-stdout', dest='redirect_stdout', action='store_false', default=True, |
1178 | help=u"Don't redirect stdout") |
1179 | |
1180 | + args = parser.parse_args() |
1181 | + |
1182 | + global redirect_stderr, redirect_stdout |
1183 | + redirect_stderr = args.redirect_stderr |
1184 | + redirect_stdout = args.redirect_stdout |
1185 | |
1186 | sys.exit(wicd.commandline.get_args().action() or 0) |
1187 | |
1188 | - if os.getuid() != 0: |
1189 | - print(("Root privileges are required for the daemon to run properly." + |
1190 | - " Exiting.")) |
1191 | - sys.exit(1) |
1192 | - |
1193 | - if not os.path.exists(wpath.networks): |
1194 | - os.makedirs(wpath.networks) |
1195 | - |
1196 | - if redirect_stderr or redirect_stdout: |
1197 | - logpath = os.path.join(wpath.log, 'wicd.log') |
1198 | - if not os.path.exists(wpath.log): |
1199 | - os.makedirs(wpath.log) |
1200 | - os.chmod(wpath.log, 0o755) |
1201 | - output = ManagedStdio(logpath) |
1202 | - if os.path.exists(logpath): |
1203 | - try: |
1204 | - os.chmod(logpath, int(wpath.log_perms, 8)) |
1205 | - except OSError: |
1206 | - print('unable to chmod log file to %s' % wpath.log_perms) |
1207 | - |
1208 | - try: |
1209 | - if wpath.log_group: |
1210 | - import grp |
1211 | - group = grp.getgrnam(wpath.log_group) |
1212 | - os.chown(logpath, 0, group[2]) |
1213 | - except OSError: |
1214 | - print('unable to chown log file to %s' % group[2]) |
1215 | - |
1216 | - if redirect_stdout: |
1217 | - sys.stdout = output |
1218 | - if redirect_stderr: |
1219 | - sys.stderr = output |
1220 | - |
1221 | - |
1222 | |
1223 | -def on_exit(child_pid): |
1224 | +def on_exit(signum, frame): |
1225 | """ Called when a SIGTERM is caught, kills monitor.py before exiting. """ |
1226 | print('Removing PID file...') |
1227 | if os.path.exists(wpath.pidfile): |
1228 | @@ -1822,4 +1904,4 @@ def on_exit(child_pid): |
1229 | sys.exit(0) |
1230 | |
1231 | if __name__ == '__main__': |
1232 | - main() |
1233 | \ No newline at end of file |
1234 | + main() |
1235 | diff --git a/src/wicd/daemon/monitor.py b/src/wicd/daemon/monitor.py |
1236 | index 89f4e6b..20c0142 100755 |
1237 | --- a/src/wicd/daemon/monitor.py |
1238 | +++ b/src/wicd/daemon/monitor.py |
1239 | @@ -10,6 +10,7 @@ when appropriate. |
1240 | # |
1241 | # Copyright (C) 2007 - 2009 Adam Blackburn |
1242 | # Copyright (C) 2007 - 2009 Dan O'Reilly |
1243 | +# Copyright (C) 2024 Takahiro Yoshizawa |
1244 | # |
1245 | # This program is free software; you can redistribute it and/or modify |
1246 | # it under the terms of the GNU General Public License Version 2 as |
1247 | @@ -84,7 +85,7 @@ class ConnectionStatus(object): |
1248 | self.reconnecting = False |
1249 | self.reconnect_tries = 0 |
1250 | self.signal_changed = False |
1251 | - self.iwconfig = "" |
1252 | + self.iwlink = "" |
1253 | self.trigger_reconnect = False |
1254 | self.__lost_dbus_count = 0 |
1255 | self._to_time = daemon.GetBackendUpdateInterval() |
1256 | @@ -162,7 +163,7 @@ class ConnectionStatus(object): |
1257 | if the signal strength is 0, and if it remains there |
1258 | for too long, triggers a wireless disconnect. |
1259 | |
1260 | - Returns True if wireless connection is active, and |
1261 | + Returns True if wireless connection is active, and |
1262 | False otherwise. |
1263 | |
1264 | """ |
1265 | @@ -172,9 +173,9 @@ class ConnectionStatus(object): |
1266 | return False |
1267 | |
1268 | if daemon.NeedsExternalCalls(): |
1269 | - self.iwconfig = wireless.GetIwconfig() |
1270 | + self.iwlink = wireless.GetIwLink() |
1271 | else: |
1272 | - self.iwconfig = '' |
1273 | + self.iwlink = '' |
1274 | # Reset this, just in case. |
1275 | self.tried_reconnect = False |
1276 | bssid = wireless.GetApBssid() |
1277 | @@ -196,11 +197,11 @@ class ConnectionStatus(object): |
1278 | self.connection_lost_counter = 0 |
1279 | |
1280 | if (wifi_signal != self.last_strength or |
1281 | - self.network != self.last_network): |
1282 | + self.network != self.last_network): |
1283 | self.last_strength = wifi_signal |
1284 | self.last_network = self.network |
1285 | self.signal_changed = True |
1286 | - daemon.SetCurrentInterface(daemon.GetWirelessInterface()) |
1287 | + daemon.SetCurrentInterface(daemon.GetWirelessInterface()) |
1288 | |
1289 | return True |
1290 | |
1291 | @@ -255,12 +256,14 @@ class ConnectionStatus(object): |
1292 | daemon.AutoConnect(False, reply_handler=lambda *a:None, |
1293 | error_handler=lambda *a:None) |
1294 | return self.update_state(misc.NOT_CONNECTED) |
1295 | + |
1296 | + wireless.SetLastScan('operating_mode', wireless.GetMode()) |
1297 | return self.update_state(misc.WIRELESS, wifi_ip=wifi_ip) |
1298 | |
1299 | state = misc.NOT_CONNECTED |
1300 | if self.last_state == misc.WIRELESS: |
1301 | from_wireless = True |
1302 | - else: |
1303 | + elif not wireless.GetMode().lower() == "ibss": |
1304 | from_wireless = False |
1305 | self.auto_reconnect(from_wireless) |
1306 | return self.update_state(state) |
1307 | @@ -268,7 +271,7 @@ class ConnectionStatus(object): |
1308 | def update_state(self, state, wired_ip=None, wifi_ip=None): |
1309 | """ Set the current connection state. """ |
1310 | # Set our connection state/info. |
1311 | - iwconfig = self.iwconfig |
1312 | + iwlink = self.iwlink |
1313 | if state == misc.NOT_CONNECTED: |
1314 | info = [""] |
1315 | elif state == misc.SUSPENDED: |
1316 | @@ -278,14 +281,14 @@ class ConnectionStatus(object): |
1317 | info = ["wired"] |
1318 | else: |
1319 | info = ["wireless", |
1320 | - misc.noneToBlankString(wireless.GetCurrentNetwork(iwconfig))] |
1321 | + misc.noneToBlankString(wireless.GetCurrentNetwork(iwlink))] |
1322 | elif state == misc.WIRELESS: |
1323 | self.reconnect_tries = 0 |
1324 | info = [str(wifi_ip), |
1325 | - misc.noneToBlankString(wireless.GetCurrentNetwork(iwconfig)), |
1326 | + misc.noneToBlankString(wireless.GetCurrentNetwork(iwlink)), |
1327 | str(self._get_printable_sig_strength()), |
1328 | - str(wireless.GetCurrentNetworkID(iwconfig)), |
1329 | - misc.noneToBlankString(wireless.GetCurrentBitrate(iwconfig))] |
1330 | + str(wireless.GetCurrentNetworkID(iwlink)), |
1331 | + misc.noneToBlankString(wireless.GetCurrentBitrate(iwlink))] |
1332 | elif state == misc.WIRED: |
1333 | self.reconnect_tries = 0 |
1334 | info = [str(wired_ip)] |
1335 | @@ -296,12 +299,12 @@ class ConnectionStatus(object): |
1336 | daemon.SetConnectionStatus(state, info) |
1337 | |
1338 | # Send a D-Bus signal announcing status has changed if necessary. |
1339 | - if (state != self.last_state or (state == misc.WIRELESS and |
1340 | + if (state != self.last_state or (state == misc.WIRELESS and |
1341 | self.signal_changed)): |
1342 | daemon.EmitStatusChanged(state, info) |
1343 | |
1344 | if (state != self.last_state) and (state == misc.NOT_CONNECTED) and \ |
1345 | - (not daemon.GetForcedDisconnect()): |
1346 | + (not daemon.GetForcedDisconnect()) and (wireless.GetMode(iwlink).lower() != 'ibss'): |
1347 | daemon.Disconnect() |
1348 | # Disconnect() sets forced disconnect = True |
1349 | # so we'll revert that |
1350 | @@ -313,10 +316,10 @@ class ConnectionStatus(object): |
1351 | """ Get the correct signal strength format. """ |
1352 | try: |
1353 | if daemon.GetSignalDisplayType() == 0: |
1354 | - signal = wireless.GetCurrentSignalStrength(self.iwconfig) |
1355 | + signal = wireless.GetCurrentSignalStrength(self.iwlink) |
1356 | wifi_signal = int(signal) |
1357 | else: |
1358 | - signal = wireless.GetCurrentDBMStrength(self.iwconfig) |
1359 | + signal = wireless.GetCurrentDBMStrength(self.iwlink) |
1360 | if always_positive: |
1361 | # because dBm is negative, add 99 to the signal. This way, |
1362 | # if the signal drops below -99, wifi_signal will == 0, and |
1363 | @@ -326,7 +329,7 @@ class ConnectionStatus(object): |
1364 | else: |
1365 | wifi_signal = int(signal) |
1366 | except TypeError: |
1367 | - wifi_signal = 0 |
1368 | + wifi_signal = 0 |
1369 | |
1370 | return wifi_signal |
1371 | |
1372 | @@ -357,7 +360,7 @@ class ConnectionStatus(object): |
1373 | |
1374 | # If we just lost a wireless connection, try to connect to that |
1375 | # network again. Otherwise just call Autoconnect. |
1376 | - cur_net_id = wireless.GetCurrentNetworkID(self.iwconfig) |
1377 | + cur_net_id = wireless.GetCurrentNetworkID(self.iwlink) |
1378 | if from_wireless and cur_net_id > -1: |
1379 | # make sure disconnect scripts are run |
1380 | # before we reconnect |
1381 | diff --git a/src/wicd/dbus.py b/src/wicd/dbus.py |
1382 | index a98d275..e017cec 100644 |
1383 | --- a/src/wicd/dbus.py |
1384 | +++ b/src/wicd/dbus.py |
1385 | @@ -30,8 +30,11 @@ wicd.commandline.get_parser().add_argument('--session-dbus', dest='DBus', |
1386 | if getattr(dbus, "version", (0, 0, 0)) < (0, 80, 0): |
1387 | import dbus.glib |
1388 | else: |
1389 | - from dbus.mainloop.glib import DBusGMainLoop |
1390 | - DBusGMainLoop(set_as_default=True) |
1391 | + import sys |
1392 | + |
1393 | + if not any(mod.startswith('wicd.frontends.gtk') for mod in sys.modules): |
1394 | + from dbus.mainloop.glib import DBusGMainLoop |
1395 | + DBusGMainLoop(set_as_default=True) |
1396 | |
1397 | |
1398 | |
1399 | @@ -101,4 +104,4 @@ class DBusManager(object): |
1400 | dbus_manager = DBusManager() |
1401 | del DBusManager |
1402 | |
1403 | -method = service.method |
1404 | \ No newline at end of file |
1405 | +method = service.method |
1406 | diff --git a/encryption/templates/active b/src/wicd/encryption/templates/active |
1407 | similarity index 100% |
1408 | rename from encryption/templates/active |
1409 | rename to src/wicd/encryption/templates/active |
1410 | diff --git a/encryption/templates/active_wired b/src/wicd/encryption/templates/active_wired |
1411 | similarity index 100% |
1412 | rename from encryption/templates/active_wired |
1413 | rename to src/wicd/encryption/templates/active_wired |
1414 | diff --git a/encryption/templates/eap b/src/wicd/encryption/templates/eap |
1415 | similarity index 100% |
1416 | rename from encryption/templates/eap |
1417 | rename to src/wicd/encryption/templates/eap |
1418 | diff --git a/encryption/templates/eap-tls b/src/wicd/encryption/templates/eap-tls |
1419 | similarity index 100% |
1420 | rename from encryption/templates/eap-tls |
1421 | rename to src/wicd/encryption/templates/eap-tls |
1422 | diff --git a/encryption/templates/leap b/src/wicd/encryption/templates/leap |
1423 | similarity index 100% |
1424 | rename from encryption/templates/leap |
1425 | rename to src/wicd/encryption/templates/leap |
1426 | diff --git a/encryption/templates/peap b/src/wicd/encryption/templates/peap |
1427 | similarity index 100% |
1428 | rename from encryption/templates/peap |
1429 | rename to src/wicd/encryption/templates/peap |
1430 | diff --git a/encryption/templates/peap-tkip b/src/wicd/encryption/templates/peap-tkip |
1431 | similarity index 100% |
1432 | rename from encryption/templates/peap-tkip |
1433 | rename to src/wicd/encryption/templates/peap-tkip |
1434 | diff --git a/encryption/templates/psu b/src/wicd/encryption/templates/psu |
1435 | similarity index 100% |
1436 | rename from encryption/templates/psu |
1437 | rename to src/wicd/encryption/templates/psu |
1438 | diff --git a/encryption/templates/ttls b/src/wicd/encryption/templates/ttls |
1439 | similarity index 100% |
1440 | rename from encryption/templates/ttls |
1441 | rename to src/wicd/encryption/templates/ttls |
1442 | diff --git a/encryption/templates/wep-hex b/src/wicd/encryption/templates/wep-hex |
1443 | similarity index 100% |
1444 | rename from encryption/templates/wep-hex |
1445 | rename to src/wicd/encryption/templates/wep-hex |
1446 | diff --git a/encryption/templates/wep-passphrase b/src/wicd/encryption/templates/wep-passphrase |
1447 | similarity index 100% |
1448 | rename from encryption/templates/wep-passphrase |
1449 | rename to src/wicd/encryption/templates/wep-passphrase |
1450 | diff --git a/encryption/templates/wep-shared b/src/wicd/encryption/templates/wep-shared |
1451 | similarity index 100% |
1452 | rename from encryption/templates/wep-shared |
1453 | rename to src/wicd/encryption/templates/wep-shared |
1454 | diff --git a/encryption/templates/wired_8021x b/src/wicd/encryption/templates/wired_8021x |
1455 | similarity index 100% |
1456 | rename from encryption/templates/wired_8021x |
1457 | rename to src/wicd/encryption/templates/wired_8021x |
1458 | diff --git a/encryption/templates/wpa b/src/wicd/encryption/templates/wpa |
1459 | similarity index 100% |
1460 | rename from encryption/templates/wpa |
1461 | rename to src/wicd/encryption/templates/wpa |
1462 | diff --git a/encryption/templates/wpa-peap b/src/wicd/encryption/templates/wpa-peap |
1463 | similarity index 100% |
1464 | rename from encryption/templates/wpa-peap |
1465 | rename to src/wicd/encryption/templates/wpa-peap |
1466 | diff --git a/encryption/templates/wpa-psk b/src/wicd/encryption/templates/wpa-psk |
1467 | similarity index 100% |
1468 | rename from encryption/templates/wpa-psk |
1469 | rename to src/wicd/encryption/templates/wpa-psk |
1470 | diff --git a/encryption/templates/wpa-psk-hex b/src/wicd/encryption/templates/wpa-psk-hex |
1471 | similarity index 100% |
1472 | rename from encryption/templates/wpa-psk-hex |
1473 | rename to src/wicd/encryption/templates/wpa-psk-hex |
1474 | diff --git a/encryption/templates/wpa2-leap b/src/wicd/encryption/templates/wpa2-leap |
1475 | similarity index 100% |
1476 | rename from encryption/templates/wpa2-leap |
1477 | rename to src/wicd/encryption/templates/wpa2-leap |
1478 | diff --git a/encryption/templates/wpa2-peap b/src/wicd/encryption/templates/wpa2-peap |
1479 | similarity index 100% |
1480 | rename from encryption/templates/wpa2-peap |
1481 | rename to src/wicd/encryption/templates/wpa2-peap |
1482 | diff --git a/src/wicd/errors.py b/src/wicd/errors.py |
1483 | index b5539c7..994bb9d 100644 |
1484 | --- a/src/wicd/errors.py |
1485 | +++ b/src/wicd/errors.py |
1486 | @@ -46,4 +46,37 @@ class transform_exception(object): |
1487 | except self.in_exc_type as e: |
1488 | raise self.out_exc_type(e) |
1489 | |
1490 | - return transform_exception_wrapper |
1491 | \ No newline at end of file |
1492 | + return transform_exception_wrapper |
1493 | + |
1494 | +class WiCDCommandNotFound(WiCDError): |
1495 | + def __init__(self, path_list): |
1496 | + # Store the path list for later use in the error message |
1497 | + self.path_list = path_list |
1498 | + |
1499 | + def __str__(self): |
1500 | + # Return the formatted error message |
1501 | + return f'Executable not found in {self.path_list}' |
1502 | + |
1503 | + |
1504 | +class WiCDCommandFailure(WiCDError): |
1505 | + def __init__(self, command, returncode, stdout, stderr): |
1506 | + # Store the command, return code, stdout, and stderr for error reporting |
1507 | + self.command = command |
1508 | + self.returncode = returncode |
1509 | + self.stdout = stdout |
1510 | + self.stderr = stderr |
1511 | + |
1512 | + def __str__(self): |
1513 | + # Return a formatted error message including the command, return code, and output |
1514 | + return (f"Command '{self.command}' failed with return code {self.returncode}.\n" |
1515 | + f"Output: {self.stdout}\n" |
1516 | + f"Error: {self.stderr}") |
1517 | + |
1518 | +class WiCDPopenFailure(WiCDError): |
1519 | + def __init__(self, err): |
1520 | + # Store the command, return code, stdout, and stderr for error reporting |
1521 | + self.error = err |
1522 | + |
1523 | + def __str__(self): |
1524 | + # Return a formatted error message including the command, return code, and output |
1525 | + return (f"Error: {self.error}") |
1526 | diff --git a/src/wicd/frontends/cli.py b/src/wicd/frontends/cli.py |
1527 | index 425e7e7..288e9b4 100755 |
1528 | --- a/src/wicd/frontends/cli.py |
1529 | +++ b/src/wicd/frontends/cli.py |
1530 | @@ -2,6 +2,7 @@ |
1531 | # vim: set fileencoding=utf8 |
1532 | # |
1533 | # Copyright (C) 2021 Andreas Messer |
1534 | +# Copyright (C) 2024 Takahiro Yoshizawa |
1535 | # |
1536 | # This program is free software; you can redistribute it and/or modify |
1537 | # it under the terms of the GNU General Public License as published by |
1538 | @@ -52,7 +53,7 @@ def main(): |
1539 | daemon = wicd.dbus.dbus_manager.ifaces['daemon'] |
1540 | wireless = wicd.dbus.dbus_manager.ifaces['wireless'] |
1541 | wired = wicd.dbus.dbus_manager.ifaces['wired'] |
1542 | - config = wicd.dbus.dbus_manager.ifaces['config'] |
1543 | +# config = wicd.dbus.dbus_manager.ifaces['config'] |
1544 | |
1545 | if not daemon: |
1546 | print(('Error connecting to wicd via D-Bus. ' + \ |
1547 | @@ -69,6 +70,7 @@ def main(): |
1548 | |
1549 | if args.status: |
1550 | status, info = daemon.GetConnectionStatus() |
1551 | + conn_type = "" |
1552 | if status in (misc.WIRED, misc.WIRELESS): |
1553 | connected = True |
1554 | status_msg = _('Connected') |
1555 | @@ -176,8 +178,10 @@ def main(): |
1556 | wireless.GetWirelessProperty(network_id, "mode"))) |
1557 | print(("Channel: %s" % \ |
1558 | wireless.GetWirelessProperty(network_id, "channel"))) |
1559 | + bitrates = wireless.GetWirelessProperty(network_id, "bitrates") |
1560 | + bitrates_str = ', '.join(str(bitrate) for bitrate in bitrates) |
1561 | print(("Bit Rates: %s" % \ |
1562 | - wireless.GetWirelessProperty(network_id, "bitrates"))) |
1563 | + bitrates_str)) |
1564 | op_performed = True |
1565 | |
1566 | # network properties |
1567 | @@ -192,20 +196,29 @@ def main(): |
1568 | network_id = wireless.GetCurrentNetworkID(0) |
1569 | is_valid_wireless_network_id(network_id) |
1570 | if not args.set_to: |
1571 | - print((wireless.GetWirelessProperty(network_id, |
1572 | - args.network_property))) |
1573 | + result = wireless.GetWirelessProperty(network_id, args.network_property) |
1574 | + if isinstance(result, list): |
1575 | + property_str = ', '.join(str(item) for item in result) |
1576 | + else: |
1577 | + property_str = result |
1578 | + print(property_str) |
1579 | else: |
1580 | wireless.SetWirelessProperty(network_id, \ |
1581 | args.network_property, args.set_to) |
1582 | elif args.wired: |
1583 | if not args.set_to: |
1584 | - print((wired.GetWiredProperty(args.network_property))) |
1585 | + result = wired.GetWiredProperty(args.network_property) |
1586 | + if isinstance(result, list): |
1587 | + property_str = ', '.join(str(item) for item in result) |
1588 | + else: |
1589 | + property_str = result |
1590 | + print(property_str) |
1591 | else: |
1592 | wired.SetWiredProperty(args.network_property, args.set_to) |
1593 | op_performed = True |
1594 | |
1595 | if args.disconnect: |
1596 | - daemon.Disconnect() |
1597 | +# daemon.Disconnect() |
1598 | if args.wireless: |
1599 | if wireless.GetCurrentNetworkID(0) > -1: |
1600 | print(("Disconnecting from %s on %s" % \ |
1601 | @@ -215,6 +228,7 @@ def main(): |
1602 | if wired.CheckPluggedIn(): |
1603 | print(("Disconnecting from wired connection on %s" % \ |
1604 | wired.DetectWiredInterface())) |
1605 | + daemon.Disconnect() |
1606 | op_performed = True |
1607 | |
1608 | if args.connect: |
1609 | @@ -265,7 +279,7 @@ def main(): |
1610 | if len(prop) == 0: |
1611 | return "None" |
1612 | else: |
1613 | - tmp = [(x[0], x[1].replace('_', ' ')) for x in type['required']] |
1614 | + tmp = [(x[0], x[1].replace('_', ' ')) for x in prop] |
1615 | return ', '.join("%s (%s)" % (x, y) for x, y in tmp) |
1616 | |
1617 | if args.wireless and args.list_encryption_types: |
1618 | @@ -282,12 +296,12 @@ def main(): |
1619 | i += 1 |
1620 | op_performed = True |
1621 | |
1622 | - if args.save and args.network > -1: |
1623 | + if args.save and ((args.wireless and args.network > -1) or (args.wired and args.name)): |
1624 | if args.wireless: |
1625 | is_valid_wireless_network_id(args.network) |
1626 | - config.SaveWirelessNetworkProfile(args.network) |
1627 | + wireless.SaveWirelessNetworkProfile(args.network) |
1628 | elif args.wired: |
1629 | - config.SaveWiredNetworkProfile(args.name) |
1630 | + wired.SaveWiredNetworkProfile(args.name) |
1631 | op_performed = True |
1632 | |
1633 | if not op_performed: |
1634 | diff --git a/src/wicd/frontends/gtk/__main__.py b/src/wicd/frontends/gtk/__main__.py |
1635 | index b8ccd5b..49021b7 100644 |
1636 | --- a/src/wicd/frontends/gtk/__main__.py |
1637 | +++ b/src/wicd/frontends/gtk/__main__.py |
1638 | @@ -4,6 +4,7 @@ |
1639 | # Copyright (C) 2007 - 2009 Adam Blackburn |
1640 | # Copyright (C) 2007 - 2009 Dan O'Reilly |
1641 | # Copyright (C) 2021 Andreas Messer |
1642 | +# Copyright (C) 2024 Takahiro Yoshizawa |
1643 | # |
1644 | # This program is free software; you can redistribute it and/or modify |
1645 | # it under the terms of the GNU General Public License Version 2 as |
1646 | @@ -30,14 +31,15 @@ import os |
1647 | import atexit |
1648 | from dbus import DBusException |
1649 | |
1650 | +gi.require_version('AyatanaAppIndicator3', '0.1') |
1651 | try: |
1652 | - import appindicator |
1653 | + from gi.repository import AyatanaAppIndicator3 as appindicator |
1654 | USE_APP_INDICATOR = True |
1655 | except ImportError: |
1656 | USE_APP_INDICATOR = False |
1657 | |
1658 | try: |
1659 | - import pynotify |
1660 | + import notify2 as pynotify |
1661 | except ImportError: |
1662 | HAS_NOTIFY = False |
1663 | else: |
1664 | @@ -104,13 +106,18 @@ class NetworkMenuItem(gtk.ImageMenuItem): |
1665 | """ Network menu item. """ |
1666 | def __init__(self, lbl, is_active=False): |
1667 | gtk.ImageMenuItem.__init__(self) |
1668 | - self.label = gtk.Label(lbl) |
1669 | + self.label = gtk.Label() |
1670 | + self.label.set_label(lbl) |
1671 | if is_active: |
1672 | atrlist = pango.AttrList() |
1673 | - atrlist.insert(pango.AttrWeight(pango.WEIGHT_BOLD, 0, 50)) |
1674 | + attr = pango.attr_weight_new(pango.Weight.BOLD) |
1675 | + attr.start_index = 0 |
1676 | + attr.end_index = 50 |
1677 | + atrlist.insert(attr) |
1678 | self.label.set_attributes(atrlist) |
1679 | - self.label.set_justify(gtk.JUSTIFY_LEFT) |
1680 | - self.label.set_alignment(0, 0) |
1681 | + self.label.set_justify(gtk.Justification.LEFT) |
1682 | + self.label.set_halign(gtk.Align.START) |
1683 | + self.label.set_valign(gtk.Align.START) |
1684 | self.add(self.label) |
1685 | self.label.show() |
1686 | |
1687 | @@ -138,6 +145,8 @@ class TrayIcon(object): |
1688 | if displayapp: |
1689 | self.tr.toggle_wicd_gui() |
1690 | self.icon_info = self.TrayConnectionInfo(self, self.tr, animate) |
1691 | + |
1692 | + # Use prefs.py |
1693 | self.tr.icon_info = self.icon_info |
1694 | print(('displaytray %s' % displaytray)) |
1695 | self.tr.visible(displaytray) |
1696 | @@ -213,15 +222,15 @@ class TrayIcon(object): |
1697 | if (self.network_type == "none"): |
1698 | self.tr.tooltip = (_('Not connected')) |
1699 | elif (self.network_type == "wireless"): |
1700 | - self.tr.tooltip = (_(f'Connected to $A at $B (IP: $C)') |
1701 | - .replace('$A', self.network_name) |
1702 | - .replace('$B', self.network_str) |
1703 | + self.tr.tooltip = (_(f'Connected to $A at $B (IP: $C)') \ |
1704 | + .replace('$A', self.network_name) \ |
1705 | + .replace('$B', self.network_str) \ |
1706 | .replace('$C', self.network_addr)) |
1707 | elif (self.network_type == "wired"): |
1708 | - self.tr.tooltip = (_('Connected to wired network (IP: $A)') |
1709 | + self.tr.tooltip = (_('Connected to wired network (IP: $A)') \ |
1710 | .replace('$A', self.network_addr)) |
1711 | elif (self.network_type == "killswitch"): |
1712 | - self.tr.tooltip = (_('Not connected') + "(" + |
1713 | + self.tr.tooltip = (_('Not connected') + "(" + \ |
1714 | _('Wireless Kill Switch Enabled') + ")") |
1715 | elif (self.network_type == "no_daemon"): |
1716 | self.tr.tooltip = (_('Wicd daemon unreachable')) |
1717 | @@ -229,6 +238,11 @@ class TrayIcon(object): |
1718 | return True |
1719 | |
1720 | def _show_notification(self, title, details, image=None): |
1721 | + if title is None: |
1722 | + title = "" |
1723 | + if details is None: |
1724 | + details = "" |
1725 | + |
1726 | if self.should_notify: |
1727 | try: |
1728 | if not self._last_bubble: |
1729 | @@ -236,8 +250,8 @@ class TrayIcon(object): |
1730 | title, details, image) |
1731 | self._last_bubble.show() |
1732 | else: |
1733 | - self._last_bubble.clear_actions() |
1734 | - self._last_bubble.clear_hints() |
1735 | +# self._last_bubble.clear_actions() |
1736 | +# self._last_bubble.clear_hints() |
1737 | self._last_bubble.update(title, details, image) |
1738 | self._last_bubble.show() |
1739 | except Exception as e: |
1740 | @@ -263,9 +277,9 @@ class TrayIcon(object): |
1741 | self.network_addr = str(info[0]) |
1742 | self.network_type = "wired" |
1743 | self.tr.set_from_name('wired') |
1744 | - #status_string = _('Connected to wired network (IP: $A)'). \ |
1745 | - # replace('$A',wired_ip) |
1746 | - #self.tr.set_tooltip(status_string) |
1747 | + status_string = _('Connected to wired network (IP: $A)'). \ |
1748 | + replace('$A',wired_ip) |
1749 | + self.tr.tooltip = status_string |
1750 | self._show_notification(_('Wired Network'), |
1751 | _('Connection established'), |
1752 | 'network-wired') |
1753 | @@ -275,6 +289,8 @@ class TrayIcon(object): |
1754 | @catchdbus |
1755 | def set_wireless_state(self, info): |
1756 | """ Sets the icon info for a wireless state. """ |
1757 | + if len(info) < 5: |
1758 | + return |
1759 | lock = '' |
1760 | wireless_ip = info[0] |
1761 | self.network = info[1] |
1762 | @@ -288,13 +304,14 @@ class TrayIcon(object): |
1763 | self.network_br = info[4] |
1764 | self.set_signal_image(int(info[2]), lock) |
1765 | |
1766 | + status_string = (_("Not connected")) |
1767 | if wireless.GetWirelessProperty(cur_net_id, "encryption"): |
1768 | lock = "-lock" |
1769 | - # status_string = (_('Connected to $A at $B (IP: $C)') |
1770 | - #.replace('$A', self.network) |
1771 | - # .replace('$B', sig_string) |
1772 | - # .replace('$C', str(wireless_ip))) |
1773 | - #self.tr.set_tooltip(status_string) |
1774 | + status_string = (_('Connected to $A at $B (IP: $C)') |
1775 | + .replace('$A', self.network) |
1776 | + .replace('$B', sig_string) |
1777 | + .replace('$C', str(wireless_ip))) |
1778 | + self.tr.tooltip = status_string |
1779 | self.set_signal_image(int(strength), lock) |
1780 | self._show_notification(self.network, |
1781 | _('Connection established'), |
1782 | @@ -306,14 +323,14 @@ class TrayIcon(object): |
1783 | """ Sets the icon info for a connecting state. """ |
1784 | wired = False |
1785 | if info[0] == 'wired' and len(info) == 1: |
1786 | - cur_network = _('Wired Network') |
1787 | + cur_network = (_('Wired Network')) |
1788 | wired = True |
1789 | else: |
1790 | cur_network = info[1] |
1791 | status_string = _('Connecting') + " to " + \ |
1792 | cur_network + "..." |
1793 | self.update_tooltip() |
1794 | - # self.tr.set_tooltip(status_string) |
1795 | + self.tr.tooltip = status_string |
1796 | self.tr.set_from_name('no-signal') |
1797 | if wired: |
1798 | self._show_notification(cur_network, |
1799 | @@ -335,7 +352,7 @@ class TrayIcon(object): |
1800 | _('Wireless Kill Switch Enabled') + ")") |
1801 | else: |
1802 | status = _('Not connected') |
1803 | - # self.tr.set_tooltip(status) |
1804 | + self.tr.tooltip = status |
1805 | self._show_notification(_('Disconnected'), None, 'stop') |
1806 | self.update_tooltip() |
1807 | |
1808 | @@ -345,6 +362,9 @@ class TrayIcon(object): |
1809 | if not DBUS_AVAIL: |
1810 | return False |
1811 | |
1812 | + if self.tr.submenu_open: |
1813 | + return False |
1814 | + |
1815 | if not state or not info: |
1816 | [state, info] = daemon.GetConnectionStatus() |
1817 | |
1818 | @@ -480,51 +500,61 @@ class TrayIcon(object): |
1819 | def __init__(self, parent): |
1820 | super().__init__() |
1821 | |
1822 | + self.ind = None |
1823 | + |
1824 | + self.xdg_current_desktop = os.environ.get("XDG_CURRENT_DESKTOP", "").lower() |
1825 | + |
1826 | self.list = [] |
1827 | self.label = None |
1828 | self.data = None |
1829 | |
1830 | - menu = """ |
1831 | - <ui> |
1832 | - <menubar name="Menubar"> |
1833 | - <menu action="Menu"> |
1834 | - <menu action="Connect"> |
1835 | - </menu> |
1836 | - <separator/> |
1837 | - <menuitem action="Info"/> |
1838 | - <menuitem action="Quit"/> |
1839 | - </menu> |
1840 | - </menubar> |
1841 | - </ui> |
1842 | - """ |
1843 | - actions = [ |
1844 | - ('Menu', None, 'Menu'), |
1845 | - ('Connect', gtk.STOCK_CONNECT, _('Connect')), |
1846 | - ('Info', gtk.STOCK_INFO, _('_Connection Info'), None, |
1847 | - _('Information about the current connection'), |
1848 | - self.on_conn_info), |
1849 | - ('Quit', gtk.STOCK_QUIT, _('_Quit'), None, |
1850 | - _('Quit wicd-tray-icon'), self.on_quit), |
1851 | - ] |
1852 | - actg = gtk.ActionGroup(name='Actions') |
1853 | - actg.add_actions(actions) |
1854 | - self.manager = gtk.UIManager() |
1855 | - self.manager.insert_action_group(actg, 0) |
1856 | - self.manager.add_ui_from_string(menu) |
1857 | - self.menu = (self.manager.get_widget('/Menubar/Menu/Quit'). |
1858 | - props.parent) |
1859 | + self.get_new_menu() |
1860 | + |
1861 | self.gui_win = None |
1862 | self.current_icon_name = None |
1863 | self._is_scanning = False |
1864 | - net_menuitem = self.manager.get_widget("/Menubar/Menu/Connect/") |
1865 | if not USE_APP_INDICATOR: |
1866 | - net_menuitem.connect("activate", self.on_net_menu_activate) |
1867 | + self.connect_item.connect("activate", self.on_net_menu_activate) |
1868 | |
1869 | self.parent = parent |
1870 | self.time = 2 # Time between updates |
1871 | self.cont = 'Stop' |
1872 | self.conn_info_txt = '' |
1873 | |
1874 | + def get_new_menu(self): |
1875 | + self.menu = gtk.Menu() |
1876 | + |
1877 | + self.connect_item = gtk.MenuItem(label=_('Connect')) |
1878 | + self.connect_submenu = gtk.Menu() |
1879 | + self.connect_item.set_submenu(self.connect_submenu) |
1880 | + self.menu.append(self.connect_item) |
1881 | + |
1882 | + info_item = gtk.MenuItem(label=_('Connection Info')) |
1883 | + info_item.connect('activate', self.on_conn_info) |
1884 | + self.menu.append(info_item) |
1885 | + |
1886 | + separator = gtk.SeparatorMenuItem() |
1887 | + self.menu.append(separator) |
1888 | + |
1889 | + quit_item = gtk.MenuItem(label=_('Quit')) |
1890 | + quit_item.connect('activate', self.on_quit) |
1891 | + self.menu.append(quit_item) |
1892 | + self.connect_submenu.connect('show', self.on_connect_submenu_show) |
1893 | + self.connect_submenu.connect('hide', self.on_connect_submenu_hide) |
1894 | + |
1895 | + self.menu.show_all() |
1896 | + self.connect_submenu.show_all() |
1897 | + |
1898 | + self.submenu_open = False |
1899 | + |
1900 | + self.populate_network_menu() |
1901 | + |
1902 | + def on_connect_submenu_show(self, menu): |
1903 | + self.submenu_open = True |
1904 | + |
1905 | + def on_connect_submenu_hide(self, menu): |
1906 | + self.submenu_open = False |
1907 | + |
1908 | def tray_scan_started(self): |
1909 | """ Callback for when a wireless scan is started. """ |
1910 | if not DBUS_AVAIL: |
1911 | @@ -549,6 +579,24 @@ class TrayIcon(object): |
1912 | # 'cannot be completed')) |
1913 | pass |
1914 | |
1915 | + @catchdbus |
1916 | + def update_tray(self, state=None, info=None): |
1917 | + if not DBUS_AVAIL: |
1918 | + return False |
1919 | + |
1920 | + if self.submenu_open: |
1921 | + return False |
1922 | + |
1923 | + info_list = [""] |
1924 | + if info is not None: |
1925 | + info_list = [str(item) for item in info] |
1926 | + |
1927 | + if len(info_list) < 3: |
1928 | + return |
1929 | + if info_list != [''] and self._is_scanning == False: |
1930 | + for item in self.connect_submenu.get_children(): |
1931 | + item.set_sensitive(True) |
1932 | + |
1933 | def on_quit(self, widget=None): |
1934 | """ Closes the tray icon. """ |
1935 | sys.exit(0) |
1936 | @@ -569,7 +617,7 @@ class TrayIcon(object): |
1937 | "Wicd Connection Info", |
1938 | None, |
1939 | 0, |
1940 | - (gtk.STOCK_OK, gtk.RESPONSE_CLOSE) |
1941 | + (gtk.STOCK_OK, gtk.ResponseType.CLOSE) |
1942 | ) |
1943 | |
1944 | # Create labels |
1945 | @@ -686,18 +734,31 @@ TX:''')) |
1946 | else: |
1947 | wireless.ConnectWireless(net_id) |
1948 | |
1949 | - item = NetworkMenuItem(lbl, is_active) |
1950 | + item = gtk.MenuItem() |
1951 | image = gtk.Image() |
1952 | + label = gtk.Label() |
1953 | + label.set_label(lbl) |
1954 | + box = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=6) |
1955 | + |
1956 | + if is_active: |
1957 | + atrlist = pango.AttrList() |
1958 | + attr = pango.attr_weight_new(pango.Weight.BOLD) |
1959 | + attr.start_index = 0 |
1960 | + attr.end_index = 50 |
1961 | + atrlist.insert(attr) |
1962 | + label.set_attributes(atrlist) |
1963 | |
1964 | if type_ == "__wired__": |
1965 | image.set_from_icon_name("network-wired", |
1966 | - gtk.ICON_SIZE_SMALL_TOOLBAR) |
1967 | + gtk.IconSize.SMALL_TOOLBAR) |
1968 | else: |
1969 | image.set_from_icon_name(self._get_img(n_id), |
1970 | - gtk.ICON_SIZE_SMALL_TOOLBAR) |
1971 | - item.set_image(image) |
1972 | + gtk.IconSize.SMALL_TOOLBAR) |
1973 | + box.pack_start(image, False, False, 0) |
1974 | del image |
1975 | item.connect("activate", network_selected, type_, n_id) |
1976 | + box.pack_start(label, False, False, 0) |
1977 | + item.add(box) |
1978 | net_menu.append(item) |
1979 | item.show() |
1980 | if is_connecting: |
1981 | @@ -709,7 +770,7 @@ TX:''')) |
1982 | """ Determines which image to use for the wireless entries. """ |
1983 | def fix_strength(val, default): |
1984 | """ Assigns given strength to a default value if needed. """ |
1985 | - return val and int(val) or default |
1986 | + return val and int(float(val)) or default |
1987 | |
1988 | def get_prop(prop): |
1989 | return wireless.GetWirelessProperty(net_id, prop) |
1990 | @@ -771,14 +832,14 @@ TX:''')) |
1991 | @catchdbus |
1992 | def populate_network_menu(self, data=None): |
1993 | """ Populates the network list submenu. """ |
1994 | + |
1995 | def get_prop(net_id, prop): |
1996 | return wireless.GetWirelessProperty(net_id, prop) |
1997 | |
1998 | - net_menuitem = self.manager.get_widget("/Menubar/Menu/Connect/") |
1999 | - submenu = net_menuitem.get_submenu() |
2000 | - self._clear_menu(submenu) |
2001 | + self._clear_menu(self.connect_submenu) |
2002 | + |
2003 | if not DBUS_AVAIL: |
2004 | - net_menuitem.show() |
2005 | + self.connect_item.show() |
2006 | return |
2007 | |
2008 | is_connecting = daemon.CheckIfConnecting() |
2009 | @@ -791,10 +852,10 @@ TX:''')) |
2010 | is_active = True |
2011 | else: |
2012 | is_active = False |
2013 | - self._add_item_to_menu(submenu, "Wired Network", "__wired__", 0, |
2014 | + self._add_item_to_menu(self.connect_submenu, "Wired Network", "__wired__", 0, |
2015 | is_connecting, is_active) |
2016 | sep = gtk.SeparatorMenuItem() |
2017 | - submenu.append(sep) |
2018 | + self.connect_submenu.append(sep) |
2019 | sep.show() |
2020 | |
2021 | if num_networks > 0: |
2022 | @@ -808,28 +869,29 @@ TX:''')) |
2023 | is_active = True |
2024 | else: |
2025 | is_active = False |
2026 | - self._add_item_to_menu(submenu, essid, "wifi", x, |
2027 | + self._add_item_to_menu(self.connect_submenu, essid, "wifi", x, |
2028 | is_connecting, is_active) |
2029 | else: |
2030 | no_nets_item = gtk.MenuItem(_('No wireless networks found.')) |
2031 | no_nets_item.set_sensitive(False) |
2032 | no_nets_item.show() |
2033 | - submenu.append(no_nets_item) |
2034 | + self.connect_submenu.append(no_nets_item) |
2035 | |
2036 | - submenu.reposition() |
2037 | - net_menuitem.show() |
2038 | + self.connect_submenu.reposition() |
2039 | + self.connect_submenu.show_all() |
2040 | + self.connect_item.show() |
2041 | + self.menu.show_all() |
2042 | |
2043 | def init_network_menu(self): |
2044 | """ Set the right-click network menu to the scanning state. """ |
2045 | - net_menuitem = self.manager.get_widget("/Menubar/Menu/Connect/") |
2046 | - submenu = net_menuitem.get_submenu() |
2047 | - self._clear_menu(submenu) |
2048 | + self._clear_menu(self.connect_submenu) |
2049 | |
2050 | - loading_item = gtk.MenuItem(_('Scanning') + "...") |
2051 | + loading_item = gtk.MenuItem() |
2052 | + loading_item.set_label(_('Scanning') + "...") |
2053 | loading_item.set_sensitive(False) |
2054 | loading_item.show() |
2055 | - submenu.append(loading_item) |
2056 | - net_menuitem.show() |
2057 | + self.connect_submenu.append(loading_item) |
2058 | + self.connect_item.show() |
2059 | |
2060 | def _clear_menu(self, menu): |
2061 | """ Clear the right-click menu. """ |
2062 | @@ -876,6 +938,8 @@ TX:''')) |
2063 | self.set_from_name('no-signal') |
2064 | self.tooltip = "Initializing wicd..." |
2065 | |
2066 | + self.icon_info: Optional[TrayConnectionInfo] = None |
2067 | + |
2068 | def on_popup_menu(self, status, button, timestamp): |
2069 | """ Opens the right click menu for the tray icon. """ |
2070 | self.init_network_menu() |
2071 | @@ -898,30 +962,36 @@ TX:''')) |
2072 | self.set_visible(val) |
2073 | |
2074 | if USE_APP_INDICATOR: |
2075 | - class IndicatorTrayIconGUI(TrayIconGUI, gtk.StatusIcon): |
2076 | + class IndicatorTrayIconGUI(TrayIconGUI): |
2077 | """ Class for creating the wicd AppIndicator. |
2078 | - This is required on recent versions of Unity (>=13.04). |
2079 | - |
2080 | Uses appindicator.Indicator to implement a tray icon. |
2081 | - |
2082 | """ |
2083 | def __init__(self, parent): |
2084 | super().__init__(parent) |
2085 | + self.current_icon_name = '' |
2086 | + self.ind = appindicator.Indicator.new( |
2087 | + "wicd", "network-idle", appindicator.IndicatorCategory.APPLICATION_STATUS) |
2088 | + self.ind.set_status(appindicator.IndicatorStatus.ACTIVE) |
2089 | + |
2090 | + self.get_new_menu() |
2091 | + self.get_new_indicator_menu() |
2092 | + self.ind.set_menu(self.menu) |
2093 | |
2094 | - self.ind = appindicator.Indicator( |
2095 | - "wicd", "wicd-gtk", appindicator.CATEGORY_SYSTEM_SERVICES, wpath.images) |
2096 | + self.icon_info: Optional[TrayConnectionInfo] = None |
2097 | |
2098 | + def get_new_indicator_menu(self): |
2099 | # Rescaning when hovering over the net_menu doesn't work. |
2100 | # (AFAICT, AppIndicator menus don't report PRELIGHT status.) |
2101 | # We use a separate menu item instead. |
2102 | - rescan = gtk.MenuItem("Rescan") |
2103 | + rescan = gtk.MenuItem() |
2104 | + rescan.set_label(_("Rescan")) |
2105 | self.menu.prepend(rescan) |
2106 | rescan.connect("activate", self.on_rescan) |
2107 | rescan.show() |
2108 | |
2109 | sep = gtk.SeparatorMenuItem() |
2110 | - self.menu.prepend(sep) |
2111 | sep.show() |
2112 | + self.menu.prepend(sep) |
2113 | |
2114 | # AppIndicator does not support tooltips so we use a |
2115 | # menu item to contain what was the tooltip. |
2116 | @@ -929,12 +999,45 @@ TX:''')) |
2117 | # Also, since AppIndicator does not support actions on |
2118 | # clicking the tray icon, we use this tooltip menu |
2119 | # item to toggle the GUI |
2120 | - self.tooltip_item = gtk.MenuItem("Initializing wicd...") |
2121 | + self.tooltip_item = gtk.MenuItem() |
2122 | + self.tooltip_item.set_label(_("Initializing wicd...")) |
2123 | self.menu.prepend(self.tooltip_item) |
2124 | self.tooltip_item.connect("activate", self.on_activate) |
2125 | self.tooltip_item.show() |
2126 | + if self.ind: |
2127 | + self.ind.set_menu(self.menu) |
2128 | |
2129 | - self.ind.set_menu(self.menu) |
2130 | + def populate_network_menu(self, data=None): |
2131 | + super().populate_network_menu() |
2132 | + if self.ind: |
2133 | + self.ind.set_menu(self.menu) |
2134 | + |
2135 | + def _clear_menu(self, menu): |
2136 | + """ Clear the right-click menu in the context of Ayatana AppIndicator. """ |
2137 | + self.menu = gtk.Menu() |
2138 | + self.get_new_indicator_menu() |
2139 | + self.connect_item = gtk.MenuItem(label=_('Connect')) |
2140 | + self.connect_submenu = gtk.Menu() |
2141 | + self.connect_item.set_submenu(self.connect_submenu) |
2142 | + self.menu.append(self.connect_item) |
2143 | + info_item = gtk.MenuItem(label=_('Connection Info')) |
2144 | + info_item.connect('activate', self.on_conn_info) |
2145 | + self.menu.append(info_item) |
2146 | + |
2147 | + separator = gtk.SeparatorMenuItem() |
2148 | + self.menu.append(separator) |
2149 | + |
2150 | + quit_item = gtk.MenuItem(label=_('Quit')) |
2151 | + quit_item.connect('activate', self.on_quit) |
2152 | + self.menu.append(quit_item) |
2153 | + |
2154 | + self.connect_submenu.connect('show', self.on_connect_submenu_show) |
2155 | + self.connect_submenu.connect('hide', self.on_connect_submenu_hide) |
2156 | + |
2157 | + self.menu.show_all() |
2158 | + |
2159 | + if self.ind: |
2160 | + self.ind.set_menu(self.menu) |
2161 | |
2162 | def on_rescan(self, *data): |
2163 | """ Triggers a network rescan that updates the 'Connect' menu when the 'Rescan' menu item is selected. """ |
2164 | @@ -945,13 +1048,13 @@ TX:''')) |
2165 | """ Sets a new tray icon picture. """ |
2166 | if path != self.current_icon_path: |
2167 | self.current_icon_path = path |
2168 | - self.ind.set_icon(path) |
2169 | - |
2170 | + self.ind.set_icon_full(path, "") |
2171 | + |
2172 | def set_from_name(self, name=None): |
2173 | """ Sets a new tray icon picture. """ |
2174 | if name != self.current_icon_name: |
2175 | self.current_icon_name = name |
2176 | - self.ind.set_icon(name) |
2177 | + self.ind.set_icon_full(name, "") |
2178 | |
2179 | def visible(self, val): |
2180 | """ Set if the icon is visible or not. |
2181 | @@ -960,7 +1063,14 @@ TX:''')) |
2182 | hides the tray icon. |
2183 | |
2184 | """ |
2185 | - self.ind.set_status(val and appindicator.STATUS_ACTIVE or appindicator.STATUS_PASSIVE) |
2186 | + if val: |
2187 | + self.ind.set_status(appindicator.IndicatorStatus.ACTIVE) |
2188 | + else: |
2189 | + self.ind.set_status(appindicator.IndicatorStatus.PASSIVE) |
2190 | + |
2191 | + def tray_scan_ended(self): |
2192 | + super().tray_scan_ended() |
2193 | + self.ind.set_menu(self.menu) |
2194 | |
2195 | @property |
2196 | def tooltip(self): |
2197 | @@ -989,6 +1099,13 @@ Arguments: |
2198 | |
2199 | def setup_dbus(force=True): |
2200 | """ Initialize DBus. """ |
2201 | + import dbus |
2202 | + if getattr(dbus, "version", (0, 0, 0)) < (0, 80, 0): |
2203 | + import dbus.glib |
2204 | + else: |
2205 | + from dbus.mainloop.glib import DBusGMainLoop |
2206 | + DBusGMainLoop(set_as_default=True) |
2207 | + |
2208 | global daemon, wireless, wired, DBUS_AVAIL, lost_dbus_id |
2209 | print("Connecting to daemon...") |
2210 | try: |
2211 | @@ -1090,6 +1207,8 @@ def main(): |
2212 | 'LaunchChooser', 'org.wicd.daemon') |
2213 | bus.add_signal_receiver(tray_icon.icon_info.update_tray_icon, |
2214 | 'StatusChanged', 'org.wicd.daemon') |
2215 | + bus.add_signal_receiver(tray_icon.tr.update_tray, |
2216 | + 'StatusChanged', 'org.wicd.daemon') |
2217 | bus.add_signal_receiver(tray_icon.tr.tray_scan_ended, 'SendEndScanSignal', |
2218 | 'org.wicd.daemon.wireless') |
2219 | bus.add_signal_receiver(tray_icon.tr.tray_scan_started, |
2220 | diff --git a/src/wicd/frontends/gtk/configscript.py b/src/wicd/frontends/gtk/configscript.py |
2221 | index 5603af4..dcd3b26 100755 |
2222 | --- a/src/wicd/frontends/gtk/configscript.py |
2223 | +++ b/src/wicd/frontends/gtk/configscript.py |
2224 | @@ -28,20 +28,22 @@ run as the current user. |
2225 | |
2226 | import sys |
2227 | import os |
2228 | +import importlib.resources as resources |
2229 | import gi |
2230 | gi.require_version('Gtk', '3.0') |
2231 | from gi.repository import Gtk as gtk |
2232 | |
2233 | from wicd import wpath |
2234 | from wicd.translations import _ |
2235 | -from wicd import dbusmanager |
2236 | +from wicd.dbus import dbus_manager |
2237 | from wicd.configmanager import ConfigManager |
2238 | |
2239 | -dbus = dbusmanager.DBusManager() |
2240 | -dbus.connect_to_dbus() |
2241 | +#dbus = dbus_manager.DBusManager() |
2242 | +#dbus.connect_to_dbus() |
2243 | |
2244 | -wireless = dbus.get_interface("wireless") |
2245 | -wired = dbus.get_interface("wired") |
2246 | +#dbus_manager.connect() |
2247 | +wireless = dbus_manager.get_interface("wireless") |
2248 | +wired = dbus_manager.get_interface("wired") |
2249 | |
2250 | |
2251 | def none_to_blank(text): |
2252 | @@ -127,7 +129,8 @@ def main (argv): |
2253 | |
2254 | script_info = get_script_info(network, network_type) |
2255 | |
2256 | - gladefile = os.path.join(wpath.gtk, "wicd.ui") |
2257 | + gladefile = str(resources.files("wicd.frontends.gtk.resources") / "wicd.ui") |
2258 | + |
2259 | wTree = gtk.Builder() |
2260 | wTree.set_translation_domain('wicd') |
2261 | wTree.add_from_file(gladefile) |
2262 | diff --git a/src/wicd/frontends/gtk/gui.py b/src/wicd/frontends/gtk/gui.py |
2263 | index 140a2f0..48e3218 100644 |
2264 | --- a/src/wicd/frontends/gtk/gui.py |
2265 | +++ b/src/wicd/frontends/gtk/gui.py |
2266 | @@ -9,6 +9,7 @@ Module containing the code for the main wicd GUI. |
2267 | # |
2268 | # Copyright (C) 2007-2009 Adam Blackburn |
2269 | # Copyright (C) 2007-2009 Dan O'Reilly |
2270 | +# Copyright (C) 2024 Takahiro Yoshizawa |
2271 | # |
2272 | # This program is free software; you can redistribute it and/or modify |
2273 | # it under the terms of the GNU General Public License Version 2 as |
2274 | @@ -22,14 +23,13 @@ Module containing the code for the main wicd GUI. |
2275 | # You should have received a copy of the GNU General Public License |
2276 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
2277 | # |
2278 | - |
2279 | import os |
2280 | import sys |
2281 | import time |
2282 | import gi |
2283 | gi.require_version('Gtk', '3.0') |
2284 | from gi.repository import Gtk as gtk |
2285 | -from gi.repository import Gdk |
2286 | +from gi.repository import Gdk as gdk |
2287 | from gi.repository import GLib as gobject |
2288 | from itertools import chain |
2289 | from dbus import DBusException |
2290 | @@ -112,10 +112,10 @@ class WiredProfileChooser: |
2291 | |
2292 | dialog = gtk.Dialog( |
2293 | title=_('Wired connection detected'), |
2294 | - flags=gtk.DIALOG_MODAL, |
2295 | - buttons=(gtk.STOCK_CONNECT, 1, gtk.STOCK_CANCEL, 2) |
2296 | + flags=gtk.DialogFlags.MODAL, |
2297 | + buttons=("network-connect", 1, "process-stop", 2) |
2298 | ) |
2299 | - dialog.set_has_separator(False) |
2300 | +# dialog.set_has_separator(False) |
2301 | dialog.set_size_request(400, 150) |
2302 | instruct_label = gtk.Label( |
2303 | _('Select or create a wired profile to connect with') + ':\n' |
2304 | @@ -125,7 +125,9 @@ class WiredProfileChooser: |
2305 | ) |
2306 | |
2307 | wired_net_entry.is_full_gui = False |
2308 | - instruct_label.set_alignment(0, 0) |
2309 | +# instruct_label.set_alignment(0, 0) |
2310 | + instruct_label.set_xalign(0) |
2311 | + instruct_label.set_yalign(0) |
2312 | stoppopcheckbox.set_active(False) |
2313 | |
2314 | # Remove widgets that were added to the normal WiredNetworkEntry |
2315 | @@ -134,13 +136,13 @@ class WiredProfileChooser: |
2316 | wired_net_entry.vbox_top.remove(wired_net_entry.profile_help) |
2317 | |
2318 | # pylint: disable-msg=E1101 |
2319 | - dialog.vbox.pack_start(instruct_label, fill=False, expand=False) |
2320 | + dialog.vbox.pack_start(instruct_label, fill=False, expand=False, padding=0) |
2321 | # pylint: disable-msg=E1101 |
2322 | - dialog.vbox.pack_start(wired_net_entry.profile_help, False, False) |
2323 | + dialog.vbox.pack_start(wired_net_entry.profile_help, False, False, padding=0) |
2324 | # pylint: disable-msg=E1101 |
2325 | - dialog.vbox.pack_start(wired_net_entry.hbox_temp, False, False) |
2326 | + dialog.vbox.pack_start(wired_net_entry.hbox_temp, False, False, padding=0) |
2327 | # pylint: disable-msg=E1101 |
2328 | - dialog.vbox.pack_start(stoppopcheckbox, False, False) |
2329 | + dialog.vbox.pack_start(stoppopcheckbox, False, False, padding=0) |
2330 | dialog.show_all() |
2331 | |
2332 | wired_profiles = wired_net_entry.combo_profile_names |
2333 | @@ -186,6 +188,7 @@ class appGui(WicdGtkUi): |
2334 | self.wTree.set_translation_domain('wicd') |
2335 | self.wTree.add_from_file(self.gladefile) |
2336 | self.window = self.wTree.get_object("window1") |
2337 | + self._connect_thread_started = False |
2338 | |
2339 | dic = { |
2340 | "refresh_clicked": self.refresh_clicked, |
2341 | @@ -217,7 +220,7 @@ class appGui(WicdGtkUi): |
2342 | self.wired_network_box.show_all() |
2343 | self.network_list = gtk.VBox(False, 0) |
2344 | self.all_network_list.pack_start(self.wired_network_box, False, False, 0) |
2345 | - self.all_network_list.pack_start(self.network_list, True, True, 0) |
2346 | + self.all_network_list.pack_start(self.network_list, True, False, 0) |
2347 | self.network_list.show_all() |
2348 | self.status_area = self.wTree.get_object("connecting_hbox") |
2349 | self.status_bar = self.wTree.get_object("statusbar") |
2350 | @@ -247,6 +250,7 @@ class appGui(WicdGtkUi): |
2351 | self.window.connect('key-release-event', self.key_event) |
2352 | |
2353 | bus = dbus_manager.bus |
2354 | + setup_dbus() |
2355 | |
2356 | bus.add_signal_receiver(self.dbus_scan_finished, 'SendEndScanSignal', |
2357 | 'org.wicd.daemon.wireless') |
2358 | @@ -279,10 +283,10 @@ class appGui(WicdGtkUi): |
2359 | print("Starting the Ad-Hoc Network Creation Process...") |
2360 | dialog = gtk.Dialog( |
2361 | title=_('Create an Ad-Hoc Network'), |
2362 | - flags=gtk.DIALOG_MODAL, |
2363 | - buttons=(gtk.STOCK_CANCEL, 2, gtk.STOCK_OK, 1) |
2364 | + flags=gtk.DialogFlags.MODAL, |
2365 | + buttons=("process-stop", 2, gtk.STOCK_OK, 1) |
2366 | ) |
2367 | - dialog.set_has_separator(False) |
2368 | +# dialog.set_has_separator(False) |
2369 | dialog.set_size_request(400, -1) |
2370 | self.chkbox_use_encryption = \ |
2371 | gtk.CheckButton(_('Use Encryption (WEP only)')) |
2372 | @@ -305,19 +309,19 @@ class appGui(WicdGtkUi): |
2373 | |
2374 | vbox_ah = gtk.VBox(False, 0) |
2375 | self.wired_network_box = gtk.VBox(False, 0) |
2376 | - vbox_ah.pack_start(self.chkbox_use_encryption, False, False) |
2377 | - vbox_ah.pack_start(self.key_entry, False, False) |
2378 | + vbox_ah.pack_start(self.chkbox_use_encryption, False, False, 0) |
2379 | + vbox_ah.pack_start(self.key_entry, False, False, 0) |
2380 | vbox_ah.show() |
2381 | # pylint: disable-msg=E1101 |
2382 | - dialog.vbox.pack_start(essid_entry) |
2383 | + dialog.vbox.pack_start(essid_entry, False, False, 0) |
2384 | # pylint: disable-msg=E1101 |
2385 | - dialog.vbox.pack_start(ip_entry) |
2386 | + dialog.vbox.pack_start(ip_entry, False, False, 0) |
2387 | # pylint: disable-msg=E1101 |
2388 | - dialog.vbox.pack_start(channel_entry) |
2389 | + dialog.vbox.pack_start(channel_entry, False, False, 0) |
2390 | # pylint: disable-msg=E1101 |
2391 | - dialog.vbox.pack_start(chkbox_use_ics) |
2392 | + dialog.vbox.pack_start(chkbox_use_ics, False, False, 0) |
2393 | # pylint: disable-msg=E1101 |
2394 | - dialog.vbox.pack_start(vbox_ah) |
2395 | + dialog.vbox.pack_start(vbox_ah, False, False, 0) |
2396 | # pylint: disable-msg=E1101 |
2397 | dialog.vbox.set_spacing(5) |
2398 | dialog.show_all() |
2399 | @@ -342,10 +346,10 @@ class appGui(WicdGtkUi): |
2400 | wireless.ReloadConfig() |
2401 | dialog = gtk.Dialog( |
2402 | title=_('List of saved networks'), |
2403 | - flags=gtk.DIALOG_MODAL, |
2404 | + flags=gtk.DialogFlags.MODAL, |
2405 | buttons=(gtk.STOCK_DELETE, 1, gtk.STOCK_OK, 2) |
2406 | ) |
2407 | - dialog.set_has_separator(True) |
2408 | +# dialog.set_has_separator(True) |
2409 | dialog.set_size_request(400, 200) |
2410 | |
2411 | networks = gtk.ListStore(str, str) |
2412 | @@ -355,7 +359,7 @@ class appGui(WicdGtkUi): |
2413 | else: |
2414 | networks.append((entry[0], _('Global settings for this ESSID'))) |
2415 | tree = gtk.TreeView(model=networks) |
2416 | - tree.get_selection().set_mode(gtk.SELECTION_MULTIPLE) |
2417 | + tree.get_selection().set_mode(gtk.SelectionMode.MULTIPLE) |
2418 | |
2419 | cell = gtk.CellRendererText() |
2420 | |
2421 | @@ -366,10 +370,10 @@ class appGui(WicdGtkUi): |
2422 | tree.append_column(column) |
2423 | |
2424 | scroll = gtk.ScrolledWindow() |
2425 | - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
2426 | + scroll.set_policy(gtk.PolicyType.AUTOMATIC, gtk.PolicyType.AUTOMATIC) |
2427 | scroll.add(tree) |
2428 | # pylint: disable-msg=E1101 |
2429 | - dialog.vbox.pack_start(scroll) |
2430 | + dialog.vbox.pack_start(scroll, True, True, 0) |
2431 | # pylint: disable-msg=E1101 |
2432 | dialog.vbox.set_spacing(5) |
2433 | dialog.show_all() |
2434 | @@ -386,15 +390,15 @@ class appGui(WicdGtkUi): |
2435 | to_remove['bssid'].append(model.get_value(it, 1)) |
2436 | |
2437 | confirm = gtk.MessageDialog( |
2438 | - flags=gtk.DIALOG_MODAL, |
2439 | - type=gtk.MESSAGE_INFO, |
2440 | - buttons=gtk.BUTTONS_YES_NO, |
2441 | + flags=gtk.DialogFlags.MODAL, |
2442 | + type=gtk.MessageType.INFO, |
2443 | + buttons=gtk.ButtonsType.YES_NO, |
2444 | message_format=_('Are you sure you want to discard' + |
2445 | ' settings for the selected networks?') |
2446 | ) |
2447 | confirm.format_secondary_text('\n'.join(to_remove['essid'])) |
2448 | response = confirm.run() |
2449 | - if response == gtk.RESPONSE_YES: |
2450 | + if response == gtk.ResponseType.YES: |
2451 | for x in to_remove['bssid']: |
2452 | wireless.DeleteWirelessNetwork(x) |
2453 | wireless.ReloadConfig() |
2454 | @@ -434,6 +438,8 @@ class appGui(WicdGtkUi): |
2455 | "Dan O'Reilly", |
2456 | "Andrew Psaltis", |
2457 | "David Paleino" |
2458 | + "Andreas Messer" |
2459 | + "Takahiro Yoshizawa" |
2460 | ]) |
2461 | dialog.set_website("http://launchpad.net/wicd") |
2462 | dialog.run() |
2463 | @@ -441,8 +447,9 @@ class appGui(WicdGtkUi): |
2464 | |
2465 | def key_event(self, widget, event=None): |
2466 | """ Handle key-release-events. """ |
2467 | - if event.state & gtk.gdk.CONTROL_MASK and \ |
2468 | - gtk.gdk.keyval_name(event.keyval) in ["w", "q"]: |
2469 | +# if event.state & gtk.gdk.CONTROL_MASK and \ |
2470 | + if event.state & gdk.ModifierType.CONTROL_MASK and \ |
2471 | + gdk.keyval_name(event.keyval) in ["w", "q"]: |
2472 | self.exit() |
2473 | |
2474 | def settings_dialog(self, widget, event=None): |
2475 | @@ -459,16 +466,16 @@ class appGui(WicdGtkUi): |
2476 | """ Prompts the user for a hidden network, then scans for it. """ |
2477 | dialog = gtk.Dialog( |
2478 | title=('Hidden Network'), |
2479 | - flags=gtk.DIALOG_MODAL, |
2480 | - buttons=(gtk.STOCK_CONNECT, 1, gtk.STOCK_CANCEL, 2) |
2481 | + flags=gtk.DialogFlags.MODAL, |
2482 | + buttons=("network-connect", 1, "process-stop", 2) |
2483 | ) |
2484 | - dialog.set_has_separator(False) |
2485 | +# dialog.set_has_separator(False) |
2486 | lbl = gtk.Label(_('Hidden Network ESSID')) |
2487 | textbox = gtk.Entry() |
2488 | # pylint: disable-msg=E1101 |
2489 | - dialog.vbox.pack_start(lbl) |
2490 | + dialog.vbox.pack_start(lbl, False, False, 0) |
2491 | # pylint: disable-msg=E1101 |
2492 | - dialog.vbox.pack_start(textbox) |
2493 | + dialog.vbox.pack_start(textbox, False, False, 0) |
2494 | dialog.show_all() |
2495 | button = dialog.run() |
2496 | if button == 1: |
2497 | @@ -505,7 +512,8 @@ class appGui(WicdGtkUi): |
2498 | if not self.is_visible: |
2499 | return True |
2500 | |
2501 | - daemon.UpdateState() |
2502 | + if not daemon is None: |
2503 | + daemon.UpdateState() |
2504 | if self.connecting: |
2505 | # If we're connecting, don't wait for the monitor to send |
2506 | # us a signal, since it won't until the connection is made. |
2507 | @@ -542,10 +550,11 @@ class appGui(WicdGtkUi): |
2508 | if self.connecting: |
2509 | # Adjust our state from connecting->connected. |
2510 | self._set_not_connecting_state() |
2511 | - self.set_status(_('Connected to $A at $B (IP: $C)').replace |
2512 | - ('$A', info[1]).replace |
2513 | - ('$B', daemon.FormatSignalForPrinting(info[2])).replace |
2514 | - ('$C', info[0])) |
2515 | + if daemon is not None: |
2516 | + self.set_status(_('Connected to $A at $B (IP: $C)').replace |
2517 | + ('$A', info[1]).replace |
2518 | + ('$B', daemon.FormatSignalForPrinting(info[2])).replace |
2519 | + ('$C', info[0])) |
2520 | return True |
2521 | |
2522 | def set_not_connected_state(self, info): |
2523 | @@ -560,21 +569,24 @@ class appGui(WicdGtkUi): |
2524 | """ Set not-connecting state. """ |
2525 | if self.connecting: |
2526 | if self.update_cb: |
2527 | - gobject.source_remove(self.update_cb) |
2528 | + gobject.source_remove(self.update_cb) |
2529 | + self.update_cb = None |
2530 | + self.connecting = False |
2531 | self.update_cb = misc.timeout_add(2, self.update_statusbar) |
2532 | self.connecting = False |
2533 | if self.pulse_active: |
2534 | self.pulse_active = False |
2535 | gobject.idle_add(self.all_network_list.set_sensitive, True) |
2536 | - gobject.idle_add(self.status_area.hide_all) |
2537 | + gobject.idle_add(self.status_area.hide) |
2538 | if self.statusID: |
2539 | - gobject.idle_add(self.status_bar.remove_message, 1, self.statusID) |
2540 | + gobject.idle_add(self.status_bar.remove, 1, self.statusID) |
2541 | |
2542 | def set_connecting_state(self, info): |
2543 | """ Set connecting state. """ |
2544 | if not self.connecting: |
2545 | if self.update_cb: |
2546 | gobject.source_remove(self.update_cb) |
2547 | + self.update_cb = None |
2548 | self.update_cb = misc.timeout_add(500, self.update_statusbar, |
2549 | milli=True) |
2550 | self.connecting = True |
2551 | @@ -584,7 +596,7 @@ class appGui(WicdGtkUi): |
2552 | gobject.idle_add(self.all_network_list.set_sensitive, False) |
2553 | gobject.idle_add(self.status_area.show_all) |
2554 | if self.statusID: |
2555 | - gobject.idle_add(self.status_bar.remove_message, 1, self.statusID) |
2556 | + gobject.idle_add(self.status_bar.remove, 1, self.statusID) |
2557 | if info[0] == "wireless": |
2558 | stat = wireless.CheckWirelessConnectingMessage() |
2559 | gobject.idle_add(self.set_status, "%s: %s" % (info[1], stat)) |
2560 | @@ -652,12 +664,12 @@ class appGui(WicdGtkUi): |
2561 | self._remove_items_from_vbox(self.wired_network_box) |
2562 | self._remove_items_from_vbox(self.network_list) |
2563 | label = gtk.Label("%s..." % _('Scanning')) |
2564 | - self.network_list.pack_start(label) |
2565 | + self.network_list.pack_start(label, False, False, 10) |
2566 | self.network_list.show_all() |
2567 | if wired.CheckPluggedIn() or daemon.GetAlwaysShowWiredInterface(): |
2568 | printLine = True # In this case we print a separator. |
2569 | wirednet = WiredNetworkEntry() |
2570 | - self.wired_network_box.pack_start(wirednet, False, False) |
2571 | + self.wired_network_box.pack_start(wirednet, False, False, 10) |
2572 | wirednet.connect_button.connect("clicked", self.connect, |
2573 | "wired", 0, wirednet) |
2574 | wirednet.disconnect_button.connect("clicked", self.disconnect, |
2575 | @@ -713,7 +725,7 @@ class appGui(WicdGtkUi): |
2576 | else: |
2577 | printLine = True |
2578 | tempnet = WirelessNetworkEntry(x) |
2579 | - self.network_list.pack_start(tempnet, False, False) |
2580 | + self.network_list.pack_start(tempnet, False, False, 10) |
2581 | tempnet.connect_button.connect("clicked", |
2582 | self.connect, "wireless", x, |
2583 | tempnet) |
2584 | @@ -729,7 +741,7 @@ class appGui(WicdGtkUi): |
2585 | label = gtk.Label(_('Wireless Kill Switch Enabled') + ".") |
2586 | else: |
2587 | label = gtk.Label(_('No wireless networks found.')) |
2588 | - self.network_list.pack_start(label) |
2589 | + self.network_list.pack_start(label, False, False, 0) |
2590 | label.show() |
2591 | self.update_connect_buttons(force_check=True) |
2592 | self.network_list.set_sensitive(True) |
2593 | @@ -803,7 +815,7 @@ class appGui(WicdGtkUi): |
2594 | |
2595 | """ |
2596 | result = dialog.run() |
2597 | - if result == gtk.RESPONSE_ACCEPT: |
2598 | + if result == gtk.ResponseType.OK: |
2599 | if self.save_settings(nettype, networkid, networkentry): |
2600 | return True |
2601 | else: |
2602 | @@ -857,7 +869,7 @@ class appGui(WicdGtkUi): |
2603 | self.all_network_list.set_sensitive(False) |
2604 | if self.statusID: |
2605 | gobject.idle_add( |
2606 | - self.status_bar.remove_message, 1, self.statusID) |
2607 | + self.status_bar.remove, 1, self.statusID) |
2608 | gobject.idle_add( |
2609 | self.set_status, _('Disconnecting active connections...')) |
2610 | gobject.idle_add(self.status_area.show_all) |
2611 | @@ -870,13 +882,14 @@ class appGui(WicdGtkUi): |
2612 | self.edit_advanced(None, nettype, networkid, networkentry) |
2613 | return False |
2614 | setup_interface_for_connection() |
2615 | - wireless.ConnectWireless(networkid, reply_handler=handler, |
2616 | - error_handler=handler) |
2617 | + wireless.ConnectWireless(networkid) |
2618 | elif nettype == "wired": |
2619 | setup_interface_for_connection() |
2620 | wired.ConnectWired(reply_handler=handler, error_handler=handler) |
2621 | |
2622 | - gobject.source_remove(self.update_cb) |
2623 | + if self.update_cb: |
2624 | + gobject.source_remove(self.update_cb) |
2625 | + self.update_cb = None |
2626 | misc.timeout_add(100, self._wait_for_connect_thread_start, milli=True) |
2627 | |
2628 | def disconnect(self, widget, nettype, networkid, networkentry): |
2629 | @@ -902,7 +915,7 @@ class appGui(WicdGtkUi): |
2630 | wired.DisconnectWired(reply_handler=handler, error_handler=handler) |
2631 | else: |
2632 | wireless.DisconnectWireless(reply_handler=handler, |
2633 | - error_handler=handler) |
2634 | + error_handler=handler) |
2635 | |
2636 | def wait_for_events(self, amt=0): |
2637 | """ Wait for any pending gtk events to finish before moving on. |
2638 | @@ -925,7 +938,10 @@ class appGui(WicdGtkUi): |
2639 | |
2640 | """ |
2641 | self.window.hide() |
2642 | - gobject.source_remove(self.update_cb) |
2643 | + |
2644 | + if self.update_cb: |
2645 | + gobject.source_remove(self.update_cb) |
2646 | + self.update_cb = None |
2647 | |
2648 | dbus_manager.bus.remove_signal_receiver(self._do_statusbar_update, 'StatusChanged', |
2649 | 'org.wicd.daemon') |
2650 | @@ -934,6 +950,7 @@ class appGui(WicdGtkUi): |
2651 | sys.exit(0) |
2652 | |
2653 | self.is_visible = False |
2654 | + daemon.SetGUIOpen(False) |
2655 | return True |
2656 | |
2657 | def show_win(self): |
2658 | @@ -951,6 +968,7 @@ class appGui(WicdGtkUi): |
2659 | self.wait_for_events(0.1) |
2660 | gobject.idle_add(self.refresh_clicked) |
2661 | self._do_statusbar_update(*daemon.GetConnectionStatus()) |
2662 | + bus = dbus_manager.get_bus() |
2663 | bus.add_signal_receiver(self._do_statusbar_update, 'StatusChanged', |
2664 | 'org.wicd.daemon') |
2665 | self.update_cb = misc.timeout_add(2, self.update_statusbar) |
2666 | diff --git a/src/wicd/frontends/gtk/guiutil.py b/src/wicd/frontends/gtk/guiutil.py |
2667 | index 08ab8ec..8492971 100644 |
2668 | --- a/src/wicd/frontends/gtk/guiutil.py |
2669 | +++ b/src/wicd/frontends/gtk/guiutil.py |
2670 | @@ -25,7 +25,8 @@ import wicd.wpath as wpath |
2671 | |
2672 | HAS_NOTIFY = True |
2673 | try: |
2674 | - import pynotify |
2675 | +# import pynotify |
2676 | + import notify2 as pynotify |
2677 | if not pynotify.init("Wicd"): |
2678 | print('Could not initalize pynotify') |
2679 | HAS_NOTIFY = False |
2680 | @@ -90,9 +91,9 @@ def string_input(prompt, secondary, textbox_label): |
2681 | |
2682 | dialog = gtk.MessageDialog( |
2683 | None, |
2684 | - gtk.DIALOG_MODAL, |
2685 | - gtk.MESSAGE_QUESTION, |
2686 | - gtk.BUTTONS_OK_CANCEL, |
2687 | + gtk.DialogFlags.MODAL, |
2688 | + gtk.MessageType.QUESTION, |
2689 | + gtk.ButtonsType.OK_CANCEL, |
2690 | None) |
2691 | |
2692 | # set the text |
2693 | @@ -102,19 +103,21 @@ def string_input(prompt, secondary, textbox_label): |
2694 | |
2695 | entry = gtk.Entry() |
2696 | # allow the user to press enter instead of clicking OK |
2697 | - entry.connect("activate", dialog_response, dialog, gtk.RESPONSE_OK) |
2698 | + entry.connect("activate", dialog_response, dialog, gtk.ResponseType.OK) |
2699 | |
2700 | # create an hbox and pack the label and entry in |
2701 | hbox = gtk.HBox() |
2702 | - hbox.pack_start(gtk.Label(textbox_label), False, 4, 4) |
2703 | - hbox.pack_start(entry) |
2704 | +# hbox.pack_start(gtk.Label(textbox_label), False, 4, 4) |
2705 | + hbox.pack_start(gtk.Label(textbox_label), False, False, 4) |
2706 | +# hbox.pack_start(entry) |
2707 | + hbox.pack_start(entry, False, False, 10) |
2708 | |
2709 | # pack the boxes and show the dialog |
2710 | # pylint: disable-msg=E1101 |
2711 | dialog.vbox.pack_end(hbox, True, True, 0) |
2712 | dialog.show_all() |
2713 | |
2714 | - if dialog.run() == gtk.RESPONSE_OK: |
2715 | + if dialog.run() == gtk.ResponseType.OK: |
2716 | text = entry.get_text() |
2717 | dialog.destroy() |
2718 | return text |
2719 | @@ -134,7 +137,9 @@ class LeftAlignedLabel(gtk.Label): |
2720 | """GtkLabel with text aligned to left. """ |
2721 | def __init__(self, label=None): |
2722 | gtk.Label.__init__(self, label) |
2723 | - self.set_alignment(0.0, 0.5) |
2724 | +# self.set_alignment(0.0, 0.5) |
2725 | + self.set_xalign(0.0) |
2726 | + self.set_yalign(0.5) |
2727 | |
2728 | |
2729 | class LabelEntry(gtk.HBox): |
2730 | @@ -146,8 +151,8 @@ class LabelEntry(gtk.HBox): |
2731 | self.label = LeftAlignedLabel() |
2732 | self.label.set_text(text) |
2733 | self.label.set_size_request(170, -1) |
2734 | - self.pack_start(self.label, fill=True, expand=True) |
2735 | - self.pack_start(self.entry, fill=False, expand=False) |
2736 | + self.pack_start(self.label, fill=True, expand=True, padding=10) |
2737 | + self.pack_start(self.entry, fill=False, expand=False, padding=10) |
2738 | self.label.show() |
2739 | self.entry.show() |
2740 | self.entry.connect('focus-out-event', self.hide_characters) |
2741 | @@ -158,7 +163,7 @@ class LabelEntry(gtk.HBox): |
2742 | def set_text(self, text): |
2743 | """ Set text of the GtkEntry. """ |
2744 | # For compatibility... |
2745 | - self.entry.set_text(text) |
2746 | + self.entry.set_text(str(text)) |
2747 | |
2748 | def get_text(self): |
2749 | """ Get text of the GtkEntry. """ |
2750 | @@ -192,7 +197,9 @@ class GreyLabel(gtk.Label): |
2751 | |
2752 | def set_label(self, text): |
2753 | self.set_markup(text) |
2754 | - self.set_alignment(0, 0) |
2755 | +# self.set_alignment(0, 0) |
2756 | + self.set_xalign(0) |
2757 | + self.set_yalign(0) |
2758 | |
2759 | |
2760 | class ProtectedLabelEntry(gtk.HBox): |
2761 | @@ -209,9 +216,12 @@ class ProtectedLabelEntry(gtk.HBox): |
2762 | self.check.set_size_request(5, -1) |
2763 | self.check.set_active(False) |
2764 | self.check.set_focus_on_click(False) |
2765 | - self.pack_start(self.label, fill=True, expand=True) |
2766 | - self.pack_start(self.check, fill=True, expand=True) |
2767 | - self.pack_start(self.entry, fill=False, expand=False) |
2768 | +# self.pack_start(self.label, fill=True, expand=True) |
2769 | + self.pack_start(self.label, fill=True, expand=True, padding=10) |
2770 | +# self.pack_start(self.check, fill=True, expand=True) |
2771 | + self.pack_start(self.check, fill=True, expand=True, padding=10) |
2772 | +# self.pack_start(self.entry, fill=False, expand=False) |
2773 | + self.pack_start(self.entry, fill=False, expand=False, padding=10) |
2774 | self.label.show() |
2775 | self.check.show() |
2776 | self.entry.show() |
2777 | @@ -221,7 +231,7 @@ class ProtectedLabelEntry(gtk.HBox): |
2778 | def set_entry_text(self, text): |
2779 | """ Set text of the GtkEntry. """ |
2780 | # For compatibility... |
2781 | - self.entry.set_text(text) |
2782 | + self.entry.set_text(str(text)) |
2783 | |
2784 | def get_entry_text(self): |
2785 | """ Get text of the GtkEntry. """ |
2786 | @@ -252,8 +262,8 @@ class LabelCombo(gtk.HBox): |
2787 | cell = gtk.CellRendererText() |
2788 | self.combo.pack_start(cell, True) |
2789 | self.combo.add_attribute(cell, 'text', 0) |
2790 | - self.pack_start(self.label, fill=True, expand=True) |
2791 | - self.pack_start(self.combo, fill=False, expand=False) |
2792 | + self.pack_start(self.label, fill=True, expand=True, padding=10) |
2793 | + self.pack_start(self.combo, fill=False, expand=False, padding=10) |
2794 | self.label.show() |
2795 | self.combo.show() |
2796 | self.show() |
2797 | diff --git a/src/wicd/frontends/gtk/netentry.py b/src/wicd/frontends/gtk/netentry.py |
2798 | index 97a5f31..7e4941b 100644 |
2799 | --- a/src/wicd/frontends/gtk/netentry.py |
2800 | +++ b/src/wicd/frontends/gtk/netentry.py |
2801 | @@ -10,6 +10,7 @@ contained within them. |
2802 | # Copyright (C) 2008-2009 Dan O'Reilly |
2803 | # Copyright (C) 2009 Andrew Psaltis |
2804 | # Copyright (C) 2011 David Paleino |
2805 | +# Copyright (C) 2024 Takahiro Yoshizawa |
2806 | # |
2807 | # This program is free software; you can redistribute it and/or modify |
2808 | # it under the terms of the GNU General Public License Version 2 as |
2809 | @@ -26,7 +27,8 @@ contained within them. |
2810 | |
2811 | import gi |
2812 | gi.require_version('Gtk', '3.0') |
2813 | -from gi.repository import Gtk as gtk |
2814 | +#from gi.repository import Gtk as gtk |
2815 | +from gi.repository import Gtk as gtk, Gdk as gdk |
2816 | import os |
2817 | |
2818 | import wicd.misc as misc |
2819 | @@ -70,12 +72,12 @@ class AdvancedSettingsDialog(gtk.Dialog): |
2820 | gtk.Dialog.__init__( |
2821 | self, |
2822 | title=title, |
2823 | - flags=gtk.DIALOG_MODAL, |
2824 | + flags=gtk.DialogFlags.MODAL, |
2825 | buttons=( |
2826 | gtk.STOCK_CANCEL, |
2827 | - gtk.RESPONSE_REJECT, |
2828 | + gtk.ResponseType.NO, |
2829 | gtk.STOCK_OK, |
2830 | - gtk.RESPONSE_ACCEPT |
2831 | + gtk.ResponseType.OK |
2832 | ) |
2833 | ) |
2834 | |
2835 | @@ -97,14 +99,14 @@ class AdvancedSettingsDialog(gtk.Dialog): |
2836 | self.chkbox_use_dhcp_hostname = gtk.CheckButton() |
2837 | self.txt_dhcp_hostname = LabelEntry("DHCP Hostname") |
2838 | dhcp_hostname_hbox.pack_start( |
2839 | - self.chkbox_use_dhcp_hostname, fill=False, expand=False) |
2840 | - dhcp_hostname_hbox.pack_start(self.txt_dhcp_hostname) |
2841 | + self.chkbox_use_dhcp_hostname, fill=False, expand=False, padding=0) |
2842 | + dhcp_hostname_hbox.pack_start(self.txt_dhcp_hostname, False, False, 0) |
2843 | self.chkbox_static_ip = gtk.CheckButton(_('Use Static IPs')) |
2844 | self.chkbox_static_dns = gtk.CheckButton(_('Use Static DNS')) |
2845 | self.chkbox_global_dns = gtk.CheckButton(_('Use global DNS servers')) |
2846 | self.hbox_dns = gtk.HBox(False, 0) |
2847 | - self.hbox_dns.pack_start(self.chkbox_static_dns) |
2848 | - self.hbox_dns.pack_start(self.chkbox_global_dns) |
2849 | + self.hbox_dns.pack_start(self.chkbox_static_dns, False, False, 0) |
2850 | + self.hbox_dns.pack_start(self.chkbox_global_dns, False, False, 0) |
2851 | |
2852 | # Set up the script settings button |
2853 | self.script_button = gtk.Button() |
2854 | @@ -117,31 +119,31 @@ class AdvancedSettingsDialog(gtk.Dialog): |
2855 | |
2856 | self.button_hbox = gtk.HBox(False, 2) |
2857 | self.button_hbox.pack_start( |
2858 | - self.script_button, fill=False, expand=False) |
2859 | + self.script_button, fill=False, expand=False, padding=0) |
2860 | self.button_hbox.show() |
2861 | |
2862 | self.swindow = gtk.ScrolledWindow() |
2863 | - self.swindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) |
2864 | + self.swindow.set_policy(gtk.PolicyType.NEVER, gtk.PolicyType.AUTOMATIC) |
2865 | self.viewport = gtk.Viewport() |
2866 | - self.viewport.set_shadow_type(gtk.SHADOW_NONE) |
2867 | + self.viewport.set_shadow_type(gtk.ShadowType.NONE) |
2868 | self.cvbox = gtk.VBox() |
2869 | self.viewport.add(self.cvbox) |
2870 | self.swindow.add(self.viewport) |
2871 | # pylint: disable-msg=E1101 |
2872 | - self.vbox.pack_start(self.swindow) |
2873 | + self.vbox.pack_start(self.swindow, True, True, 0) |
2874 | |
2875 | assert(isinstance(self.cvbox, gtk.VBox)) |
2876 | - self.cvbox.pack_start(self.chkbox_static_ip, fill=False, expand=False) |
2877 | - self.cvbox.pack_start(self.txt_ip, fill=False, expand=False) |
2878 | - self.cvbox.pack_start(self.txt_netmask, fill=False, expand=False) |
2879 | - self.cvbox.pack_start(self.txt_gateway, fill=False, expand=False) |
2880 | - self.cvbox.pack_start(self.hbox_dns, fill=False, expand=False) |
2881 | - self.cvbox.pack_start(self.txt_domain, fill=False, expand=False) |
2882 | - self.cvbox.pack_start(self.txt_search_dom, fill=False, expand=False) |
2883 | - self.cvbox.pack_start(self.txt_dns_1, fill=False, expand=False) |
2884 | - self.cvbox.pack_start(self.txt_dns_2, fill=False, expand=False) |
2885 | - self.cvbox.pack_start(self.txt_dns_3, fill=False, expand=False) |
2886 | - self.cvbox.pack_start(dhcp_hostname_hbox, fill=False, expand=False) |
2887 | + self.cvbox.pack_start(self.chkbox_static_ip, fill=False, expand=False, padding=0) |
2888 | + self.cvbox.pack_start(self.txt_ip, fill=False, expand=False, padding=0) |
2889 | + self.cvbox.pack_start(self.txt_netmask, fill=False, expand=False, padding=0) |
2890 | + self.cvbox.pack_start(self.txt_gateway, fill=False, expand=False, padding=0) |
2891 | + self.cvbox.pack_start(self.hbox_dns, fill=False, expand=False, padding=0) |
2892 | + self.cvbox.pack_start(self.txt_domain, fill=False, expand=False, padding=0) |
2893 | + self.cvbox.pack_start(self.txt_search_dom, fill=False, expand=False, padding=0) |
2894 | + self.cvbox.pack_start(self.txt_dns_1, fill=False, expand=False, padding=0) |
2895 | + self.cvbox.pack_start(self.txt_dns_2, fill=False, expand=False, padding=0) |
2896 | + self.cvbox.pack_start(self.txt_dns_3, fill=False, expand=False, padding=0) |
2897 | + self.cvbox.pack_start(dhcp_hostname_hbox, fill=False, expand=False, padding=0) |
2898 | self.cvbox.pack_end( |
2899 | self.button_hbox, fill=False, expand=False, padding=5) |
2900 | |
2901 | @@ -162,7 +164,7 @@ class AdvancedSettingsDialog(gtk.Dialog): |
2902 | def set_default_size(self): |
2903 | """ Set default window size. """ |
2904 | width, height = self.get_size() |
2905 | - s_height = gtk.gdk.screen_height() |
2906 | + s_height = gdk.Screen.height() |
2907 | if s_height < 768: |
2908 | height = s_height * .75 |
2909 | else: |
2910 | @@ -350,7 +352,8 @@ class AdvancedSettingsDialog(gtk.Dialog): |
2911 | else: |
2912 | box = LabelEntry(field_text) |
2913 | |
2914 | - self.vbox_encrypt_info.pack_start(box) |
2915 | +# self.vbox_encrypt_info.pack_start(box) |
2916 | + self.vbox_encrypt_info.pack_start(box, False, False, 0) |
2917 | # Add the data to a dict, so that the information |
2918 | # can be easily accessed by giving the name of the wanted |
2919 | # data. |
2920 | @@ -378,7 +381,8 @@ class WiredSettingsDialog(AdvancedSettingsDialog): |
2921 | ## This section is largely copied from WirelessSettingsDialog, but with |
2922 | ## some changes |
2923 | # Set up encryption stuff |
2924 | - self.combo_encryption = gtk.combo_box_new_text() |
2925 | +# self.combo_encryption = gtk.combo_box_new_text() |
2926 | + self.combo_encryption = gtk.ComboBoxText() |
2927 | self.chkbox_encryption = gtk.CheckButton(_('Use Encryption')) |
2928 | # Make the vbox to hold the encryption stuff. |
2929 | self.vbox_encrypt_info = gtk.VBox(False, 0) |
2930 | @@ -394,9 +398,9 @@ class WiredSettingsDialog(AdvancedSettingsDialog): |
2931 | self.change_encrypt_method() |
2932 | self.toggle_encryption() |
2933 | |
2934 | - self.cvbox.pack_start(self.chkbox_encryption, False, False) |
2935 | - self.cvbox.pack_start(self.combo_encryption, False, False) |
2936 | - self.cvbox.pack_start(self.vbox_encrypt_info, False, False) |
2937 | + self.cvbox.pack_start(self.chkbox_encryption, False, False, 0) |
2938 | + self.cvbox.pack_start(self.combo_encryption, False, False, 0) |
2939 | + self.cvbox.pack_start(self.vbox_encrypt_info, False, False, 0) |
2940 | |
2941 | # Connect signals. |
2942 | self.chkbox_encryption.connect("toggled", self.toggle_encryption) |
2943 | @@ -413,7 +417,14 @@ class WiredSettingsDialog(AdvancedSettingsDialog): |
2944 | def edit_scripts(self, widget=None, event=None): |
2945 | """ Launch the script editting dialog. """ |
2946 | profile = self.prof_name |
2947 | - cmdend = [os.path.join(wpath.gtk, "configscript.py"), profile, "wired"] |
2948 | + spec = misc.find_configscript() |
2949 | + cmdend = [] |
2950 | + if spec and spec.origin: |
2951 | + cmdend.extend(["python3", spec.origin, profile, "wired"]) |
2952 | + else: |
2953 | + print("configscript not found") |
2954 | + return |
2955 | + |
2956 | if os.getuid() != 0: |
2957 | cmdbase = misc.get_sudo_cmd( |
2958 | _('You must enter your password to configure scripts'), |
2959 | @@ -520,7 +531,8 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): |
2960 | |
2961 | # Set up encryption stuff |
2962 | self.networkID = networkID |
2963 | - self.combo_encryption = gtk.combo_box_new_text() |
2964 | +# self.combo_encryption = gtk.combo_box_new_text() |
2965 | + self.combo_encryption = gtk.ComboBoxText() |
2966 | self.chkbox_encryption = gtk.CheckButton(_('Use Encryption')) |
2967 | self.chkbox_global_settings = gtk.CheckButton( |
2968 | _('Use these settings for all networks sharing this essid')) |
2969 | @@ -529,14 +541,22 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): |
2970 | |
2971 | self.combo_rate = LabelCombo(_('Wireless bitrate')) |
2972 | rates = gtk.ListStore(str) |
2973 | - self.bitrates = wireless.GetAvailableBitrates() |
2974 | - self.bitrates.append('auto') |
2975 | +# self.bitrates = list(wireless.GetAvailableBitrates()) |
2976 | + self.bitrates = [str(item) for item in wireless.GetAvailableBitrates()] |
2977 | +# self.bitrates = wireless.GetWirelessProperty(networkID, 'bitrates') |
2978 | + # Temporary workaround for the issue where an error occurs if the list has only one item. |
2979 | + if len(self.bitrates) == 0: |
2980 | + self.bitrates = ['auto', ''] |
2981 | + elif len(self.bitrates) == 1: |
2982 | + self.bitrates.append('') |
2983 | + else: |
2984 | + self.bitrates.append('auto') |
2985 | for br in self.bitrates: |
2986 | rates.append((br,)) |
2987 | self.combo_rate.set_model(rates) |
2988 | - self.chkbox_lower_rate = gtk.CheckButton(_('Allow lower bitrates')) |
2989 | - rate_vbox.pack_start(self.combo_rate) |
2990 | - rate_vbox.pack_start(self.chkbox_lower_rate) |
2991 | +# self.chkbox_lower_rate = gtk.CheckButton(_('Allow lower bitrates')) |
2992 | + rate_vbox.pack_start(self.combo_rate, False, False, 0) |
2993 | +# rate_vbox.pack_start(self.chkbox_lower_rate, False, False, 0) |
2994 | |
2995 | # Make the vbox to hold the encryption stuff. |
2996 | self.vbox_encrypt_info = gtk.VBox(False, 0) |
2997 | @@ -546,7 +566,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): |
2998 | self.encrypt_types = misc.LoadEncryptionMethods() |
2999 | |
3000 | information_button = gtk.Button(stock=gtk.STOCK_INFO) |
3001 | - self.button_hbox.pack_start(information_button, False, False) |
3002 | + self.button_hbox.pack_start(information_button, False, False, 0) |
3003 | information_button.connect( |
3004 | 'clicked', |
3005 | lambda *a, **k: WirelessInformationDialog(networkID, self) |
3006 | @@ -569,11 +589,11 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): |
3007 | self.combo_encryption.set_active(0) |
3008 | self.change_encrypt_method() |
3009 | |
3010 | - self.cvbox.pack_start(rate_vbox, False, False) |
3011 | - self.cvbox.pack_start(self.chkbox_global_settings, False, False) |
3012 | - self.cvbox.pack_start(self.chkbox_encryption, False, False) |
3013 | - self.cvbox.pack_start(self.combo_encryption, False, False) |
3014 | - self.cvbox.pack_start(self.vbox_encrypt_info, False, False) |
3015 | + self.cvbox.pack_start(rate_vbox, False, False, 0) |
3016 | + self.cvbox.pack_start(self.chkbox_global_settings, False, False, 0) |
3017 | + self.cvbox.pack_start(self.chkbox_encryption, False, False, 0) |
3018 | + self.cvbox.pack_start(self.combo_encryption, False, False, 0) |
3019 | + self.cvbox.pack_start(self.vbox_encrypt_info, False, False, 0) |
3020 | |
3021 | # Connect signals. |
3022 | self.chkbox_encryption.connect("toggled", self.toggle_encryption) |
3023 | @@ -590,8 +610,14 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): |
3024 | |
3025 | def edit_scripts(self, widget=None, event=None): |
3026 | """ Launch the script editting dialog. """ |
3027 | - cmdend = [os.path.join(wpath.gtk, "configscript.py"), |
3028 | - str(self.networkID), "wireless"] |
3029 | + spec = misc.find_configscript() |
3030 | + cmdend = [] |
3031 | + if spec and spec.origin: |
3032 | + cmdend.extend(["python3", spec.origin, str(self.networkID), "wireless"]) |
3033 | + else: |
3034 | + print("configscript not found") |
3035 | + return |
3036 | + |
3037 | if os.getuid() != 0: |
3038 | cmdbase = misc.get_sudo_cmd( |
3039 | _('You must enter your password to configure scripts'), |
3040 | @@ -659,11 +685,11 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): |
3041 | if chosen_bitrate not in self.bitrates: |
3042 | chosen_bitrate = 'auto' |
3043 | self.combo_rate.set_active(self.bitrates.index(chosen_bitrate)) |
3044 | - self.chkbox_lower_rate.set_active( |
3045 | - bool( |
3046 | - wireless.GetWirelessProperty(networkID, 'allow_lower_bitrates') |
3047 | - ) |
3048 | - ) |
3049 | +# self.chkbox_lower_rate.set_active( |
3050 | +# bool( |
3051 | +# wireless.GetWirelessProperty(networkID, 'allow_lower_bitrates') |
3052 | +# ) |
3053 | +# ) |
3054 | |
3055 | activeID = -1 # Set the menu to this item when we are done |
3056 | user_enctype = wireless.GetWirelessProperty(networkID, "enctype") |
3057 | @@ -725,14 +751,17 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): |
3058 | if self.combo_rate.get_active() == -1: |
3059 | self.set_net_prop('bitrate', 'auto') |
3060 | else: |
3061 | + value = self.bitrates[self.combo_rate.get_active()] |
3062 | + if value == "": |
3063 | + value = 'auto' |
3064 | self.set_net_prop( |
3065 | 'bitrate', |
3066 | - self.bitrates[self.combo_rate.get_active()] |
3067 | + value |
3068 | ) |
3069 | - self.set_net_prop( |
3070 | - 'allow_lower_bitrates', |
3071 | - bool(self.chkbox_lower_rate.get_active()) |
3072 | - ) |
3073 | +# self.set_net_prop( |
3074 | +# 'allow_lower_bitrates', |
3075 | +# bool(self.chkbox_lower_rate.get_active()) |
3076 | +# ) |
3077 | wireless.SaveWirelessNetworkProfile(networkid) |
3078 | return True |
3079 | |
3080 | @@ -753,7 +782,7 @@ class NetworkEntry(gtk.HBox): |
3081 | setup_dbus() |
3082 | gtk.HBox.__init__(self, False, 2) |
3083 | self.image = gtk.Image() |
3084 | - self.pack_start(self.image, False, False) |
3085 | + self.pack_start(self.image, False, False, 0) |
3086 | |
3087 | # Create an HBox to hold the buttons |
3088 | self.buttons_hbox = gtk.HBox(False, 6) |
3089 | @@ -761,38 +790,42 @@ class NetworkEntry(gtk.HBox): |
3090 | # Set up the Connect button |
3091 | self.connect_button = gtk.Button(stock=gtk.STOCK_CONNECT) |
3092 | self.connect_hbox = gtk.HBox(False, 2) |
3093 | - self.connect_hbox.pack_start(self.connect_button, False, False) |
3094 | + self.connect_hbox.pack_start(self.connect_button, False, False, 0) |
3095 | self.connect_hbox.show() |
3096 | |
3097 | # Set up the Disconnect button |
3098 | self.disconnect_button = gtk.Button(stock=gtk.STOCK_DISCONNECT) |
3099 | - self.connect_hbox.pack_start(self.disconnect_button, False, False) |
3100 | + self.connect_hbox.pack_start(self.disconnect_button, False, False, 0) |
3101 | |
3102 | # Create a label to hold the name of the entry |
3103 | self.name_label = gtk.Label() |
3104 | - self.name_label.set_alignment(0, 0.5) |
3105 | +# self.name_label.set_alignment(0, 0.5) |
3106 | + self.name_label.set_xalign(0) |
3107 | + self.name_label.set_yalign(0.5) |
3108 | |
3109 | # Set up the VBox that goes in the gtk.Expander |
3110 | self.expander_vbox = gtk.VBox(False, 1) |
3111 | self.expander_vbox.show() |
3112 | - self.pack_end(self.expander_vbox) |
3113 | + self.pack_end(self.expander_vbox, True, True, 10) |
3114 | |
3115 | # Set up the advanced settings button |
3116 | self.advanced_button = gtk.Button() |
3117 | self.advanced_image = gtk.Image() |
3118 | self.advanced_image.set_from_stock(gtk.STOCK_EDIT, 4) |
3119 | self.advanced_image.set_padding(4, 0) |
3120 | - self.advanced_button.set_alignment(.5, .5) |
3121 | +# self.advanced_button.set_alignment(.5, .5) |
3122 | + self.advanced_button.set_halign(.5) |
3123 | + self.advanced_button.set_valign(.5) |
3124 | self.advanced_button.set_label(_('Properties')) |
3125 | self.advanced_button.set_image(self.advanced_image) |
3126 | |
3127 | - self.buttons_hbox.pack_start(self.connect_hbox, False, False) |
3128 | - self.buttons_hbox.pack_start(self.advanced_button, False, False) |
3129 | + self.buttons_hbox.pack_start(self.connect_hbox, False, False, 0) |
3130 | + self.buttons_hbox.pack_start(self.advanced_button, False, False, 0) |
3131 | |
3132 | self.vbox_top = gtk.VBox(False, 0) |
3133 | - self.expander_vbox.pack_start(self.name_label) |
3134 | - self.expander_vbox.pack_start(self.vbox_top) |
3135 | - self.expander_vbox.pack_start(self.buttons_hbox) |
3136 | + self.expander_vbox.pack_start(self.name_label, False, False, 0) |
3137 | + self.expander_vbox.pack_start(self.vbox_top, False, False, 0) |
3138 | + self.expander_vbox.pack_start(self.buttons_hbox, False, False, 0) |
3139 | |
3140 | def destroy_called(self, *args): |
3141 | """ Clean up everything. """ |
3142 | @@ -808,9 +841,11 @@ class WiredNetworkEntry(NetworkEntry): |
3143 | NetworkEntry.__init__(self) |
3144 | # Center the picture and pad it a bit |
3145 | self.image.set_padding(0, 0) |
3146 | - self.image.set_alignment(.5, .5) |
3147 | +# self.image.set_alignment(.5, .5) |
3148 | + self.image.set_halign(.5) |
3149 | + self.image.set_valign(.5) |
3150 | self.image.set_size_request(60, -1) |
3151 | - self.image.set_from_icon_name("wired-gui", gtk.ICON_SIZE_DND) |
3152 | + self.image.set_from_icon_name("wired-gui", gtk.IconSize.SMALL_TOOLBAR) |
3153 | self.image.show() |
3154 | self.connect_button.show() |
3155 | |
3156 | @@ -828,22 +863,23 @@ class WiredNetworkEntry(NetworkEntry): |
3157 | ) |
3158 | self.chkbox_default_profile = gtk.CheckButton( |
3159 | _('Use as default profile (overwrites any previous default)')) |
3160 | - self.combo_profile_names = gtk.combo_box_new_text() |
3161 | +# self.combo_profile_names = gtk.combo_box_new_text() |
3162 | + self.combo_profile_names = gtk.ComboBoxText() |
3163 | |
3164 | # Format the profile help label. |
3165 | - self.profile_help.set_justify(gtk.JUSTIFY_LEFT) |
3166 | + self.profile_help.set_justify(gtk.Justification.LEFT) |
3167 | self.profile_help.set_line_wrap(True) |
3168 | |
3169 | # Pack the various VBox objects. |
3170 | self.hbox_temp = gtk.HBox(False, 0) |
3171 | self.hbox_def = gtk.HBox(False, 0) |
3172 | - self.vbox_top.pack_start(self.profile_help, True, True) |
3173 | - self.vbox_top.pack_start(self.hbox_def) |
3174 | - self.vbox_top.pack_start(self.hbox_temp) |
3175 | - self.hbox_temp.pack_start(self.combo_profile_names, True, True) |
3176 | - self.hbox_temp.pack_start(self.button_add, False, False) |
3177 | - self.hbox_temp.pack_start(self.button_delete, False, False) |
3178 | - self.hbox_def.pack_start(self.chkbox_default_profile, False, False) |
3179 | + self.vbox_top.pack_start(self.profile_help, True, True, 0) |
3180 | + self.vbox_top.pack_start(self.hbox_def, False, False, 0) |
3181 | + self.vbox_top.pack_start(self.hbox_temp, False, False, 0) |
3182 | + self.hbox_temp.pack_start(self.combo_profile_names, True, True, 0) |
3183 | + self.hbox_temp.pack_start(self.button_add, False, False, 0) |
3184 | + self.hbox_temp.pack_start(self.button_delete, False, False, 0) |
3185 | + self.hbox_def.pack_start(self.chkbox_default_profile, False, False, 0) |
3186 | |
3187 | # Connect events |
3188 | self.button_add.connect("clicked", self.add_profile) |
3189 | @@ -855,7 +891,8 @@ class WiredNetworkEntry(NetworkEntry): |
3190 | # Build profile list. |
3191 | self.profile_list = wired.GetWiredProfileList() |
3192 | default_prof = wired.GetDefaultWiredNetwork() |
3193 | - if self.profile_list: |
3194 | + profile_help_flag = False |
3195 | + if self.profile_list and not all(str(p) == '' for p in self.profile_list): |
3196 | starting_index = 0 |
3197 | for x, prof in enumerate(self.profile_list): |
3198 | self.combo_profile_names.append_text(prof) |
3199 | @@ -865,16 +902,24 @@ class WiredNetworkEntry(NetworkEntry): |
3200 | else: |
3201 | print("no wired profiles found") |
3202 | self.profile_help.show() |
3203 | + profile_help_flag = True |
3204 | + if self.is_full_gui: |
3205 | + self.button_delete.set_sensitive(False) |
3206 | + self.advanced_button.set_sensitive(False) |
3207 | + self.connect_button.set_sensitive(False) |
3208 | + self.chkbox_default_profile.set_sensitive(False) |
3209 | + |
3210 | |
3211 | self.advanced_dialog = \ |
3212 | WiredSettingsDialog(self.combo_profile_names.get_active_text()) |
3213 | |
3214 | # Show everything, but hide the profile help label. |
3215 | self.show_all() |
3216 | - self.profile_help.hide() |
3217 | + if not profile_help_flag: |
3218 | + self.profile_help.hide() |
3219 | |
3220 | # Toggle the default profile checkbox to the correct state. |
3221 | - if to_bool(wired.GetWiredProperty("default")): |
3222 | + if to_bool(wired.GetWiredProperty("default")) and self.profile_list and not all(str(p) == '' for p in self.profile_list): |
3223 | self.chkbox_default_profile.set_active(True) |
3224 | else: |
3225 | self.chkbox_default_profile.set_active(False) |
3226 | @@ -919,7 +964,9 @@ class WiredNetworkEntry(NetworkEntry): |
3227 | "computer. It allows you to easily distinguish between different " |
3228 | "network profiles.", |
3229 | "Profile name:" |
3230 | - ).strip() |
3231 | + ) |
3232 | + if response: |
3233 | + response = response.strip() |
3234 | |
3235 | # if response is "" or None |
3236 | if not response: |
3237 | @@ -941,27 +988,34 @@ class WiredNetworkEntry(NetworkEntry): |
3238 | self.button_delete.set_sensitive(True) |
3239 | self.connect_button.set_sensitive(True) |
3240 | self.advanced_button.set_sensitive(True) |
3241 | + self.chkbox_default_profile.set_sensitive(True) |
3242 | |
3243 | def remove_profile(self, widget): |
3244 | """ Remove a profile from the profile list. """ |
3245 | print("removing profile") |
3246 | - profile_name = self.combo_profile_names.get_active_text() |
3247 | - wired.DeleteWiredNetworkProfile(profile_name) |
3248 | - self.combo_profile_names.remove_text(self.combo_profile_names. |
3249 | + model = self.combo_profile_names.get_model() |
3250 | + if len(model) > 0: |
3251 | + profile_name = self.combo_profile_names.get_active_text() |
3252 | + wired.DeleteWiredNetworkProfile(profile_name) |
3253 | + self.combo_profile_names.remove(self.combo_profile_names. |
3254 | get_active()) |
3255 | - self.combo_profile_names.set_active(0) |
3256 | - self.advanced_dialog.prof_name = \ |
3257 | - self.combo_profile_names.get_active_text() |
3258 | - if not wired.GetWiredProfileList(): |
3259 | - self.profile_help.show() |
3260 | - entry = self.combo_profile_names.child |
3261 | - entry.set_text("") |
3262 | - if self.is_full_gui: |
3263 | - self.button_delete.set_sensitive(False) |
3264 | - self.advanced_button.set_sensitive(False) |
3265 | - self.connect_button.set_sensitive(False) |
3266 | - else: |
3267 | - self.profile_help.hide() |
3268 | + self.combo_profile_names.set_active(0) |
3269 | + self.advanced_dialog.prof_name = \ |
3270 | + self.combo_profile_names.get_active_text() |
3271 | + profile_list = wired.GetWiredProfileList() |
3272 | + if not profile_list or all(str(p) == '' for p in profile_list): |
3273 | + self.profile_help.show() |
3274 | + model_after_remove = self.combo_profile_names.get_model() |
3275 | + if len(model_after_remove) > 0: |
3276 | + entry = self.combo_profile_names.child |
3277 | + entry.set_text("") |
3278 | + if self.is_full_gui: |
3279 | + self.button_delete.set_sensitive(False) |
3280 | + self.advanced_button.set_sensitive(False) |
3281 | + self.connect_button.set_sensitive(False) |
3282 | + self.chkbox_default_profile.set_sensitive(False) |
3283 | + else: |
3284 | + self.profile_help.hide() |
3285 | |
3286 | def toggle_default_profile(self, widget): |
3287 | """ Change the default profile. """ |
3288 | @@ -1003,7 +1057,9 @@ class WirelessNetworkEntry(NetworkEntry): |
3289 | |
3290 | self.networkID = networkID |
3291 | self.image.set_padding(0, 0) |
3292 | - self.image.set_alignment(.5, .5) |
3293 | +# self.image.set_alignment(.5, .5) |
3294 | + self.image.set_halign(.5) |
3295 | + self.image.set_valign(.5) |
3296 | self.image.set_size_request(60, -1) |
3297 | self.image.show() |
3298 | self.essid = noneToBlankString( |
3299 | @@ -1020,7 +1076,7 @@ class WirelessNetworkEntry(NetworkEntry): |
3300 | |
3301 | self.set_signal_strength( |
3302 | wireless.GetWirelessProperty(networkID, 'quality'), |
3303 | - wireless.GetWirelessProperty(networkID, 'strength') |
3304 | + wireless.GetWirelessProperty(networkID, 'strength'), |
3305 | ) |
3306 | self.set_encryption( |
3307 | wireless.GetWirelessProperty(networkID, 'encryption'), |
3308 | @@ -1038,8 +1094,8 @@ class WirelessNetworkEntry(NetworkEntry): |
3309 | ) |
3310 | # Add the wireless network specific parts to the NetworkEntry |
3311 | # VBox objects. |
3312 | - self.vbox_top.pack_start(self.chkbox_autoconnect, False, False) |
3313 | - self.vbox_top.pack_start(self.chkbox_neverconnect, False, False) |
3314 | + self.vbox_top.pack_start(self.chkbox_autoconnect, False, False, 0) |
3315 | + self.vbox_top.pack_start(self.chkbox_neverconnect, False, False, 0) |
3316 | |
3317 | if to_bool(self.format_entry(networkID, "automatic")): |
3318 | self.chkbox_autoconnect.set_active(True) |
3319 | @@ -1113,8 +1169,8 @@ class WirelessNetworkEntry(NetworkEntry): |
3320 | self.connect_button.set_sensitive(False) |
3321 | if not apbssid: |
3322 | apbssid = wireless.GetApBssid() |
3323 | - if state == misc.WIRELESS and \ |
3324 | - apbssid == wireless.GetWirelessProperty(self.networkID, "bssid"): |
3325 | + if state == misc.WIRELESS and apbssid is not None and \ |
3326 | + apbssid.upper() == wireless.GetWirelessProperty(self.networkID, "bssid").upper(): |
3327 | self.disconnect_button.show() |
3328 | self.connect_button.hide() |
3329 | else: |
3330 | @@ -1128,9 +1184,10 @@ class WirelessNetworkEntry(NetworkEntry): |
3331 | else: |
3332 | strength = -1 |
3333 | if dbm_strength: |
3334 | - dbm_strength = int(dbm_strength) |
3335 | + dbm_strength = int(float(dbm_strength)) |
3336 | else: |
3337 | dbm_strength = -100 |
3338 | + |
3339 | display_type = daemon.GetSignalDisplayType() |
3340 | if daemon.GetWPADriver() == 'ralink legacy' or display_type == 1: |
3341 | # Use the -xx dBm signal strength to display a signal icon |
3342 | @@ -1159,7 +1216,7 @@ class WirelessNetworkEntry(NetworkEntry): |
3343 | signal_img = 'signal-25' |
3344 | ending = "%" |
3345 | disp_strength = str(strength) |
3346 | - self.image.set_from_icon_name(signal_img, gtk.ICON_SIZE_DND) |
3347 | + self.image.set_from_icon_name(signal_img, gtk.IconSize.SMALL_TOOLBAR) |
3348 | self.lbl_strength.set_label(disp_strength + ending) |
3349 | self.image.show() |
3350 | |
3351 | @@ -1181,6 +1238,7 @@ class WirelessNetworkEntry(NetworkEntry): |
3352 | return noneToBlankString(wireless.GetWirelessProperty(networkid, label)) |
3353 | |
3354 | |
3355 | + |
3356 | class WirelessInformationDialog(gtk.Dialog): |
3357 | """ Wireless information dialog. """ |
3358 | def __init__(self, networkID, parent): |
3359 | @@ -1188,21 +1246,31 @@ class WirelessInformationDialog(gtk.Dialog): |
3360 | |
3361 | # Make the combo box. |
3362 | self.lbl_strength = gtk.Label() |
3363 | - self.lbl_strength.set_alignment(0, 0.5) |
3364 | +# self.lbl_strength.set_alignment(0, 0.5) |
3365 | + self.lbl_strength.set_xalign(0) |
3366 | + self.lbl_strength.set_xalign(0.5) |
3367 | self.lbl_encryption = gtk.Label() |
3368 | - self.lbl_encryption.set_alignment(0, 0.5) |
3369 | +# self.lbl_encryption.set_alignment(0, 0.5) |
3370 | + self.lbl_encryption.set_xalign(0) |
3371 | + self.lbl_encryption.set_yalign(0.5) |
3372 | self.lbl_mac = gtk.Label() |
3373 | - self.lbl_mac.set_alignment(0, 0.5) |
3374 | +# self.lbl_mac.set_alignment(0, 0.5) |
3375 | + self.lbl_mac.set_xalign(0) |
3376 | + self.lbl_mac.set_yalign(0.5) |
3377 | self.lbl_channel = gtk.Label() |
3378 | - self.lbl_channel.set_alignment(0, 0.5) |
3379 | +# self.lbl_channel.set_alignment(0, 0.5) |
3380 | + self.lbl_channel.set_xalign(0) |
3381 | + self.lbl_channel.set_yalign(0.5) |
3382 | self.lbl_mode = gtk.Label() |
3383 | - self.lbl_mode.set_alignment(0, 0.5) |
3384 | +# self.lbl_mode.set_alignment(0, 0.5) |
3385 | + self.lbl_mode.set_xalign(0) |
3386 | + self.lbl_mode.set_yalign(0.5) |
3387 | self.hbox_status = gtk.HBox(False, 5) |
3388 | |
3389 | # Set the values of the network info labels. |
3390 | self.set_signal_strength( |
3391 | wireless.GetWirelessProperty(networkID, 'quality'), |
3392 | - wireless.GetWirelessProperty(networkID, 'strength') |
3393 | + wireless.GetWirelessProperty(networkID, 'strength'), |
3394 | ) |
3395 | self.set_mac_address(wireless.GetWirelessProperty(networkID, 'bssid')) |
3396 | self.set_mode(wireless.GetWirelessProperty(networkID, 'mode')) |
3397 | @@ -1214,11 +1282,12 @@ class WirelessInformationDialog(gtk.Dialog): |
3398 | |
3399 | self.set_title('Network Information') |
3400 | vbox = self.vbox |
3401 | - self.set_has_separator(False) |
3402 | +# self.set_has_separator(False) |
3403 | table = gtk.Table(5, 2) |
3404 | table.set_col_spacings(12) |
3405 | # pylint: disable-msg=E1101 |
3406 | - vbox.pack_start(table) |
3407 | +# vbox.pack_start(table) |
3408 | + vbox.pack_start(table, False, False, 0) |
3409 | |
3410 | # Pack the network status HBox. |
3411 | table.attach(LeftAlignedLabel('Signal strength:'), 0, 1, 0, 1) |
3412 | @@ -1239,7 +1308,7 @@ class WirelessInformationDialog(gtk.Dialog): |
3413 | # pylint: disable-msg=E1101 |
3414 | vbox.show_all() |
3415 | |
3416 | - self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) |
3417 | + self.add_button(gtk.STOCK_CLOSE, gtk.ResponseType.CLOSE) |
3418 | self.show() |
3419 | self.run() |
3420 | self.destroy() |
3421 | @@ -1251,7 +1320,7 @@ class WirelessInformationDialog(gtk.Dialog): |
3422 | else: |
3423 | strength = -1 |
3424 | if dbm_strength is not None: |
3425 | - dbm_strength = int(dbm_strength) |
3426 | + dbm_strength = int(float(dbm_strength)) |
3427 | else: |
3428 | dbm_strength = -100 |
3429 | display_type = daemon.GetSignalDisplayType() |
3430 | @@ -1308,3 +1377,4 @@ class WirelessInformationDialog(gtk.Dialog): |
3431 | def format_entry(self, networkid, label): |
3432 | """ Helper method for fetching/formatting wireless properties. """ |
3433 | return noneToBlankString(wireless.GetWirelessProperty(networkid, label)) |
3434 | + |
3435 | diff --git a/src/wicd/frontends/gtk/prefs.py b/src/wicd/frontends/gtk/prefs.py |
3436 | index 006999c..dc74993 100644 |
3437 | --- a/src/wicd/frontends/gtk/prefs.py |
3438 | +++ b/src/wicd/frontends/gtk/prefs.py |
3439 | @@ -10,6 +10,7 @@ handles recieving/sendings the settings from/to the daemon. |
3440 | # |
3441 | # Copyright (C) 2008-2009 Adam Blackburn |
3442 | # Copyright (C) 2008-2009 Dan O'Reilly |
3443 | +# Copyright (C) 2024 Takahiro Yoshizawa |
3444 | # |
3445 | # This program is free software; you can redistribute it and/or modify |
3446 | # it under the terms of the GNU General Public License Version 2 as |
3447 | @@ -27,6 +28,8 @@ handles recieving/sendings the settings from/to the daemon. |
3448 | import gi |
3449 | gi.require_version('Gtk', '3.0') |
3450 | from gi.repository import Gtk as gtk |
3451 | +gi.require_version('Gdk', '3.0') |
3452 | +from gi.repository import Gdk as gdk |
3453 | from gi.repository import GObject as gobject |
3454 | import os |
3455 | |
3456 | @@ -211,7 +214,8 @@ class PreferencesDialog(object): |
3457 | |
3458 | # if pynotify isn't installed disable the option |
3459 | try: |
3460 | - import pynotify |
3461 | +# import pynotify |
3462 | + import notify2 as pynotify |
3463 | except ImportError: |
3464 | self.notificationscheckbox.set_active(False) |
3465 | self.notificationscheckbox.set_sensitive(False) |
3466 | @@ -344,7 +348,7 @@ class PreferencesDialog(object): |
3467 | cell = gtk.CellRendererText() |
3468 | combobox.pack_start(cell, True) |
3469 | combobox.add_attribute(cell, 'text', 0) |
3470 | - return combobox |
3471 | + return liststore, combobox |
3472 | |
3473 | def setup_label(name, lbl=""): |
3474 | """ Sets up a label for the given widget name. """ |
3475 | @@ -381,10 +385,10 @@ class PreferencesDialog(object): |
3476 | self.dialog = self.wTree.get_object("pref_dialog") |
3477 | self.dialog.set_title(_('Preferences')) |
3478 | self.dialog.set_icon_name('wicd-gtk') |
3479 | - width = int(gtk.gdk.screen_width() / 2.4) |
3480 | + width = int(gdk.Screen.get_default().get_width() / 2.4) |
3481 | if width > 450: |
3482 | width = 450 |
3483 | - self.dialog.resize(width, int(gtk.gdk.screen_height() / 2)) |
3484 | + self.dialog.resize(width, int(gdk.Screen.get_default().get_height() / 2)) |
3485 | |
3486 | self.wiredcheckbox = setup_label( |
3487 | "pref_always_check", |
3488 | @@ -401,6 +405,7 @@ class PreferencesDialog(object): |
3489 | ) |
3490 | self.debugmodecheckbox = setup_label("pref_debug_check", |
3491 | _('Enable debug mode')) |
3492 | +# iw {interfac} scan does not allow Linq Quality to be obtained, so it was fixed to dBm. |
3493 | self.displaytypecheckbox = setup_label( |
3494 | "pref_dbm_check", |
3495 | _('Use dBm to measure signal strength') |
3496 | @@ -456,13 +461,13 @@ class PreferencesDialog(object): |
3497 | self.ktsussradio = setup_label("ktsuss_radio") |
3498 | |
3499 | # Replacement for the combo box hack |
3500 | - self.wpadrivercombo = build_combobox("pref_wpa_combobox") |
3501 | + self.wpadriverlist, self.wpadrivercombo = build_combobox("pref_wpa_combobox") |
3502 | self.wpadrivers = wireless.GetWpaSupplicantDrivers() |
3503 | self.wpadrivers.append("ralink_legacy") |
3504 | self.wpadrivers.append('none') |
3505 | |
3506 | for x in self.wpadrivers: |
3507 | - self.wpadrivercombo.append_text(x) |
3508 | + self.wpadriverlist.append([x]) |
3509 | |
3510 | self.entryWirelessInterface = self.wTree.get_object("pref_wifi_entry") |
3511 | self.entryWiredInterface = self.wTree.get_object("pref_wired_entry") |
3512 | @@ -476,7 +481,7 @@ class PreferencesDialog(object): |
3513 | self.dns2Entry = self.wTree.get_object("pref_dns2_entry") |
3514 | self.dns3Entry = self.wTree.get_object("pref_dns3_entry") |
3515 | |
3516 | - self.backendcombo = build_combobox("pref_backend_combobox") |
3517 | + self.backendlist, self.backendcombo = build_combobox("pref_backend_combobox") |
3518 | self.backendcombo.connect("changed", self.be_combo_changed) |
3519 | # Load backend combobox |
3520 | self.backends = daemon.GetBackendList() |
3521 | @@ -486,7 +491,7 @@ class PreferencesDialog(object): |
3522 | if x: |
3523 | if x == 'ioctl': |
3524 | x = 'ioctl NOT SUPPORTED' |
3525 | - self.backendcombo.append_text(x) |
3526 | + self.backendlist.append([x]) |
3527 | |
3528 | def be_combo_changed(self, combo): |
3529 | """ Update the description label for the given backend. """ |
3530 | diff --git a/src/wicd/frontends/gtk/resources/wicd.ui b/src/wicd/frontends/gtk/resources/wicd.ui |
3531 | index befd477..5c0d3a7 100644 |
3532 | --- a/src/wicd/frontends/gtk/resources/wicd.ui |
3533 | +++ b/src/wicd/frontends/gtk/resources/wicd.ui |
3534 | @@ -3,12 +3,12 @@ |
3535 | <requires lib="gtk+" version="2.16"/> |
3536 | <!-- interface-naming-policy toplevel-contextual --> |
3537 | <object class="GtkWindow" id="window1"> |
3538 | - <property name="width_request">450</property> |
3539 | +<!--- <property name="width_request">450</property> --> |
3540 | <property name="height_request">400</property> |
3541 | <property name="visible">True</property> |
3542 | <property name="title" translatable="yes">Wicd Network Manager</property> |
3543 | <property name="window_position">center</property> |
3544 | - <property name="default_width">550</property> |
3545 | + <property name="default_width">380</property> |
3546 | <property name="icon_name">wicd-gtk</property> |
3547 | <property name="gravity">center</property> |
3548 | <accel-groups> |
3549 | @@ -219,7 +219,7 @@ |
3550 | <object class="GtkHBox" id="connecting_hbox"> |
3551 | <property name="border_width">4</property> |
3552 | <child> |
3553 | - <object class="GtkSpinner" id="progressbar"> |
3554 | + <object class="GtkProgressBar" id="progressbar"> |
3555 | <property name="tooltip_text" translatable="yes">Connecting...</property> |
3556 | </object> |
3557 | <packing> |
3558 | @@ -1499,6 +1499,7 @@ to read its description.</property> |
3559 | <property name="receives_default">False</property> |
3560 | <property name="draw_indicator">True</property> |
3561 | </object> |
3562 | + |
3563 | </child> |
3564 | </object> |
3565 | <packing> |
3566 | diff --git a/src/wicd/logfile.py b/src/wicd/logfile.py |
3567 | index 1838d36..c639753 100644 |
3568 | --- a/src/wicd/logfile.py |
3569 | +++ b/src/wicd/logfile.py |
3570 | @@ -3,6 +3,7 @@ |
3571 | # |
3572 | # Copyright (C) 1999-2006 Keith Dart <keith@kdart.com> |
3573 | # Copyright (C) 2008-2009 Dan O'Reilly <oreilldf@gmail.com> |
3574 | +# Copyright (C) 2024 Takahiro Yoshizawa <kuro@takahiro.org> |
3575 | # |
3576 | # This library is free software; you can redistribute it and/or |
3577 | # modify it under the terms of the GNU Lesser General Public |
3578 | @@ -59,10 +60,17 @@ class LogFile(io.FileIO): |
3579 | self.eol = True |
3580 | data = data[:-1] |
3581 | |
3582 | - super(LogFile, self).write(data.replace( |
3583 | - b'\n', b'\n' + self.get_time().encode("utf-8") + b' :: ')) |
3584 | + if isinstance(data, bytes): |
3585 | + timestamp = self.get_time().encode('utf-8') |
3586 | + data = data.replace(b'\n', b'\n' + timestamp + b' :: ') |
3587 | + else: |
3588 | + timestamp = self.get_time() |
3589 | + data = data.replace('\n', '\n' + timestamp + ' :: ') |
3590 | + data = data.encode('utf-8') |
3591 | + super(LogFile, self).write(data) |
3592 | + |
3593 | if self.eol: |
3594 | - super(LogFile, self).write('\n') |
3595 | + super(LogFile, self).write(b'\n') |
3596 | |
3597 | self.flush() |
3598 | if self.written > self.maxsize: |
3599 | diff --git a/src/wicd/misc.py b/src/wicd/misc.py |
3600 | index 6f5a5f8..014ce30 100644 |
3601 | --- a/src/wicd/misc.py |
3602 | +++ b/src/wicd/misc.py |
3603 | @@ -8,6 +8,7 @@ throughout wicd. |
3604 | # |
3605 | # Copyright (C) 2007 - 2009 Adam Blackburn |
3606 | # Copyright (C) 2007 - 2009 Dan O'Reilly |
3607 | +# Copyright (C) 2024 Takahiro Yoshizawa |
3608 | # |
3609 | # This program is free software; you can redistribute it and/or modify |
3610 | # it under the terms of the GNU General Public License Version 2 as |
3611 | @@ -27,13 +28,15 @@ import locale |
3612 | import sys |
3613 | import re |
3614 | import string |
3615 | +import importlib.util |
3616 | from gi.repository import GLib as gobject |
3617 | from threading import Thread |
3618 | -from subprocess import Popen, STDOUT, PIPE, call |
3619 | +from subprocess import Popen, STDOUT, PIPE, call, DEVNULL |
3620 | from subprocess import getoutput |
3621 | from itertools import repeat, chain, zip_longest |
3622 | -from pipes import quote |
3623 | +from shlex import quote |
3624 | import socket |
3625 | +import glob |
3626 | |
3627 | from wicd.translations import _ |
3628 | |
3629 | @@ -140,7 +143,10 @@ def Run(cmd, include_stderr=False, return_pipe=False, |
3630 | else: |
3631 | err = None |
3632 | fds = False |
3633 | - std_in = None |
3634 | + |
3635 | + # Measures to address the issue of dhcpcd terminating with an error when using dhcpcd on Ubuntu 24.02. |
3636 | + # Previously, it was set to None. |
3637 | + std_in = DEVNULL |
3638 | |
3639 | # We need to make sure that the results of the command we run |
3640 | # are in English, so we set up a temporary environment. |
3641 | @@ -291,7 +297,9 @@ def ParseEncryption(network): |
3642 | and creating a config file for it |
3643 | |
3644 | """ |
3645 | - enctemplate = open(wpath.encryption + network["enctype"]) |
3646 | + package_dir = os.path.dirname(os.path.abspath(__file__)) |
3647 | + encryption_path = os.path.join(package_dir, 'encryption', 'templates', '') |
3648 | + enctemplate = open(encryption_path + network["enctype"]) |
3649 | template = enctemplate.readlines() |
3650 | if network.get('essid'): |
3651 | config_file = "ap_scan=1\n" |
3652 | @@ -354,7 +362,9 @@ def LoadEncryptionMethods(wired = False): |
3653 | else: |
3654 | active_fname = "active" |
3655 | try: |
3656 | - enctypes = open(wpath.encryption + active_fname,"r").readlines() |
3657 | + package_dir = os.path.dirname(os.path.abspath(__file__)) |
3658 | + encryption_path = os.path.join(package_dir, 'encryption', 'templates', '') |
3659 | + enctypes = open(encryption_path + active_fname,"r").readlines() |
3660 | except IOError as e: |
3661 | print("Fatal Error: template index file is missing.") |
3662 | raise IOError(e) |
3663 | @@ -386,7 +396,9 @@ def _parse_enc_template(enctype): |
3664 | return line.replace(key, "").replace("=", "").strip() |
3665 | |
3666 | try: |
3667 | - f = open(os.path.join(wpath.encryption, enctype), "r") |
3668 | + package_dir = os.path.dirname(os.path.abspath(__file__)) |
3669 | + encryption_path = os.path.join(package_dir, 'encryption', 'templates', '') |
3670 | + f = open(os.path.join(encryption_path, enctype), "r") |
3671 | except IOError: |
3672 | print(("Failed to open template file %s" % enctype)) |
3673 | return None |
3674 | @@ -451,12 +463,17 @@ def noneToString(text): |
3675 | |
3676 | def sanitize_config(s): |
3677 | """ Sanitize property names to be used in config-files. """ |
3678 | - allowed = str.ascii_letters + '_' + string.digits |
3679 | - table = str.maketrans(allowed, ' ' * len(allowed)) |
3680 | +# allowed = string.ascii_letters + '_' + string.digits |
3681 | +# table = str.maketrans(allowed, ' ' * len(allowed)) |
3682 | +# |
3683 | +# # s is a dbus.String -- since we don't allow unicode property keys, |
3684 | +# # make it simple. |
3685 | +# return s.encode('ascii', 'replace').translate(None, table) |
3686 | |
3687 | - # s is a dbus.String -- since we don't allow unicode property keys, |
3688 | - # make it simple. |
3689 | - return s.encode('ascii', 'replace').translate(None, table) |
3690 | + # There was an error with return s.encode('ascii', 'replace').translate(None, table), so it was fixed. |
3691 | + result = ''.join(c if c in string.ascii_letters + string.digits + '_' else ' ' for c in s) |
3692 | + |
3693 | + return result |
3694 | |
3695 | def sanitize_escaped(s): |
3696 | """ Sanitize double-escaped unicode strings. """ |
3697 | @@ -538,9 +555,17 @@ def get_sudo_cmd(msg, prog_num=0): |
3698 | return None |
3699 | if re.search("(pkexec|su-to-root)$", sudo_prog): |
3700 | msg_flag = "" |
3701 | + elif "kdesu" in sudo_prog: |
3702 | + msg_flag = "" |
3703 | + msg = "" |
3704 | else: |
3705 | msg_flag = "--caption" |
3706 | - return [sudo_prog, msg_flag, msg] |
3707 | + if msg_flag == "" and msg == "": |
3708 | + return [sudo_prog] |
3709 | + elif msg_flag == "": |
3710 | + return [sudo_prog, msg] |
3711 | + else: |
3712 | + return [sudo_prog, msg_flag, msg] |
3713 | |
3714 | def choose_sudo_prog(prog_num=0): |
3715 | """ Try to intelligently decide which graphical sudo program to use. """ |
3716 | @@ -548,6 +573,13 @@ def choose_sudo_prog(prog_num=0): |
3717 | return find_path(_sudo_dict[prog_num]) |
3718 | desktop_env = detect_desktop_environment() |
3719 | env_path = os.environ['PATH'].split(":") |
3720 | + |
3721 | + libexec_path = ["/usr/lib/libexec", "/usr/libexec"] |
3722 | + libexec_path.extend(glob.glob("/usr/lib/*/libexec")) |
3723 | + for path in libexec_path: |
3724 | + for dirpath, _, _ in os.walk(path): |
3725 | + env_path.append(dirpath) |
3726 | + |
3727 | paths = [] |
3728 | |
3729 | if desktop_env == "kde": |
3730 | @@ -575,6 +607,13 @@ def find_path(cmd): |
3731 | if not paths: |
3732 | paths = ["/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", |
3733 | "/sbin", "/bin"] |
3734 | + |
3735 | + libexec_path = ["/usr/lib/libexec", "/usr/libexec"] |
3736 | + libexec_path.extend(glob.glob("/usr/lib/*/libexec")) |
3737 | + for path in libexec_path: |
3738 | + for dirpath, _, _ in os.walk(path): |
3739 | + paths.append(dirpath) |
3740 | + |
3741 | for path in paths: |
3742 | if os.path.exists(os.path.join(path, cmd)): |
3743 | return os.path.join(path, cmd) |
3744 | @@ -650,3 +689,18 @@ def grouper(n, iterable, fillvalue=None): |
3745 | """ |
3746 | args = [iter(iterable)] * n |
3747 | return zip_longest(fillvalue=fillvalue, *args) |
3748 | + |
3749 | +def find_configscript(): |
3750 | + """ Find the path to the config script. """ |
3751 | + original_pythonnousersite = os.environ.get("PYTHONNOUSERSITE") |
3752 | + os.environ["PYTHONNOUSERSITE"] = "1" |
3753 | + |
3754 | + try: |
3755 | + spec = importlib.util.find_spec("wicd.frontends.gtk.configscript") |
3756 | + finally: |
3757 | + if original_pythonnousersite is not None: |
3758 | + os.environ["PYTHONNOUSERSITE"] = original_pythonnousersite |
3759 | + else: |
3760 | + del os.environ["PYTHONNOUSERSITE"] |
3761 | + |
3762 | + return spec |
3763 | diff --git a/src/wicd/networking.py b/src/wicd/networking.py |
3764 | index 9a4a0c5..f1c5a17 100644 |
3765 | --- a/src/wicd/networking.py |
3766 | +++ b/src/wicd/networking.py |
3767 | @@ -23,6 +23,7 @@ class WiredConnectThread() -- Connection thread for wired |
3768 | # Copyright (C) 2007 - 2009 Dan O'Reilly |
3769 | # Copyright (C) 2007 - 2009 Byron Hillis |
3770 | # Copyright (C) 2009 Andrew Psaltis |
3771 | +# Copyright (C) 2024 Takahiro Yoshizawa |
3772 | # |
3773 | # This program is free software; you can redistribute it and/or modify |
3774 | # it under the terms of the GNU General Public License Version 2 as |
3775 | @@ -441,7 +442,7 @@ class ConnectThread(threading.Thread): |
3776 | self.SetStatus('flushing_routing_table') |
3777 | print('Flushing the routing table...') |
3778 | iface.FlushRoutes() |
3779 | - |
3780 | + |
3781 | @abortable |
3782 | def set_broadcast_address(self, iface): |
3783 | """ Set the broadcast address for the given interface. """ |
3784 | @@ -690,25 +691,25 @@ class Wireless(Controller): |
3785 | self.connecting_thread.start() |
3786 | return True |
3787 | |
3788 | - def GetSignalStrength(self, iwconfig=""): |
3789 | + def GetSignalStrength(self, iwlink=""): |
3790 | """ Get signal strength of the current network. |
3791 | |
3792 | Returns: |
3793 | The current signal strength. |
3794 | |
3795 | """ |
3796 | - return self.wiface.GetSignalStrength(iwconfig) |
3797 | + return self.wiface.GetSignalStrength(iwlink) |
3798 | |
3799 | - def GetDBMStrength(self, iwconfig=""): |
3800 | + def GetDBMStrength(self, iwlink=""): |
3801 | """ Get the dBm signal strength of the current network. |
3802 | |
3803 | Returns: |
3804 | The current dBm signal strength. |
3805 | |
3806 | """ |
3807 | - return self.wiface.GetDBMStrength(iwconfig) |
3808 | + return self.wiface.GetDBMStrength(iwlink) |
3809 | |
3810 | - def GetCurrentNetwork(self, iwconfig=""): |
3811 | + def GetCurrentNetwork(self, iwlink=""): |
3812 | """ Get current network name. |
3813 | |
3814 | Returns: |
3815 | @@ -717,19 +718,20 @@ class Wireless(Controller): |
3816 | """ |
3817 | if self.connecting_thread and self.connecting_thread.is_connecting: |
3818 | return self.connecting_thread.network['essid'] |
3819 | - return self.wiface.GetCurrentNetwork(iwconfig) |
3820 | + |
3821 | + return self.wiface.GetCurrentNetwork(iwlink) |
3822 | |
3823 | def GetBSSID(self): |
3824 | """ Get the BSSID of the current access point. |
3825 | - |
3826 | + |
3827 | Returns: |
3828 | The MAC Adress of the active access point as a string, or |
3829 | None the BSSID can't be found. |
3830 | - |
3831 | + |
3832 | """ |
3833 | return self.wiface.GetBSSID() |
3834 | |
3835 | - def GetCurrentBitrate(self, iwconfig): |
3836 | + def GetCurrentBitrate(self, iwlink): |
3837 | """ Get the current bitrate of the interface. |
3838 | |
3839 | Returns: |
3840 | @@ -737,9 +739,9 @@ class Wireless(Controller): |
3841 | None the bitrate can't be found. |
3842 | |
3843 | """ |
3844 | - return self.wiface.GetCurrentBitrate(iwconfig) |
3845 | + return self.wiface.GetCurrentBitrate(iwlink) |
3846 | |
3847 | - def GetOperationalMode(self, iwconfig): |
3848 | + def GetOperationalMode(self, iwlink): |
3849 | """ Get the current operational mode of the interface. |
3850 | |
3851 | Returns: |
3852 | @@ -747,17 +749,17 @@ class Wireless(Controller): |
3853 | None if the operational mode can't be found. |
3854 | |
3855 | """ |
3856 | - return self.wiface.GetOperationalMode(iwconfig) |
3857 | - |
3858 | - def GetAvailableAuthMethods(self, iwlistauth): |
3859 | - """ Get the available authentication methods for the interface. |
3860 | - |
3861 | - Returns: |
3862 | - The available authentication methods of the interface as a string, or |
3863 | - None if the auth methods can't be found. |
3864 | - |
3865 | - """ |
3866 | - return self.wiface.GetAvailableAuthMethods(iwlistauth) |
3867 | + return self.wiface.GetOperationalMode(iwlink) |
3868 | + |
3869 | +# def GetAvailableAuthMethods(self, iwlistauth): |
3870 | +# """ Get the available authentication methods for the interface. |
3871 | +# |
3872 | +# Returns: |
3873 | +# The available authentication methods of the interface as a string, or |
3874 | +# None if the auth methods can't be found. |
3875 | +# |
3876 | +# """ |
3877 | +# return self.wiface.GetAvailableAuthMethods(iwlistauth) |
3878 | |
3879 | def GetAvailableBitrates(self): |
3880 | """ Get the available bitrates for the interface. |
3881 | @@ -768,10 +770,14 @@ class Wireless(Controller): |
3882 | """ |
3883 | return self.wiface.GetAvailableBitrates() |
3884 | |
3885 | - def GetIwconfig(self): |
3886 | +# def GetIwconfig(self): |
3887 | +# """ Get the out of iwconfig. """ |
3888 | +# return self.wiface.GetIwconfig() |
3889 | + |
3890 | + def GetIwLink(self): |
3891 | """ Get the out of iwconfig. """ |
3892 | - return self.wiface.GetIwconfig() |
3893 | - |
3894 | + return self.wiface.GetIwLink() |
3895 | + |
3896 | def GetWpaSupplicantDrivers(self): |
3897 | """ Returns all valid wpa_supplicant drivers on the system. """ |
3898 | return BACKEND.GetWpaSupplicantDrivers() |
3899 | @@ -800,16 +806,19 @@ class Wireless(Controller): |
3900 | wiface.StopWPA() |
3901 | print('Putting wireless interface down') |
3902 | wiface.Down() |
3903 | - print('Setting mode, channel, and essid') |
3904 | - wiface.SetMode('ad-hoc') |
3905 | - wiface.SetChannel(channel) |
3906 | - wiface.SetEssid(essid) |
3907 | + print('Setting mode') |
3908 | +# wiface.SetMode('ad-hoc') |
3909 | + wiface.SetMode('ibss') # ad-hoc |
3910 | +# wiface.SetChannel(channel) |
3911 | +# wiface.SetEssid(essid) |
3912 | # Right now it just assumes you're using WEP |
3913 | if enc_used: |
3914 | print('Setting encryption key') |
3915 | - wiface.SetKey(key) |
3916 | + wiface.SetKey(key, essid) |
3917 | print('Putting interface up') |
3918 | wiface.Up() |
3919 | + print('Setting essid and channel') |
3920 | + wiface.SetAdHocEssid(essid, channel) |
3921 | print('Setting IP address') |
3922 | wiface.SetAddress(ip, '255.255.255.0') |
3923 | |
3924 | @@ -874,11 +883,11 @@ class Wireless(Controller): |
3925 | |
3926 | """ |
3927 | if BACKEND.NeedsExternalCalls(): |
3928 | - iwconfig = self.GetIwconfig() |
3929 | + iwlink = self.GetIwLink() |
3930 | else: |
3931 | - iwconfig = None |
3932 | - bssid = self.wiface.GetBSSID(iwconfig) |
3933 | - essid = self.wiface.GetCurrentNetwork(iwconfig) |
3934 | + iwlink = None |
3935 | + bssid = self.wiface.GetBSSID(iwlink) |
3936 | + essid = self.wiface.GetCurrentNetwork(iwlink) |
3937 | |
3938 | Controller.Disconnect(self, 'wireless', essid, bssid) |
3939 | self.StopWPA() |
3940 | @@ -887,6 +896,9 @@ class Wireless(Controller): |
3941 | """ Sets the wpa_supplicant driver associated with the interface. """ |
3942 | self.wiface.SetWpaDriver(driver) |
3943 | |
3944 | + def GetMode(self): |
3945 | + return self.wiface.GetMode() |
3946 | + |
3947 | |
3948 | class WirelessConnectThread(ConnectThread): |
3949 | """ A thread class to perform the connection to a wireless network. |
3950 | @@ -942,7 +954,7 @@ class WirelessConnectThread(ConnectThread): |
3951 | """ |
3952 | wiface = self.iface |
3953 | self.is_connecting = True |
3954 | - |
3955 | + |
3956 | # Run pre-connection script. |
3957 | self.run_global_scripts_if_needed(wpath.preconnectscripts, |
3958 | extra_parameters=('wireless', |
3959 | @@ -960,8 +972,9 @@ class WirelessConnectThread(ConnectThread): |
3960 | self.stop_wpa(wiface) |
3961 | self.flush_routes(wiface) |
3962 | self.flush_dns_addresses(wiface) |
3963 | - wiface.SetMode(self.network['mode']) |
3964 | - wiface.SetBitrate(self.bitrate, self.allow_lower_bitrates) |
3965 | + wiface.SetMode(self.network['operating_mode']) |
3966 | + wiface.SetBitrate(self.bitrate, essid=self.network['essid'], |
3967 | + freq=self.network['freq']) |
3968 | |
3969 | # Put interface up. |
3970 | self.SetStatus('configuring_interface') |
3971 | @@ -979,7 +992,7 @@ class WirelessConnectThread(ConnectThread): |
3972 | if self.wpa_driver == 'ralink legacy': |
3973 | if self.network.get('key'): |
3974 | wiface.Authenticate(self.network) |
3975 | - |
3976 | + |
3977 | # Validate Authentication. |
3978 | if self.network.get('enctype'): |
3979 | self.SetStatus('validating_authentication') |
3980 | @@ -993,7 +1006,7 @@ class WirelessConnectThread(ConnectThread): |
3981 | self.set_ip_address(wiface) |
3982 | self.set_dns_addresses(wiface) |
3983 | self.verify_association(wiface) |
3984 | - |
3985 | + |
3986 | # Run post-connection script. |
3987 | self.run_global_scripts_if_needed(wpath.postconnectscripts, |
3988 | extra_parameters=('wireless', |
3989 | @@ -1041,14 +1054,14 @@ class WirelessConnectThread(ConnectThread): |
3990 | self.abort_connection('association_failed') |
3991 | else: |
3992 | print('not verifying') |
3993 | - |
3994 | + |
3995 | @abortable |
3996 | def generate_psk_and_authenticate(self, wiface): |
3997 | """ Generates a PSK and authenticates if necessary. |
3998 | - |
3999 | + |
4000 | Generates a PSK, and starts the authentication process |
4001 | if encryption is on. |
4002 | - |
4003 | + |
4004 | """ |
4005 | # Check to see if we need to generate a PSK (only for non-ralink |
4006 | # cards). |
4007 | @@ -1059,7 +1072,7 @@ class WirelessConnectThread(ConnectThread): |
4008 | self.SetStatus('generating_psk') |
4009 | print('Generating psk...') |
4010 | self.network['psk'] = wiface.GeneratePSK(self.network) |
4011 | - |
4012 | + |
4013 | if not self.network.get('psk'): |
4014 | self.network['psk'] = self.network['key'] |
4015 | print(('WARNING: PSK generation failed! Falling back to ' + \ |
4016 | @@ -1215,7 +1228,7 @@ class WiredConnectThread(ConnectThread): |
4017 | # Run pre-connection script. |
4018 | self.run_global_scripts_if_needed(wpath.preconnectscripts, |
4019 | extra_parameters=('wired', 'wired', |
4020 | - self.network['profilename']) |
4021 | + self.network.get('profilename', ())) |
4022 | ) |
4023 | self.run_script_if_needed(self.before_script, 'pre-connection', 'wired', |
4024 | 'wired') |
4025 | @@ -1243,7 +1256,7 @@ class WiredConnectThread(ConnectThread): |
4026 | # Run post-connection script. |
4027 | self.run_global_scripts_if_needed(wpath.postconnectscripts, |
4028 | extra_parameters=('wired', 'wired', |
4029 | - self.network['profilename']) |
4030 | + self.network.get('profilename', ())) |
4031 | ) |
4032 | self.run_script_if_needed(self.after_script, 'post-connection', 'wired', |
4033 | 'wired') |
4034 | diff --git a/src/wicd/wnettools.py b/src/wicd/wnettools.py |
4035 | index 875316a..07f9345 100644 |
4036 | --- a/src/wicd/wnettools.py |
4037 | +++ b/src/wicd/wnettools.py |
4038 | @@ -17,6 +17,7 @@ class BaseWirelessInterface() -- Control a wireless network interface. |
4039 | # Copyright (C) 2007 - 2009 Dan O'Reilly |
4040 | # Copyright (C) 2007 - 2009 Byron Hillis |
4041 | # Copyright (C) 2009 Andrew Psaltis |
4042 | +# Copyright (C) 2024 Takahiro Yoshizawa |
4043 | # |
4044 | # This program is free software; you can redistribute it and/or modify |
4045 | # it under the terms of the GNU General Public License Version 2 as |
4046 | @@ -45,36 +46,42 @@ from shlex import quote |
4047 | from . import wpath |
4048 | from . import misc |
4049 | from .misc import find_path |
4050 | +import wicd.config |
4051 | |
4052 | from wicd import daemon |
4053 | |
4054 | -ifconfig_tool = wicd.tools.ExternalCommand(["/sbin/ifconfig", "/usr/sbin/ifconfig"]) |
4055 | +import tempfile |
4056 | + |
4057 | +ifconfig_tool = wicd.tools.ExternalCommand(["/sbin/ifconfig", "/usr/sbin/ifconfig", "/bin/ifconfig", "/usr/bin/ifconfig"]) |
4058 | |
4059 | # Regular expressions. |
4060 | _re_mode = (re.I | re.M | re.S) |
4061 | essid_pattern = re.compile('\tSSID: ?(.*?)\n', _re_mode) |
4062 | +essid_pattern2 = re.compile(r"SSID:\s([^\n]+)", _re_mode) |
4063 | ap_mac_pattern = re.compile('BSS (([0-9a-f]{2}:?){6})+\(', _re_mode) |
4064 | channel_pattern = re.compile('\tDS Parameter set: channel ?(\d+)\n', _re_mode) |
4065 | strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)', _re_mode) |
4066 | altstrength_pattern = re.compile('.*Signal level:?=? ?(\d+)\s*/?\s*(\d*)', |
4067 | _re_mode) |
4068 | signaldbm_pattern = re.compile('\tsignal: (-[\d.]*) dBm', _re_mode) |
4069 | +signaldbm_pattern2 = re.compile(r"signal:\s(-?\d+\s?)dBm", _re_mode) |
4070 | bitrates_pattern = re.compile('([\d\.]+)\*?\s+', _re_mode) |
4071 | mode_pattern = re.compile('\tcapability: (ESS|IBSS) ', _re_mode) |
4072 | freq_pattern = re.compile('.*freq: (\d+)\n', _re_mode) |
4073 | wep_pattern = re.compile('\tcapability: \w+ (Privacy) ', _re_mode) |
4074 | rsn_pattern = re.compile('RSN:\t \* (Version: 1)', _re_mode) |
4075 | wpa_pattern = re.compile('WPA:\t \* (Version: 1)', _re_mode) |
4076 | +txpower_pattern = re.compile(r"txpower\s+([\d.]+)\s+dBm", _re_mode) |
4077 | +txbitrate_pattern = re.compile(r"tx bitrate:\s*([\d.]+)\s*MBit/s", _re_mode) |
4078 | |
4079 | #iwconfig-only regular expressions. |
4080 | ip_up = re.compile(r'flags=[0.9]*<([^>]*)>', re.S) |
4081 | ip_pattern = re.compile(r'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)', |
4082 | re.S) |
4083 | ip_pattern1 = re.compile(r'inet ([^.]*\.[^.]*\.[^.]*\.[0-9]*)', re.S) |
4084 | -bssid_pattern = re.compile('.*[(Access Point)|(Cell)]: ' + \ |
4085 | - '(([0-9A-Z]{2}:){5}[0-9A-Z]{2})', _re_mode) |
4086 | -bitrate_pattern = re.compile('.*Bit Rate[=:](.*?/s)', _re_mode) |
4087 | -opmode_pattern = re.compile('.*Mode:(.*?) ', _re_mode) |
4088 | +bssid_pattern = re.compile(r"Connected to ([0-9A-Fa-f:]{17}) \(on [^)]+\)", _re_mode) |
4089 | +freq_pattern = re.compile(r"freq:\s*(\d+)", _re_mode) |
4090 | +opmode_pattern = re.compile(r"type\s+(\w+)", _re_mode) |
4091 | authmethods_pattern = re.compile('.*Authentication capabilities ' + \ |
4092 | ':\n(.*?)Current', _re_mode) |
4093 | |
4094 | @@ -90,6 +97,7 @@ blacklist_norm = list(";`$!*|><&\\") |
4095 | blacklist_strict_t = str.maketrans(dict.fromkeys(blacklist_strict, None)) |
4096 | blacklist_norm_t = str.maketrans(dict.fromkeys(blacklist_norm, None)) |
4097 | |
4098 | + |
4099 | def _sanitize_string(string): |
4100 | """ Sanitize string. """ |
4101 | if string: |
4102 | @@ -320,11 +328,11 @@ class BaseInterface(object): |
4103 | |
4104 | def _get_dhcp_command(self, flavor=None, hostname=None, staticdns=False): |
4105 | """ Returns the correct DHCP client command. |
4106 | - |
4107 | + |
4108 | Given a type of DHCP request (create or release a lease), |
4109 | this method will build a command to complete the request |
4110 | using the correct dhcp client, and cli options. |
4111 | - |
4112 | + |
4113 | """ |
4114 | def get_client_name(cl): |
4115 | """ Converts the integer value for a dhcp client to a string. """ |
4116 | @@ -501,10 +509,10 @@ class BaseInterface(object): |
4117 | @neediface(False) |
4118 | def Up(self): |
4119 | """ Bring the network interface up. |
4120 | - |
4121 | + |
4122 | Returns: |
4123 | True |
4124 | - |
4125 | + |
4126 | """ |
4127 | ifconfig_tool( self.iface, 'up' ) |
4128 | return True |
4129 | @@ -512,14 +520,14 @@ class BaseInterface(object): |
4130 | @neediface(False) |
4131 | def Down(self): |
4132 | """ Take down the network interface. |
4133 | - |
4134 | + |
4135 | Returns: |
4136 | True |
4137 | - |
4138 | + |
4139 | """ |
4140 | ifconfig_tool( self.iface, 'down' ) |
4141 | return True |
4142 | - |
4143 | + |
4144 | @timedcache(2) |
4145 | @neediface("") |
4146 | def GetIfconfig(self): |
4147 | @@ -547,13 +555,13 @@ class BaseInterface(object): |
4148 | args = [self.iface] |
4149 | |
4150 | if ip: |
4151 | - cmd.append(ip) |
4152 | + args.append(str(ip)) |
4153 | if netmask: |
4154 | - cmd.append(netmask) |
4155 | + args.extend(['netmask', netmask]) |
4156 | if broadcast: |
4157 | - cmd.extend(['broadcast', broadcast]) |
4158 | + args.extend(['broadcast', broadcast]) |
4159 | |
4160 | - ifconfig_tool(args) |
4161 | + ifconfig_tool([], *args) |
4162 | |
4163 | def _parse_dhclient(self, pipe): |
4164 | """ Parse the output of dhclient. |
4165 | @@ -573,11 +581,11 @@ class BaseInterface(object): |
4166 | |
4167 | while not dhclient_complete: |
4168 | line = pipe.readline() |
4169 | - if line == '': # Empty string means dhclient is done. |
4170 | + if line == b'': # Empty string means dhclient is done. |
4171 | dhclient_complete = True |
4172 | else: |
4173 | - print(misc.to_unicode(line.strip('\n'))) |
4174 | - if line.startswith('bound'): |
4175 | + print(misc.to_unicode(line.strip(b'\n'))) |
4176 | + if line.startswith(b'bound'): |
4177 | dhclient_success = True |
4178 | dhclient_complete = True |
4179 | |
4180 | @@ -598,7 +606,7 @@ class BaseInterface(object): |
4181 | |
4182 | while not pump_complete: |
4183 | line = pipe.readline() |
4184 | - if line == '': |
4185 | + if line == b'': |
4186 | pump_complete = True |
4187 | elif line.strip().lower().startswith('Operation failed.'): |
4188 | pump_success = False |
4189 | @@ -619,13 +627,12 @@ class BaseInterface(object): |
4190 | """ |
4191 | dhcpcd_complete = False |
4192 | dhcpcd_success = True |
4193 | - |
4194 | while not dhcpcd_complete: |
4195 | line = pipe.readline() |
4196 | - if "Error" in line or "timed out" in line: |
4197 | + if b"Error" in line or b"timed out" in line: |
4198 | dhcpcd_success = False |
4199 | dhcpcd_complete = True |
4200 | - elif line == '': |
4201 | + elif line == b'': |
4202 | dhcpcd_complete = True |
4203 | print(misc.to_unicode(line)) |
4204 | |
4205 | @@ -646,10 +653,10 @@ class BaseInterface(object): |
4206 | |
4207 | while not udhcpc_complete: |
4208 | line = pipe.readline() |
4209 | - if line.endswith("failing."): |
4210 | + if line.endswith(b"failing."): |
4211 | udhcpc_success = False |
4212 | udhcpc_complete = True |
4213 | - elif line == '': |
4214 | + elif line == b'': |
4215 | udhcpc_complete = True |
4216 | print(line) |
4217 | |
4218 | @@ -688,6 +695,7 @@ class BaseInterface(object): |
4219 | if self.verbose: |
4220 | print(cmd) |
4221 | self.dhcp_object = misc.Run(cmd, include_stderr=True, return_obj=True) |
4222 | + |
4223 | pipe = self.dhcp_object.stdout |
4224 | client_dict = { misc.DHCLIENT : self._parse_dhclient, |
4225 | misc.DHCPCD : self._parse_dhcpcd, |
4226 | @@ -702,6 +710,10 @@ class BaseInterface(object): |
4227 | print("ERROR: no dhcp client found") |
4228 | ret = None |
4229 | self.dhcp_object.wait() |
4230 | + if os.path.exists(wicd.config.resolvconf_path) and not os.path.islink(wicd.config.resolvconf_path): |
4231 | + # After running dhclient, addressing the issue |
4232 | + # where the permissions of /etc/resolv.conf are set to 0600. |
4233 | + os.chmod(wicd.config.resolvconf_path, 0o644) |
4234 | return ret |
4235 | |
4236 | @neediface(False) |
4237 | @@ -733,13 +745,36 @@ class BaseInterface(object): |
4238 | Only useful for resolvconf-based setups. |
4239 | |
4240 | """ |
4241 | - daemon.resolver.get_manager().flush_dns(self.iface) |
4242 | +# daemon.resolver.get_manager().flush_dns(self.iface) |
4243 | + pass |
4244 | |
4245 | @neediface(False) |
4246 | def SetDNS(self, dns1=None, dns2=None, dns3=None, |
4247 | dns_dom=None, search_dom=None): |
4248 | - daemon.resolver.get_manager().set_dns(self.iface, dns1 = dns1, dns2 = dns2, dns3 = dns3, dns_dom = dns_dom, search_dom = search_dom) |
4249 | - |
4250 | +# daemon.resolver.get_manager().set_dns(self.iface, dns1 = dns1, dns2 = dns2, dns3 = dns3, dns_dom = dns_dom, search_dom = search_dom) |
4251 | + resolv_params = "" |
4252 | + if dns_dom: |
4253 | + resolv_params += 'domain %s\n' % dns_dom |
4254 | + if search_dom: |
4255 | + resolv_params += 'search %s\n' % search_dom |
4256 | + |
4257 | + valid_dns_list = [] |
4258 | + for dns in (dns1, dns2, dns3): |
4259 | + if dns: |
4260 | + if misc.IsValidIP(dns): |
4261 | + if self.verbose: |
4262 | + print('Setting DNS : ' + dns) |
4263 | + valid_dns_list.append("nameserver %s\n" % dns) |
4264 | + else: |
4265 | + print('DNS IP %s is not a valid IP address, skipping' % dns) |
4266 | + |
4267 | + if valid_dns_list: |
4268 | + resolv_params += ''.join(valid_dns_list) |
4269 | + |
4270 | + resolv = open("/etc/resolv.conf", "w") |
4271 | + resolv.write(resolv_params + "\n") |
4272 | + resolv.close() |
4273 | + |
4274 | @neediface(False) |
4275 | def FlushRoutes(self): |
4276 | """ Flush network routes for this device. """ |
4277 | @@ -828,7 +863,7 @@ class BaseInterface(object): |
4278 | % flags_file) |
4279 | return self._slow_is_up(ifconfig) |
4280 | return bool(int(flags, 16) & 1) |
4281 | - |
4282 | + |
4283 | @neediface(False) |
4284 | def StopWPA(self): |
4285 | """ Terminates wpa using wpa_cli""" |
4286 | @@ -836,8 +871,8 @@ class BaseInterface(object): |
4287 | if self.verbose: |
4288 | print(cmd) |
4289 | misc.Run(cmd) |
4290 | - |
4291 | - |
4292 | + |
4293 | + |
4294 | def _slow_is_up(self, ifconfig=None): |
4295 | """ Determine if an interface is up using ifconfig. """ |
4296 | if not ifconfig: |
4297 | @@ -1003,7 +1038,16 @@ class BaseWirelessInterface(BaseInterface): |
4298 | essid -- essid to set the interface to |
4299 | |
4300 | """ |
4301 | - cmd = ['iwconfig', self.iface, 'essid', '--', str(essid)] |
4302 | +# cmd = ['iwconfig', self.iface, 'essid', '--', str(essid)] |
4303 | + cmd = ['iw', self.iface, 'connect', str(essid)] |
4304 | + if self.verbose: |
4305 | + print(str(cmd)) |
4306 | + misc.Run(cmd) |
4307 | + |
4308 | + @neediface(False) |
4309 | + def SetAdHocEssid(self, essid, channel): |
4310 | + freq = self._ChannelToFreq(int(channel)) |
4311 | + cmd = ['iw', self.iface, 'ibss', 'join', str(essid), str(freq), 'fixed-freq'] |
4312 | if self.verbose: |
4313 | print(str(cmd)) |
4314 | misc.Run(cmd) |
4315 | @@ -1011,26 +1055,56 @@ class BaseWirelessInterface(BaseInterface): |
4316 | @neediface(False) |
4317 | def GetKillSwitchStatus(self): |
4318 | """ Determines if the wireless killswitch is enabled. |
4319 | - |
4320 | + |
4321 | Returns: |
4322 | True if the killswitch is enabled, False otherwise. |
4323 | - |
4324 | + |
4325 | """ |
4326 | - output = self.GetIwconfig() |
4327 | + output = self.GetIwDevInfo() |
4328 | + |
4329 | + killswitch_pattern = misc.RunRegex(txpower_pattern, output) |
4330 | |
4331 | - killswitch_pattern = re.compile('.*radio off', re.I | re.M | re.S) |
4332 | - if killswitch_pattern.search(output): |
4333 | - radiostatus = True |
4334 | + if killswitch_pattern: |
4335 | + if float(killswitch_pattern) != 0: |
4336 | + radiostatus = True |
4337 | + else: |
4338 | + radiostatus = False |
4339 | else: |
4340 | radiostatus = False |
4341 | |
4342 | return radiostatus |
4343 | - |
4344 | + |
4345 | +# @timedcache(2) |
4346 | +# @neediface(False) |
4347 | +# def GetIwconfig(self): |
4348 | +# """ Returns the output of iwconfig for this interface. """ |
4349 | +# cmd = "iwconfig " + self.iface |
4350 | +# |
4351 | +# if self.verbose: |
4352 | +# print(cmd) |
4353 | +# return misc.Run(cmd) |
4354 | + |
4355 | + @timedcache(2) |
4356 | + @neediface(False) |
4357 | + def GetIwLink(self): |
4358 | + cmd = "iw %s link" % self.iface |
4359 | + if self.verbose: |
4360 | + print(cmd) |
4361 | + return misc.Run(cmd) |
4362 | + |
4363 | + @timedcache(2) |
4364 | + @neediface(False) |
4365 | + def GetIwInfo(self): |
4366 | + cmd = "iw %s info" % self.iface |
4367 | + if self.verbose: |
4368 | + print(cmd) |
4369 | + return misc.Run(cmd) |
4370 | + |
4371 | @timedcache(2) |
4372 | @neediface(False) |
4373 | - def GetIwconfig(self): |
4374 | - """ Returns the output of iwconfig for this interface. """ |
4375 | - cmd = "iwconfig " + self.iface |
4376 | + def GetIwDevInfo(self): |
4377 | + cmd = "iw dev " + self.iface + " info" |
4378 | + |
4379 | if self.verbose: |
4380 | print(cmd) |
4381 | return misc.Run(cmd) |
4382 | @@ -1059,61 +1133,126 @@ class BaseWirelessInterface(BaseInterface): |
4383 | ret = freq_dict[freq] |
4384 | except KeyError: |
4385 | print("Couldn't determine channel number for frequency:", str(freq)) |
4386 | - |
4387 | + |
4388 | return ret |
4389 | |
4390 | - def _GetRalinkInfo(self): |
4391 | - """ Get a network info list used for ralink drivers |
4392 | - |
4393 | - Calls iwpriv <wireless interface> get_site_survey, which |
4394 | - on some ralink cards will return encryption and signal |
4395 | - strength info for wireless networks in the area. |
4396 | - |
4397 | + def _ChannelToFreq(self, channel: int) -> int: |
4398 | + """ |
4399 | + A function to convert Wi-Fi channel numbers to frequency (MHz). |
4400 | + |
4401 | + :param channel: Wi-Fi channel number (1–165) |
4402 | + :return: Frequency (MHz) (raises an exception if the channel is unsupported) |
4403 | """ |
4404 | - iwpriv = misc.Run('iwpriv ' + self.iface + ' get_site_survey') |
4405 | + if 1 <= channel <= 13: # 2.4GHz band |
4406 | + return 2407 + channel * 5 |
4407 | + elif channel == 14: # Japan-specific channel |
4408 | + return 2484 |
4409 | + elif 36 <= channel <= 165 and channel % 4 == 0: # 5GHz band |
4410 | + return 5000 + (channel - 36) * 5 + 180 |
4411 | + else: |
4412 | + raise ValueError(f"Channel {channel} is not supported") |
4413 | + |
4414 | +# def _GetRalinkInfo(self): |
4415 | +# """ Get a network info list used for ralink drivers |
4416 | +# |
4417 | +# Calls iwpriv <wireless interface> get_site_survey, which |
4418 | +# on some ralink cards will return encryption and signal |
4419 | +# strength info for wireless networks in the area. |
4420 | +# |
4421 | +# """ |
4422 | +# iwpriv = misc.Run('iwpriv ' + self.iface + ' get_site_survey') |
4423 | +# if self.verbose: |
4424 | +# print(iwpriv) |
4425 | +# lines = iwpriv.splitlines()[2:] |
4426 | +# aps = {} |
4427 | +# patt = re.compile("((?:[0-9A-Z]{2}:){5}[0-9A-Z]{2})") |
4428 | +# for x in lines: |
4429 | +# ap = {} |
4430 | +# info = x.split(" ") |
4431 | +# info = [x.strip() for x in info if x.strip()] |
4432 | +# if len(info) < 5: |
4433 | +# continue |
4434 | +# if re.match(patt, info[2].upper()): |
4435 | +# bssid = info[2].upper() |
4436 | +# offset = -1 |
4437 | +# elif re.match(patt, info[3].upper()): |
4438 | +# bssid = info[3].upper() |
4439 | +# offset = 0 |
4440 | +# else: # Invalid |
4441 | +# print('Invalid iwpriv line. Skipping it.') |
4442 | +# continue |
4443 | +# ap['nettype'] = info[-1] |
4444 | +# ap['strength'] = info[1] |
4445 | +# if info[4 + offset] == 'WEP': |
4446 | +# ap['encryption_method'] = 'WEP' |
4447 | +# ap['enctype'] = 'WEP' |
4448 | +# ap['keyname'] = 'Key1' |
4449 | +# ap['authmode'] = info[5 + offset] |
4450 | +# elif info[5 + offset] in ['WPA-PSK', 'WPA']: |
4451 | +# ap['encryption_method'] = 'WPA' |
4452 | +# ap['authmode'] = "WPAPSK" |
4453 | +# ap['keyname'] = "WPAPSK" |
4454 | +# ap['enctype'] = info[4 + offset] |
4455 | +# elif info[5 + offset] == 'WPA2-PSK': |
4456 | +# ap['encryption_method'] = 'WPA2' |
4457 | +# ap['authmode'] = "WPA2PSK" |
4458 | +# ap['keyname'] = "WPA2PSK" |
4459 | +# ap['enctype'] = info[4 + offset] |
4460 | +# elif info[4 + offset] == "NONE": |
4461 | +# ap['encryption_method'] = None |
4462 | +# else: |
4463 | +# print("Unknown AuthMode, can't assign encryption_method!") |
4464 | +# ap['encryption_method'] = 'Unknown' |
4465 | +# aps[bssid] = ap |
4466 | +# if self.verbose: |
4467 | +# print(str(aps)) |
4468 | +# return aps |
4469 | + def _GetRalinkInfo(self): |
4470 | + iw_scan = misc.Run("iw dev " + self.iface + " scan") |
4471 | if self.verbose: |
4472 | - print(iwpriv) |
4473 | - lines = iwpriv.splitlines()[2:] |
4474 | + print(iw_scan) |
4475 | + |
4476 | aps = {} |
4477 | - patt = re.compile("((?:[0-9A-Z]{2}:){5}[0-9A-Z]{2})") |
4478 | - for x in lines: |
4479 | - ap = {} |
4480 | - info = x.split(" ") |
4481 | - info = [x.strip() for x in info if x.strip()] |
4482 | - if len(info) < 5: |
4483 | + bss_pattern = re.compile(r"BSS\s+([0-9A-Fa-f:]{17})") |
4484 | + ssid_pattern = re.compile(r"SSID:\s(.+)") |
4485 | + signal_pattern = re.compile(r"signal:\s(-?\d+)\s+dBm") |
4486 | + encryption_pattern = re.compile(r"(RSN|WEP|NONE)") |
4487 | + |
4488 | + current_bssid = None |
4489 | + for line in iw_scan.splitlines(): |
4490 | + line = line.strip() |
4491 | + |
4492 | + bssid_match = bss_pattern.match(line) |
4493 | + if bssid_match: |
4494 | + current_bssid = bssid_match.group(1).upper() |
4495 | + aps[current_bssid] = {"nettype": None, "strength": None, "encryption_method": None} |
4496 | continue |
4497 | - if re.match(patt, info[2].upper()): |
4498 | - bssid = info[2].upper() |
4499 | - offset = -1 |
4500 | - elif re.match(patt, info[3].upper()): |
4501 | - bssid = info[3].upper() |
4502 | - offset = 0 |
4503 | - else: # Invalid |
4504 | - print('Invalid iwpriv line. Skipping it.') |
4505 | + |
4506 | + if current_bssid is None: |
4507 | continue |
4508 | - ap['nettype'] = info[-1] |
4509 | - ap['strength'] = info[1] |
4510 | - if info[4 + offset] == 'WEP': |
4511 | - ap['encryption_method'] = 'WEP' |
4512 | - ap['enctype'] = 'WEP' |
4513 | - ap['keyname'] = 'Key1' |
4514 | - ap['authmode'] = info[5 + offset] |
4515 | - elif info[5 + offset] in ['WPA-PSK', 'WPA']: |
4516 | - ap['encryption_method'] = 'WPA' |
4517 | - ap['authmode'] = "WPAPSK" |
4518 | - ap['keyname'] = "WPAPSK" |
4519 | - ap['enctype'] = info[4 + offset] |
4520 | - elif info[5 + offset] == 'WPA2-PSK': |
4521 | - ap['encryption_method'] = 'WPA2' |
4522 | - ap['authmode'] = "WPA2PSK" |
4523 | - ap['keyname'] = "WPA2PSK" |
4524 | - ap['enctype'] = info[4 + offset] |
4525 | - elif info[4 + offset] == "NONE": |
4526 | - ap['encryption_method'] = None |
4527 | - else: |
4528 | - print("Unknown AuthMode, can't assign encryption_method!") |
4529 | - ap['encryption_method'] = 'Unknown' |
4530 | - aps[bssid] = ap |
4531 | + |
4532 | + ssid_match = ssid_pattern.match(line) |
4533 | + if ssid_match: |
4534 | + aps[current_bssid]["nettype"] = ssid_match.group(1) |
4535 | + continue |
4536 | + |
4537 | + signal_match = signal_pattern.match(line) |
4538 | + if signal_match: |
4539 | + aps[current_bssid]["strength"] = signal_match.group(1) |
4540 | + continue |
4541 | + |
4542 | + encryption_match = encryption_pattern.search(line) |
4543 | + if encryption_match: |
4544 | + encryption = encryption_match.group(1) |
4545 | + if encryption == "RSN": |
4546 | + aps[current_bssid]["encryption_method"] = "WPA2" |
4547 | + elif encryption == "WEP": |
4548 | + aps[current_bssid]["encryption_method"] = "WEP" |
4549 | + elif encryption == "NONE": |
4550 | + aps[current_bssid]["encryption_method"] = None |
4551 | + else: |
4552 | + aps[current_bssid]["encryption_method"] = "Unknown" |
4553 | + |
4554 | if self.verbose: |
4555 | print(str(aps)) |
4556 | return aps |
4557 | @@ -1149,15 +1288,34 @@ class BaseWirelessInterface(BaseInterface): |
4558 | |
4559 | """ |
4560 | mode = _sanitize_string_strict(mode) |
4561 | +# if not mode: |
4562 | +# mode = 'master' |
4563 | +# if mode.lower() == 'master': |
4564 | +# mode = 'managed' |
4565 | +# cmd = 'iwconfig %s mode %s' % (self.iface, mode) |
4566 | + |
4567 | if not mode: |
4568 | - mode = 'master' |
4569 | - if mode.lower() == 'master': |
4570 | + mode = '__ap' |
4571 | + if mode.lower() == '__ap': |
4572 | mode = 'managed' |
4573 | - cmd = 'iwconfig %s mode %s' % (self.iface, mode) |
4574 | + cmd = 'iw %s set type %s' % (self.iface, mode) |
4575 | if self.verbose: |
4576 | print(cmd) |
4577 | misc.Run(cmd) |
4578 | |
4579 | + @neediface("") |
4580 | + def GetMode(self, iwinfo=None): |
4581 | + if not iwinfo: |
4582 | + output = self.GetIwInfo() |
4583 | + else: |
4584 | + output = iwinfo |
4585 | + |
4586 | + opmode = misc.RunRegex(opmode_pattern, output) |
4587 | + if opmode: |
4588 | + opmode = opmode.strip() |
4589 | + return opmode |
4590 | + |
4591 | + |
4592 | @neediface(False) |
4593 | def SetChannel(self, channel): |
4594 | """ Set the channel of the wireless interface. |
4595 | @@ -1170,26 +1328,28 @@ class BaseWirelessInterface(BaseInterface): |
4596 | print('WARNING: Invalid channel found. Aborting!') |
4597 | return False |
4598 | |
4599 | - cmd = 'iwconfig %s channel %s' % (self.iface, str(channel)) |
4600 | +# cmd = 'iwconfig %s channel %s' % (self.iface, str(channel)) |
4601 | + cmd = 'iw %s set channel %s' % (self.iface, str(channel)) |
4602 | if self.verbose: |
4603 | print(cmd) |
4604 | misc.Run(cmd) |
4605 | |
4606 | @neediface(False) |
4607 | - def SetKey(self, key): |
4608 | + def SetKey(self, key, essid): |
4609 | """ Set the encryption key of the wireless interface. |
4610 | |
4611 | Keyword arguments: |
4612 | key -- encryption key to set |
4613 | |
4614 | """ |
4615 | - cmd = 'iwconfig %s key %s' % (self.iface, key) |
4616 | +# cmd = 'iwconfig %s key %s' % (self.iface, key) |
4617 | + cmd = 'iw %s connect %s key 0:%s' % (self.iface, essid, key) |
4618 | if self.verbose: |
4619 | print(cmd) |
4620 | misc.Run(cmd) |
4621 | |
4622 | @neediface(False) |
4623 | - def SetBitrate(self, bitrate, allow_lower=False): |
4624 | + def SetBitrate(self, bitrate, essid, freq): |
4625 | ''' Set the desired bitrate for the interface. |
4626 | |
4627 | Keyword arguments: |
4628 | @@ -1199,13 +1359,26 @@ class BaseWirelessInterface(BaseInterface): |
4629 | # FIXME: what if, in future, bitrates won't be "M(egabit per second)" |
4630 | #+anymore? |
4631 | if bitrate == 'auto': |
4632 | - cmd = 'iwconfig %s rate auto' |
4633 | +# cmd = 'iwconfig %s rate auto' % self.iface |
4634 | + pass |
4635 | else: |
4636 | - if allow_lower: |
4637 | - cmd = 'iwconfig %s rate %sM auto' % (self.iface, bitrate) |
4638 | - else: |
4639 | - cmd = 'iwconfig %s rate %sM fixed' % (self.iface, bitrate) |
4640 | - misc.Run(cmd) |
4641 | +# if allow_lower: |
4642 | +# cmd = 'iwconfig %s rate %sM auto' % (self.iface, bitrate) |
4643 | +# else: |
4644 | +# cmd = 'iwconfig %s rate %sM fixed' % (self.iface, bitrate) |
4645 | + bitrate_mode = "" |
4646 | + if freq: |
4647 | + freq = int(freq) |
4648 | + if freq >= 2412 and freq <= 2472: |
4649 | + bitrate_mode = "legacy-2.4" |
4650 | + elif freq >= 5180 and freq <= 5825: |
4651 | + bitrate_mode = "legacy-5" |
4652 | + |
4653 | + if bitrate_mode != "": |
4654 | + cmd = "iw %s set bitrates %s %s" % (self.iface, bitrate_mode, bitrate) |
4655 | + if self.verbose: |
4656 | + print(cmd) |
4657 | + misc.Run(cmd) |
4658 | |
4659 | @neediface(False) |
4660 | def Associate(self, essid, channel=None, bssid=None): |
4661 | @@ -1218,24 +1391,27 @@ class BaseWirelessInterface(BaseInterface): |
4662 | |
4663 | """ |
4664 | self.SetEssid(essid) |
4665 | - base = "iwconfig %s" % self.iface |
4666 | +# base = "iwconfig %s" % self.iface |
4667 | + base = "iw %s" % self.iface |
4668 | if channel and str(channel).isdigit(): |
4669 | - cmd = "%s channel %s" % (base, str(channel)) |
4670 | +# cmd = "%s channel %s" % (base, str(channel)) |
4671 | + cmd = "%s set channel %s" % (base, str(channel)) |
4672 | if self.verbose: |
4673 | print(cmd) |
4674 | misc.Run(cmd) |
4675 | if bssid: |
4676 | - cmd = "%s ap %s" % (base, bssid) |
4677 | +# cmd = "%s ap %s" % (base, bssid) |
4678 | + cmd = "%s connect %s %s" % (base, essid, bssid) |
4679 | if self.verbose: |
4680 | print(cmd) |
4681 | misc.Run(cmd) |
4682 | - |
4683 | + |
4684 | def GeneratePSK(self, network): |
4685 | - """ Generate a PSK using wpa_passphrase. |
4686 | + """ Generate a PSK using wpa_passphrase. |
4687 | |
4688 | Keyword arguments: |
4689 | network -- dictionary containing network info |
4690 | - |
4691 | + |
4692 | """ |
4693 | wpa_pass_path = misc.find_path('wpa_passphrase') |
4694 | if not wpa_pass_path: |
4695 | @@ -1271,46 +1447,83 @@ class BaseWirelessInterface(BaseInterface): |
4696 | print(cmd) |
4697 | misc.Run(cmd) |
4698 | |
4699 | - def _AuthenticateRalinkLegacy(self, network): |
4700 | - """ Authenticate with the specified wireless network. |
4701 | - |
4702 | - This function handles Ralink legacy cards that cannot use |
4703 | - wpa_supplicant. |
4704 | - |
4705 | - Keyword arguments: |
4706 | - network -- dictionary containing network info |
4707 | +# def _AuthenticateRalinkLegacy(self, network): |
4708 | +# """ Authenticate with the specified wireless network. |
4709 | +# |
4710 | +# This function handles Ralink legacy cards that cannot use |
4711 | +# wpa_supplicant. |
4712 | +# |
4713 | +# Keyword arguments: |
4714 | +# network -- dictionary containing network info |
4715 | +# |
4716 | +# """ |
4717 | +# if network.get('key') != None: |
4718 | +# try: |
4719 | +# info = self._GetRalinkInfo()[network.get('bssid')] |
4720 | +# except KeyError: |
4721 | +# print("Could not find current network in iwpriv " + \ |
4722 | +# "get_site_survey results. Cannot authenticate.") |
4723 | +# return |
4724 | +# |
4725 | +# if info['enctype'] == "WEP" and info['authtype'] == 'OPEN': |
4726 | +# print('Setting up WEP') |
4727 | +# cmd = ''.join(['iwconfig ', self.iface, ' key ', |
4728 | +# network.get('key')]) |
4729 | +# if self.verbose: |
4730 | +# print(cmd) |
4731 | +# misc.Run(cmd) |
4732 | +# else: |
4733 | +# cmd_list = [] |
4734 | +# cmd_list.append('NetworkType=' + info['nettype']) |
4735 | +# cmd_list.append('AuthMode=' + info['authmode']) |
4736 | +# cmd_list.append('EncrypType=' + info['enctype']) |
4737 | +# cmd_list.append('SSID="%s"' % network['essid']) |
4738 | +# cmd_list.append('%(keyname)s="%(key)s"' % network) |
4739 | +# if info['nettype'] == 'SHARED' and info['enctype'] == 'WEP': |
4740 | +# cmd_list.append('DefaultKeyID=1') |
4741 | +# |
4742 | +# for cmd in cmd_list: |
4743 | +# cmd = ['iwpriv', self.iface, 'set', cmd] |
4744 | +# if self.verbose: |
4745 | +# print(' '.join(cmd)) |
4746 | +# misc.Run(cmd) |
4747 | |
4748 | - """ |
4749 | - if network.get('key') != None: |
4750 | + def _AuthenticateRalinkLegacy(self, network): |
4751 | + if network.get('key') is not None: |
4752 | try: |
4753 | info = self._GetRalinkInfo()[network.get('bssid')] |
4754 | except KeyError: |
4755 | - print("Could not find current network in iwpriv " + \ |
4756 | - "get_site_survey results. Cannot authenticate.") |
4757 | + print("Could not find current network in iw scan results. Cannot authenticate.") |
4758 | return |
4759 | - |
4760 | - if info['enctype'] == "WEP" and info['authtype'] == 'OPEN': |
4761 | + |
4762 | + if info['enctype'] == "WEP" and info['authmode'] == 'OPEN': |
4763 | print('Setting up WEP') |
4764 | - cmd = ''.join(['iwconfig ', self.iface, ' key ', |
4765 | - network.get('key')]) |
4766 | + cmd = 'iw dev ', self.iface, ' connect ', network['essid'], ' key ', f'0:{network["key"]}' |
4767 | if self.verbose: |
4768 | print(cmd) |
4769 | + result = subprocess.run(cmd, capture_output=True, text=True) |
4770 | misc.Run(cmd) |
4771 | else: |
4772 | - cmd_list = [] |
4773 | - cmd_list.append('NetworkType=' + info['nettype']) |
4774 | - cmd_list.append('AuthMode=' + info['authmode']) |
4775 | - cmd_list.append('EncrypType=' + info['enctype']) |
4776 | - cmd_list.append('SSID="%s"' % network['essid']) |
4777 | - cmd_list.append('%(keyname)s="%(key)s"' % network) |
4778 | - if info['nettype'] == 'SHARED' and info['enctype'] == 'WEP': |
4779 | - cmd_list.append('DefaultKeyID=1') |
4780 | - |
4781 | - for cmd in cmd_list: |
4782 | - cmd = ['iwpriv', self.iface, 'set', cmd] |
4783 | - if self.verbose: |
4784 | - print(' '.join(cmd)) |
4785 | - misc.Run(cmd) |
4786 | + print('Setting up WPA/WPA2/WPA3') |
4787 | + wpa_supplicant_conf = f""" |
4788 | + network={{ |
4789 | + ssid="{network['essid']}" |
4790 | + psk="{network['key']}" |
4791 | + key_mgmt={info['authmode']} |
4792 | + pairwise={info['enctype']} |
4793 | + }} |
4794 | + """ |
4795 | + with tempfile.NamedTemporaryFile(delete=True) as temp_file: |
4796 | + conf_path = temp_file.name |
4797 | + temp_file.write(wpa_supplicant_conf.encode('utf-8')) |
4798 | + |
4799 | + if self.verbose: |
4800 | + print(f"WPA Supplicant Config:\n{wpa_supplicant_conf}") |
4801 | + |
4802 | + cmd = 'wpa_supplicant -i ', self.iface, ' -c ', conf_path, ' -B ' |
4803 | + if self.verbose: |
4804 | + print(cmd) |
4805 | + misc.Run(cmd) |
4806 | |
4807 | @neediface([]) |
4808 | def GetNetworks(self, essid=None): |
4809 | @@ -1339,6 +1552,12 @@ class BaseWirelessInterface(BaseInterface): |
4810 | # has an essid named Cell... |
4811 | networks = results.split( '\nBSS ' ) |
4812 | |
4813 | + # If the first element does not start with 'BSS ', add it |
4814 | + networks[0] = 'BSS ' + networks[0] if not networks[0].strip().startswith('BSS') else networks[0] |
4815 | + |
4816 | + # Add 'BSS ' to other elements |
4817 | + networks = [net if i == 0 else 'BSS ' + net for i, net in enumerate(networks)] |
4818 | + |
4819 | # Get available network info from iwpriv get_site_survey |
4820 | # if we're using a ralink card (needed to get encryption info) |
4821 | if self.wpa_driver == RALINK_DRIVER: |
4822 | @@ -1361,6 +1580,10 @@ class BaseWirelessInterface(BaseInterface): |
4823 | or not entry['hidden']): |
4824 | access_points[entry['bssid']] = entry |
4825 | |
4826 | + operating_mode = self.GetMode() |
4827 | + for ap in access_points.values(): |
4828 | + ap['operating_mode'] = operating_mode |
4829 | + |
4830 | return list(access_points.values()) |
4831 | |
4832 | def _ParseAccessPoint(self, cell, ralink_info): |
4833 | @@ -1415,6 +1638,9 @@ class BaseWirelessInterface(BaseInterface): |
4834 | else: |
4835 | ap['bitrates'] = None |
4836 | |
4837 | + # freq |
4838 | + ap['freq'] = misc.RunRegex(freq_pattern, cell) |
4839 | + |
4840 | # BSSID |
4841 | ap['bssid'] = misc.RunRegex(ap_mac_pattern, cell) |
4842 | |
4843 | @@ -1457,6 +1683,7 @@ class BaseWirelessInterface(BaseInterface): |
4844 | # Link Quality |
4845 | # Set strength to -1 if the quality is not found |
4846 | ap['quality'] = self._get_link_quality(cell) |
4847 | + |
4848 | # FIXME I got no idea what to grab on the "iw scan" |
4849 | if ap['quality'] is None: |
4850 | ap['quality'] = -1 |
4851 | @@ -1539,133 +1766,138 @@ class BaseWirelessInterface(BaseInterface): |
4852 | misc.Run(cmd) |
4853 | |
4854 | @neediface("") |
4855 | - def GetBSSID(self, iwconfig=None): |
4856 | + def GetBSSID(self, iwlink=None): |
4857 | """ Get the MAC address for the interface. """ |
4858 | - if not iwconfig: |
4859 | - output = self.GetIwconfig() |
4860 | + if not iwlink: |
4861 | + output = self.GetIwLink() |
4862 | else: |
4863 | - output = iwconfig |
4864 | - |
4865 | + output = iwlink |
4866 | + |
4867 | bssid = misc.RunRegex(bssid_pattern, output) |
4868 | return bssid |
4869 | |
4870 | @neediface("") |
4871 | - def GetCurrentBitrate(self, iwconfig=None): |
4872 | + def GetCurrentBitrate(self, iwlink=None): |
4873 | """ Get the current bitrate for the interface. """ |
4874 | - if not iwconfig: |
4875 | - output = self.GetIwconfig() |
4876 | + if not iwlink: |
4877 | + output = self.GetIwLink() |
4878 | else: |
4879 | - output = iwconfig |
4880 | - |
4881 | - bitrate = misc.RunRegex(bitrate_pattern, output) |
4882 | - return bitrate |
4883 | + output = iwlink |
4884 | + |
4885 | + freq = misc.RunRegex(txbitrate_pattern, output) |
4886 | + return freq |
4887 | |
4888 | @neediface("") |
4889 | - def GetOperationalMode(self, iwconfig=None): |
4890 | - """ Get the operational mode for the interface. """ |
4891 | - if not iwconfig: |
4892 | - output = self.GetIwconfig() |
4893 | + def GetCurrentFreq(self, iwlink=None): |
4894 | + """ Get the current bitrate for the interface. """ |
4895 | + if not iwlink: |
4896 | + output = self.GetIwLink() |
4897 | else: |
4898 | - output = iwconfig |
4899 | - |
4900 | - opmode = misc.RunRegex(opmode_pattern, output) |
4901 | - if opmode: |
4902 | - opmode = opmode.strip() |
4903 | - return opmode |
4904 | + output = iwlink |
4905 | + |
4906 | + freq = misc.RunRegex(freq_pattern, output) |
4907 | + return freq |
4908 | |
4909 | @neediface("") |
4910 | - def GetAvailableAuthMethods(self, iwlistauth=None): |
4911 | - """ Get the available authentication methods for the interface. """ |
4912 | - if not iwlistauth: |
4913 | - cmd = 'iwlist ' + self.iface + ' auth' |
4914 | - if self.verbose: |
4915 | - print(cmd) |
4916 | - output = misc.Run(cmd) |
4917 | - else: |
4918 | - output = iwlistauth |
4919 | - |
4920 | - authm = misc.RunRegex(authmethods_pattern, output) |
4921 | - authm_list = [m.strip() for m in authm.split('\n') if m.strip()] |
4922 | - return ';'.join(authm_list) |
4923 | + def GetOperationalMode(self, iwinfo=None): |
4924 | + """ Get the operational mode for the interface. """ |
4925 | + return self.GetMode(iwinfo) |
4926 | + |
4927 | +# @neediface("") |
4928 | +# def GetAvailableAuthMethods(self, iwlistauth=None): |
4929 | +# """ Get the available authentication methods for the interface. """ |
4930 | +# if not iwlistauth: |
4931 | +# cmd = 'iwlist ' + self.iface + ' auth' |
4932 | +# if self.verbose: |
4933 | +# print(cmd) |
4934 | +# output = misc.Run(cmd) |
4935 | +# else: |
4936 | +# output = iwlistauth |
4937 | +# |
4938 | +# authm = misc.RunRegex(authmethods_pattern, output) |
4939 | +# authm_list = [m.strip() for m in authm.split('\n') if m.strip()] |
4940 | +# return ';'.join(authm_list) |
4941 | |
4942 | @neediface('') |
4943 | def GetAvailableBitrates(self): |
4944 | - """ Get the available bitrates the wifi card can use. """ |
4945 | - |
4946 | - cmd = 'iwlist ' + self.iface + ' rate' |
4947 | - if self.verbose: |
4948 | - print(cmd) |
4949 | - rates = misc.Run(cmd) |
4950 | - |
4951 | - # process the output |
4952 | - rates = rates.split('\n') |
4953 | - rates = [x.strip().split(' ')[0] for x in rates] |
4954 | - rates = [x for x in rates if x and x[0].isdigit()] |
4955 | - return dbus.Array(rates, signature='v') |
4956 | + try: |
4957 | + cmd = "iw list" |
4958 | + if self.verbose: |
4959 | + print(cmd) |
4960 | + output = misc.Run(cmd) |
4961 | + pattern = r"Bitrates \(non-HT\):((?:\n\s+\*\s[\d.]+(?: Mbps)?(?: \(.*\))?)*)" |
4962 | + match = re.search(pattern, output) |
4963 | + if match: |
4964 | + bitrates_section = match.group(1) |
4965 | + bitrates = re.findall(r"\*\s([\d.]+)", bitrates_section) |
4966 | + return dbus.Array(bitrates, signature='v') |
4967 | + else: |
4968 | + return dbus.Array([], signature='v') |
4969 | + except Exception as e: |
4970 | + print(f"Error: {e}") |
4971 | + return dbus.Array([], signature='v') |
4972 | |
4973 | def _get_link_quality(self, output): |
4974 | """ Parse out the link quality from iwlist scan or iwconfig output. """ |
4975 | - try: |
4976 | - [(strength, max_strength)] = strength_pattern.findall(output) |
4977 | - except ValueError: |
4978 | - (strength, max_strength) = (None, None) |
4979 | + signal_dbm = misc.RunRegex(signaldbm_pattern, output) |
4980 | + if signal_dbm is None: |
4981 | + return 101 |
4982 | |
4983 | - if strength in ['', None]: |
4984 | - try: |
4985 | - [(strength, max_strength)] = altstrength_pattern.findall(output) |
4986 | - except ValueError: |
4987 | - # if the pattern was unable to match anything |
4988 | - # we'll return 101, which will allow us to stay |
4989 | - # connected even though we don't know the strength |
4990 | - # it also allows us to tell if |
4991 | - return 101 |
4992 | - if strength not in ['', None] and max_strength: |
4993 | - return (100 * int(strength) // int(max_strength)) |
4994 | - elif strength not in ["", None]: |
4995 | - return int(strength) |
4996 | - else: |
4997 | - return None |
4998 | + quality = self._convert_dbm_to_quality(float(signal_dbm)) |
4999 | + return quality |
5000 |
The diff has been truncated for viewing.