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