aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2010-05-18 21:34:26 +0200
committerMichael Albinus2010-05-18 21:34:26 +0200
commit3a8e7cbdaec8cb210c09d296bb94b6bbb2f6ab5d (patch)
treef8d9e3049a219047387caf04ca9ba0be01ac72f6
parent224b70cbc50f55b8e9a65b9b8666ce2bff6d796b (diff)
downloademacs-3a8e7cbdaec8cb210c09d296bb94b6bbb2f6ab5d.tar.gz
emacs-3a8e7cbdaec8cb210c09d296bb94b6bbb2f6ab5d.zip
Add visualization code for secrets.
* net/secrets.el (secrets-mode): New major mode. (secrets-show-secrets, secrets-show-collections) (secrets-expand-collection, secrets-expand-item) (secrets-tree-widget-after-toggle-function) (secrets-tree-widget-show-password): New defuns.
-rw-r--r--lisp/ChangeLog11
-rw-r--r--lisp/net/secrets.el149
2 files changed, 159 insertions, 1 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index cb0ca655188..9c7359caf46 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,12 @@
12010-05-18 Michael Albinus <michael.albinus@gmx.de>
2
3 Add visualization code for secrets.
4 * net/secrets.el (secrets-mode): New major mode.
5 (secrets-show-secrets, secrets-show-collections)
6 (secrets-expand-collection, secrets-expand-item)
7 (secrets-tree-widget-after-toggle-function)
8 (secrets-tree-widget-show-password): New defuns.
9
12010-05-18 Stefan Monnier <monnier@iro.umontreal.ca> 102010-05-18 Stefan Monnier <monnier@iro.umontreal.ca>
2 11
3 * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB. 12 * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
@@ -146,7 +155,7 @@
1462010-05-13 Michael Albinus <michael.albinus@gmx.de> 1552010-05-13 Michael Albinus <michael.albinus@gmx.de>
147 156
148 * net/tramp.el (with-progress-reporter): Create reporter object 157 * net/tramp.el (with-progress-reporter): Create reporter object
149 only when the message would be displayed. Handled nested calls. 158 only when the message would be displayed. Handle nested calls.
150 (tramp-handle-load, tramp-handle-file-local-copy) 159 (tramp-handle-load, tramp-handle-file-local-copy)
151 (tramp-handle-insert-file-contents, tramp-handle-write-region) 160 (tramp-handle-insert-file-contents, tramp-handle-write-region)
152 (tramp-maybe-send-script, tramp-find-shell): 161 (tramp-maybe-send-script, tramp-find-shell):
diff --git a/lisp/net/secrets.el b/lisp/net/secrets.el
index c45f6fbb276..a7225d663e3 100644
--- a/lisp/net/secrets.el
+++ b/lisp/net/secrets.el
@@ -129,6 +129,9 @@
129;; (secrets-search-items "session" :user "joe") 129;; (secrets-search-items "session" :user "joe")
130;; => ("my item" "another item") 130;; => ("my item" "another item")
131 131
132;; Interactively, collections, items and their attributes could be
133;; inspected by the command `secrets-show-secrets'.
134
132;;; Code: 135;;; Code:
133 136
134;; It has been tested with GNOME Keyring 2.29.92. An implementation 137;; It has been tested with GNOME Keyring 2.29.92. An implementation
@@ -148,6 +151,13 @@
148 151
149(require 'dbus) 152(require 'dbus)
150 153
154(declare-function tree-widget-set-theme "tree-widget")
155(declare-function widget-create-child-and-convert "wid-edit")
156(declare-function widget-default-value-set "wid-edit")
157(declare-function widget-field-end "wid-edit")
158(declare-function widget-member "wid-edit")
159(defvar tree-widget-after-toggle-functions)
160
151(defvar secrets-enabled nil 161(defvar secrets-enabled nil
152 "Whether there is a daemon offering the Secret Service API.") 162 "Whether there is a daemon offering the Secret Service API.")
153 163
@@ -665,6 +675,145 @@ If there is no such item, or the item doesn't own this attribute, return nil."
665 :session secrets-service item-path 675 :session secrets-service item-path
666 secrets-interface-item "Delete"))))) 676 secrets-interface-item "Delete")))))
667 677
678;;; Visualization.
679
680(define-derived-mode secrets-mode nil "Secrets"
681 "Major mode for presenting search results of a Xesam search.
682In this mode, widgets represent the search results.
683
684\\{secrets-mode-map}
685Turning on Xesam mode runs the normal hook `xesam-mode-hook'. It
686can be used to set `xesam-notify-function', which must a search
687engine specific, widget :notify function to visualize xesam:url."
688 ;; Keymap.
689 (setq secrets-mode-map (copy-keymap special-mode-map))
690 (set-keymap-parent secrets-mode-map widget-keymap)
691 (define-key secrets-mode-map "z" 'kill-this-buffer)
692
693 ;; When we toggle, we must set temporary widgets.
694 (set (make-local-variable 'tree-widget-after-toggle-functions)
695 '(secrets-tree-widget-after-toggle-function))
696
697 (when (not (called-interactively-p 'interactive))
698 ;; Initialize buffer.
699 (setq buffer-read-only t)
700 (let ((inhibit-read-only t))
701 (erase-buffer))))
702
703;; It doesn't make sense to call it interactively.
704(put 'secrets-mode 'disabled t)
705
706;; The very first buffer created with `secrets-mode' does not have the
707;; keymap etc. So we create a dummy buffer. Stupid.
708(with-temp-buffer (secrets-mode))
709
710;;;###autoload
711(defun secrets-show-secrets ()
712 "Display a list of collections from the Secret Service API.
713The collections are in tree view, that means they can be expanded
714to the corresponding secret items, which could also be expanded
715to their attributes."
716 (interactive)
717 ;; Create the search buffer.
718 (with-current-buffer (get-buffer-create "*Secrets*")
719 (switch-to-buffer-other-window (current-buffer))
720 ;; Inialize buffer with `secrets-mode'.
721 (secrets-mode)
722 (secrets-show-collections)))
723
724(defun secrets-show-collections ()
725 "Show all available collections."
726 (let ((inhibit-read-only t)
727 (alias (secrets-get-alias "default")))
728 (erase-buffer)
729 (tree-widget-set-theme "folder")
730 (dolist (coll (secrets-list-collections))
731 (widget-create
732 `(tree-widget
733 :tag ,coll
734 :collection ,coll
735 :open nil
736 :sample-face bold
737 :expander secrets-expand-collection)))))
738
739(defun secrets-expand-collection (widget)
740 "Expand items of collection shown as WIDGET."
741 (let ((coll (widget-get widget :collection)))
742 (mapcar
743 (lambda (item)
744 `(tree-widget
745 :tag ,item
746 :collection ,coll
747 :item ,item
748 :open nil
749 :sample-face bold
750 :expander secrets-expand-item))
751 (secrets-list-items coll))))
752
753(defun secrets-expand-item (widget)
754 "Expand password and attributes of item shown as WIDGET."
755 (let* ((coll (widget-get widget :collection))
756 (item (widget-get widget :item))
757 (attributes (secrets-get-attributes coll item))
758 ;; padding is needed to format attribute names.
759 (padding
760 (1+
761 (apply
762 'max
763 (cons
764 (length "password")
765 (mapcar
766 (lambda (attribute) (length (symbol-name (car attribute))))
767 attributes))))))
768 (cons
769 ;; The password widget.
770 `(editable-field :tag "password"
771 :secret ?*
772 :value ,(secrets-get-secret coll item)
773 :sample-face widget-button-pressed
774 ;; We specify :size in order to limit the field.
775 :size 0
776 :format ,(concat
777 "%{%t%}:"
778 (make-string (- padding (length "password")) ? )
779 "%v\n"))
780 (mapcar
781 (lambda (attribute)
782 (let ((name (symbol-name (car attribute)))
783 (value (cdr attribute)))
784 ;; The attribute widget.
785 `(editable-field :tag ,name
786 :value ,value
787 :sample-face widget-documentation
788 ;; We specify :size in order to limit the field.
789 :size 0
790 :format ,(concat
791 "%{%t%}:"
792 (make-string (- padding (length name)) ? )
793 "%v\n"))))
794 attributes))))
795
796(defun secrets-tree-widget-after-toggle-function (widget &rest ignore)
797 "Add a temporary widget to show the password."
798 (dolist (child (widget-get widget :children))
799 (when (widget-member child :secret)
800 (goto-char (widget-field-end child))
801 (widget-insert " ")
802 (widget-create-child-and-convert
803 child 'push-button
804 :notify 'secrets-tree-widget-show-password
805 "Show password")))
806 (widget-setup))
807
808(defun secrets-tree-widget-show-password (widget &rest ignore)
809 "Show password, and remove temporary widget."
810 (let ((parent (widget-get widget :parent)))
811 (widget-put parent :secret nil)
812 (widget-default-value-set parent (widget-get parent :value))
813 (widget-setup)))
814
815;;; Initialization.
816
668(when (dbus-ping :session secrets-service 100) 817(when (dbus-ping :session secrets-service 100)
669 818
670 ;; We must reset all variables, when there is a new instance of the 819 ;; We must reset all variables, when there is a new instance of the