summaryrefslogtreecommitdiff
path: root/lisp/allout.el
diff options
context:
space:
mode:
authorKen Manheimer <ken.manheimer@gmail.com>2011-07-04 18:16:10 -0400
committerKen Manheimer <ken.manheimer@gmail.com>2011-07-04 18:16:10 -0400
commit13aa217bacf43ef70b68e5287e714366e77ae61d (patch)
tree9b10994dcb416dd3dc966d452866b21377273108 /lisp/allout.el
parentac89b32c15b8962fd388b1f568f0945885a017c7 (diff)
downloademacs-13aa217bacf43ef70b68e5287e714366e77ae61d.tar.gz
* allout.el (allout-encrypt-unencrypted-on-saves): Do not provide insecure
exception for current topic. Also note that auto-saves are handled differently. (allout-auto-save-temporarily-disabled), (allout-just-did-undo): State variables for tracking auto-save inhibition situation. (allout-write-contents-hook-handler): Rename from 'allout-write-file-hook-handler', and describe how it depends on write-contents-functions sensitivity to non-nil value to prevent file write. (allout-auto-save-hook-handler): Remove. auto-save does not check this in individual buffers, only in the starting buffer, so this is not the right way for us to inhibit auto-save in a buffer according to its condition. (allout-mode): Use new allout-write-contents-hook-handler, and only with write-contents-functions. Remove auto-save provisions - they're implemented elsewhere. (allout-before-change-handler): If undo is in progress, note that for attention of allout-post-command-business. (allout-post-command-business): If the command we're following was an undo, check for change in the status of encrypted items and adjust auto-save inhibitions accordingly. (allout-toggle-subtree-encryption): Adjust auto-save inhibition according to whether there are or aren't any plain-text topics pending encryption. (allout-inhibit-auto-save-info-for-decryption): Adjust buffer-saved-size and some allout state to inhibit auto-saves if there are plain-text topics pending encryption. (allout-maybe-resume-auto-save-info-after-encryption): Adjust buffer-saved-size and some allout state to not inhibit auto-saves if there are no longer any plain-text topics pending encryption. (allout-next-topic-pending-encryption), (allout-encrypt-decrypted): No longer provide for exemption of the current topic.
Diffstat (limited to 'lisp/allout.el')
-rw-r--r--lisp/allout.el206
1 files changed, 118 insertions, 88 deletions
diff --git a/lisp/allout.el b/lisp/allout.el
index d238745df17..5b8a7a7de1a 100644
--- a/lisp/allout.el
+++ b/lisp/allout.el
@@ -823,37 +823,32 @@ formatted copy."
:group 'allout-encryption)
;;;_ = allout-encrypt-unencrypted-on-saves
(defcustom allout-encrypt-unencrypted-on-saves t
- "When saving, should topics pending encryption be encrypted?
-
-The idea is to prevent file-system exposure of any un-encrypted stuff, and
-mostly covers both deliberate file writes and auto-saves.
-
- - Yes: encrypt all topics pending encryption, even if it's the one
- currently being edited. (In that case, the currently edited topic
- will be automatically decrypted before any user interaction, so they
- can continue editing but the copy on the file system will be
- encrypted.)
- Auto-saves will use the \"All except current topic\" mode if this
- one is selected, to avoid practical difficulties -- see below.
- - All except current topic: skip the topic currently being edited, even if
- it's pending encryption. This may expose the current topic on the
- file sytem, but avoids the nuisance of prompts for the encryption
- passphrase in the middle of editing for, eg, autosaves.
- This mode is used for auto-saves for both this option and \"Yes\".
- - No: leave it to the user to encrypt any unencrypted topics.
-
-For practical reasons, auto-saves always use the 'except-current policy
-when auto-encryption is enabled. (Otherwise, spurious passphrase prompts
-and unavoidable timing collisions are too disruptive.) If security for a
-file requires that even the current topic is never auto-saved in the clear,
-disable auto-saves for that file."
-
- :type '(choice (const :tag "Yes" t)
- (const :tag "All except current topic" except-current)
- (const :tag "No" nil))
- :version "22.1"
+ "If non-nil, topics pending encryption are encrypted during buffer saves.
+
+This provents file-system exposure of un-encrypted contents of
+items marked for encryption.
+
+When non-nil, if the topic currently being edited is decrypted,
+it will be encrypted for saving but automatically decrypted
+before any subsequent user interaction, so it is once again clear
+text for editing though the file system copy is encrypted.
+
+\(Auto-saves are handled differently. Buffers with plain-text
+exposed encrypted topics are exempted from auto saves until all
+such topics are encrypted.)"
+
+ :type 'boolean
+ :version "23.1"
:group 'allout-encryption)
(make-variable-buffer-local 'allout-encrypt-unencrypted-on-saves)
+(defvar allout-auto-save-temporarily-disabled nil
+ "True while topic encryption is pending and auto-saving was active.
+
+The value of buffer-saved-size at the time of decryption is used,
+for restoring when all encryptions are established.")
+(defvar allout-just-did-undo nil
+ "True just after undo commands, until allout-post-command-business.")
+(make-variable-buffer-local 'allout-just-did-undo)
;;;_ + Developer
;;;_ = allout-developer group
@@ -1564,39 +1559,43 @@ See `allout-encryption-ciphertext-rejection-regexps' for rejection reasons.")
(defmacro allout-mode-p ()
"Return t if `allout-mode' is active in current buffer."
'allout-mode)
-;;;_ > allout-write-file-hook-handler ()
-(defun allout-write-file-hook-handler ()
- "Implement `allout-encrypt-unencrypted-on-saves' policy for file writes."
+;;;_ > allout-write-contents-hook-handler ()
+(defun allout-write-contents-hook-handler ()
+ "Implement `allout-encrypt-unencrypted-on-saves' for file writes
+
+Return nil if all goes smoothly, or else return an informative
+message if an error is encountered. The message will serve as a
+non-nil return on `write-contents-functions' to prevent saving of
+the buffer while it has decrypted content.
+
+This behavior depends on emacs versions that implement the
+`write-contents-functions' hook."
(if (or (not (allout-mode-p))
(not (boundp 'allout-encrypt-unencrypted-on-saves))
(not allout-encrypt-unencrypted-on-saves))
nil
- (let ((except-mark (and (equal allout-encrypt-unencrypted-on-saves
- 'except-current)
- (point-marker))))
- (if (save-excursion (goto-char (point-min))
- (allout-next-topic-pending-encryption except-mark))
- (progn
- (message "auto-encrypting pending topics")
- (sit-for 0)
- (condition-case failure
+ (if (save-excursion (goto-char (point-min))
+ (allout-next-topic-pending-encryption))
+ (progn
+ (message "auto-encrypting pending topics")
+ (sit-for 0)
+ (condition-case failure
+ (progn
(setq allout-after-save-decrypt
- (allout-encrypt-decrypted except-mark))
- (error (message
- "allout-write-file-hook-handler suppressing error %s"
- failure)
- (sit-for 2)))))
- ))
- nil)
-;;;_ > allout-auto-save-hook-handler ()
-(defun allout-auto-save-hook-handler ()
- "Implement `allout-encrypt-unencrypted-on-saves' policy for auto save."
-
- (if (and (allout-mode-p) allout-encrypt-unencrypted-on-saves)
- ;; Always implement 'except-current policy when enabled.
- (let ((allout-encrypt-unencrypted-on-saves 'except-current))
- (allout-write-file-hook-handler))))
+ (allout-encrypt-decrypted))
+ ;; aok - return nil:
+ nil)
+ (error
+ ;; whoops - probably some still-decrypted items, return non-nil:
+ (let ((text (format (concat "%s contents write inhibited due to"
+ " encrypted topic encryption error:"
+ " %s")
+ (buffer-name (current-buffer))
+ failure)))
+ (message text)(sit-for 2)
+ text)))))
+ ))
;;;_ > allout-after-saves-handler ()
(defun allout-after-saves-handler ()
"Decrypt topic encrypted for save, if it's currently being edited.
@@ -1960,12 +1959,7 @@ OPEN: A TOPIC that is not CLOSED, though its OFFSPRING or BODY may be."
:lighter " Allout"
:keymap 'allout-mode-map
- (let ((write-file-hook-var-name (cond ((boundp 'write-file-functions)
- 'write-file-functions)
- ((boundp 'write-file-hooks)
- 'write-file-hooks)
- (t 'local-write-file-hooks)))
- (use-layout (if (listp allout-layout)
+ (let ((use-layout (if (listp allout-layout)
allout-layout
allout-default-layout)))
@@ -1984,9 +1978,8 @@ OPEN: A TOPIC that is not CLOSED, though its OFFSPRING or BODY may be."
(remove-hook 'post-command-hook 'allout-post-command-business t)
(remove-hook 'before-change-functions 'allout-before-change-handler t)
(remove-hook 'isearch-mode-end-hook 'allout-isearch-end-handler t)
- (remove-hook write-file-hook-var-name
- 'allout-write-file-hook-handler t)
- (remove-hook 'auto-save-hook 'allout-auto-save-hook-handler t)
+ (remove-hook 'write-contents-functions
+ 'allout-write-contents-hook-handler t)
(remove-overlays (point-min) (point-max)
'category 'allout-exposure-category))
@@ -2019,9 +2012,8 @@ OPEN: A TOPIC that is not CLOSED, though its OFFSPRING or BODY may be."
(add-hook 'post-command-hook 'allout-post-command-business nil t)
(add-hook 'before-change-functions 'allout-before-change-handler nil t)
(add-hook 'isearch-mode-end-hook 'allout-isearch-end-handler nil t)
- (add-hook write-file-hook-var-name 'allout-write-file-hook-handler
+ (add-hook 'write-contents-functions 'allout-write-contents-hook-handler
nil t)
- (add-hook 'auto-save-hook 'allout-auto-save-hook-handler nil t)
;; Stash auto-fill settings and adjust so custom allout auto-fill
;; func will be used if auto-fill is active or activated. (The
@@ -2154,8 +2146,10 @@ internal functions use this feature cohesively bunch changes."
See `allout-overlay-interior-modification-handler' for details."
- (when (and (allout-mode-p) undo-in-progress (allout-hidden-p))
- (allout-show-children))
+ (when (and (allout-mode-p) undo-in-progress)
+ (setq allout-just-did-undo t)
+ (if (allout-hidden-p)
+ (allout-show-children)))
;; allout-overlay-interior-modification-handler on an overlay handles
;; this in other emacs, via `allout-exposure-category's 'modification-hooks.
@@ -3308,12 +3302,29 @@ coordinating with allout activity.")
- Implement (and clear) `allout-post-goto-bullet', for hot-spot
outline commands.
+- If the command we're following was an undo, check for change in
+ the status of encrypted items and adjust auto-save inhibitions
+ accordingly.
+
- Decrypt topic currently being edited if it was encrypted for a save."
- ; Apply any external change func:
(if (not (allout-mode-p)) ; In allout-mode.
nil
+ (when allout-just-did-undo
+ (setq allout-just-did-undo nil)
+ (cond ((and (= buffer-saved-size -1)
+ allout-auto-save-temporarily-disabled)
+ ;; user possibly undid a decryption, deinhibit auto-save:
+ (allout-maybe-resume-auto-save-info-after-encryption))
+ ((save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (not (allout-next-topic-pending-encryption))))
+ ;; plain-text encrypted items are present, inhibit auto-save:
+ (allout-inhibit-auto-save-info-for-decryption (buffer-size)))))
+
(if (and (boundp 'allout-after-save-decrypt)
allout-after-save-decrypt)
(allout-after-saves-handler))
@@ -5899,6 +5910,8 @@ See `allout-toggle-current-subtree-encryption' for more details."
" shift it in to make it encryptable")))
(let* ((allout-buffer (current-buffer))
+ ;; for use with allout-auto-save-temporarily-disabled, if necessary:
+ (was-buffer-saved-size buffer-saved-size)
;; Assess location:
(bullet-pos allout-recent-prefix-beginning)
(after-bullet-pos (point))
@@ -5978,6 +5991,12 @@ See `allout-toggle-current-subtree-encryption' for more details."
;; Add the is-encrypted bullet qualifier:
(goto-char after-bullet-pos)
(insert "*"))))
+
+ ;; adjust buffer's auto-save eligibility:
+ (if was-encrypted
+ (allout-inhibit-auto-save-info-for-decryption was-buffer-saved-size)
+ (allout-maybe-resume-auto-save-info-after-encryption))
+
(run-hook-with-args 'allout-structure-added-hook
bullet-pos subtree-end))))
;;;_ > allout-encrypt-string (text decrypt allout-buffer keymode-cue
@@ -6029,6 +6048,7 @@ signal."
(epg-context-set-passphrase-callback
context #'epa-passphrase-callback-function)
context))
+
(encoding (with-current-buffer allout-buffer
buffer-file-coding-system))
(multibyte (with-current-buffer allout-buffer
@@ -6150,8 +6170,29 @@ signal."
result-text))
(error (concat "Encryption produced non-armored text, which"
"conflicts with allout mode -- reconfigure!")))
-
(t result-text))))
+;;;_ > allout-inhibit-auto-save-info-for-decryption
+(defun allout-inhibit-auto-save-info-for-decryption (was-buffer-saved-size)
+ "Temporarily prevent auto-saves in this buffer when an item is decrypted.
+
+WAS-BUFFER-SAVED-SIZE is the value of buffer-saved-size *before*
+the decryption."
+ (when (not (or (= buffer-saved-size -1) (= was-buffer-saved-size -1)))
+ (setq allout-auto-save-temporarily-disabled was-buffer-saved-size
+ buffer-saved-size -1)))
+;;;_ > allout-maybe-resume-auto-save-info-after-encryption ()
+(defun allout-maybe-resume-auto-save-info-after-encryption ()
+ "Restore auto-save info, *if* there are no topics pending encryption."
+ (when (and allout-auto-save-temporarily-disabled
+ (= buffer-saved-size -1)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (not (allout-next-topic-pending-encryption)))))
+ (setq buffer-saved-size allout-auto-save-temporarily-disabled
+ allout-auto-save-temporarily-disabled nil)))
+
;;;_ > allout-encrypted-topic-p ()
(defun allout-encrypted-topic-p ()
"True if the current topic is encryptable and encrypted."
@@ -6162,14 +6203,10 @@ signal."
(save-match-data (looking-at "\\*")))
)
)
-;;;_ > allout-next-topic-pending-encryption (&optional except-mark)
-(defun allout-next-topic-pending-encryption (&optional except-mark)
+;;;_ > allout-next-topic-pending-encryption ()
+(defun allout-next-topic-pending-encryption ()
"Return the point of the next topic pending encryption, or nil if none.
-EXCEPT-MARK identifies a point whose containing topics should be excluded
-from encryption. This supports 'except-current mode of
-`allout-encrypt-unencrypted-on-saves'.
-
Such a topic has the `allout-topic-encryption-bullet' without an
immediately following '*' that would mark the topic as being encrypted. It
must also have content."
@@ -6204,10 +6241,7 @@ must also have content."
(setq content-beg (point))
(backward-char 1)
(allout-end-of-subtree)
- (if (or (<= (point) content-beg)
- (and except-mark
- (<= content-beg except-mark)
- (>= (point) except-mark)))
+ (if (<= (point) content-beg)
;; Continue looking
(setq got nil)
;; Got it!
@@ -6219,14 +6253,10 @@ must also have content."
)
)
)
-;;;_ > allout-encrypt-decrypted (&optional except-mark)
-(defun allout-encrypt-decrypted (&optional except-mark)
+;;;_ > allout-encrypt-decrypted ()
+(defun allout-encrypt-decrypted ()
"Encrypt topics pending encryption except those containing exemption point.
-EXCEPT-MARK identifies a point whose containing topics should be excluded
-from encryption. This supports the `except-current' mode of
-`allout-encrypt-unencrypted-on-saves'.
-
If a topic that is currently being edited was encrypted, we return a list
containing the location of the topic and the location of the cursor just
before the topic was encrypted. This can be used, eg, to decrypt the topic
@@ -6242,7 +6272,7 @@ save. See `allout-encrypt-unencrypted-on-saves' for more info."
bo-subtree
editing-topic editing-point)
(goto-char (point-min))
- (while (allout-next-topic-pending-encryption except-mark)
+ (while (allout-next-topic-pending-encryption)
(setq was-modified (buffer-modified-p))
(when (save-excursion
(and (boundp 'allout-encrypt-unencrypted-on-saves)