summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Zlatanov <tzz@lifelogs.com>2020-06-23 18:19:32 -0400
committerTed Zlatanov <tzz@lifelogs.com>2020-07-12 16:44:10 -0400
commitda5b4b6d0856501a163217529c2db2f891e284c0 (patch)
tree9690b6c43bce85a46b01c3769fc2558a7fa923f0
parent0256303f24b1fc193f1d6c1861abf81fd5ee374a (diff)
downloademacs-scratch/tzz/prettify-text-mode.tar.gz
Create and document auth-source-reveal-modescratch/tzz/prettify-text-mode
* lisp/auth-source.el (auth-source-reveal-mode): Add new minor mode to hide passwords. Remove authinfo-mode which provided a major mode for the same purpose before. Use the text-coverup API. * doc/misc/auth.texi (Hiding passwords in text buffers): Document auth-source-reveal-mode.
-rw-r--r--doc/misc/auth.texi45
-rw-r--r--lisp/auth-source.el110
2 files changed, 123 insertions, 32 deletions
diff --git a/doc/misc/auth.texi b/doc/misc/auth.texi
index 61dc62e7711..fc98b773432 100644
--- a/doc/misc/auth.texi
+++ b/doc/misc/auth.texi
@@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*-
-@set VERSION 0.3
+@set VERSION 0.4
@setfilename ../../info/auth.info
@settitle Emacs auth-source Library @value{VERSION}
@@ -58,6 +58,7 @@ It is a way for multiple applications to share a single configuration
* Overview:: Overview of the auth-source library.
* Help for users::
* Multiple GMail accounts with Gnus::
+* Hiding passwords in text buffers::
* Secret Service API::
* The Unix password store::
* Help for developers::
@@ -280,6 +281,48 @@ machine gmail login account@@gmail.com password "account password" port imap
machine gmail2 login account2@@gmail.com password "account2 password" port imap
@end example
+@node Hiding passwords in text buffers
+@chapter Hiding passwords in text buffers
+
+Emacs users and developers have to look at netrc files in text or JSON
+formats sometimes. Pro Tip: one easy way to protect from
+password-shoulder-surfers is to enter a hair band, grow long hair,
+curl it daily until it creates a visual barrier, become famous, keep
+using Emacs.
+
+An alternative is to enable @code{auth-source-reveal-mode} as follows:
+
+@example
+(require 'auth-source)
+(setq prettify-symbols-unprettify-at-point 'right-edge) ;; or customize it
+
+(add-hook 'prog-mode-hook 'turn-on-auth-source-reveal-mode)
+(add-hook 'text-mode-hook 'turn-on-auth-source-reveal-mode)
+(add-hook 'json-mode-hook 'turn-on-auth-source-reveal-mode)
+@end example
+
+Underneath, the @code{prettify-text} API is used to hide passwords
+based on a regular expression for netrc plain text or JSON files.
+
+You should definitely customize
+@code{prettify-text-unprettify-at-point} to be t or
+@code{right-edge}. If it's nil (the default), the password will not be
+revealed when you're inside it, which will annoy you AND
+password-shoulder-surfers. Note this is different from
+@code{prettify-symbols-unprettify-at-point} which only governs
+@code{prettify-symbols-mode} behavior.
+
+You can further customize the following.
+@defvar auth-source-reveal-regex
+A regular expression matching the text preceding the password (or, in JSON format, the key under which the password lives). By default it will be just ``password'' which also matches e.g. ``my_password''.
+
+Use only non-capturing parens inside this regular expression.
+@end defvar
+
+@defvar auth-source-reveal-json-modes
+This is a list of modes where the JSON regular expression logic should be installed, instead of the plaintext logic. By default this includes @code{json-mode} for instance.
+@end defvar
+
@node Secret Service API
@chapter Secret Service API
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 7a0e09b9e8e..2892cc09925 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -44,6 +44,7 @@
(require 'cl-lib)
(require 'eieio)
+(require 'prog-mode)
(autoload 'secrets-create-item "secrets")
(autoload 'secrets-delete-item "secrets")
@@ -2405,44 +2406,91 @@ MODE can be \"login\" or \"password\"."
(setq password (funcall password)))
(list user password auth-info)))
-;;; Tiny mode for editing .netrc/.authinfo modes (that basically just
-;;; hides passwords).
+;;; Tiny minor mode for editing .netrc/.authinfo modes (that basically
+;;; just hides passwords).
-(defcustom authinfo-hidden "password"
- "Regexp matching elements in .authinfo/.netrc files that should be hidden."
+(defcustom auth-source-reveal-regex "password"
+ "Regexp matching tokens or JSON keys in .authinfo/.netrc/JSON files.
+The text following the tokens or under the JSON keys will be hidden."
:type 'regexp
:version "27.1")
-;;;###autoload
-(define-derived-mode authinfo-mode fundamental-mode "Authinfo"
- "Mode for editing .authinfo/.netrc files.
+(defcustom auth-source-reveal-json-modes '(json-mode js-mode js2-mode rjsx-mode)
+ "List of symbols for modes that should use JSON parsing logic."
+ :type 'list
+ :version "27.1")
-This is just like `fundamental-mode', but hides passwords. The
-passwords are revealed when point moved into the password.
+(defcustom auth-source-reveal-hider '(?* (base-right . base-left) ?© (base-right . base-left) ?© (base-right . base-left) ?*)
+ "A character or a composition list to hide passwords.
+In the composition list form, you can use the format
+(?h (base-right . base-left) ?i (base-right . base-left) ?d (base-right . base-left) ?e)
+to show the string \"hide\" (by aligning character left/right baselines).
-\\{authinfo-mode-map}"
- (authinfo--hide-passwords (point-min) (point-max))
- (reveal-mode))
+Other composition keywords you can use: top-left/tl,
+top-center/tc, top-right/tr, base-left/Bl, base-center/Bc,
+base-right/Br, bottom-left/bl, bottom-center/bc, bottom-right/br,
+center-left/cl, center-center/cc, center-right/cr."
+ :type '(choice
+ (const :tag "A single copyright sign" ?©)
+ (character :tag "Any character")
+ (sexp :tag "A composition list"))
+ :version "27.1")
-(defun authinfo--hide-passwords (start end)
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char start)
- (while (re-search-forward (format "\\(\\s-\\|^\\)\\(%s\\)\\s-+"
- authinfo-hidden)
- nil t)
- (when (auth-source-netrc-looking-at-token)
- (let ((overlay (make-overlay (match-beginning 0) (match-end 0))))
- (overlay-put overlay 'display (propertize "****"
- 'face 'warning))
- (overlay-put overlay 'reveal-toggle-invisible
- #'authinfo--toggle-display)))))))
-
-(defun authinfo--toggle-display (overlay hide)
- (if hide
- (overlay-put overlay 'display (propertize "****" 'face 'warning))
- (overlay-put overlay 'display nil)))
+(defun auth-source-reveal-compose-p (start end _outer_match _true_match)
+ "Return true iff the text between START and END should be composed.
+All arguments are currently ignored, always returning t for
+`auth-source-reveal-mode'. This overrides the default for
+`text-coverup-compose-predicate'."
+ ;; Check that the chars should really be composed into a symbol.
+ t)
+
+;;;###autoload
+(define-minor-mode auth-source-reveal-mode
+ "Toggle password hiding for auth-source files using `text-coverup-mode'.
+
+If called interactively, enable auth-source-reveal mode if ARG is
+positive, and disable it if ARG is zero or negative. If called
+from Lisp, also enable the mode if ARG is omitted or nil, and
+toggle it if ARG is toggle; disable the mode otherwise.
+
+When auth-source-reveal mode is enabled, passwords will be
+hidden. To reveal them when point is inside them, see
+`text-coverup-uncover-at-point'.
+
+See `auth-source-password-hide-regex' for the regex matching the
+tokens and keys associated with passwords."
+ ;; The initial value.
+ :init-value nil
+ ;; The indicator for the mode line.
+ :lighter " asr"
+ :group 'auth-source
+
+ (let ((identifier 'auth-source-reveal-regexp)) ; The identifier symbol.
+ (if auth-source-reveal-mode
+ ;; Install the coverup magic.
+ (when (text-coverup-add-coverup
+ identifier
+ ;; The regexp to hide/reveal.
+ (if (apply #'derived-mode-p auth-source-reveal-json-modes)
+ (format "\"?password\"?[:[:blank:]]+\"\\([^\t\r\n\"]+\\)\""
+ auth-source-reveal-regex)
+ (format "\\b%s\\b\\s-+\\([^ \t\r\n]+\\)"
+ auth-source-reveal-regex))
+ ;; The replacement symbol or composed string.
+ auth-source-reveal-hider
+ ;; A custom compose matcher.
+ #'auth-source-reveal-compose-p)
+ (unless text-coverup-uncover-at-point
+ (auth-source-do-warn
+ "Please set `%s' to _see_ passwords at point"
+ 'text-coverup-uncover-at-point)))
+ ;; Else, when disabling, remove the coverups for our identifier.
+ (text-coverup-remove-coverups identifier))))
+
+;;;###autoload
+(defun turn-on-auth-source-reveal-mode ()
+ (when (not auth-source-reveal-mode)
+ (auth-source-reveal-mode 1)))
(provide 'auth-source)