]> code.delx.au - gnu-emacs-elpa/blob - packages/enwc/enwc.el
multishell - merge code tidying, still on 1.0.8.
[gnu-emacs-elpa] / packages / enwc / enwc.el
1 ;;; enwc.el --- The Emacs Network Client
2
3 ;; Copyright (C) 2012,2013 Free Software Foundation, Inc.
4
5 ;; Author: Ian Dunn
6 ;; Keywords: enwc, network, wicd, manager, nm
7 ;; Version: 1.0
8
9 ;; This file is part of ENWC
10
11 ;; ENWC is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; any later version.
15
16 ;; ENWC is distributed in the hope that it will be useful, but WITHOUT
17 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 ;; License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with ENWC; see the file COPYING. If not, write to the Free
23 ;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 ;; 02110-1301, USA.
25
26 ;; connect
27 ;; disconnect
28 ;; scan
29 ;; get-prop
30 ;; save-profile
31 ;; get-networks
32 ;; check-connecting
33 ;; get-current-nw-id
34
35 ;;; Commentary:
36 ;; In order to use this, add
37 ;;
38 ;; (require 'enwc-setup)
39 ;; (enwc-setup)
40 ;;
41 ;; to your .emacs file.
42
43 (require 'dbus)
44 (require 'wid-edit)
45 (require 'tabulated-list)
46
47 ;;; Code:
48
49 (eval-when-compile
50 (require 'cl))
51
52 (defgroup enwc nil
53 "*The Emacs Network Client"
54 :prefix "ewnc-"
55 :group 'applications)
56
57 (defcustom enwc-wireless-device "wlan0"
58 "The wireless device to use for ENWC."
59 :group 'enwc
60 :type 'string)
61
62 (defcustom enwc-wired-device "eth0"
63 "The wired device to use for ENWC."
64 :group 'enwc
65 :type 'string)
66
67 (defcustom enwc-backends '(wicd nm)
68 "The list of backends to be used by ENWC.
69 These will be checked in the order designated here,
70 and the first active backend found will be used."
71 :group 'enwc
72 :type 'list)
73
74 ;;; The function variables for the abstract layer.
75
76 (defvar enwc-scan-func nil
77 "The function variable for the scan function.
78 This variable is set during setup.")
79
80 (defvar enwc-get-nw-func nil
81 "A function variable to be used in `enwc-get-nw'.
82 This is redefined during setup to be the function to get the network
83 list.")
84
85 (defvar enwc-get-wireless-nw-prop-func nil
86 "A function variable to be used in `enwc-get-wireless-nw-prop'.
87 This is redefined during setup to be the function to get
88 a wireless network property.")
89
90 (defvar enwc-get-wireless-nw-props-func nil)
91
92 (defvar enwc-get-encryption-type-func nil
93 "A function variable to be used in `enwc-get-encryption-type'.
94 This is redefined during setup to be the function to get the encryption
95 type for the selected backend.")
96
97 (defvar enwc-wireless-connect-func nil
98 "The function variable for the wireless connect function.
99 This is redefined during setup to be the function to connect
100 for the selected backend.")
101
102 (defvar enwc-get-current-nw-id-func nil
103 "The function variable to be used in `enwc-get-current-nw-id'.
104 This is redefined during setup to be the function to get
105 the current network id.")
106
107 (defvar enwc-check-connecting-func nil
108 "The function variable to be used in `enwc-check-connecting'.
109 This is redefined during setup to be the function to
110 check whether or not ENWC is connecting.")
111
112 (defvar enwc-wireless-disconnect-func nil
113 "The function variable for the wireless disconnect function.
114 This is redefined during setup to be the function to
115 disconnect from the wireless network.")
116
117 (defvar enwc-get-wired-profiles-func nil
118 "The function variable to be used in `enwc-get-wired-profiles'.
119 This is redefined during setup to be the function to
120 get the list of wired network profiles.")
121
122 (defvar enwc-wired-connect-func nil
123 "The function variable for the wired connect function.
124 This is redefined during setup to be the function
125 to connect to a wired network.")
126
127 (defvar enwc-wired-disconnect-func nil
128 "The function variable for the wired disconnect function.
129 This is redefined during setup to be the function
130 to disconnect from a wired network.")
131
132 (defvar enwc-is-wired-func nil
133 "The function variable to be used in `enwc-is-wired'.
134 This is redefined during setup to be the function to
135 check whether or not a wired connection is active.")
136
137 (defvar enwc-get-wired-nw-prop-func nil
138 "The function variable to be used in `enwc-get-wired-nw-prop'.
139 This is redefined during setup to be the function to get
140 a network property from a wired network.")
141
142 (defvar enwc-get-sec-types-func nil
143 "The function variable to be used in `enwc-get-sec-types'.
144 This is redefined during setup to be the function to get
145 the security types for a given network.")
146
147 (defvar enwc-get-ip-addr-func nil
148 "The function variable to be used in `enwc-get-ip-addr'.
149 This is redefined during setup to be the function to get
150 the IP Address of a given network.")
151
152 (defvar enwc-get-netmask-func nil
153 "The function variable to be used in `enwc-get-netmask'.
154 This is redefined during setup to be the function to get
155 the Netmask of a given network.")
156
157 (defvar enwc-get-gateway-func nil
158 "The function variable to be used in `enwc-get-gateway'.
159 This is redefined during setup to be the function to get
160 the Gateway of a given network.")
161
162 (defvar enwc-get-dns-func nil
163 "The function variable to be used in `enwc-get-dns'.
164 This is redefined during setup to be the function to get
165 the DNS Server Addresses for a given network.")
166
167 (defvar enwc-get-nw-info-func nil)
168
169 (defvar enwc-save-nw-settings-func nil
170 "The function variable to be used in `enwc-save-nw-settings'.
171 This is redefined during setup to be the function to save
172 the network settings of a given network.")
173
174 (defvar enwc-details-list nil
175 "The network details list.
176
177 This is redefined during setup to be the details list
178 for the selected backend.
179
180 This usually includes signal strength, essid, encryption type,
181 bssid, mode, and channel.")
182
183 (defvar enwc-display-string " [0%] "
184 "The mode line display string.
185 This is altered every second to display the current network strength
186 in `enwc-update-mode-line'.")
187
188 ;; (setq tabulated-list-format (vector `("ID" ,enwc-id-width sort) ...))
189 ;; (setq tabulated-list-entries `((,id [id str essid encrypt ...]) ...))
190 ;; (tabulated-list-init-header)
191 ;; (tabulated-list-print)
192
193 (defvar enwc-wireless-headers '("ID" "STR" "ESSID"
194 "ENCRYPT" "BSSID" "MODE" "CHNL")
195 "The list of headers to be displayed in the ENWC buffer.
196 These correspond to the details in `enwc-details-list'.")
197
198 (defvar enwc-id-width 3
199 "The width of the id column.")
200 (defvar enwc-str-width 5
201 "The width of the strength column.")
202 (defvar enwc-essid-width 5
203 "The initial width of the essid column.
204 This is reset in wicd-scan-internal.")
205 (defvar enwc-encrypt-width 10
206 "The width of the encryption column.")
207 (defvar enwc-bssid-width 18
208 "The width of the bssid column.")
209 (defvar enwc-mode-width 16
210 "The width of the mode column.")
211 (defvar enwc-chnl-width 3
212 "The width of the channel column.")
213
214 (defvar enwc-last-scan nil
215 "The most recent scan results.")
216
217 (defvar enwc-access-points nil
218 "The most recent access point list.")
219
220 (defvar enwc-using-wired nil
221 "Whether or not wired mode is active.
222
223 This is `non-NIL' if ENWC is using wired connections.
224 Note that this is NOT the same as `enwc-is-wired'. This checks
225 whether or not ENWC is in wired mode.")
226
227 (defvar enwc-scan-done nil
228 "Whether or not a scan is finished.")
229
230 (defvar enwc-edit-id nil
231 "This is the network id of the network being edited.")
232
233 (defvar enwc-scan-requested nil)
234
235 (defvar enwc-scan-interactive nil)
236
237 (make-local-variable 'enwc-edit-id)
238 ;; The Fonts
239
240 (defface enwc-header-face
241 '((((class color) (background light))
242 (:foreground "Blue"))
243 (((class color) (background dark))
244 (:foreground "Blue"))
245 (t (:background "Blue")))
246 "The face for the headers."
247 :group 'enwc)
248
249 (defface enwc-connected-face
250 '((((class color) (background dark))
251 (:foreground "Green"))
252 (((class color) (background light))
253 (:foreground "Green"))
254 (t (:background "Green")))
255 "The face for the connected network."
256 :group 'enwc)
257
258
259 ;; Small helper function.
260
261 (defun enwc-detail-to-ident (detail)
262 "Converts detail DETAIL to a constant identifier."
263 (case (intern detail)
264 ((essid Ssid) "essid")
265 ((bssid HwAddress) "bssid")
266 ((quality Strength) "quality")
267 ((encryption Flags) "encryption")
268 ((mode Mode) "mode")
269 ((channel Frequency) "channel")))
270
271 ;;;;;;;;;;;;;;;;;;;;
272 ;; ENWC functions
273 ;;;;;;;;;;;;;;;;;;;;
274
275 (defun enwc-do-scan ()
276 "Runs a backend scan."
277 (funcall enwc-scan-func))
278
279 (defun enwc-get-nw ()
280 "Gets the identifiers for the access points
281 from a previous scan."
282 (funcall enwc-get-nw-func))
283
284 (defun enwc-get-current-nw-id ()
285 "Gets the id of the current network id,
286 or `nil' if there isn't one."
287 (funcall enwc-get-current-nw-id-func enwc-using-wired))
288
289 (defun enwc-check-connecting-p ()
290 "Checks to see if there is a connection
291 in progress. Returns `non-NIL' if there is one,
292 `NIL' otherwise."
293 (funcall enwc-check-connecting-func))
294
295 (defun enwc-get-wireless-nw-prop (id prop)
296 "Gets property PROP from wireless network with id
297 ID and returns it."
298 (funcall enwc-get-wireless-nw-prop-func id prop))
299
300 (defun enwc-get-wireless-nw-props (id)
301 (funcall enwc-get-wireless-nw-props-func id))
302
303 (defun enwc-get-encryption-type (id)
304 "Gets the encryption type used by the wireless
305 network with id ID."
306 (funcall enwc-get-encryption-type-func id))
307
308 (defun enwc-get-wired-profiles ()
309 "Gets the list of wired profiles."
310 (funcall enwc-get-wired-profiles-func))
311
312 (defun enwc-wireless-connect (id)
313 "Begins a connection to wireless network with
314 id ID."
315 (funcall enwc-wireless-connect-func id))
316
317 (defun enwc-wireless-disconnect ()
318 "Disconnects the wireless."
319 (funcall enwc-wireless-disconnect-func))
320
321 (defun enwc-wired-connect (id)
322 "Connects to the wired profile with id ID."
323 (funcall enwc-wired-connect-func id))
324
325 (defun enwc-wired-disconnect ()
326 "Disconnects from the current network."
327 (funcall enwc-wired-disconnect-func))
328
329 (defun enwc-is-wired-p ()
330 "Checks whether or not ENWC is connected to
331 a wired network.
332 Note that this is NOT the same as `enwc-using-wired'.
333 This checks for an active wired connection."
334 (funcall enwc-is-wired-func))
335
336 (defun enwc-get-sec-types (wired)
337 "Gets the security types for network.
338 WIRED is set to indicate whether or not this is
339 a wired network."
340 (funcall enwc-get-sec-types-func wired))
341
342 (defun enwc-get-network-ent (wired id ent)
343 "Gets network entry ENT from the network with network id ID.
344 WIRED is set to indicate whether or not this is
345 a wired network."
346 (if wired
347 nil
348 (enwc-get-wireless-nw-prop id ent)))
349
350 (defun enwc-get-wired-nw-prop (id prop)
351 "Gets network property PROP from
352 the wired network with network id ID."
353 (funcall enwc-get-wired-nw-prop-func id prop))
354
355 (defun enwc-get-ip-addr (wired id)
356 "Gets the IP Address from the network with network id ID.
357 WIRED is set to indicate whether or not this is
358 a wired network."
359 (funcall enwc-get-ip-addr-func wired id))
360
361 (defun enwc-get-netmask (wired id)
362 "Gets the Netmask from the network with network id ID.
363 WIRED is set to indicate whether or not this is
364 a wired network."
365 (funcall enwc-get-netmask-func wired id))
366
367 (defun enwc-get-gateway (wired id)
368 "Gets the Gateway from the network with network id ID.
369 WIRED is set to indicate whether or not this is
370 a wired network."
371 (funcall enwc-get-gateway-func wired id))
372
373 (defun enwc-get-dns (wired id)
374 "Gets the DNS Servers from the network with network id ID.
375 WIRED is set to indicate whether or not this is
376 a wired network."
377 (funcall enwc-get-dns-func wired id))
378
379 (defun enwc-get-nw-info (wired id)
380 (funcall enwc-get-nw-info-func wired id))
381
382 (defun enwc-save-nw-settings (wired id settings)
383 "Saves network settings SETTINGS to the network profile with
384 network id ID.
385 SETTINGS is an association list with entries for the IP Address,
386 Netmask, Gateway, DNS Servers, and Security.
387 WIRED is set to indicate whether or not this is
388 a wired network."
389 (funcall enwc-save-nw-settings-func wired id settings))
390
391 ;;;;;;;;;;;;;;;;;;;;;
392 ;; Actual Functions
393 ;;;;;;;;;;;;;;;;;;;;;
394
395 (defun enwc-is-valid-nw-id (id)
396 "Confirms that ID is a valid network id."
397 (<= 0 id))
398
399 (defun enwc-get-nw-prop (wired id prop)
400 "Small function to get network property PROP from the network
401 with network id ID.
402 WIRED indicates whether or not this is a wired connection."
403 (if wired
404 (enwc-get-wired-nw-prop id prop)
405 (enwc-get-wireless-nw-prop id prop)))
406
407 (defun enwc-update-mode-line ()
408 "Updates the mode line with the current network strength.
409 If no network is connected, then prints 0%.
410 If wired is active, then prints 100%.
411 If ENWC is in the process of connecting, then prints *%.
412 This is initiated during setup, and runs once every second."
413 (let ((cur-id (enwc-get-current-nw-id))
414 (conn (enwc-check-connecting-p))
415 str)
416 (setq str
417 (if (enwc-is-wired-p)
418 100
419 (if (and
420 (enwc-is-valid-nw-id cur-id)
421 enwc-last-scan)
422 (cdr (assoc "quality" (nth cur-id enwc-last-scan)))
423 0)))
424 (setq enwc-display-string (concat " ["
425 (if conn
426 "*"
427 (number-to-string str))
428 "%] "))))
429
430 ;;;;;;;;;;;;;;;;;;
431 ;; Scan internal
432 ;;;;;;;;;;;;;;;;;;
433
434 (defun enwc-scan-internal-wireless ()
435 "The initial scan routine.
436 This initiates a scan using D-Bus, then exits,
437 waiting for the callback."
438 (message "Scanning...")
439 (setq enwc-scan-requested t)
440 (setq enwc-scan-done nil)
441 (enwc-do-scan))
442
443 (defun enwc-process-scan (&rest args)
444 "The scanning callback.
445 After a scan has been performed, this processes and displays
446 the scan results."
447 (if (or enwc-using-wired (not enwc-scan-requested))
448 nil
449 (setq enwc-scan-requested nil)
450 (let ((cur-id 0))
451 (message "Scanning... Done")
452 (setq enwc-access-points (enwc-get-nw)
453 enwc-essid-width 5)
454 (setq enwc-last-scan
455 (mapcar (lambda (x)
456 (let ((ret-itm (cons (cons "id" cur-id) nil))
457 (prop-list (enwc-get-wireless-nw-props x)))
458 (setq cur-id (1+ cur-id))
459 (dolist (det enwc-details-list)
460 (let ((cur-item (cdr (assoc det prop-list)))
461 (ident (enwc-detail-to-ident det))
462 pos-len)
463 (if (string= ident "essid")
464 (progn
465 (setq pos-len (length cur-item))
466 (setq enwc-essid-width
467 (max enwc-essid-width
468 pos-len))))
469 (if (string= ident "encryption")
470 (setq cur-item
471 (if cur-item
472 (enwc-get-encryption-type x)
473 "Unsecured")))
474 (setq ret-itm (append ret-itm
475 (cons (cons ident
476 cur-item)
477 nil)))))
478 ret-itm))
479 (number-sequence 0 (1- (length enwc-access-points))))))
480 (setq enwc-essid-width (1+ enwc-essid-width))
481 (setq enwc-scan-done t)
482 (if enwc-scan-interactive
483 (progn
484 (enwc-display-wireless-networks enwc-last-scan)
485 ;;(goto-char 0)
486 ;;(forward-line)
487 ))))
488
489 (defun enwc-scan-internal-wired ()
490 "The scanning routine for a wired connection.
491 This gets the list of wired network profiles."
492 (message "Updating Profiles...")
493 (let ((profs (enwc-get-wired-profiles))
494 cur-prof fin-profs)
495 (while profs
496 (setq cur-prof (pop profs))
497 (if cur-prof
498 (setq fin-profs (cons cur-prof
499 fin-profs))))
500 (message "Updating Profiles... Done")
501 (setq enwc-access-points fin-profs)
502 (setq enwc-last-scan fin-profs)
503 fin-profs))
504
505 (defun enwc-scan-internal ()
506 "The entry point for the internal scan routines.
507 This checks whether or not wired is being used,
508 and runs the appropriate function."
509 (if enwc-using-wired
510 (enwc-scan-internal-wired)
511 (enwc-scan-internal-wireless)))
512
513 ;;;;;;;;;;;;;;;;;;;;;
514 ;; Display Networks
515 ;;;;;;;;;;;;;;;;;;;;;
516
517 (defun enwc-display-wired-networks (networks)
518 "Displays the wired networks specified in the list NETWORKS.
519 NETWORKS must be in the form returned from
520 `enwc-scan-internal-wired'."
521 (if (not (listp networks))
522 (error "NETWORKS must be a list of networks."))
523 (let ((inhibit-read-only t))
524 (erase-buffer)
525 (insert (propertize "Profile" 'face 'enwc-header-face))
526 (insert "\n")
527 (dolist (pr networks)
528 (insert pr)
529 (insert "\n"))))
530
531 (defun enwc-insert-ent (ent width)
532 "Small function to insert a network property entry.
533 ENT is the entry, and WIDTH is the column width."
534 (insert ent)
535 (insert-char 32 (- width (length ent))))
536
537 (defun enwc-display-wireless-networks (networks)
538 "Displays the networks in the list NETWORKS in the current buffer.
539 NETWORKS must be in the format returned by
540 `enwc-scan-internal-wireless'."
541 (if (not (eq major-mode 'enwc-mode))
542 (enwc-setup-buffer))
543 (if (not (listp networks))
544 (error "NETWORKS must be a list of association lists."))
545 (let (;;(inhibit-read-only t)
546 (cur-id (enwc-get-current-nw-id))
547 entries)
548 ;;(erase-buffer)
549 (let ((header enwc-wireless-headers)
550 (pos 0))
551
552 (setq tabulated-list-format
553 (vector '("ID" 2)
554 '("STR" 4)
555 `("ESSID" ,enwc-essid-width)
556 '("ENCRYPT" 9)
557 '("BSSID" 17)
558 '("MODE" 15)
559 '("CHNL" 2)))
560
561 ;; (dolist (hd header)
562 ;; (insert (propertize hd 'face 'enwc-header-face))
563 ;; (setq pos (length hd))
564 ;; (insert-char 32 (- (symbol-value (intern (concat "enwc-"
565 ;; (downcase hd)
566 ;; "-width")))
567 ;; pos)))
568 )
569 ;;(insert "\n")
570
571 ;;TODO: Setup faces.
572 (dolist (nw networks)
573 (let ((id (cdr (assoc "id" nw)))
574 entry)
575 (setq entry (list nil
576 (vector
577 (number-to-string (cdr (assoc "id" nw)))
578 (concat (number-to-string (cdr (assoc "quality" nw)))
579 "%")
580 (cdr (assoc "essid" nw))
581 (cdr (assoc "encryption" nw))
582 (cdr (assoc "bssid" nw))
583 (cdr (assoc "mode" nw))
584 (cdr (assoc "channel" nw)))))
585 (setq entries (cons entry entries))))
586
587 (setq tabulated-list-entries (nreverse entries))
588 (tabulated-list-init-header)
589
590 ;; (dolist (nw networks)
591 ;; (let* ((id (propertize (number-to-string (cdr (assoc "id" nw)))
592 ;; 'width enwc-id-width))
593 ;; (str (propertize (concat (number-to-string (cdr (assoc "quality"
594 ;; nw)))
595 ;; "%")
596 ;; 'width enwc-str-width))
597 ;; (essid (propertize (cdr (assoc "essid" nw))
598 ;; 'width enwc-essid-width))
599 ;; (encrypt (propertize (cdr (assoc "encryption" nw))
600 ;; 'width enwc-encrypt-width))
601 ;; (bssid (propertize (cdr (assoc "bssid" nw))
602 ;; 'width enwc-bssid-width))
603 ;; (mode (propertize (cdr (assoc "mode" nw))
604 ;; 'width enwc-mode-width))
605 ;; (chnl (propertize (cdr (assoc "channel" nw))
606 ;; 'width enwc-chnl-width))
607 ;; props)
608
609 ;; (setq props (list id str essid encrypt bssid mode chnl))
610
611 ;; (dolist (ent props)
612 ;; (if (eq (string-to-number id) cur-id)
613 ;; (setq ent (propertize ent 'face 'enwc-connected-face)))
614 ;; (enwc-insert-ent ent (get-text-property 0 'width ent)))
615 ;; (insert "\n")))
616 (tabulated-list-print)
617 ))
618
619 (defun enwc-display-networks (networks)
620 "Displays the network in NETWORKS. This is an entry to the display
621 functions, and checks whether or not ENWC is using wired."
622 (if (not (eq major-mode 'enwc-mode))
623 (enwc-setup-buffer))
624 (if (not (listp networks))
625 (error "NETWORKS must be a list."))
626 (if enwc-using-wired
627 (enwc-display-wired-networks networks)
628 (enwc-display-wireless-networks networks)))
629
630 (defun enwc-scan ()
631 "The frontend of the scanning routine. Sets up and moves to
632 the ENWC buffer if necessary, and scans and displays the networks."
633 (interactive)
634 (setq enwc-scan-interactive t)
635 (if (not (eq major-mode 'enwc-mode))
636 (switch-to-buffer "*ENWC*"))
637 (if enwc-using-wired
638 (progn
639 (enwc-scan-internal)
640 ;;(enwc-display-networks enwc-last-scan)
641 (goto-char 0)
642 (forward-line))
643 (enwc-scan-internal)))
644
645 (defun enwc-find-network (essid &optional networks)
646 "Checks through NETWORKS for the network with essid ESSID,
647 and returns the network identifier. Uses `enwc-last-scan' if
648 NETWORKS is nil. If the network is not found, then it returns nil.
649
650 When called interactively, this only prints out what it finds.
651 Otherwise, it actually returns it."
652 (interactive "sNetwork ESSID: ")
653 (if (not (or networks enwc-last-scan))
654 (progn
655 (setq enwc-scan-interactive nil)
656 (enwc-scan-internal)))
657 (let ((nets (or networks enwc-last-scan))
658 need-break cur-net)
659 (if (not nets)
660 (setq nets enwc-last-scan))
661 (while (and nets (not need-break))
662 (let (cur-essid)
663 (setq cur-net (pop nets))
664 (setq cur-essid (cdr (assoc "essid" cur-net)))
665 (if (string= cur-essid essid)
666 (setq need-break t))))
667 (if need-break
668 (if (called-interactively-p 'any)
669 (message (number-to-string (cdr (assoc "id" cur-net))))
670 (cdr (assoc "id" cur-net)))
671 (if (called-interactively-p 'any)
672 (message "Network not found.")
673 nil))))
674
675 ;;;;;;;;;;;;;;;;;;;;
676 ;; Connect Network
677 ;;;;;;;;;;;;;;;;;;;;
678
679 (defun enwc-connect-network (id)
680 "Connect to network with id ID.
681 This is an entry point for the internal connection functions,
682 and checks whether or not ENWC is using wired."
683 (let (cur-net)
684 (if enwc-using-wired
685 (progn
686 (enwc-wired-connect id)
687 (setq cur-net (nth id (enwc-get-wired-profiles))))
688 (enwc-wireless-connect id)
689 (if enwc-last-scan
690 (setq cur-net (cdr (assoc "essid" (nth id enwc-last-scan)))))
691 cur-net)))
692
693 (defun enwc-connect-to-network (net-id)
694 "Connects the the network with network id NET-ID.
695 Confirms that NET-ID is a valid network id.
696 This calls `enwc-connect-network' as a subroutine."
697 (interactive "nNetwork ID: ")
698 (if (not (numberp net-id))
699 (error "NET-ID must be a number"))
700 (let ((num-ids (length enwc-last-scan))
701 cur-net)
702 (if (or (< net-id 0) (>= net-id num-ids))
703 (error "Invalid network id."))
704 (setq cur-net (enwc-connect-network net-id))
705 (message (concat "Connecting to " cur-net))))
706
707 (defun enwc-connect-to-network-essid (essid)
708 "Connects to the network with essid ESSID."
709 (interactive "sNetwork ESSID: ")
710 (let ((net-id (enwc-find-network essid)))
711 (if net-id
712 (enwc-connect-to-network net-id)
713 (message "Network not found."))))
714
715 (defun enwc-connect-to-network-at-point ()
716 "Connects to the network at the current line number.
717 Moves to the enwc buffer if necessary."
718 (interactive)
719 (if (not (eq major-mode 'enwc-mode))
720 (enwc-setup-buffer))
721 (let ((id (- (line-number-at-pos) 1)))
722 (enwc-connect-to-network id)))
723
724 (defun enwc-disconnect ()
725 "Disconnects from the network, if any."
726 (interactive)
727 (if (not (eq major-mode 'enwc-mode))
728 (enwc-setup-buffer))
729 (if enwc-using-wired
730 (enwc-wired-disconnect)
731 (enwc-wireless-disconnect)))
732
733 (defun enwc-toggle-wired ()
734 "Toggle the display and mode between wireless and wired.
735 This function also sets the variable `enwc-using-wired'."
736 (interactive)
737 (if (not (eq major-mode 'enwc-mode))
738 (enwc-setup-buffer))
739 (let ((inhibit-read-only t))
740 (erase-buffer)
741 (setq enwc-using-wired (not enwc-using-wired))
742 (enwc-scan)))
743
744 (defun enwc ()
745 "The main front-end to ENWC.
746 This sets up the buffer and scans for networks.
747 In order to use this, one must have already run
748 `enwc-setup'.
749
750 \\{enwc-mode-map}"
751 (interactive)
752 (enwc-setup-buffer)
753 (enwc-scan))
754
755 ;; Settings for access point AP
756 ;;
757 ;; IPv4 Settings:
758 ;; Address =
759 ;; Netmask =
760 ;; Gateway =
761 ;;
762 ;; DNS 1 =
763 ;; DNS 2 =
764 ;;
765 ;; Security:
766 ;; Type =
767 ;;
768
769 (defun enwc-edit-view-entry ()
770 "View the text of the entry at point.
771 This is mostly useful to view the text of the hidden entries."
772 (interactive)
773 (if (not (get-buffer "*ENWC Edit*"))
774 (error "Not editing a network entry."))
775 (if (not (eq (current-buffer) (get-buffer "*ENWC Edit*")))
776 (switch-to-buffer "*ENWC Edit*"))
777 (if (not (widget-at))
778 (error "No widget at point"))
779 (message (widget-field-value-get (widget-at))))
780
781 (defun enwc-display-sec-reqs (widget &rest stuff)
782 "Display the security requirements.
783 This is a callback to the security selection widget.
784 WIDGET is always the menu drop-down of security types."
785 (let (reqs
786 (inhibit-read-only t)
787 type-wid-list)
788 ;; First, erase any of the old ones.
789 (goto-char (1+ (widget-get widget :to)))
790 (widget-forward 1)
791 (while (>= (point) (widget-get widget :to))
792 (widget-delete (widget-at))
793 (widget-forward 1))
794 (goto-char (point-max))
795 ;; Then check to see if widget-value is None
796 (if (string= (widget-value widget) "None")
797 nil
798 (setq type-wid-list
799 (cadr (assoc "reqs"
800 (cdr (assoc (widget-value widget)
801 (enwc-get-sec-types enwc-using-wired))))))
802 (setq reqs
803 (mapcar (lambda (x)
804 (if (not (eq (length (cdr x)) 0))
805 (widget-create 'editable-field
806 :format (concat " "
807 (cdr x)
808 ": %v")
809 :secret ?*
810 :keymap 'enwc-edit-field-map
811 :value (or (enwc-get-nw-prop enwc-using-wired
812 enwc-edit-id
813 (car x))
814 ""))))
815 type-wid-list))
816 (widget-setup)
817 reqs)))
818
819 (defun enwc-setup-edit-buffer ()
820 "Setup the edit buffer. This removes the old one if neccessary,
821 and redisplays the settings from the network profile
822 with id `enwc-edit-id', which is set in `enwc-edit-entry-at-point'."
823 (if (get-buffer "*ENWC Edit*")
824 (kill-buffer "*ENWC Edit*"))
825 (with-current-buffer (get-buffer-create "*ENWC Edit*")
826 (let ((sec-types (enwc-get-sec-types enwc-using-wired))
827 (nw-info (enwc-get-nw-info enwc-using-wired enwc-edit-id))
828 ip-addr netmask gateway dns-1 dns-2
829 addr-wid net-wid gate-wid
830 dns-1-wid dns-2-wid dns-list
831 type-wid type-wid-list)
832
833 (widget-insert (concat "Settings for access point "
834 (cdr (assoc "essid"
835 (nth enwc-edit-id
836 enwc-last-scan)))
837 "\n"))
838 (widget-insert "\n")
839 ;; ip
840 (widget-insert "IPv4 Settings:\n")
841 (setq addr-wid (widget-create 'editable-field
842 :format " Address: %v"
843 :value (or (assoc "addr" nw-info) "")))
844 ;; netmask
845 (setq net-wid (widget-create 'editable-field
846 :format " Netmask: %v"
847 :value (or (assoc "netmask" nw-info) "")))
848
849 ;; gateway
850 (setq gate-wid (widget-create 'editable-field
851 :format " Gateway: %v"
852 :value (or (assoc "gateway" nw-info) "")))
853 ;; dns1
854 (widget-insert "\n")
855 ;;(setq dns-list (enwc-get-dns enwc-using-wired enwc-edit-id))
856 (setq dns-1-wid (widget-create 'editable-field
857 :format " DNS 1: %v"
858 :value (or (assoc "dns1" nw-info) "")))
859
860 ;; dns2
861 (setq dns-2-wid (widget-create 'editable-field
862 :format " DNS 2: %v"
863 :value (or (assoc "dns2" nw-info) "")))
864
865 (widget-insert "\n")
866 (widget-insert "Security:\n")
867 (setq type-wid (apply 'widget-create
868 'menu-choice
869 :tag "Type "
870 :value (or (assoc "enctype" nw-info) "None")
871 :notify 'enwc-display-sec-reqs
872 '(item :tag "No Encryption"
873 :value "None")
874 (mapcar (lambda (x)
875 `(item :format "%t\n"
876 :value ,(car x)
877 :tag ,(cdr (assoc "Name" (cdr x)))))
878 sec-types)))
879 (enwc-display-sec-reqs type-wid)
880 (use-local-map enwc-edit-map)
881 (widget-setup)))
882
883 (switch-to-buffer "*ENWC Edit*"))
884
885 (defun enwc-edit-save ()
886 "Save the network settings."
887 ;; Basically, just iterate through the widgets,
888 ;; retrieving values from each.
889 (interactive)
890 (if (not (get-buffer "*ENWC Edit*"))
891 (error "Not editing a network entry."))
892 (if (not (eq (current-buffer) (get-buffer "*ENWC Edit*")))
893 (switch-to-buffer "*ENWC Edit*"))
894 (goto-char 0)
895 (let (settings start-pos type-wid-list)
896
897 (widget-forward 1)
898 (setq settings
899 (append settings
900 (cons (cons "addr"
901 (widget-field-value-get (widget-at)))
902 nil)))
903 (widget-forward 1)
904 (setq settings
905 (append settings
906 (cons (cons "netmask"
907 (widget-field-value-get (widget-at)))
908 nil)))
909 (widget-forward 1)
910 (setq settings
911 (append settings
912 (cons (cons "gateway"
913 (widget-field-value-get (widget-at)))
914 nil)))
915 (widget-forward 1)
916 (setq settings
917 (append settings
918 (cons (cons "dns1"
919 (widget-field-value-get (widget-at)))
920 nil)))
921 (widget-forward 1)
922 (setq settings
923 (append settings
924 (cons (cons "dns2"
925 (widget-field-value-get (widget-at)))
926 nil)))
927 (widget-forward 1)
928 (setq settings
929 (append settings
930 (cons (cons "enctype"
931 (widget-value (widget-at)))
932 nil)))
933 (setq start-pos (widget-get (widget-at) :to))
934 (if (not (string= (widget-value (widget-at)) "None"))
935 (setq type-wid-list
936 (cadr (assoc "reqs"
937 (cdr (assoc (widget-value (widget-at))
938 (enwc-get-sec-types enwc-using-wired)))))))
939 (dolist (x type-wid-list)
940 (widget-forward 1)
941 (if (not (string= (widget-field-value-get (widget-at)) ""))
942 (setq settings
943 (append settings
944 (cons (cons (car x)
945 (widget-field-value-get (widget-at)))
946 nil)))))
947 (print settings)
948
949 (enwc-save-nw-settings enwc-using-wired enwc-edit-id settings)))
950
951 (defun enwc-edit-entry-at-point ()
952 "Edit the current network entry."
953 (interactive)
954 (setq enwc-edit-id (- (line-number-at-pos) 1))
955 (select-window (split-window))
956 (enwc-setup-edit-buffer))
957
958 (defvar enwc-mode-map
959 (let ((map (make-sparse-keymap)))
960 (define-key map (kbd "R") 'enwc-scan)
961 (define-key map (kbd "C") 'enwc-connect-to-network-essid)
962 (define-key map (kbd "D") 'enwc-disconnect)
963 (define-key map (kbd "W") 'enwc-toggle-wired)
964 (define-key map (kbd "E") 'enwc-edit-entry-at-point)
965 (define-key map (kbd "RET") 'enwc-connect-to-network-at-point)
966 map)
967 "The keymap for network display in ENWC.")
968
969 (defvar enwc-edit-map
970 (let ((map (copy-keymap widget-keymap)))
971 (define-key map (kbd "C-x C-s") 'enwc-edit-save)
972 map)
973 "The keymap for editing network profiles with ENWC.")
974
975 (defvar enwc-edit-field-map
976 (let ((map (copy-keymap widget-field-keymap)))
977 (define-key map (kbd "C-x C-a") 'enwc-edit-view-entry)
978 map)
979 "The keymap for editable fields within the ENWC edit buffer.")
980
981 (define-derived-mode enwc-mode tabulated-list-mode "enwc"
982 "Mode for working with network connections.
983 \\{enwc-mode-map}"
984 ;;(setq buffer-read-only t)
985 (add-hook 'tabulated-list-revert-hook 'enwc-scan nil t)
986 )
987
988 (defun enwc-setup-buffer ()
989 "Sets up the ENWC buffer.
990 This first checks to see that it exists,
991 and if it doesn't, then create it."
992 (if (not (get-buffer "*ENWC*"))
993 (with-current-buffer (get-buffer-create "*ENWC*")
994 ;;(use-local-map enwc-mode-map)
995 ;;(setq major-mode 'enwc-mode
996 ;; mode-name "enwc")
997 (enwc-mode)
998 ;;(setq buffer-read-only t)
999 ))
1000 (switch-to-buffer "*ENWC*"))
1001
1002 (provide 'enwc)
1003
1004 ;;; enwc.el ends here