X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/8973bd8b49ff3f383645921dfaa7ce71abc9a91f..2c0f29abb2928f672043cf97d689770bd2265064:/packages/enwc/enwc.el diff --git a/packages/enwc/enwc.el b/packages/enwc/enwc.el new file mode 100644 index 000000000..a131516c1 --- /dev/null +++ b/packages/enwc/enwc.el @@ -0,0 +1,1003 @@ +;;; enwc.el --- The Emacs Network Client + +;; Copyright (C) 2012,2013 Free Software Foundation + +;; Author: Ian Dunn +;; Keywords: enwc, network, wicd, manager, nm + +;; This file is part of ENWC + +;; ENWC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; ENWC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with ENWC; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +;; 02110-1301, USA. + +;; connect +;; disconnect +;; scan +;; get-prop +;; save-profile +;; get-networks +;; check-connecting +;; get-current-nw-id + +;;; Commentary: +;; In order to use this, add +;; +;; (require 'enwc-setup) +;; (enwc-setup) +;; +;; to your .emacs file. + +(require 'dbus) +(require 'wid-edit) +(require 'tabulated-list) + +;;; Code: + +(eval-when-compile + (require 'cl)) + +(defgroup enwc nil + "*The Emacs Network Client" + :prefix "ewnc-" + :group 'applications) + +(defcustom enwc-wireless-device "wlan0" + "The wireless device to use for ENWC." + :group 'enwc + :type 'string) + +(defcustom enwc-wired-device "eth0" + "The wired device to use for ENWC." + :group 'enwc + :type 'string) + +(defcustom enwc-backends '(wicd nm) + "The list of backends to be used by ENWC. +These will be checked in the order designated here, +and the first active backend found will be used." + :group 'enwc + :type 'list) + +;;; The function variables for the abstract layer. + +(defvar enwc-scan-func nil + "The function variable for the scan function. +This variable is set during setup.") + +(defvar enwc-get-nw-func nil + "A function variable to be used in `enwc-get-nw'. +This is redefined during setup to be the function to get the network + list.") + +(defvar enwc-get-wireless-nw-prop-func nil + "A function variable to be used in `enwc-get-wireless-nw-prop'. +This is redefined during setup to be the function to get +a wireless network property.") + +(defvar enwc-get-wireless-nw-props-func nil) + +(defvar enwc-get-encryption-type-func nil + "A function variable to be used in `enwc-get-encryption-type'. +This is redefined during setup to be the function to get the encryption +type for the selected backend.") + +(defvar enwc-wireless-connect-func nil + "The function variable for the wireless connect function. +This is redefined during setup to be the function to connect +for the selected backend.") + +(defvar enwc-get-current-nw-id-func nil + "The function variable to be used in `enwc-get-current-nw-id'. +This is redefined during setup to be the function to get +the current network id.") + +(defvar enwc-check-connecting-func nil + "The function variable to be used in `enwc-check-connecting'. +This is redefined during setup to be the function to +check whether or not ENWC is connecting.") + +(defvar enwc-wireless-disconnect-func nil + "The function variable for the wireless disconnect function. +This is redefined during setup to be the function to +disconnect from the wireless network.") + +(defvar enwc-get-wired-profiles-func nil + "The function variable to be used in `enwc-get-wired-profiles'. +This is redefined during setup to be the function to +get the list of wired network profiles.") + +(defvar enwc-wired-connect-func nil + "The function variable for the wired connect function. +This is redefined during setup to be the function +to connect to a wired network.") + +(defvar enwc-wired-disconnect-func nil + "The function variable for the wired disconnect function. +This is redefined during setup to be the function +to disconnect from a wired network.") + +(defvar enwc-is-wired-func nil + "The function variable to be used in `enwc-is-wired'. +This is redefined during setup to be the function to +check whether or not a wired connection is active.") + +(defvar enwc-get-wired-nw-prop-func nil + "The function variable to be used in `enwc-get-wired-nw-prop'. +This is redefined during setup to be the function to get +a network property from a wired network.") + +(defvar enwc-get-sec-types-func nil + "The function variable to be used in `enwc-get-sec-types'. +This is redefined during setup to be the function to get +the security types for a given network.") + +(defvar enwc-get-ip-addr-func nil + "The function variable to be used in `enwc-get-ip-addr'. +This is redefined during setup to be the function to get +the IP Address of a given network.") + +(defvar enwc-get-netmask-func nil + "The function variable to be used in `enwc-get-netmask'. +This is redefined during setup to be the function to get +the Netmask of a given network.") + +(defvar enwc-get-gateway-func nil + "The function variable to be used in `enwc-get-gateway'. +This is redefined during setup to be the function to get +the Gateway of a given network.") + +(defvar enwc-get-dns-func nil + "The function variable to be used in `enwc-get-dns'. +This is redefined during setup to be the function to get +the DNS Server Addresses for a given network.") + +(defvar enwc-get-nw-info-func nil) + +(defvar enwc-save-nw-settings-func nil + "The function variable to be used in `enwc-save-nw-settings'. +This is redefined during setup to be the function to save +the network settings of a given network.") + +(defvar enwc-details-list nil + "The network details list. + +This is redefined during setup to be the details list +for the selected backend. + +This usually includes signal strength, essid, encryption type, +bssid, mode, and channel.") + +(defvar enwc-display-string " [0%] " + "The mode line display string. +This is altered every second to display the current network strength +in `enwc-update-mode-line'.") + +;; (setq tabulated-list-format (vector `("ID" ,enwc-id-width sort) ...)) +;; (setq tabulated-list-entries `((,id [id str essid encrypt ...]) ...)) +;; (tabulated-list-init-header) +;; (tabulated-list-print) + +(defvar enwc-wireless-headers '("ID" "STR" "ESSID" + "ENCRYPT" "BSSID" "MODE" "CHNL") + "The list of headers to be displayed in the ENWC buffer. +These correspond to the details in `enwc-details-list'.") + +(defvar enwc-id-width 3 + "The width of the id column.") +(defvar enwc-str-width 5 + "The width of the strength column.") +(defvar enwc-essid-width 5 + "The initial width of the essid column. +This is reset in wicd-scan-internal.") +(defvar enwc-encrypt-width 10 + "The width of the encryption column.") +(defvar enwc-bssid-width 18 + "The width of the bssid column.") +(defvar enwc-mode-width 16 + "The width of the mode column.") +(defvar enwc-chnl-width 3 + "The width of the channel column.") + +(defvar enwc-last-scan nil + "The most recent scan results.") + +(defvar enwc-access-points nil + "The most recent access point list.") + +(defvar enwc-using-wired nil + "Whether or not wired mode is active. + +This is `non-NIL' if ENWC is using wired connections. +Note that this is NOT the same as `enwc-is-wired'. This checks +whether or not ENWC is in wired mode.") + +(defvar enwc-scan-done nil + "Whether or not a scan is finished.") + +(defvar enwc-edit-id nil + "This is the network id of the network being edited.") + +(defvar enwc-scan-requested nil) + +(defvar enwc-scan-interactive nil) + +(make-local-variable 'enwc-edit-id) +;; The Fonts + +(defface enwc-header-face + '((((class color) (background light)) + (:foreground "Blue")) + (((class color) (background dark)) + (:foreground "Blue")) + (t (:background "Blue"))) + "The face for the headers." + :group 'enwc) + +(defface enwc-connected-face + '((((class color) (background dark)) + (:foreground "Green")) + (((class color) (background light)) + (:foreground "Green")) + (t (:background "Green"))) + "The face for the connected network." + :group 'enwc) + + +;; Small helper function. + +(defun enwc-detail-to-ident (detail) + "Converts detail DETAIL to a constant identifier." + (case (intern detail) + ((essid Ssid) "essid") + ((bssid HwAddress) "bssid") + ((quality Strength) "quality") + ((encryption Flags) "encryption") + ((mode Mode) "mode") + ((channel Frequency) "channel"))) + +;;;;;;;;;;;;;;;;;;;; +;; ENWC functions +;;;;;;;;;;;;;;;;;;;; + +(defun enwc-do-scan () + "Runs a backend scan." + (funcall enwc-scan-func)) + +(defun enwc-get-nw () + "Gets the identifiers for the access points +from a previous scan." + (funcall enwc-get-nw-func)) + +(defun enwc-get-current-nw-id () + "Gets the id of the current network id, +or `nil' if there isn't one." + (funcall enwc-get-current-nw-id-func enwc-using-wired)) + +(defun enwc-check-connecting-p () + "Checks to see if there is a connection +in progress. Returns `non-NIL' if there is one, +`NIL' otherwise." + (funcall enwc-check-connecting-func)) + +(defun enwc-get-wireless-nw-prop (id prop) + "Gets property PROP from wireless network with id +ID and returns it." + (funcall enwc-get-wireless-nw-prop-func id prop)) + +(defun enwc-get-wireless-nw-props (id) + (funcall enwc-get-wireless-nw-props-func id)) + +(defun enwc-get-encryption-type (id) + "Gets the encryption type used by the wireless +network with id ID." + (funcall enwc-get-encryption-type-func id)) + +(defun enwc-get-wired-profiles () + "Gets the list of wired profiles." + (funcall enwc-get-wired-profiles-func)) + +(defun enwc-wireless-connect (id) + "Begins a connection to wireless network with +id ID." + (funcall enwc-wireless-connect-func id)) + +(defun enwc-wireless-disconnect () + "Disconnects the wireless." + (funcall enwc-wireless-disconnect-func)) + +(defun enwc-wired-connect (id) + "Connects to the wired profile with id ID." + (funcall enwc-wired-connect-func id)) + +(defun enwc-wired-disconnect () + "Disconnects from the current network." + (funcall enwc-wired-disconnect-func)) + +(defun enwc-is-wired-p () + "Checks whether or not ENWC is connected to +a wired network. +Note that this is NOT the same as `enwc-using-wired'. +This checks for an active wired connection." + (funcall enwc-is-wired-func)) + +(defun enwc-get-sec-types (wired) + "Gets the security types for network. +WIRED is set to indicate whether or not this is +a wired network." + (funcall enwc-get-sec-types-func wired)) + +(defun enwc-get-network-ent (wired id ent) + "Gets network entry ENT from the network with network id ID. +WIRED is set to indicate whether or not this is +a wired network." + (if wired + nil + (enwc-get-wireless-nw-prop id ent))) + +(defun enwc-get-wired-nw-prop (id prop) + "Gets network property PROP from + the wired network with network id ID." + (funcall enwc-get-wired-nw-prop-func id prop)) + +(defun enwc-get-ip-addr (wired id) + "Gets the IP Address from the network with network id ID. +WIRED is set to indicate whether or not this is +a wired network." + (funcall enwc-get-ip-addr-func wired id)) + +(defun enwc-get-netmask (wired id) + "Gets the Netmask from the network with network id ID. +WIRED is set to indicate whether or not this is +a wired network." + (funcall enwc-get-netmask-func wired id)) + +(defun enwc-get-gateway (wired id) + "Gets the Gateway from the network with network id ID. +WIRED is set to indicate whether or not this is +a wired network." + (funcall enwc-get-gateway-func wired id)) + +(defun enwc-get-dns (wired id) + "Gets the DNS Servers from the network with network id ID. +WIRED is set to indicate whether or not this is +a wired network." + (funcall enwc-get-dns-func wired id)) + +(defun enwc-get-nw-info (wired id) + (funcall enwc-get-nw-info-func wired id)) + +(defun enwc-save-nw-settings (wired id settings) + "Saves network settings SETTINGS to the network profile with +network id ID. +SETTINGS is an association list with entries for the IP Address, +Netmask, Gateway, DNS Servers, and Security. +WIRED is set to indicate whether or not this is +a wired network." + (funcall enwc-save-nw-settings-func wired id settings)) + +;;;;;;;;;;;;;;;;;;;;; +;; Actual Functions +;;;;;;;;;;;;;;;;;;;;; + +(defun enwc-is-valid-nw-id (id) + "Confirms that ID is a valid network id." + (<= 0 id)) + +(defun enwc-get-nw-prop (wired id prop) + "Small function to get network property PROP from the network +with network id ID. +WIRED indicates whether or not this is a wired connection." + (if wired + (enwc-get-wired-nw-prop id prop) + (enwc-get-wireless-nw-prop id prop))) + +(defun enwc-update-mode-line () + "Updates the mode line with the current network strength. +If no network is connected, then prints 0%. +If wired is active, then prints 100%. +If ENWC is in the process of connecting, then prints *%. +This is initiated during setup, and runs once every second." + (let ((cur-id (enwc-get-current-nw-id)) + (conn (enwc-check-connecting-p)) + str) + (setq str + (if (enwc-is-wired-p) + 100 + (if (and + (enwc-is-valid-nw-id cur-id) + enwc-last-scan) + (cdr (assoc "quality" (nth cur-id enwc-last-scan))) + 0))) + (setq enwc-display-string (concat " [" + (if conn + "*" + (number-to-string str)) + "%] ")))) + +;;;;;;;;;;;;;;;;;; +;; Scan internal +;;;;;;;;;;;;;;;;;; + +(defun enwc-scan-internal-wireless () + "The initial scan routine. +This initiates a scan using D-Bus, then exits, +waiting for the callback." + (message "Scanning...") + (setq enwc-scan-requested t) + (setq enwc-scan-done nil) + (enwc-do-scan)) + +(defun enwc-process-scan (&rest args) + "The scanning callback. +After a scan has been performed, this processes and displays +the scan results." + (if (or enwc-using-wired (not enwc-scan-requested)) + nil + (setq enwc-scan-requested nil) + (let ((cur-id 0)) + (message "Scanning... Done") + (setq enwc-access-points (enwc-get-nw) + enwc-essid-width 5) + (setq enwc-last-scan + (mapcar (lambda (x) + (let ((ret-itm (cons (cons "id" cur-id) nil)) + (prop-list (enwc-get-wireless-nw-props x))) + (setq cur-id (1+ cur-id)) + (dolist (det enwc-details-list) + (let ((cur-item (cdr (assoc det prop-list))) + (ident (enwc-detail-to-ident det)) + pos-len) + (if (string= ident "essid") + (progn + (setq pos-len (length cur-item)) + (setq enwc-essid-width + (max enwc-essid-width + pos-len)))) + (if (string= ident "encryption") + (setq cur-item + (if cur-item + (enwc-get-encryption-type x) + "Unsecured"))) + (setq ret-itm (append ret-itm + (cons (cons ident + cur-item) + nil))))) + ret-itm)) + (number-sequence 0 (1- (length enwc-access-points)))))) + (setq enwc-essid-width (1+ enwc-essid-width)) + (setq enwc-scan-done t) + (if enwc-scan-interactive + (progn + (enwc-display-wireless-networks enwc-last-scan) + ;;(goto-char 0) + ;;(forward-line) + )))) + +(defun enwc-scan-internal-wired () + "The scanning routine for a wired connection. +This gets the list of wired network profiles." + (message "Updating Profiles...") + (let ((profs (enwc-get-wired-profiles)) + cur-prof fin-profs) + (while profs + (setq cur-prof (pop profs)) + (if cur-prof + (setq fin-profs (cons cur-prof + fin-profs)))) + (message "Updating Profiles... Done") + (setq enwc-access-points fin-profs) + (setq enwc-last-scan fin-profs) + fin-profs)) + +(defun enwc-scan-internal () + "The entry point for the internal scan routines. +This checks whether or not wired is being used, + and runs the appropriate function." + (if enwc-using-wired + (enwc-scan-internal-wired) + (enwc-scan-internal-wireless))) + +;;;;;;;;;;;;;;;;;;;;; +;; Display Networks +;;;;;;;;;;;;;;;;;;;;; + +(defun enwc-display-wired-networks (networks) + "Displays the wired networks specified in the list NETWORKS. +NETWORKS must be in the form returned from +`enwc-scan-internal-wired'." + (if (not (listp networks)) + (error "NETWORKS must be a list of networks.")) + (let ((inhibit-read-only t)) + (erase-buffer) + (insert (propertize "Profile" 'face 'enwc-header-face)) + (insert "\n") + (dolist (pr networks) + (insert pr) + (insert "\n")))) + +(defun enwc-insert-ent (ent width) + "Small function to insert a network property entry. +ENT is the entry, and WIDTH is the column width." + (insert ent) + (insert-char 32 (- width (length ent)))) + +(defun enwc-display-wireless-networks (networks) + "Displays the networks in the list NETWORKS in the current buffer. +NETWORKS must be in the format returned by +`enwc-scan-internal-wireless'." + (if (not (eq major-mode 'enwc-mode)) + (enwc-setup-buffer)) + (if (not (listp networks)) + (error "NETWORKS must be a list of association lists.")) + (let (;;(inhibit-read-only t) + (cur-id (enwc-get-current-nw-id)) + entries) + ;;(erase-buffer) + (let ((header enwc-wireless-headers) + (pos 0)) + + (setq tabulated-list-format + (vector '("ID" 2) + '("STR" 4) + `("ESSID" ,enwc-essid-width) + '("ENCRYPT" 9) + '("BSSID" 17) + '("MODE" 15) + '("CHNL" 2))) + + ;; (dolist (hd header) + ;; (insert (propertize hd 'face 'enwc-header-face)) + ;; (setq pos (length hd)) + ;; (insert-char 32 (- (symbol-value (intern (concat "enwc-" + ;; (downcase hd) + ;; "-width"))) + ;; pos))) + ) + ;;(insert "\n") + + ;;TODO: Setup faces. + (dolist (nw networks) + (let ((id (cdr (assoc "id" nw))) + entry) + (setq entry (list nil + (vector + (number-to-string (cdr (assoc "id" nw))) + (concat (number-to-string (cdr (assoc "quality" nw))) + "%") + (cdr (assoc "essid" nw)) + (cdr (assoc "encryption" nw)) + (cdr (assoc "bssid" nw)) + (cdr (assoc "mode" nw)) + (cdr (assoc "channel" nw))))) + (setq entries (cons entry entries)))) + + (setq tabulated-list-entries (nreverse entries)) + (tabulated-list-init-header) + + ;; (dolist (nw networks) + ;; (let* ((id (propertize (number-to-string (cdr (assoc "id" nw))) + ;; 'width enwc-id-width)) + ;; (str (propertize (concat (number-to-string (cdr (assoc "quality" + ;; nw))) + ;; "%") + ;; 'width enwc-str-width)) + ;; (essid (propertize (cdr (assoc "essid" nw)) + ;; 'width enwc-essid-width)) + ;; (encrypt (propertize (cdr (assoc "encryption" nw)) + ;; 'width enwc-encrypt-width)) + ;; (bssid (propertize (cdr (assoc "bssid" nw)) + ;; 'width enwc-bssid-width)) + ;; (mode (propertize (cdr (assoc "mode" nw)) + ;; 'width enwc-mode-width)) + ;; (chnl (propertize (cdr (assoc "channel" nw)) + ;; 'width enwc-chnl-width)) + ;; props) + + ;; (setq props (list id str essid encrypt bssid mode chnl)) + + ;; (dolist (ent props) + ;; (if (eq (string-to-number id) cur-id) + ;; (setq ent (propertize ent 'face 'enwc-connected-face))) + ;; (enwc-insert-ent ent (get-text-property 0 'width ent))) + ;; (insert "\n"))) + (tabulated-list-print) + )) + +(defun enwc-display-networks (networks) + "Displays the network in NETWORKS. This is an entry to the display +functions, and checks whether or not ENWC is using wired." + (if (not (eq major-mode 'enwc-mode)) + (enwc-setup-buffer)) + (if (not (listp networks)) + (error "NETWORKS must be a list.")) + (if enwc-using-wired + (enwc-display-wired-networks networks) + (enwc-display-wireless-networks networks))) + +(defun enwc-scan () + "The frontend of the scanning routine. Sets up and moves to +the ENWC buffer if necessary, and scans and displays the networks." + (interactive) + (setq enwc-scan-interactive t) + (if (not (eq major-mode 'enwc-mode)) + (switch-to-buffer "*ENWC*")) + (if enwc-using-wired + (progn + (enwc-scan-internal) + ;;(enwc-display-networks enwc-last-scan) + (goto-char 0) + (forward-line)) + (enwc-scan-internal))) + +(defun enwc-find-network (essid &optional networks) + "Checks through NETWORKS for the network with essid ESSID, +and returns the network identifier. Uses `enwc-last-scan' if +NETWORKS is nil. If the network is not found, then it returns nil. + + When called interactively, this only prints out what it finds. +Otherwise, it actually returns it." + (interactive "sNetwork ESSID: ") + (if (not (or networks enwc-last-scan)) + (progn + (setq enwc-scan-interactive nil) + (enwc-scan-internal))) + (let ((nets (or networks enwc-last-scan)) + need-break cur-net) + (if (not nets) + (setq nets enwc-last-scan)) + (while (and nets (not need-break)) + (let (cur-essid) + (setq cur-net (pop nets)) + (setq cur-essid (cdr (assoc "essid" cur-net))) + (if (string= cur-essid essid) + (setq need-break t)))) + (if need-break + (if (called-interactively-p 'any) + (message (number-to-string (cdr (assoc "id" cur-net)))) + (cdr (assoc "id" cur-net))) + (if (called-interactively-p 'any) + (message "Network not found.") + nil)))) + +;;;;;;;;;;;;;;;;;;;; +;; Connect Network +;;;;;;;;;;;;;;;;;;;; + +(defun enwc-connect-network (id) + "Connect to network with id ID. +This is an entry point for the internal connection functions, +and checks whether or not ENWC is using wired." + (let (cur-net) + (if enwc-using-wired + (progn + (enwc-wired-connect id) + (setq cur-net (nth id (enwc-get-wired-profiles)))) + (enwc-wireless-connect id) + (if enwc-last-scan + (setq cur-net (cdr (assoc "essid" (nth id enwc-last-scan))))) + cur-net))) + +(defun enwc-connect-to-network (net-id) + "Connects the the network with network id NET-ID. +Confirms that NET-ID is a valid network id. +This calls `enwc-connect-network' as a subroutine." + (interactive "nNetwork ID: ") + (if (not (numberp net-id)) + (error "NET-ID must be a number")) + (let ((num-ids (length enwc-last-scan)) + cur-net) + (if (or (< net-id 0) (>= net-id num-ids)) + (error "Invalid network id.")) + (setq cur-net (enwc-connect-network net-id)) + (message (concat "Connecting to " cur-net)))) + +(defun enwc-connect-to-network-essid (essid) + "Connects to the network with essid ESSID." + (interactive "sNetwork ESSID: ") + (let ((net-id (enwc-find-network essid))) + (if net-id + (enwc-connect-to-network net-id) + (message "Network not found.")))) + +(defun enwc-connect-to-network-at-point () + "Connects to the network at the current line number. +Moves to the enwc buffer if necessary." + (interactive) + (if (not (eq major-mode 'enwc-mode)) + (enwc-setup-buffer)) + (let ((id (- (line-number-at-pos) 1))) + (enwc-connect-to-network id))) + +(defun enwc-disconnect () + "Disconnects from the network, if any." + (interactive) + (if (not (eq major-mode 'enwc-mode)) + (enwc-setup-buffer)) + (if enwc-using-wired + (enwc-wired-disconnect) + (enwc-wireless-disconnect))) + +(defun enwc-toggle-wired () + "Toggle the display and mode between wireless and wired. +This function also sets the variable `enwc-using-wired'." + (interactive) + (if (not (eq major-mode 'enwc-mode)) + (enwc-setup-buffer)) + (let ((inhibit-read-only t)) + (erase-buffer) + (setq enwc-using-wired (not enwc-using-wired)) + (enwc-scan))) + +(defun enwc () + "The main front-end to ENWC. +This sets up the buffer and scans for networks. +In order to use this, one must have already run +`enwc-setup'. + +\\{enwc-mode-map}" + (interactive) + (enwc-setup-buffer) + (enwc-scan)) + +;; Settings for access point AP +;; +;; IPv4 Settings: +;; Address = +;; Netmask = +;; Gateway = +;; +;; DNS 1 = +;; DNS 2 = +;; +;; Security: +;; Type = +;; + +(defun enwc-edit-view-entry () + "View the text of the entry at point. +This is mostly useful to view the text of the hidden entries." + (interactive) + (if (not (get-buffer "*ENWC Edit*")) + (error "Not editing a network entry.")) + (if (not (eq (current-buffer) (get-buffer "*ENWC Edit*"))) + (switch-to-buffer "*ENWC Edit*")) + (if (not (widget-at)) + (error "No widget at point")) + (message (widget-field-value-get (widget-at)))) + +(defun enwc-display-sec-reqs (widget &rest stuff) + "Display the security requirements. +This is a callback to the security selection widget. +WIDGET is always the menu drop-down of security types." + (let (reqs + (inhibit-read-only t) + type-wid-list) + ;; First, erase any of the old ones. + (goto-char (1+ (widget-get widget :to))) + (widget-forward 1) + (while (>= (point) (widget-get widget :to)) + (widget-delete (widget-at)) + (widget-forward 1)) + (goto-char (point-max)) + ;; Then check to see if widget-value is None + (if (string= (widget-value widget) "None") + nil + (setq type-wid-list + (cadr (assoc "reqs" + (cdr (assoc (widget-value widget) + (enwc-get-sec-types enwc-using-wired)))))) + (setq reqs + (mapcar (lambda (x) + (if (not (eq (length (cdr x)) 0)) + (widget-create 'editable-field + :format (concat " " + (cdr x) + ": %v") + :secret ?* + :keymap 'enwc-edit-field-map + :value (or (enwc-get-nw-prop enwc-using-wired + enwc-edit-id + (car x)) + "")))) + type-wid-list)) + (widget-setup) + reqs))) + +(defun enwc-setup-edit-buffer () + "Setup the edit buffer. This removes the old one if neccessary, +and redisplays the settings from the network profile + with id `enwc-edit-id', which is set in `enwc-edit-entry-at-point'." + (if (get-buffer "*ENWC Edit*") + (kill-buffer "*ENWC Edit*")) + (with-current-buffer (get-buffer-create "*ENWC Edit*") + (let ((sec-types (enwc-get-sec-types enwc-using-wired)) + (nw-info (enwc-get-nw-info enwc-using-wired enwc-edit-id)) + ip-addr netmask gateway dns-1 dns-2 + addr-wid net-wid gate-wid + dns-1-wid dns-2-wid dns-list + type-wid type-wid-list) + + (widget-insert (concat "Settings for access point " + (cdr (assoc "essid" + (nth enwc-edit-id + enwc-last-scan))) + "\n")) + (widget-insert "\n") + ;; ip + (widget-insert "IPv4 Settings:\n") + (setq addr-wid (widget-create 'editable-field + :format " Address: %v" + :value (or (assoc "addr" nw-info) ""))) + ;; netmask + (setq net-wid (widget-create 'editable-field + :format " Netmask: %v" + :value (or (assoc "netmask" nw-info) ""))) + + ;; gateway + (setq gate-wid (widget-create 'editable-field + :format " Gateway: %v" + :value (or (assoc "gateway" nw-info) ""))) + ;; dns1 + (widget-insert "\n") + ;;(setq dns-list (enwc-get-dns enwc-using-wired enwc-edit-id)) + (setq dns-1-wid (widget-create 'editable-field + :format " DNS 1: %v" + :value (or (assoc "dns1" nw-info) ""))) + + ;; dns2 + (setq dns-2-wid (widget-create 'editable-field + :format " DNS 2: %v" + :value (or (assoc "dns2" nw-info) ""))) + + (widget-insert "\n") + (widget-insert "Security:\n") + (setq type-wid (apply 'widget-create + 'menu-choice + :tag "Type " + :value (or (assoc "enctype" nw-info) "None") + :notify 'enwc-display-sec-reqs + '(item :tag "No Encryption" + :value "None") + (mapcar (lambda (x) + `(item :format "%t\n" + :value ,(car x) + :tag ,(cdr (assoc "Name" (cdr x))))) + sec-types))) + (enwc-display-sec-reqs type-wid) + (use-local-map enwc-edit-map) + (widget-setup))) + + (switch-to-buffer "*ENWC Edit*")) + +(defun enwc-edit-save () + "Save the network settings." + ;; Basically, just iterate through the widgets, + ;; retrieving values from each. + (interactive) + (if (not (get-buffer "*ENWC Edit*")) + (error "Not editing a network entry.")) + (if (not (eq (current-buffer) (get-buffer "*ENWC Edit*"))) + (switch-to-buffer "*ENWC Edit*")) + (goto-char 0) + (let (settings start-pos type-wid-list) + + (widget-forward 1) + (setq settings + (append settings + (cons (cons "addr" + (widget-field-value-get (widget-at))) + nil))) + (widget-forward 1) + (setq settings + (append settings + (cons (cons "netmask" + (widget-field-value-get (widget-at))) + nil))) + (widget-forward 1) + (setq settings + (append settings + (cons (cons "gateway" + (widget-field-value-get (widget-at))) + nil))) + (widget-forward 1) + (setq settings + (append settings + (cons (cons "dns1" + (widget-field-value-get (widget-at))) + nil))) + (widget-forward 1) + (setq settings + (append settings + (cons (cons "dns2" + (widget-field-value-get (widget-at))) + nil))) + (widget-forward 1) + (setq settings + (append settings + (cons (cons "enctype" + (widget-value (widget-at))) + nil))) + (setq start-pos (widget-get (widget-at) :to)) + (if (not (string= (widget-value (widget-at)) "None")) + (setq type-wid-list + (cadr (assoc "reqs" + (cdr (assoc (widget-value (widget-at)) + (enwc-get-sec-types enwc-using-wired))))))) + (dolist (x type-wid-list) + (widget-forward 1) + (if (not (string= (widget-field-value-get (widget-at)) "")) + (setq settings + (append settings + (cons (cons (car x) + (widget-field-value-get (widget-at))) + nil))))) + (print settings) + + (enwc-save-nw-settings enwc-using-wired enwc-edit-id settings))) + +(defun enwc-edit-entry-at-point () + "Edit the current network entry." + (interactive) + (setq enwc-edit-id (- (line-number-at-pos) 1)) + (select-window (split-window)) + (enwc-setup-edit-buffer)) + +(defvar enwc-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "R") 'enwc-scan) + (define-key map (kbd "C") 'enwc-connect-to-network-essid) + (define-key map (kbd "D") 'enwc-disconnect) + (define-key map (kbd "W") 'enwc-toggle-wired) + (define-key map (kbd "E") 'enwc-edit-entry-at-point) + (define-key map (kbd "RET") 'enwc-connect-to-network-at-point) + map) + "The keymap for network display in ENWC.") + +(defvar enwc-edit-map + (let ((map (copy-keymap widget-keymap))) + (define-key map (kbd "C-x C-s") 'enwc-edit-save) + map) + "The keymap for editing network profiles with ENWC.") + +(defvar enwc-edit-field-map + (let ((map (copy-keymap widget-field-keymap))) + (define-key map (kbd "C-x C-a") 'enwc-edit-view-entry) + map) + "The keymap for editable fields within the ENWC edit buffer.") + +(define-derived-mode enwc-mode tabulated-list-mode "enwc" + "Mode for working with network connections. +\\{enwc-mode-map}" + ;;(setq buffer-read-only t) + (add-hook 'tabulated-list-revert-hook 'enwc-scan nil t) + ) + +(defun enwc-setup-buffer () + "Sets up the ENWC buffer. +This first checks to see that it exists, +and if it doesn't, then create it." + (if (not (get-buffer "*ENWC*")) + (with-current-buffer (get-buffer-create "*ENWC*") + ;;(use-local-map enwc-mode-map) + ;;(setq major-mode 'enwc-mode + ;; mode-name "enwc") + (enwc-mode) + ;;(setq buffer-read-only t) + )) + (switch-to-buffer "*ENWC*")) + +(provide 'enwc) + +;;; enwc.el ends here