diff options
| author | Jens Schmidt | 2023-05-21 21:37:35 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2023-05-31 15:53:10 +0300 |
| commit | 372bc1278c2d7c2440bb3d528f4c4e03402d21b5 (patch) | |
| tree | 49ed4941aa7d6aef24b250116eaba75b55fb7479 | |
| parent | 23a14e7b9026a8572fe8ae8759232e08cd37910a (diff) | |
| download | emacs-372bc1278c2d7c2440bb3d528f4c4e03402d21b5.tar.gz emacs-372bc1278c2d7c2440bb3d528f4c4e03402d21b5.zip | |
Add internal documentation on plstore.el
* lisp/plstore.el: Add internal documentation and some words of
warning in the user documentation. (Bug#63627)
| -rw-r--r-- | lisp/plstore.el | 133 |
1 files changed, 131 insertions, 2 deletions
diff --git a/lisp/plstore.el b/lisp/plstore.el index 0276a752a0f..1a0dacffb01 100644 --- a/lisp/plstore.el +++ b/lisp/plstore.el | |||
| @@ -24,6 +24,14 @@ | |||
| 24 | 24 | ||
| 25 | ;; Plist based data store providing search and partial encryption. | 25 | ;; Plist based data store providing search and partial encryption. |
| 26 | ;; | 26 | ;; |
| 27 | ;; By default, this package uses symmetric encryption, which means | ||
| 28 | ;; that you have to enter the password protecting your store more | ||
| 29 | ;; often than you probably expect to. To use public key encryption | ||
| 30 | ;; with this package, create a GnuPG key and customize user option | ||
| 31 | ;; `plstore-encrypt-to' to use it. You can then configure the GnuPG | ||
| 32 | ;; agent to adjust caching and expiration of the passphrase for your | ||
| 33 | ;; store. | ||
| 34 | ;; | ||
| 27 | ;; Creating: | 35 | ;; Creating: |
| 28 | ;; | 36 | ;; |
| 29 | ;; ;; Open a new store associated with ~/.emacs.d/auth.plist. | 37 | ;; ;; Open a new store associated with ~/.emacs.d/auth.plist. |
| @@ -43,12 +51,16 @@ | |||
| 43 | ;; ;; Kill the buffer visiting ~/.emacs.d/auth.plist. | 51 | ;; ;; Kill the buffer visiting ~/.emacs.d/auth.plist. |
| 44 | ;; (plstore-close store) | 52 | ;; (plstore-close store) |
| 45 | ;; | 53 | ;; |
| 54 | ;; Avoid marking one property both as public *and* secret, as the | ||
| 55 | ;; behavior of this package with respect to such duplicate properties | ||
| 56 | ;; is not (yet) defined. | ||
| 57 | ;; | ||
| 46 | ;; Searching: | 58 | ;; Searching: |
| 47 | ;; | 59 | ;; |
| 48 | ;; (setq store (plstore-open (expand-file-name "~/.emacs.d/auth.plist"))) | 60 | ;; (setq store (plstore-open (expand-file-name "~/.emacs.d/auth.plist"))) |
| 49 | ;; | 61 | ;; |
| 50 | ;; ;; As the entry "foo" associated with "foo.example.org" has no | 62 | ;; ;; As the entry "foo" associated with "foo.example.org" has no |
| 51 | ;; ;; secret properties, no need to decryption. | 63 | ;; ;; secret properties, no need for decryption. |
| 52 | ;; (plstore-find store '(:host ("foo.example.org"))) | 64 | ;; (plstore-find store '(:host ("foo.example.org"))) |
| 53 | ;; | 65 | ;; |
| 54 | ;; ;; As the entry "bar" associated with "bar.example.org" has a | 66 | ;; ;; As the entry "bar" associated with "bar.example.org" has a |
| @@ -73,10 +85,112 @@ | |||
| 73 | ;; | 85 | ;; |
| 74 | ;; where the prefixing `:secret-' means the property (without | 86 | ;; where the prefixing `:secret-' means the property (without |
| 75 | ;; `:secret-' prefix) is marked as secret. Thus, when you save the | 87 | ;; `:secret-' prefix) is marked as secret. Thus, when you save the |
| 76 | ;; buffer, the `:secret-user' property is encrypted as `:user'. | 88 | ;; buffer, the `:secret-user' property is encrypted as `:user'. Do |
| 89 | ;; not use a property consisting solely of the prefix, as the behavior | ||
| 90 | ;; of this package with respect to such properties is not (yet) | ||
| 91 | ;; defined. | ||
| 77 | ;; | 92 | ;; |
| 78 | ;; You can toggle the view between encrypted form and the decrypted | 93 | ;; You can toggle the view between encrypted form and the decrypted |
| 79 | ;; form with C-c C-c. | 94 | ;; form with C-c C-c. |
| 95 | ;; | ||
| 96 | ;; If you have opened a plstore with `plstore-open' you should not | ||
| 97 | ;; edit its underlying buffer in `plstore-mode' or in any other way at | ||
| 98 | ;; the same time, since your manual changes will be overwritten when | ||
| 99 | ;; `plstore-save' is called on that plstore. | ||
| 100 | ;; | ||
| 101 | ;; Internals: | ||
| 102 | ;; | ||
| 103 | ;; This is information on the internal data structure and functions of | ||
| 104 | ;; this package. None of it should be necessary to actually use it. | ||
| 105 | ;; For easier reading, we usually do not distinguish in this internal | ||
| 106 | ;; documentation between a Lisp object and its printed representation. | ||
| 107 | ;; | ||
| 108 | ;; A plstore corresponds to an alist mapping strings to property | ||
| 109 | ;; lists. Internally, that alist is organized as two alists, one | ||
| 110 | ;; mapping to the non-secret properties and placeholders for the | ||
| 111 | ;; secret properties (called "template alist" with identifier ALIST) | ||
| 112 | ;; and one mapping to the secret properties ("secret alist", | ||
| 113 | ;; SECRET-ALIST). The secret alist is read from and written to file | ||
| 114 | ;; as pgp-encrypted printed representation of the alist ("encrypted | ||
| 115 | ;; data", ENCRYPTED-DATA). | ||
| 116 | ;; | ||
| 117 | ;; During the lifetime of a plstore, a third type of alist may pop up, | ||
| 118 | ;; which maps to the merged non-secret properties and plain-text | ||
| 119 | ;; secret properties ("merged alist", MERGED-ALIST). | ||
| 120 | ;; | ||
| 121 | ;; After executing the "foo", "bar", "baz" example from above the | ||
| 122 | ;; alists described above look like the following: | ||
| 123 | ;; | ||
| 124 | ;; Template Alist: | ||
| 125 | ;; | ||
| 126 | ;; (("foo" :host "foo.example.org" :port 80) | ||
| 127 | ;; ("bar" :secret-user t :host "bar.example.org") | ||
| 128 | ;; ("baz" :secret-password t :host "baz.example.org")) | ||
| 129 | ;; | ||
| 130 | ;; Secret Alist: | ||
| 131 | ;; | ||
| 132 | ;; (("bar" :user "test") | ||
| 133 | ;; ("baz" :password "test")) | ||
| 134 | ;; | ||
| 135 | ;; Merged Alist: | ||
| 136 | ;; | ||
| 137 | ;; (("foo" :host "foo.example.org" :port 80) | ||
| 138 | ;; ("bar" :user "test" :host "bar.example.org") | ||
| 139 | ;; ("baz" :password "test" :host "baz.example.org")) | ||
| 140 | ;; | ||
| 141 | ;; Finally, a plstore requires a buffer ("plstore buffer", BUFFER) for | ||
| 142 | ;; conversion between its Lisp objects and its file representation. | ||
| 143 | ;; It is important to note that this buffer is *not* continuously | ||
| 144 | ;; synchronized as the plstore changes. During the lifetime of a | ||
| 145 | ;; plstore, its buffer is read from in function `plstore-open' and | ||
| 146 | ;; (destructively) written to in `plstore-save', but not touched | ||
| 147 | ;; otherwise. We call the file visited by the plstore buffer the | ||
| 148 | ;; associated file of the plstore. | ||
| 149 | ;; | ||
| 150 | ;; With the identifiers defined above a plstore is a vector with the | ||
| 151 | ;; following elements and accessor functions: | ||
| 152 | ;; | ||
| 153 | ;; [ | ||
| 154 | ;; BUFFER ; plstore--get/set-buffer | ||
| 155 | ;; ALIST ; plstore--get/set-alist | ||
| 156 | ;; ENCRYPTED-DATA ; plstore--get/set-encrypted-data | ||
| 157 | ;; SECRET-ALIST ; plstore--get/set-secret-alist | ||
| 158 | ;; MERGED-ALIST ; plstore--get/set-merged-alist | ||
| 159 | ;; ] | ||
| 160 | ;; | ||
| 161 | ;; When a plstore is created through `plstore-open', its ALIST and | ||
| 162 | ;; ENCRYPTED-DATA are initialized from the contents of BUFFER without | ||
| 163 | ;; any decryption taking place, and MERGED-ALIST is initialized as a | ||
| 164 | ;; copy of ALIST. (Which means that at that stage the merged alist | ||
| 165 | ;; still contains the secret property placeholders!) | ||
| 166 | ;; | ||
| 167 | ;; During on-demand decryption of a plstore through function | ||
| 168 | ;; `plstore--decrypt', SECRET-ALIST is populated from ENCRYPTED-DATA, | ||
| 169 | ;; which is in turn replaced by value nil. (Which further serves as | ||
| 170 | ;; an indicator that the plstore has been decrypted already.) In | ||
| 171 | ;; addition, MERGED-ALIST is recomputed by function | ||
| 172 | ;; `plstore--merge-secret' to replace the secret property placeholders | ||
| 173 | ;; by their plain-text secret property equivalents. | ||
| 174 | ;; | ||
| 175 | ;; The file representation of a plstore consists of two Lisp forms plus | ||
| 176 | ;; markers to introduce them: | ||
| 177 | ;; | ||
| 178 | ;; ;;; public entries | ||
| 179 | ;; ALIST | ||
| 180 | ;; ;;; secret entries | ||
| 181 | ;; ENCRYPTED-DATA | ||
| 182 | ;; | ||
| 183 | ;; Both of these are optional, but the first section must be present | ||
| 184 | ;; if the second one is. If both sections are missing, the plstore is | ||
| 185 | ;; empty. If the second section is missing, it contains only | ||
| 186 | ;; non-secret data. If present, the printed representation of the | ||
| 187 | ;; encrypted data includes the delimiting double quotes. | ||
| 188 | ;; | ||
| 189 | ;; The plstore API (`plstore-open', `plstore-put', etc.) and the | ||
| 190 | ;; plstore mode implemented by `plstore-mode' are orthogonal to each | ||
| 191 | ;; other and should not be mixed up. In particular, encoding and | ||
| 192 | ;; decoding a plstore mode buffer with `plstore-mode-toggle-display' | ||
| 193 | ;; is not related in any way to the state of the plstore buffer. | ||
| 80 | 194 | ||
| 81 | ;;; Code: | 195 | ;;; Code: |
| 82 | 196 | ||
| @@ -457,6 +571,21 @@ If no one is selected, symmetric encryption will be performed. " | |||
| 457 | (plstore--insert-buffer plstore) | 571 | (plstore--insert-buffer plstore) |
| 458 | (save-buffer))) | 572 | (save-buffer))) |
| 459 | 573 | ||
| 574 | ;; The functions related to plstore mode unfortunately introduce yet | ||
| 575 | ;; another alist format ("decoded alist"). After executing the "foo", | ||
| 576 | ;; "bar", "baz" example from above the decoded alist of the plstore | ||
| 577 | ;; would look like the following: | ||
| 578 | ;; | ||
| 579 | ;; (("foo" :host "foo.example.org" :port 80) | ||
| 580 | ;; ("bar" :secret-user "test" :host "bar.example.org") | ||
| 581 | ;; ("baz" :secret-password "test" :host "baz.example.org")) | ||
| 582 | ;; | ||
| 583 | ;; Even more unfortunately, variable and function names of the | ||
| 584 | ;; following are a bit mixed up IMHO: With the current names, the | ||
| 585 | ;; result of function `plstore--encode' is used to create what is | ||
| 586 | ;; presented as "decoded form of a plstore" to the user. And variable | ||
| 587 | ;; `plstore-encoded' is non-nil if a buffer shows the decoded form. | ||
| 588 | |||
| 460 | (defun plstore--encode (plstore) | 589 | (defun plstore--encode (plstore) |
| 461 | (plstore--decrypt plstore) | 590 | (plstore--decrypt plstore) |
| 462 | (let ((merged-alist (plstore--get-merged-alist plstore))) | 591 | (let ((merged-alist (plstore--get-merged-alist plstore))) |