unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* new version of allout.el - patch and ChangeLog
@ 2005-09-30 17:24 Ken Manheimer
  2005-09-30 21:06 ` Sascha Wilde
       [not found] ` <E1ELj0L-0000Pn-3T@fencepost.gnu.org>
  0 siblings, 2 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-09-30 17:24 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 1881 bytes --]

attached is a patch and ChangeLog for a substantial new version of
allout.el, emacs' alternative (and much more extensive) outliner.  i
think it's ready to revise the distributed version.

this version adds topic encryption, using GPG.  it also includes
several fixes and enhancements, described in the ChangeLog entry

below is the synopsis of just the encryption features, from the ChangeLog entry.

	  - new subsystem supporting easy gpg topic encryption/decryption.

	    salient features:

	    - both public- and symmetric-key modes are supported.
	    - encryption being on a per-topic basis means you can
	      intersperse encrypted and clear-text data in a single file
	      to your heart's content.
	    - user-provided symmetric-key hints, with consistency
	      verification to help user avoid confusion
	    - time-limited key reuse, a la (and using) mailcrypt's
	      mc-passwd-timeout
	    - write-file-hook and auto-save-hook activities to support auto
	      encryption of pending topics on save; provision to skip
	      currently-edited topic to avoid editing disturbance

	    topic encryption functionality depends on both mailcrypt and
	    crypt++ packages.  (non-encryption allout functionality is not
	    disrupted if either mailcrypt or crypt++ are absent.)

	    `allout-toggle-current-subtree-encryption' is the central
	    routine.

	    there are a five new encryption customization variables:

	    - allout-topic-encryption-bullet
	    - allout-default-encryption-scheme
	    - allout-key-verifier-handling
	    - allout-key-hint-handling
	    - allout-encrypt-unencrypted-on-saves

	    topic encryption is included in mouse menu

	    docstring for `allout-toggle-current-subtree-encryption'
	    and customization variables provide detailed description.

ken manheimer
ken.manheimer@gmail.com

[-- Attachment #2: allout-patch.txt --]
[-- Type: text/plain, Size: 115417 bytes --]

--- allout.el.~1.61.~	2005-08-06 18:13:41.000000000 -0400
+++ allout.el	2005-09-30 13:09:03.000000000 -0400
@@ -3,10 +3,11 @@
 ;; Copyright (C) 1992, 1993, 1994, 2001, 2002, 2003, 2004,
 ;;   2005 Free Software Foundation, Inc.
 
-;; Author: Ken Manheimer <klm@zope.com>
-;; Maintainer: Ken Manheimer <klm@zope.com>
+;; Author: Ken Manheimer <ken dot manheimer at gmail dot com>
+;; Maintainer: Ken Manheimer <ken dot manheimer at gmail dot com>
 ;; Created: Dec 1991 - first release to usenet
-;; Keywords: outlines mode wp languages
+;; Version: $Id: allout.el,v 1.67 2005/09/30 17:15:24 klm Exp $||
+;; Keywords: outlines wp languages
 
 ;; This file is part of GNU Emacs.
 
@@ -34,43 +35,68 @@
 ;; programming languages.  (For an example, see the allout code
 ;; itself, which is organized in ;; an outline framework.)
 ;;
-;; In addition to outline navigation and exposure, allout includes:
+;; Some features:
 ;;
-;;  - topic-oriented repositioning, cut, and paste
-;;  - integral outline exposure-layout
-;;  - incremental search with dynamic exposure and reconcealment of hidden text
+;;  - classic outline-mode topic-oriented navigation and exposure adjustment
+;;  - topic-oriented editing including coherent topic and subtopic
+;;    creation, promotion, demotion, cut/paste across depths, etc
+;;  - incremental search with dynamic exposure and reconcealment of text
+;;  - customizable bullet format enbles programming-language specific
+;;    outlining, for ultimate code-folding editing.  (allout code itself is
+;;    formatted as an outline - do ESC-x eval-current-buffer in allout.el
+;;    to try it out.)
+;;  - configurable per-file initial exposure settings
+;;  - symmetric-key and key-pair topic encryption, plus reliable key
+;;    verification and user-supplied hint maintenance.  (see
+;;    allout-toggle-current-subtree-encryption docstring.)
 ;;  - automatic topic-number maintenance
-;;  - "Hot-spot" operation, for single-keystroke maneuvering and
-;;    exposure control.  (See the `allout-mode' docstring.)
+;;  - "hot-spot" operation, for single-keystroke maneuvering and
+;;    exposure control (see the allout-mode docstring)
+;;  - easy rendering of exposed portions into numbered, latex, indented, etc
+;;    outline styles
 ;;
-;; and many other features.
+;; and more.
 ;;
 ;; The outline menubar additions provide quick reference to many of
-;; the features, and see the docstring of the function `allout-init'
-;; for instructions on priming your Emacs session for automatic
-;; activation of `allout-mode'.
+;; the features, and see the docstring of the variable `allout-init'
+;; for instructions on priming your emacs session for automatic
+;; activation of allout-mode.
 ;;
 ;; See the docstring of the variables `allout-layout' and
 ;; `allout-auto-activation' for details on automatic activation of
-;; allout `allout-mode' as a minor mode.  (It has changed since allout
+;; `allout-mode' as a minor mode.  (It has changed since allout
 ;; 3.x, for those of you that depend on the old method.)
 ;;
 ;; Note - the lines beginning with `;;;_' are outline topic headers.
 ;;        Just `ESC-x eval-current-buffer' to give it a whirl.
 
-;; Ken Manheimer	klm@zope.com
+;; ken manheimer (ken dot manheimer at gmail dot com)
 
 ;;; Code:
 
 ;;;_* Provide
+;(provide 'outline)
 (provide 'allout)
 
+;;;_* Dependency autoloads
+(eval-when-compile 'cl)                 ; otherwise, flet compilation fouls
+(autoload 'crypt-encrypt-buffer "crypt++")
+(setq-default crypt-encryption-type 'gpg)
+
+(autoload 'mc-encrypt "mailcrypt"
+  "*Encrypt the current buffer")
+(autoload 'mc-activate-passwd "mailcrypt"
+  "Activate the passphrase matching ID, using PROMPT for a prompt.
+Return the passphrase.  If PROMPT is nil, only return value if cached.")
+(autoload 'mc-gpg-process-region "mc-gpg")
+(autoload 'mc-dectivate-passwd "mailcrypt"
+  "*Deactivate the passphrase cache.")
+
 ;;;_* USER CUSTOMIZATION VARIABLES:
 (defgroup allout nil
   "Extensive outline mode for use alone and with other modes."
   :prefix "allout-"
-  :group 'editing
-  :version "22.1")
+  :group 'outlines)
 
 ;;;_ + Layout, Mode, and Topic Header Configuration
 
@@ -111,8 +137,8 @@
 
 A list value specifies a default layout for the current buffer, to be
 applied upon activation of `allout-mode'.  Any non-nil value will
-automatically trigger `allout-mode', provided `allout-init'
-has been called to enable it.
+automatically trigger `allout-mode', provided `allout-init' has been called
+to enable it.
 
 See the docstring for `allout-init' for details on setting up for
 auto-mode-activation, and for `allout-expose-topic' for the format of
@@ -171,7 +197,7 @@
   :group 'allout)
 (make-variable-buffer-local 'allout-primary-bullet)
 ;;;_  = allout-plain-bullets-string
-(defcustom allout-plain-bullets-string ".:,;"
+(defcustom allout-plain-bullets-string ".,"
   "*The bullets normally used in outline topic prefixes.
 
 See `allout-distinctive-bullets-string' for the other kind of
@@ -185,7 +211,7 @@
   :group 'allout)
 (make-variable-buffer-local 'allout-plain-bullets-string)
 ;;;_  = allout-distinctive-bullets-string
-(defcustom allout-distinctive-bullets-string "*+-=>([{}&!?#%\"X@$~_\\"
+(defcustom allout-distinctive-bullets-string "*+-=>()[{}&!?#%\"X@$~_\\:;^"
   "*Persistent outline header bullets used to distinguish special topics.
 
 These bullets are used to distinguish topics from the run-of-the-mill
@@ -198,12 +224,13 @@
  `?' question topics
  `\(' parenthetic comment \(with a matching close paren inside)
  `[' meta-note \(with a matching close ] inside)
- `\"' a quote
+ `\"' a quotation
  `=' value settings
  `~' \"more or less\"
+ `^' see above
 
-... just for example.  (`#' typically has a special meaning to the
-software, according to the value of `allout-numbered-bullet'.)
+ ... for example.  (`#' typically has a special meaning to the software,
+according to the value of `allout-numbered-bullet'.)
 
 See `allout-plain-bullets-string' for the selection of
 alternating bullets.
@@ -337,7 +364,6 @@
 Set this var to the bullet you want to use for file cross-references."
   :type '(choice (const nil) string)
   :group 'allout)
-
 ;;;_  = allout-presentation-padding
 (defcustom allout-presentation-padding 2
   "*Presentation-format white-space padding factor, for greater indent."
@@ -381,7 +407,7 @@
   :type 'string
   :group 'allout)
 ;;;_  - allout-title
-(defcustom allout-title '(or buffer-file-name (current-buffer-name))
+(defcustom allout-title '(or buffer-file-name (buffer-name))
   "*Expression to be evaluated to determine the title for LaTeX
 formatted copy."
   :type 'sexp
@@ -397,6 +423,94 @@
   :type 'string
   :group 'allout)
 
+;;;_ + Topic encryption
+;;;_  = allout-topic-encryption-bullet
+(defcustom allout-topic-encryption-bullet "~"
+  "*Bullet signifying encryption of the entry's body."
+  :type '(choice (const nil) string)
+  :group 'allout)
+;;;_  = allout-default-encryption-scheme
+(defcustom allout-default-encryption-scheme 'mc-scheme-gpg
+  "*Default allout outline topic encryption mode.
+
+See mailcrypt variable `mc-schemes' and mailcrypt docs for encryption schemes."
+  :type 'symbol
+  :group 'allout)
+;;;_  = allout-key-verifier-handling
+(defcustom allout-key-verifier-handling 'situate
+  "*Dictate outline encryption key verifier handling.
+
+The key verifier is string associated with a file that is encrypted with
+the file's current symmetric encryption key.  It is used, if present, to
+confirm that the key entered by the user is the same as the established
+one, or explicitly presenting the user with the choice to go with a
+new key when a difference is encountered.
+
+The range of values are:
+
+ situate - include key verifier string as text in the file's local-vars
+           section
+ transient - establish the value as a variable in the file's buffer, but
+             don't preserve it as a file variable.
+ disabled - don't establish or do verification.
+
+See the docstring for the `allout-enable-file-variable-adjustment'
+variable for details about allout ajustment of file variables."
+  :type '(choice (const situate)
+                 (const transient)
+                 (const disabled))
+  :group 'allout)
+(make-variable-buffer-local 'allout-key-verifier-handling)
+;;;_  = allout-key-hint-handling
+(defcustom allout-key-hint-handling 'always
+  "*Dictate outline encryption key reminder handling:
+
+ always - always show reminder when prompting
+ needed - show reminder on key entry failure
+ manage - never present reminder, but still manage a file-var entry for it
+ disabled - don't even manage the file variable entry
+
+See the docstring for the `allout-enable-file-variable-adjustment'
+variable for details about allout ajustment of file variables."
+  :type '(choice (const always)
+                 (const needed)
+                 (const manage)
+                 (const disabled))
+  :group 'allout)
+(make-variable-buffer-local 'allout-key-hint-handling)
+;;;_  = allout-encrypt-unencrypted-on-saves
+(defcustom allout-encrypt-unencrypted-on-saves 'except-current
+  "*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
+       key 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 key 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))
+  :group 'allout)
+(make-variable-buffer-local 'allout-encrypt-unencrypted-on-saves)
+
 ;;;_ + Miscellaneous customization
 
 ;;;_  = allout-command-prefix
@@ -422,13 +536,15 @@
         ("\C-f" allout-forward-current-level)
         ("\C-b" allout-backward-current-level)
         ("\C-a" allout-beginning-of-current-entry)
-        ("\C-e" allout-end-of-current-entry)
+        ("\C-e" allout-end-of-entry)
                                         ; Exposure commands:
         ("\C-i" allout-show-children)
         ("\C-s" allout-show-current-subtree)
         ("\C-h" allout-hide-current-subtree)
+        ("h" allout-hide-current-subtree)
         ("\C-o" allout-show-current-entry)
         ("!" allout-show-all)
+        ("x" allout-toggle-current-subtree-encryption)
                                         ; Alteration commands:
         (" " allout-open-sibtopic)
         ("." allout-open-subtopic)
@@ -489,19 +605,22 @@
 
 (make-variable-buffer-local 'allout-reindent-bodies)
 
-;;;_  = allout-inhibit-protection
-(defcustom allout-inhibit-protection nil
-  "*Non-nil disables warnings and confirmation-checks for concealed-text edits.
-
-Outline mode uses Emacs change-triggered functions to detect unruly
-changes to concealed regions.  Set this var non-nil to disable the
-protection, potentially increasing text-entry responsiveness a bit.
-
-This var takes effect at `allout-mode' activation, so you may have to
-deactivate and then reactivate the mode if you want to toggle the
-behavior."
+;;;_  = allout-enable-file-variable-adjustment
+(defcustom allout-enable-file-variable-adjustment t
+  "*If non-nil, some allout outline actions can edit Emacs file variables text.
+
+This can range from changes to existing entries, addition of new ones,
+and creation of a new local variables section when necessary.
+
+Emacs file variables adjustments are also inhibited if `enable-local-variables'
+is nil.
+
+Operations potentially causing edits include allout encryption routines.
+See the docstring for `allout-toggle-current-subtree-encryption' for
+details."
   :type 'boolean
   :group 'allout)
+(make-variable-buffer-local 'allout-enable-file-variable-adjustment)
 
 ;;;_* CODE - no user customizations below.
 
@@ -728,12 +847,17 @@
 			      (car (cdr cell)))))))
 	    keymap-list)
     map))
-
+;;;_   = allout-prior-bindings - being deprecated.
+(defvar allout-prior-bindings nil
+  "Variable for use in V18, with allout-added-bindings, for
+resurrecting, on mode deactivation, bindings that existed before
+activation.  Being deprecated.")
+;;;_   = allout-added-bindings - being deprecated
+(defvar allout-added-bindings nil
+  "Variable for use in V18, with allout-prior-bindings, for
+resurrecting, on mode deactivation, bindings that existed before
+activation.  Being deprecated.")
 ;;;_  : Menu bar
-(defvar allout-mode-exposure-menu)
-(defvar allout-mode-editing-menu)
-(defvar allout-mode-navigation-menu)
-(defvar allout-mode-misc-menu)
 (defun produce-allout-mode-menubar-entries ()
   (require 'easymenu)
   (easy-menu-define allout-mode-exposure-menu
@@ -759,7 +883,11 @@
 		      ["Shift Topic Out" allout-shift-out t]
 		      ["Rebullet Topic" allout-rebullet-topic t]
 		      ["Rebullet Heading" allout-rebullet-current-heading t]
-		      ["Number Siblings" allout-number-siblings t]))
+		      ["Number Siblings" allout-number-siblings t]
+		      "----"
+                      ["Toggle Topic Encryption"
+                       allout-toggle-current-subtree-encryption
+                       (> (allout-current-depth) 1)]))
   (easy-menu-define allout-mode-navigation-menu
 		    allout-mode-map
 		    "Allout outline navigation menu."
@@ -775,7 +903,7 @@
 		      "----"
 		      ["Beginning of Entry"
 		       allout-beginning-of-current-entry t]
-		      ["End of Entry" allout-end-of-current-entry t]
+		      ["End of Entry" allout-end-of-entry t]
 		      ["End of Subtree" allout-end-of-current-subtree t]))
   (easy-menu-define allout-mode-misc-menu
 		    allout-mode-map
@@ -855,13 +983,6 @@
           (setq allout-mode-prior-settings rebuild)))))
   )
 ;;;_  : Mode-specific incidentals
-;;;_   = allout-during-write-cue nil
-(defvar allout-during-write-cue nil
-  "Used to inhibit outline change-protection during file write.
-
-See also `allout-post-command-business', `allout-write-file-hook',
-`allout-before-change-protect', and `allout-post-command-business'
-functions.")
 ;;;_   = allout-pre-was-isearching nil
 (defvar allout-pre-was-isearching nil
   "Cue for isearch-dynamic-exposure mechanism, implemented in
@@ -869,22 +990,28 @@
 (make-variable-buffer-local 'allout-pre-was-isearching)
 ;;;_   = allout-isearch-prior-pos nil
 (defvar allout-isearch-prior-pos nil
-  "Cue for isearch-dynamic-exposure tracking, used by `allout-isearch-expose'.")
+  "Cue for isearch-dynamic-exposure tracking, used by
+`allout-isearch-expose'.")
 (make-variable-buffer-local 'allout-isearch-prior-pos)
-;;;_   = allout-override-protect nil
-(defvar allout-override-protect nil
-  "Used in `allout-mode' for regulate of concealed-text protection mechanism.
-
-Allout outline mode regulates alteration of concealed text to protect
-against inadvertent, unnoticed changes.  This is for use by specific,
-native outline functions to temporarily override that protection.
-It's automatically reset to nil after every buffer modification.")
-(make-variable-buffer-local 'allout-override-protect)
+;;;_   = allout-isearch-did-quit
+(defvar allout-isearch-did-quit nil
+  "Distinguishes isearch conclusion and cancellation.
+
+Maintained by allout-isearch-abort \(which is wrapped around the real
+isearch-abort), and monitored by allout-isearch-expose for action.")
+(make-variable-buffer-local 'allout-isearch-did-quit)
 ;;;_   > allout-unprotected (expr)
-(defmacro allout-unprotected (expression)
-  "Evaluate EXPRESSION with `allout-override-protect' let-bound to t."
-  `(let ((allout-override-protect t))
-     ,expression))
+(defmacro allout-unprotected (expr)
+  "Enable internal outline operations to alter read-only text."
+  `(let ((was-inhibit-r-o inhibit-read-only))
+     (unwind-protect
+         (progn
+           (setq inhibit-read-only t)
+           ,expr)
+       (setq inhibit-read-only was-inhibit-r-o)
+       )
+     )
+  )
 ;;;_   = allout-undo-aggregation
 (defvar allout-undo-aggregation 30
   "Amount of successive self-insert actions to bunch together per undo.
@@ -897,14 +1024,109 @@
   "Horrible hack used to prevent invalid multiple triggering of outline
 mode from prop-line file-var activation.  Used by `allout-mode' function
 to track repeats.")
-;;;_   > allout-write-file-hook ()
-(defun allout-write-file-hook ()
-  "In `allout-mode', run as a `write-contents-functions' activity.
-
-Currently just sets `allout-during-write-cue', so outline change-protection
-knows to keep inactive during file write."
-  (setq allout-during-write-cue t)
-  nil)
+;;;_   = allout-file-key-verifier-string
+(defvar allout-file-key-verifier-string nil
+  "Name for use as a file variable for verifying encryption key across
+sessions.")
+(make-variable-buffer-local 'allout-file-key-verifier-string)
+;;;_   = allout-encryption-scheme
+(defvar allout-encryption-scheme nil
+  "*Allout outline topic encryption scheme pending for the current buffer.
+
+Intended as a file-specific (buffer local) setting, it defaults to the
+value of allout-default-encryption-scheme if nil.")
+(make-variable-buffer-local 'allout-encryption-scheme)
+;;;_   = allout-key-verifier-string
+(defvar allout-key-verifier-string nil
+  "Setting used to test solicited encryption keys against that already
+associated with a file.
+
+It consists of an encrypted random string useful only to verify that a key
+entered by the user is effective for decryption.  The key itself is \*not*
+recorded in the file anywhere, and the encrypted contents are random binary
+characters to avoid exposing greater susceptibility to search attacks.
+
+The verifier string is retained as an Emacs file variable, as well as in
+the emacs buffer state, if file variable adjustments are enabled.  See
+`allout-enable-file-variable-adjustment' for details about that.")
+(make-variable-buffer-local 'allout-key-verifier-string)
+(setq-default allout-key-verifier-string nil)
+;;;_   = allout-key-hint-string
+(defvar allout-key-hint-string ""
+  "Variable used to retain a reminder string for a file's encryption key.
+
+See the description of `allout-key-hint-handling' for details about how
+the reminder is deployed.
+
+The hint is retained as an Emacs file variable, as well as in the emacs buffer
+state, if file variable adjustments are enabled.  See
+`allout-enable-file-variable-adjustment' for details about that.")
+(make-variable-buffer-local 'allout-key-hint-string)
+(setq-default allout-key-hint-string "")
+;;;_   = allout-after-save-decrypt
+(defvar allout-after-save-decrypt nil
+  "Internal variable, is nil or has the value of two points:
+
+ - the location of a topic to be decrypted after saving is done
+ - where to situate the cursor after the decryption is performed
+
+This is used to decrypt the topic that was currently being edited, if it
+was encrypted automatically as part of a file write or autosave.")
+(make-variable-buffer-local 'allout-after-save-decrypt)
+;;;_   > allout-write-file-hook-handler ()
+(defun allout-write-file-hook-handler ()
+  "Implement `allout-encrypt-unencrypted-on-saves' policy for file writes."
+
+  (if (or (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 2)
+            (condition-case failure
+                (setq allout-after-save-decrypt
+                      (allout-encrypt-decrypted except-mark))
+              (error (progn
+                       (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 saves."
+
+  (if  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-after-saves-handler ()
+(defun allout-after-saves-handler ()
+  "Decrypt topic encrypted for save, if it's currently being edited.
+
+Ie, if it was pending encryption and contained the point in its body before
+the save.
+
+We use values stored in `allout-after-save-decrypt' to locate the topic
+and the place for the cursor after the decryption is done."
+  (if (not (and (allout-mode-p)
+                (boundp 'allout-after-save-decrypt)
+                allout-after-save-decrypt))
+      t
+    (goto-char (car allout-after-save-decrypt))
+    (let ((was-modified (buffer-modified-p)))
+      (allout-toggle-current-subtree-encryption)
+      (if (not was-modified)
+          (set-buffer-modified-p nil)))
+    (goto-char (cadr allout-after-save-decrypt))
+    (setq allout-after-save-decrypt nil))
+  )
 
 ;;;_ #2 Mode activation
 ;;;_  = allout-mode
@@ -916,11 +1138,10 @@
   'allout-mode)
 ;;;_  = allout-explicitly-deactivated
 (defvar allout-explicitly-deactivated nil
-  "Non-nil if `allout-mode' was last deliberately deactivated.
+  "If t, `allout-mode's last deactivation was deliberate.
 So `allout-post-command-business' should not reactivate it...")
 (make-variable-buffer-local 'allout-explicitly-deactivated)
 ;;;_  > allout-init (&optional mode)
-;;;###autoload
 (defun allout-init (&optional mode)
   "Prime `allout-mode' to enable/disable auto-activation, wrt `allout-layout'.
 
@@ -939,9 +1160,9 @@
 the `allout-layout' variable.  (See `allout-layout' and
 `allout-expose-topic' docstrings for more details on auto layout).
 
-`allout-init' works by setting up (or removing)
-`allout-find-file-hook' in `find-file-hook', and giving
-`allout-auto-activation' a suitable setting.
+`allout-init' works by setting up (or removing) the allout-mode
+find-file-hook, and giving `allout-auto-activation' a suitable
+setting.
 
 To prime your Emacs session for full auto-outline operation, include
 the following two lines in your Emacs init file:
@@ -949,32 +1170,35 @@
 \(require 'allout)
 \(allout-init t)"
 
-  (interactive
-   (let ((m (completing-read
-	     (concat "Select outline auto setup mode "
-		     "(empty for report, ? for options) ")
-	     '(("nil")("full")("activate")("deactivate")
-	       ("ask") ("report") (""))
-	     nil
-	     t)))
-     (if (string= m "") 'report
-       (intern-soft m))))
+  (interactive)
+  (if (interactive-p)
+      (progn
+	(setq mode
+	      (completing-read
+	       (concat "Select outline auto setup mode "
+		       "(empty for report, ? for options) ")
+	       '(("nil")("full")("activate")("deactivate")
+		 ("ask") ("report") (""))
+	       nil
+	       t))
+	(if (string= mode "")
+	    (setq mode 'report)
+	  (setq mode (intern-soft mode)))))
   (let
       ;; convenience aliases, for consistent ref to respective vars:
       ((hook 'allout-find-file-hook)
        (curr-mode 'allout-auto-activation))
 
     (cond ((not mode)
-	   (setq find-file-hook (delq hook find-file-hook))
+	   (setq find-file-hooks (delq hook find-file-hooks))
 	   (if (interactive-p)
 	       (message "Allout outline mode auto-activation inhibited.")))
 	  ((eq mode 'report)
-	   (if (memq hook find-file-hook)
-	       ;; Just punt and use the reports from each of the modes:
-	       (allout-init (symbol-value curr-mode))
-	     (allout-init nil)
-	     (message "Allout outline mode auto-activation inhibited.")))
-	  (t (add-hook 'find-file-hook hook)
+	   (if (not (memq hook find-file-hooks))
+	       (allout-init nil)
+	     ;; Just punt and use the reports from each of the modes:
+	     (allout-init (symbol-value curr-mode))))
+	  (t (add-hook 'find-file-hooks hook)
 	     (set curr-mode		; `set', not `setq'!
 		  (cond ((eq mode 'activate)
 			 (message
@@ -1022,10 +1246,11 @@
 
 In addition to outline navigation and exposure, allout includes:
 
- - topic-oriented repositioning, cut, and paste
+ - topic-oriented repositioning, promotion/demotion, cut, and paste
  - integral outline exposure-layout
  - incremental search with dynamic exposure and reconcealment of hidden text
  - automatic topic-number maintenance
+ - easy topic encryption and decryption
  - \"Hot-spot\" operation, for single-keystroke maneuvering and
     exposure control.  \(See the allout-mode docstring.)
 
@@ -1035,7 +1260,7 @@
 special `allout-mode' features and terminology.  See also the outline
 menubar additions for quick reference to many of the features, and see
 the docstring of the function `allout-init' for instructions on
-priming your Emacs session for automatic activation of `allout-mode'.
+priming your emacs session for automatic activation of `allout-mode'.
 
 
 The bindings are dictated by the `allout-keybindings-list' and
@@ -1048,7 +1273,7 @@
 C-c C-u allout-up-current-level         | C-c C-s allout-show-current-subtree
 C-c C-f allout-forward-current-level    | C-c C-o allout-show-current-entry
 C-c C-b allout-backward-current-level   | ^U C-c C-s allout-show-all
-C-c C-e allout-end-of-current-entry     |	   allout-hide-current-leaves
+C-c C-e allout-end-of-entry             |	   allout-hide-current-leaves
 C-c C-a allout-beginning-of-current-entry, alternately, goes to hot-spot
 
 	Topic Header Production:
@@ -1064,7 +1289,7 @@
 C-c<CR>	allout-rebullet-topic	Reconcile bullets of topic and its offspring
 				- distinctive bullets are not changed, others
 				  alternated according to nesting depth.
-C-c *	allout-rebullet-current-heading Prompt for alternate bullet for
+C-c b	allout-rebullet-current-heading Prompt for alternate bullet for
 					 current topic.
 C-c #	allout-number-siblings	Number bullets of topic and siblings - the
 				offspring are not affected.  With repeat
@@ -1087,8 +1312,8 @@
 C-c C-SPC allout-mark-topic
 C-c = c	allout-copy-exposed-to-buffer
 				Duplicate outline, sans concealed text, to
-				buffer with name derived from derived from
-				that of current buffer - \"*XXX exposed*\".
+				buffer with name derived from derived from that
+				of current buffer - \"*BUFFERNAME exposed*\".
 C-c = p	allout-flatten-exposed-to-buffer
 				Like above 'copy-exposed', but convert topic
 				prefixes to section.subsection... numeric
@@ -1096,6 +1321,19 @@
 ESC ESC (allout-init t)	Setup Emacs session for outline mode
 				auto-activation.
 
+                  Encrypted Entries
+
+Outline mode supports easily togglable gpg encryption of topics, with
+niceities like support for symmetric and key-pair modes, key timeout, key
+consistency checking, user-provided hinting for symmetric key mode, and
+auto-encryption of topics pending encryption on save.  The aim is to enable
+reliable topic privacy while preventing accidents like neglected
+encryption, encryption with a mistaken key, forgetting which key was used,
+and other practical pitfalls.
+
+See the `allout-toggle-current-subtree-encryption' function and
+`allout-encrypt-unencrypted-on-saves' customization variable for details.
+
 		 HOT-SPOT Operation
 
 Hot-spot operation provides a means for easy, single-keystroke outline
@@ -1148,11 +1386,11 @@
 
 HEADER:	The first line of a topic, include the topic PREFIX and header
 	text.
-PREFIX: The leading text of a topic which distinguishes it from
-	normal text.  It has a strict form, which consists of a
-	prefix-lead string, padding, and a bullet.  The bullet may be
-	followed by a number, indicating the ordinal number of the
-	topic among its siblings, a space, and then the header text.
+PREFIX: The leading text of a topic which distinguishes it from normal
+        text.  It has a strict form, which consists of a prefix-lead
+        string, padding, and a bullet.  The bullet may be followed by a
+        number, indicating the ordinal number of the topic among its
+        siblings, a space, and then the header text.
 
 	The relative length of the PREFIX determines the nesting depth
 	of the topic.
@@ -1223,7 +1461,7 @@
      ;; off on second invocation, so we detect it as best we can, and
      ;; skip everything.
      ((and same-complex-command		; Still in same complex command
-					; as last time `allout-mode' invoked.
+                                        ; as last time `allout-mode' invoked.
 	  active			; Already activated.
 	  (not explicit-activation)	; Prop-line file-vars don't have args.
 	  (string-match "^19.1[89]"	; Bug only known to be in v19.18 and
@@ -1238,6 +1476,19 @@
 				       ; active state or *de*activation
 				       ; specifically requested:
       (setq allout-explicitly-deactivated t)
+      (if (string-match "^18\." emacs-version)
+				       ; Revoke those keys that remain
+				       ; as we set them:
+	  (let ((curr-loc (current-local-map)))
+	   (mapcar (function
+		    (lambda (cell)
+		      (if (eq (lookup-key curr-loc (car cell))
+			      (car (cdr cell)))
+			  (define-key curr-loc (car cell)
+			    (assq (car cell) allout-prior-bindings)))))
+		   allout-added-bindings)
+	   (allout-resumptions 'allout-added-bindings)
+	   (allout-resumptions 'allout-prior-bindings)))
 
       (if allout-old-style-prefixes
 	  (progn
@@ -1246,9 +1497,12 @@
       (allout-resumptions 'selective-display)
       (if (and (boundp 'before-change-functions) before-change-functions)
 	  (allout-resumptions 'before-change-functions))
-      (setq write-contents-functions
-	    (delq 'allout-write-file-hook
-		  write-contents-functions))
+      (setq local-write-file-hooks
+	   (delq 'allout-write-file-hook-handler
+		 local-write-file-hooks))
+      (setq auto-save-hook
+	   (delq 'allout-auto-save-hook-handler
+		 auto-save-hook))
       (allout-resumptions 'paragraph-start)
       (allout-resumptions 'paragraph-separate)
       (allout-resumptions (if (string-match "^18" emacs-version)
@@ -1288,25 +1542,27 @@
 		     (cons '(allout-mode . allout-mode-map)
 			   minor-mode-map-alist))))
 
+				       ; V18 minor-mode key bindings:
+				       ; Stash record of added bindings
+				       ; for later revocation:
+	(allout-resumptions 'allout-added-bindings
+			    (list allout-keybindings-list))
+	(allout-resumptions 'allout-prior-bindings
+			    (list (current-local-map)))
 				       ; and add them:
 	(use-local-map (produce-allout-mode-map allout-keybindings-list
 						(current-local-map)))
 	)
 
 				       ; selective-display is the
-				       ; Emacs conditional exposure
+				       ; emacs conditional exposure
 				       ; mechanism:
       (allout-resumptions 'selective-display '(t))
-      (if allout-inhibit-protection
-	  t
-	(allout-resumptions 'before-change-functions
-			    '(allout-before-change-protect)))
       (add-hook 'pre-command-hook 'allout-pre-command-business)
       (add-hook 'post-command-hook 'allout-post-command-business)
-				       ; Temporarily set by any outline
-				       ; functions that can be trusted to
-				       ; deal properly with concealed text.
-      (add-hook 'write-contents-functions 'allout-write-file-hook)
+      (add-hook 'local-write-file-hooks 'allout-write-file-hook-handler)
+      (make-variable-buffer-local 'auto-save-hook)
+      (add-hook 'auto-save-hook 'allout-auto-save-hook-handler)
 				       ; Custom auto-fill func, to support
 				       ; respect for topic headline,
 				       ; hanging-indents, etc:
@@ -1337,7 +1593,8 @@
       (if allout-layout
 	  (setq do-layout t))
 
-      (if allout-isearch-dynamic-expose
+      (if (and allout-isearch-dynamic-expose
+	       (not (fboundp 'allout-real-isearch-abort)))
 	  (allout-enwrap-isearch))
 
       (run-hooks 'allout-mode-hook)
@@ -1376,7 +1633,6 @@
     )					; let*
   )  					; defun
 ;;;_  > allout-minor-mode
-;;; XXX released verion doesn't do this?
 (defalias 'allout-minor-mode 'allout-mode)
 
 ;;;_ #3 Internal Position State-Tracking - "allout-recent-*" funcs
@@ -1400,12 +1656,12 @@
   "Buffer point last returned by `allout-end-of-current-subtree'.")
 (make-variable-buffer-local 'allout-recent-end-of-subtree)
 ;;;_  > allout-prefix-data (beg end)
-(defmacro allout-prefix-data (beginning end)
+(defmacro allout-prefix-data (beg end)
   "Register allout-prefix state data - BEGINNING and END of prefix.
 
 For reference by `allout-recent' funcs.  Returns BEGINNING."
   `(setq allout-recent-prefix-end ,end
-         allout-recent-prefix-beginning ,beginning))
+         allout-recent-prefix-beginning ,beg))
 ;;;_  > allout-recent-depth ()
 (defmacro allout-recent-depth ()
   "Return depth of last heading encountered by an outline maneuvering function.
@@ -1598,7 +1854,7 @@
 	    (or (match-end 2) allout-recent-prefix-end))))))
 
 ;;;_  - Subtree Charting
-;;;_   " These routines either produce or assess charts, which are
+;;;_   #1 These routines either produce or assess charts, which are
 ;;; nested lists of the locations of topics within a subtree.
 ;;;
 ;;; Use of charts enables efficient navigation of subtrees, by
@@ -1607,14 +1863,17 @@
 ;;; for assessment or adjustment of the subtree, without redundant
 ;;; traversal of the structure.
 
-;;;_   > allout-chart-subtree (&optional levels orig-depth prev-depth)
+;;;_   #2 allout-chart-subtree (&optional levels orig-depth prev-depth)
 (defun allout-chart-subtree (&optional levels orig-depth prev-depth)
   "Produce a location \"chart\" of subtopics of the containing topic.
 
 Optional argument LEVELS specifies the depth \(relative to start
-depth) for the chart.
+depth) for the chart.  Subsequent optional args are not for public
+use.
+
+Point is left at the end of the subtree.
 
-Charts are used to capture outline structure, so that outline altering
+Charts are used to capture outline structure, so that allout-altering
 routines need assess the structure only once, and then use the chart
 for their elaborate manipulations.
 
@@ -1625,11 +1884,9 @@
 The chart for a topics' offspring precedes the entry for the topic
 itself.
 
-\(fn &optional LEVELS)"
-
-  ;; The other function parameters are for internal recursion, and should
-  ;; not be specified by external callers.  ORIG-DEPTH is depth of topic at
-  ;; starting point, and PREV-DEPTH is depth of prior topic."
+The other function parameters are for internal recursion, and should
+not be specified by external callers.  ORIG-DEPTH is depth of topic at
+starting point, and PREV-DEPTH is depth of prior topic."
 
   (let ((original (not orig-depth))	; `orig-depth' set only in recursion.
 	chart curr-depth)
@@ -1696,7 +1953,7 @@
     chart				; (nreverse chart) not necessary,
 					; and maybe not preferable.
     ))
-;;;_   > allout-chart-siblings (&optional start end)
+;;;_   #3 allout-chart-siblings (&optional start end)
 (defun allout-chart-siblings (&optional start end)
   "Produce a list of locations of this and succeeding sibling topics.
 Effectively a top-level chart of siblings.  See `allout-chart-subtree'
@@ -1707,7 +1964,7 @@
 	  (while (allout-next-sibling)
 	    (setq chart (cons (point) chart)))
 	  (if chart (setq chart (nreverse chart)))))))
-;;;_   > allout-chart-to-reveal (chart depth)
+;;;_   #4 allout-chart-to-reveal (chart depth)
 (defun allout-chart-to-reveal (chart depth)
 
   "Return a flat list of hidden points in subtree CHART, up to DEPTH.
@@ -1731,7 +1988,7 @@
 	    (setq result (cons here result)))
 	(setq chart (cdr chart))))
     result))
-;;;_   X allout-chart-spec (chart spec &optional exposing)
+;;;_   #5 allout-chart-spec (chart spec &optional exposing)
 ;; (defun allout-chart-spec (chart spec &optional exposing)
 ;;   "Not yet \(if ever) implemented.
 
@@ -1835,11 +2092,18 @@
   (if (re-search-forward allout-line-boundary-regexp nil 'move)
       (prog1 (goto-char (match-beginning 0))
              (allout-prefix-data (match-beginning 2)(match-end 2)))))
-;;;_   > allout-end-of-current-subtree ()
-(defun allout-end-of-current-subtree ()
-  "Put point at the end of the last leaf in the currently visible topic."
-  (interactive)
-  (allout-back-to-current-heading)
+;;;_   > allout-end-of-subtree (&optional current)
+(defun allout-end-of-subtree (&optional current)
+  "Put point at the end of the last leaf in the containing topic.
+
+If optional CURRENT is true (default false), then put point at the end of
+the containing visible topic.
+
+Returns the value of point."
+  (interactive "P")
+  (if current
+      (allout-back-to-current-heading)
+    (allout-goto-prefix))
   (let ((level (allout-recent-depth)))
     (allout-next-heading)
     (while (and (not (eobp))
@@ -1851,9 +2115,16 @@
                '(?\n ?\r))
          (forward-char -1))
     (setq allout-recent-end-of-subtree (point))))
+;;;_   > allout-end-of-current-subtree ()
+(defun allout-end-of-current-subtree ()
+  "Put point at end of last leaf in currently visible containing topic.
+
+Returns the value of point."
+  (interactive)
+  (allout-end-of-subtree t))
 ;;;_   > allout-beginning-of-current-entry ()
 (defun allout-beginning-of-current-entry ()
-  "When not already there, position point at beginning of current topic's body.
+  "When not already there, position point at beginning of current topic header.
 
 If already there, move cursor to bullet for hot-spot operation.
 \(See `allout-mode' doc string for details on hot-spot operation.)"
@@ -1863,11 +2134,10 @@
     (if (and (interactive-p)
 	     (= (point) start-point))
 	(goto-char (allout-current-bullet-pos)))))
-;;;_   > allout-end-of-current-entry ()
-(defun allout-end-of-current-entry ()
+;;;_   > allout-end-of-entry ()
+(defun allout-end-of-entry ()
   "Position the point at the end of the current topics' entry."
   (interactive)
-  (allout-show-entry)
   (prog1 (allout-pre-next-preface)
     (if (and (not (bobp))(looking-at "^$"))
         (forward-char -1))))
@@ -1875,9 +2145,27 @@
 (defun allout-end-of-current-heading ()
   (interactive)
   (allout-beginning-of-current-entry)
-  (forward-line -1)
-  (end-of-line))
+  (re-search-forward "[\n\r]" nil t)
+  (forward-char -1))
 (defalias 'allout-end-of-heading 'allout-end-of-current-heading)
+;;;_   > allout-get-body-text ()
+(defun allout-get-body-text ()
+  "Return the unmangled body text of the topic immediately containing point."
+  (save-excursion
+    (allout-end-of-prefix)
+    (if (not (re-search-forward "[\n\r]" nil t))
+        nil
+      (backward-char 1)
+      (let ((pre-body (point)))
+        (if (not pre-body)
+            nil
+          (allout-end-of-entry)
+          (if (not (= pre-body (point)))
+              (buffer-substring-no-properties (1+ pre-body) (point))))
+        )
+      )
+    )
+  )
 
 ;;;_  - Depth-wise
 ;;;_   > allout-ascend-to-depth (depth)
@@ -1892,12 +2180,16 @@
         (if (= (allout-recent-depth) depth)
             (progn (goto-char allout-recent-prefix-beginning)
                    depth)
-          (goto-char last-good)))))
+          (goto-char last-good)
+          nil))
+    (if (interactive-p) (allout-end-of-prefix))))
 ;;;_   > allout-ascend ()
 (defun allout-ascend ()
   "Ascend one level, returning t if successful, nil if not."
-  (if (allout-beginning-of-level)
-      (allout-previous-heading)))
+  (prog1
+      (if (allout-beginning-of-level)
+	  (allout-previous-heading))
+    (if (interactive-p) (allout-end-of-prefix))))
 ;;;_   > allout-descend-to-depth (depth)
 (defun allout-descend-to-depth (depth)
   "Descend to depth DEPTH within current topic.
@@ -1917,13 +2209,13 @@
       nil))
   )
 ;;;_   > allout-up-current-level (arg &optional dont-complain)
-(defun allout-up-current-level (arg &optional dont-complain interactive)
+(defun allout-up-current-level (arg &optional dont-complain)
   "Move out ARG levels from current visible topic.
 
 Positions on heading line of containing topic.  Error if unable to
 ascend that far, or nil if unable to ascend but optional arg
 DONT-COMPLAIN is non-nil."
-  (interactive "p\np")
+  (interactive "p")
   (allout-back-to-current-heading)
   (let ((present-level (allout-recent-depth))
 	(last-good (point))
@@ -1944,12 +2236,12 @@
     (if (or failed
 	    (> arg 0))
 	(progn (goto-char last-good)
-	       (if interactive (allout-end-of-prefix))
+	       (if (interactive-p) (allout-end-of-prefix))
 	       (if (not dont-complain)
 		   (error "Can't ascend past outermost level")
-		 (if interactive (allout-end-of-prefix))
+		 (if (interactive-p) (allout-end-of-prefix))
 		 nil))
-      (if interactive (allout-end-of-prefix))
+      (if (interactive-p) (allout-end-of-prefix))
       allout-recent-prefix-beginning)))
 
 ;;;_  - Linear
@@ -1981,7 +2273,7 @@
         nil))))
 ;;;_   > allout-previous-sibling (&optional depth backward)
 (defun allout-previous-sibling (&optional depth backward)
-  "Like `allout-forward-current-level', but backwards & respect invisible topics.
+  "Like `allout-forward-current-level' backwards, respecting invisible topics.
 
 Optional DEPTH specifies depth to traverse, default current depth.
 
@@ -2015,7 +2307,7 @@
   (let ((depth (allout-depth)))
     (while (allout-previous-sibling depth nil))
     (prog1 (allout-recent-depth)
-      (allout-end-of-prefix))))
+      (if (interactive-p) (allout-end-of-prefix)))))
 ;;;_   > allout-next-visible-heading (arg)
 (defun allout-next-visible-heading (arg)
   "Move to the next ARG'th visible heading line, backward if arg is negative.
@@ -2053,13 +2345,13 @@
   (interactive "p")
   (allout-next-visible-heading (- arg)))
 ;;;_   > allout-forward-current-level (arg)
-(defun allout-forward-current-level (arg &optional interactive)
+(defun allout-forward-current-level (arg)
   "Position point at the next heading of the same level.
 
 Takes optional repeat-count, goes backward if count is negative.
 
 Returns resulting position, else nil if none found."
-  (interactive "p\np")
+  (interactive "p")
   (let ((start-depth (allout-current-depth))
 	(start-point (point))
 	(start-arg arg)
@@ -2087,7 +2379,7 @@
 		  (= (allout-recent-depth) start-depth)))
 	allout-recent-prefix-beginning
       (goto-char last-good)
-      (if (not interactive)
+      (if (not (interactive-p))
 	  nil
 	(allout-end-of-prefix)
 	(error "Hit %s level %d topic, traversed %d of %d requested"
@@ -2096,10 +2388,10 @@
 	       (- (abs start-arg) arg)
 	       (abs start-arg))))))
 ;;;_   > allout-backward-current-level (arg)
-(defun allout-backward-current-level (arg &optional interactive)
+(defun allout-backward-current-level (arg)
   "Inverse of `allout-forward-current-level'."
-  (interactive "p\np")
-  (if interactive
+  (interactive "p")
+  (if (interactive-p)
       (let ((current-prefix-arg (* -1 arg)))
 	(call-interactively 'allout-forward-current-level))
     (allout-forward-current-level (* -1 arg))))
@@ -2107,153 +2399,34 @@
 ;;;_ #5 Alteration
 
 ;;;_  - Fundamental
-;;;_   > allout-before-change-protect (beg end)
-(defun allout-before-change-protect (beg end)
-  "Outline before-change hook, regulates changes to concealed text.
-
-Reveal concealed text that would be changed by current command, and
-offer user choice to commit or forego the change.  Unchanged text is
-reconcealed.  User has option to have changed text reconcealed.
-
-Undo commands are specially treated - the user is not prompted for
-choice, the undoes are always committed (based on presumption that the
-things being undone were already subject to this regulation routine),
-and undoes always leave the changed stuff exposed.
-
-Changes to concealed regions are ignored while file is being written.
-\(This is for the sake of functions that do change the file during
-writes, like crypt and zip modes.)
-
-Locally bound in outline buffers to `before-change-functions', which
-in Emacs 19 is run before any change to the buffer.
-
-Any functions which set [`this-command' to `undo', or which set]
-`allout-override-protect' non-nil (as does, eg, allout-flag-chars)
-are exempt from this restriction."
-  (if (and (allout-mode-p)
-					; allout-override-protect
-					; set by functions that know what
-					; they're doing, eg outline internals:
-	   (not allout-override-protect)
-	   (not allout-during-write-cue)
-	   (save-match-data		; Preserve operation position state.
-					; Both beginning and end chars must
-					; be exposed:
-	     (save-excursion (if (memq this-command '(newline open-line))
-				 ;; Compensate for stupid Emacs {new,
-				 ;; open-}line display optimization:
-				 (setq beg (1+ beg)
-				       end (1+ end)))
-			     (goto-char beg)
-			     (or (allout-hidden-p)
-				 (and (not (= beg end))
-				      (goto-char end)
-				      (allout-hidden-p))))))
-      (save-match-data
-	(if (equal this-command 'undo)
-		 ;; Allow undo without inhibition.
-		 ;; - Undoing new and open-line hits stupid Emacs redisplay
-		 ;;   optimization (em 19 cmds.c, ~ line 200).
-		 ;; - Presumably, undoing what was properly protected when
-		 ;;   done.
-		 ;; - Undo may be users' only recourse in protection faults.
-		 ;; So, expose what getting changed:
-	    (progn (message "Undo! - exposing concealed target...")
-		   (if (allout-hidden-p)
-		       (allout-show-children))
-		   (message "Undo!"))
-	  (let (response
-		(rehide-completely (save-excursion (allout-goto-prefix)
-						   (allout-hidden-p)))
-		rehide-place)
-
-	    (save-excursion
-	      (if (condition-case err
-		      ;; Condition case to catch keyboard quits during reads.
-		      (progn
-					; Give them a peek where
-			(save-excursion
-			  (if (eolp) (setq rehide-place
-					   (allout-goto-prefix)))
-			  (allout-show-entry))
-					; Present the message, but...
-					; leave the cursor at the location
-					; until they respond:
-					; Then interpret the response:
-			(while
-			    (progn
-			      (message (concat "Change inside concealed"
-					       " region - do it? "
-					       "(n or 'y'/'r'eclose)"))
-			      (setq response (read-char))
-			      (not
-			       (cond ((memq response '(?r ?R))
-				      (setq response 'reclose))
-				     ((memq response '(?y ?Y ? ))
-				      (setq response t))
-				     ((memq response '(?n ?N 127))
-				      (setq response nil)
-				      t)
-				     ((eq response ??)
-				      (message
-				       "`r' means `yes, then reclose'")
-				      nil)
-				     (t (message "Please answer y, n, or r")
-					(sit-for 1)
-					nil)))))
-			response)
-		    ('quit nil))
-					; Continue:
-		  (if (eq response 'reclose)
-		      (save-excursion
-			(if rehide-place (goto-char rehide-place))
-			(if rehide-completely
-			    (allout-hide-current-entry-completely)
-			  (allout-hide-current-entry)))
-		    (if (allout-ascend-to-depth (1- (allout-recent-depth)))
-			(allout-show-children)
-		      (allout-show-to-offshoot)))
-					; Prevent:
-		(if rehide-completely
-		    (save-excursion
-		      (if rehide-place (goto-char rehide-place))
-		      (allout-hide-current-entry-completely))
-		  (allout-hide-current-entry))
-		(error "Change within concealed region prevented"))))))
-    )	; if
-  )	; defun
 ;;;_   = allout-post-goto-bullet
 (defvar allout-post-goto-bullet nil
   "Outline internal var, for `allout-pre-command-business' hot-spot operation.
 
 When set, tells post-processing to reposition on topic bullet, and
-then unset it.  Set by `allout-pre-command-business' when implementing
+then unset it.  Set by allout-pre-command-business when implementing
 hot-spot operation, where literal characters typed over a topic bullet
 are mapped to the command of the corresponding control-key on the
-`allout-mode-map'.")
+allout-mode-map.")
 (make-variable-buffer-local 'allout-post-goto-bullet)
 ;;;_   > allout-post-command-business ()
 (defun allout-post-command-business ()
-  "Outline `post-command-hook' function.
-
-- Null `allout-override-protect', so it's not left open.
+  "Outline post-command-hook function.
 
-- Implement (and clear) `allout-post-goto-bullet', for hot-spot
+- Implement (and clear) allout-post-goto-bullet, for hot-spot
   outline commands.
 
-- Massages `buffer-undo-list' so successive, standard character self-inserts
-  are aggregated.  This kludge compensates for lack of undo bunching when
-  `before-change-functions' is used."
+- Decrypt topic currently being edited if it was encrypted for a save.
+
+- Massage buffer-undo-list so successive, standard character self-inserts are
+  aggregated.  This kludge compensates for lack of undo bunching when
+  before-change-functions is used."
 
 					; Apply any external change func:
   (if (not (allout-mode-p))		; In allout-mode.
       nil
-    (setq allout-override-protect nil)
     (if allout-isearch-dynamic-expose
 	(allout-isearch-rectification))
-    (if allout-during-write-cue
-	;; Was used by allout-before-change-protect, done with it now:
-	(setq allout-during-write-cue nil))
     ;; Undo bunching business:
     (if (and (listp buffer-undo-list)	; Undo history being kept.
 	     (equal this-command 'self-insert-command)
@@ -2282,6 +2455,11 @@
 	      (setq buffer-undo-list
 		    (cons (cons prev-from cur-to)
 			  (cdr (cdr (cdr buffer-undo-list))))))))
+
+    (if (and (boundp 'allout-after-save-decrypt)
+             allout-after-save-decrypt)
+        (allout-after-saves-handler))
+
     ;; Implement -post-goto-bullet, if set: (must be after undo business)
     (if (and allout-post-goto-bullet
 	     (allout-current-bullet-pos))
@@ -2304,8 +2482,9 @@
 char.  When in this mode you can use regular cursor-positioning
 command/keystrokes to relocate the cursor off of a bullet character to
 return to regular interpretation of self-insert characters."
+
   (if (not (allout-mode-p))
-      ;; Shouldn't be invoked if not in allout allout-mode, but just in case:
+      ;; Shouldn't be invoked if not in allout-mode, but just in case:
       nil
     ;; Register isearch status:
     (if (and (boundp  'isearch-mode) isearch-mode)
@@ -2317,7 +2496,9 @@
 	(let* ((this-key-num (cond
 			      ((numberp last-command-char)
 			       last-command-char)
-			      ((fboundp 'char-to-int)
+			      ;; Only xemacs has characterp.
+			      ((and (fboundp 'characterp)
+				    (characterp last-command-char))
 			       (char-to-int last-command-char))
 			      (t 0)))
 	       mapped-binding)
@@ -2340,7 +2521,7 @@
 		      this-command mapped-binding)))))))
 ;;;_   > allout-find-file-hook ()
 (defun allout-find-file-hook ()
-  "Activate `allout-mode' when `allout-auto-activation' & `allout-layout' are non-nil.
+  "Activate `allout-mode' when `allout-auto-activation', `allout-layout' non-nil.
 
 See `allout-init' for setup instructions."
   (if (and allout-auto-activation
@@ -2353,7 +2534,7 @@
 
 Called as part of `allout-post-command-business'."
 
-  (let ((isearching isearch-mode))
+  (let ((isearching (and (boundp 'isearch-mode) isearch-mode)))
     (cond ((and isearching (not allout-pre-was-isearching))
 	   (allout-isearch-expose 'start))
 	  ((and isearching allout-pre-was-isearching)
@@ -2361,24 +2542,11 @@
 	  ((and (not isearching) allout-pre-was-isearching)
 	   (allout-isearch-expose 'final))
 	  ;; Not and wasn't isearching:
-	  (t (setq allout-isearch-prior-pos nil)))))
+	  (t (setq allout-isearch-prior-pos nil)
+	     (setq allout-isearch-did-quit nil)))))
 ;;;_   = allout-isearch-was-font-lock
 (defvar allout-isearch-was-font-lock
   (and (boundp 'font-lock-mode) font-lock-mode))
-
-;;;_   > allout-flag-region (from to flag)
-(defmacro allout-flag-region (from to flag)
-  "Hide or show lines from FROM to TO, via Emacs `selective-display' FLAG char.
-Ie, text following flag C-m \(carriage-return) is hidden until the
-next C-j (newline) char.
-
-Returns the endpoint of the region."
-  `(let ((buffer-read-only nil)
-	   (allout-override-protect t))
-       (subst-char-in-region ,from ,to
-			     (if (= ,flag ?\n) ?\r ?\n)
-			     ,flag t)))
-
 ;;;_   > allout-isearch-expose (mode)
 (defun allout-isearch-expose (mode)
   "MODE is either 'clear, 'start, 'continue, or 'final."
@@ -2403,21 +2571,56 @@
       (setq allout-isearch-prior-pos nil)
     (if (not (eq mode 'final))
 	(setq allout-isearch-prior-pos (cons (point) (allout-show-entry)))
-      (if isearch-mode-end-hook-quit
+      (if allout-isearch-did-quit
 	  nil
 	(setq allout-isearch-prior-pos nil)
-	(allout-show-children)))))
+	(allout-show-children))))
+  (setq allout-isearch-did-quit nil))
 ;;;_   > allout-enwrap-isearch ()
 (defun allout-enwrap-isearch ()
-  "Impose `isearch-abort' wrapper for dynamic exposure in isearch.
+  "Impose `allout-mode' isearch-abort wrapper for dynamic exposure in isearch.
 
 The function checks to ensure that the rebinding is done only once."
-  (add-hook 'isearch-mode-end-hook 'allout-isearch-rectification))
+
+  (add-hook 'isearch-mode-end-hook 'allout-isearch-rectification)
+  (if (fboundp 'allout-real-isearch-abort)
+      ;;
+      nil
+                                        ; Ensure load of isearch-mode:
+    (if (or (and (fboundp 'isearch-mode)
+                 (fboundp 'isearch-abort))
+            (condition-case error
+                (load-library "isearch-mode")
+              ('file-error (message
+			    "Skipping isearch-mode provisions - %s '%s'"
+			    (car (cdr error))
+			    (car (cdr (cdr error))))
+			   (sit-for 1)
+			   ;; Inhibit subsequent tries and return nil:
+			   (setq allout-isearch-dynamic-expose nil))))
+        ;; Isearch-mode loaded, encapsulate specific entry points for
+        ;; outline dynamic-exposure business:
+        (progn
+	  ;; stash crucial isearch-mode funcs under known, private
+	  ;; names, then register wrapper functions under the old
+	  ;; names, in their stead:
+          (fset 'allout-real-isearch-abort (symbol-function 'isearch-abort))
+          (fset 'isearch-abort 'allout-isearch-abort)))))
+;;;_   > allout-isearch-abort ()
+(defun allout-isearch-abort ()
+  "Wrapper for allout-real-isearch-abort \(which see), to register
+actual quits."
+  (interactive)
+  (setq allout-isearch-did-quit nil)
+  (condition-case what
+      (allout-real-isearch-abort)
+    ('quit (setq allout-isearch-did-quit t)
+	  (signal 'quit nil))))
 
 ;;; Prevent unnecessary font-lock while isearching!
 (defvar isearch-was-font-locking nil)
 (defun isearch-inhibit-font-lock ()
-  "Inhibit `font-lock-mode' while isearching - for use on `isearch-mode-hook'."
+  "Inhibit `font-lock' while isearching - for use on `isearch-mode-hook'."
   (if (and (allout-mode-p) (boundp 'font-lock-mode) font-lock-mode)
       (setq isearch-was-font-locking t
 	    font-lock-mode nil)))
@@ -2465,6 +2668,14 @@
                  (if prefix
                      (allout-get-prefix-bullet prefix)
                    (allout-get-bullet)))))
+;;;_   > allout-encrypted-type-prefix (&optional prefix)
+(defun allout-encrypted-type-prefix (&optional prefix)
+  "True if current header prefix bullet is for an encrypted entry \(body)."
+  (and allout-topic-encryption-bullet
+        (string= allout-topic-encryption-bullet
+                 (if prefix
+                     (allout-get-prefix-bullet prefix)
+                   (allout-get-bullet)))))
 ;;;_   > allout-bullet-for-depth (&optional depth)
 (defun allout-bullet-for-depth (&optional depth)
   "Return outline topic bullet suited to optional DEPTH, or current depth."
@@ -2625,15 +2836,15 @@
                                    ((allout-sibling-index))))))
     )
   )
-;;;_   > allout-open-topic (relative-depth &optional before use-sib-bullet)
-(defun allout-open-topic (relative-depth &optional before use-sib-bullet)
-  "Open a new topic at depth RELATIVE-DEPTH.
+;;;_   > allout-open-topic (relative-depth &optional before use_recent_bullet)
+(defun allout-open-topic (relative-depth &optional before use_recent_bullet)
+  "Open a new topic at depth DEPTH.
 
 New topic is situated after current one, unless optional flag BEFORE
 is non-nil, or unless current line is complete empty (not even
 whitespace), in which case open is done on current line.
 
-If USE-SIB-BULLET is true, use the bullet of the prior sibling.
+If USE_RECENT_BULLET is true, offer to use the bullet of the prior sibling.
 
 Nuances:
 
@@ -2660,9 +2871,11 @@
   (let* ((depth (+ (allout-current-depth) relative-depth))
          (opening-on-blank (if (looking-at "^\$")
                                (not (setq before nil))))
-         opening-numbered	; Will get while computing ref-topic, below
-         ref-depth		; Will get while computing ref-topic, below
-         ref-bullet		; Will get while computing ref-topic, next
+         ;; bunch o vars set while computing ref-topic
+         opening-numbered
+         opening-encrypted
+         ref-depth
+         ref-bullet
          (ref-topic (save-excursion
                       (cond ((< relative-depth 0)
                              (allout-ascend-to-depth depth))
@@ -2680,6 +2893,13 @@
                                        (allout-descend-to-depth depth))
                                    (if (allout-numbered-type-prefix)
                                        allout-numbered-bullet))))
+                      (setq opening-encrypted
+                            (save-excursion
+                              (and allout-topic-encryption-bullet
+                                   (or (<= relative-depth 0)
+                                       (allout-descend-to-depth depth))
+                                   (if (allout-numbered-type-prefix)
+                                       allout-numbered-bullet))))
                       (point)))
          dbl-space
          doing-beginning)
@@ -2718,19 +2938,24 @@
                             (if (not (bobp))
                                 (allout-previous-heading)))
 	    (if (and before (bobp))
-		(allout-unprotected (open-line 1))))
+		(allout-unprotected (allout-open-line-not-read-only))))
 
           (if (<= relative-depth 0)
               ;; Not going inwards, don't snug up:
               (if doing-beginning
-		  (allout-unprotected (open-line (if dbl-space 2 1)))
+                  (allout-unprotected
+                   (if (not dbl-space)
+                       (allout-open-line-not-read-only)
+                     (allout-open-line-not-read-only)
+                     (allout-open-line-not-read-only)))
 		(if before
 		    (progn (end-of-line)
 			   (allout-pre-next-preface)
 			   (while (= ?\r (following-char))
                              (forward-char 1))
 			   (if (not (looking-at "^$"))
-			       (allout-unprotected (open-line 1))))
+			       (allout-unprotected
+                                (allout-open-line-not-read-only))))
 		  (allout-end-of-current-subtree)))
             ;; Going inwards - double-space if first offspring is,
             ;; otherwise snug up.
@@ -2748,38 +2973,47 @@
                       (progn (forward-line -1)
                              (looking-at "^\\s-*$"))))
                 (progn (forward-line 1)
-                       (allout-unprotected (open-line 1))))
+                       (allout-unprotected
+                        (allout-open-line-not-read-only))
+                       (forward-line 1)))
             (end-of-line))
           ;;(if doing-beginning (goto-char doing-beginning))
           (if (not (bobp))
+              ;; We insert a newline char rather than using open-line to
+              ;; avoid rear-stickiness inheritence of read-only property.
               (progn (if (and (not (> depth ref-depth))
                               (not before))
-                         (allout-unprotected (open-line 1))
+                         (allout-unprotected
+                          (allout-open-line-not-read-only))
 		       (if (> depth ref-depth)
-			   (allout-unprotected (newline 1))
+                         (allout-unprotected
+                          (allout-open-line-not-read-only))
 			 (if dbl-space
-			     (allout-unprotected (open-line 1))
+                             (allout-unprotected
+                              (allout-open-line-not-read-only))
 			   (if (not before)
 			       (allout-unprotected (newline 1))))))
                      (if dbl-space
-			 (allout-unprotected (newline  1)))
+			 (allout-unprotected (newline 1)))
                      (if (and (not (eobp))
                               (not (bolp)))
                          (forward-char 1))))
           ))
     (insert (concat (allout-make-topic-prefix opening-numbered
-					       t
-					       depth)
-		    " "))
+                                              t
+                                              depth)
+                           " "))
 
     ;;(if doing-beginning (save-excursion (newline (if dbl-space 2 1))))
 
 
-    (allout-rebullet-heading (and use-sib-bullet ref-bullet);;; solicit
+    (allout-rebullet-heading (and use_recent_bullet         ;;; solicit
+                                   ref-bullet)
                               depth			     ;;; depth
                               nil 			     ;;; number-control
                               nil			     ;;; index
-                              t)     (end-of-line)
+                              t)
+    (end-of-line)
     )
   )
 ;;;_    . open-topic contingencies
@@ -2795,6 +3029,13 @@
 ;;;_     ; buffer boundaries - special provisions for beginning and end ob
 ;;;_     ; level 1 topics have special provisions also - double space.
 ;;;_     ; location of new topic
+;;;_   > allout-open-line-not-read-only ()
+(defun allout-open-line-not-read-only ()
+  "Open line and remove inherited read-only text prop from new char, if any."
+  (open-line 1)
+  (if (plist-get (text-properties-at (point)) 'read-only)
+      (allout-unprotected
+       (remove-text-properties (point) (+ 1 (point)) '(read-only nil)))))
 ;;;_   > allout-open-subtopic (arg)
 (defun allout-open-subtopic (arg)
   "Open new topic header at deeper level than the current one.
@@ -2802,7 +3043,7 @@
 Negative universal arg means to open deeper, but place the new topic
 prior to the current one."
   (interactive "p")
-  (allout-open-topic 1 (> 0 arg)))
+  (allout-open-topic 1 (> 0 arg) (< 1 arg)))
 ;;;_   > allout-open-sibtopic (arg)
 (defun allout-open-sibtopic (arg)
   "Open new topic header at same level as the current one.
@@ -2812,7 +3053,7 @@
 Negative universal arg means to place the new topic prior to the current
 one."
   (interactive "p")
-  (allout-open-topic 0 (> 0 arg) (< 1 arg)))
+  (allout-open-topic 0 (> 0 arg) (not (= 1 arg))))
 ;;;_   > allout-open-supertopic (arg)
 (defun allout-open-supertopic (arg)
   "Open new topic header at shallower level than the current one.
@@ -2821,7 +3062,7 @@
 topic prior to the current one."
 
   (interactive "p")
-  (allout-open-topic -1 (> 0 arg)))
+  (allout-open-topic -1 (> 0 arg) (< 1 arg)))
 
 ;;;_  - Outline Alteration
 ;;;_   : Topic Modification
@@ -2877,15 +3118,15 @@
 		  (setq old-indent-begin (match-beginning 1)
 			old-indent-end (match-end 1))
 		  (not (looking-at allout-regexp)))
-	   (if (> 0 (setq excess (- (current-column)
-				     old-margin)))
+	   (if (> 0 (setq excess (- (- old-indent-end old-indent-begin)
+                                    old-margin)))
 	       ;; Text starts left of old margin - don't adjust:
 	       nil
 	     ;; Text was hanging at or right of old left margin -
 	     ;; reindent it, preserving its existing indentation
 	     ;; beyond the old margin:
 	     (delete-region old-indent-begin old-indent-end)
-	     (indent-to (+ new-margin excess)))))))))
+             (indent-to (+ new-margin excess (current-column))))))))))
 ;;;_    > allout-rebullet-current-heading (arg)
 (defun allout-rebullet-current-heading (arg)
   "Solicit new bullet for current visible heading."
@@ -2922,28 +3163,30 @@
 
   "Adjust bullet of current topic prefix.
 
+All args are optional.
+
 If SOLICIT is non-nil, then the choice of bullet is solicited from
 user.  If it's a character, then that character is offered as the
 default, otherwise the one suited to the context \(according to
 distinction or depth) is offered.  If non-nil, then the
 context-specific bullet is just used.
 
-Second arg NEW-DEPTH forces the topic prefix to that depth, regardless
+Second arg DEPTH forces the topic prefix to that depth, regardless
 of the topic's current depth.
 
 Third arg NUMBER-CONTROL can force the prefix to or away from
 numbered form.  It has effect only if `allout-numbered-bullet' is
 non-nil and soliciting was not explicitly invoked (via first arg).
 Its effect, numbering or denumbering, then depends on the setting
-of the fourth arg, INDEX.
+of the forth arg, INDEX.
 
-If NUMBER-CONTROL is non-nil and fourth arg INDEX is nil, then the
+If NUMBER-CONTROL is non-nil and forth arg INDEX is nil, then the
 prefix of the topic is forced to be non-numbered.  Null index and
 non-nil NUMBER-CONTROL forces denumbering.  Non-nil INDEX (and
 non-nil NUMBER-CONTROL) forces a numbered-prefix form.  If non-nil
 INDEX is a number, then that number is used for the numbered
 prefix.  Non-nil and non-number means that the index for the
-numbered prefix will be derived by `allout-make-topic-prefix'.
+numbered prefix will be derived by allout-make-topic-prefix.
 
 Fifth arg DO-SUCCESSORS t means re-resolve count on succeeding
 siblings.
@@ -2986,9 +3229,10 @@
 					; Put in new prefix:
       (allout-unprotected (insert new-prefix))
 
-      ;; Reindent the body if elected and margin changed:
+      ;; Reindent the body if elected, margin changed, and not encrypted body:
       (if (and allout-reindent-bodies
-	       (not (= new-depth current-depth)))
+	       (not (= new-depth current-depth))
+               (not (allout-encrypted-topic-p)))
 	  (allout-reindent-body current-depth new-depth))
 
       ;; Recursively rectify successive siblings of orig topic if
@@ -3010,7 +3254,7 @@
   ) ; defun
 ;;;_    > allout-rebullet-topic (arg)
 (defun allout-rebullet-topic (arg)
-  "Like `allout-rebullet-topic-grunt', but start from topic visible at point.
+  "Rebullet the visible topic containing point and all contained subtopics.
 
 Descends into invisible as well as visible topics, however.
 
@@ -3036,18 +3280,18 @@
                                                starting-point
                                                index
                                                do-successors)
+  "Like `allout-rebullet-topic', but on nearest containing topic
+\(visible or not).
 
-  "Rebullet the topic at point, visible or invisible, and all
-contained subtopics.  See `allout-rebullet-heading' for rebulleting
-behavior.
+See `allout-rebullet-heading' for rebulleting behavior.
 
-Arg RELATIVE-DEPTH means to shift the depth of the entire
-topic that amount.
+All arguments are optional.
 
-\(fn &optional RELATIVE-DEPTH)"
+First arg RELATIVE-DEPTH means to shift the depth of the entire
+topic that amount.
 
-  ;; All args except the first one are for internal recursive use by the
-  ;; function itself.
+The rest of the args are for internal recursive use by the function
+itself.  The are STARTING-DEPTH, STARTING-POINT, and INDEX."
 
   (let* ((relative-depth (or relative-depth 0))
          (new-depth (allout-depth))
@@ -3177,13 +3421,42 @@
         (setq more (allout-next-sibling depth nil))))))
 ;;;_    > allout-shift-in (arg)
 (defun allout-shift-in (arg)
-  "Increase depth of current heading and any topics collapsed within it."
+  "Increase depth of current heading and any topics collapsed within it.
+
+We disallow shifts that would result in the topic having a depth more than
+one level greater than the immediately previous topic, to avoid containment
+discontinuity.  The first topic in the file can be adjusted to any positive
+depth, however."
   (interactive "p")
+  (if (> arg 0)
+      (save-excursion
+        (allout-back-to-current-heading)
+        (if (not (bobp))
+            (let* ((current-depth (allout-recent-depth))
+                   (start-point (point))
+                   (predecessor-depth (progn
+                                        (forward-char -1)
+                                        (allout-goto-prefix)
+                                        (if (< (point) start-point)
+                                            (allout-recent-depth)
+                                          0))))
+              (if (and (> predecessor-depth 0)
+                       (> (+ current-depth arg)
+                          (1+ predecessor-depth)))
+                  (error (concat "May not shift deeper than offspring depth"
+                                 " of previous topic")))))))
   (allout-rebullet-topic arg))
 ;;;_    > allout-shift-out (arg)
 (defun allout-shift-out (arg)
-  "Decrease depth of current heading and any topics collapsed within it."
+  "Decrease depth of current heading and any topics collapsed within it.
+
+We disallow shifts that would result in the topic having a depth more than
+one level greater than the immediately previous topic, to avoid containment
+discontinuity.  The first topic in the file can be adjusted to any positive
+depth, however."
   (interactive "p")
+  (if (< arg 0)
+      (allout-shift-in (* arg -1)))
   (allout-rebullet-topic (* arg -1)))
 ;;;_   : Surgery (kill-ring) functions with special provisions for outlines:
 ;;;_    > allout-kill-line (&optional arg)
@@ -3191,24 +3464,56 @@
   "Kill line, adjusting subsequent lines suitably for outline mode."
 
   (interactive "*P")
-  (if (not (and (allout-mode-p)		; active outline mode,
-		allout-numbered-bullet		; numbers may need adjustment,
-		(bolp)				; may be clipping topic head,
-		(looking-at allout-regexp)))	; are clipping topic head.
-      ;; Above conditions do not obtain - just do a regular kill:
-      (kill-line arg)
-    ;; Ah, have to watch out for adjustments:
-    (let* ((depth (allout-depth)))
-                                        ; Do the kill:
-      (kill-line arg)
+
+  (let ((start-point (point))
+        (leading-kill-ring-entry (car kill-ring))
+        binding)
+
+    (condition-case err
+
+        (if (not (and (allout-mode-p)        ; active outline mode,
+                      allout-numbered-bullet ; numbers may need adjustment,
+                      (bolp)                  ; may be clipping topic head,
+                      (looking-at allout-regexp))) ; are clipping topic head.
+            ;; Above conditions do not obtain - just do a regular kill:
+            (kill-line arg)
+          ;; Ah, have to watch out for adjustments:
+          (let* ((depth (allout-depth))
+                 (start-point (point))
+                 binding)
+                                        ; Do the kill, presenting option
+                                        ; for read-only text:
+            (kill-line arg)
                                         ; Provide some feedback:
-      (sit-for 0)
-      (save-excursion
+          (sit-for 0)
+          (save-excursion
                                         ; Start with the topic
                                         ; following killed line:
-        (if (not (looking-at allout-regexp))
-            (allout-next-heading))
-        (allout-renumber-to-depth depth)))))
+            (if (not (looking-at allout-regexp))
+                (allout-next-heading))
+            (allout-renumber-to-depth depth))))
+      ;; condition case handler:
+      (text-read-only
+       (goto-char start-point)
+       (setq binding (where-is-internal 'allout-kill-topic nil t))
+       (cond ((not binding) (setq binding ""))
+             ((arrayp binding)
+              (setq binding (mapconcat 'key-description (list binding) ", ")))
+             (t (setq binding (format "%s" binding))))
+       ;; ensure prior kill-ring leader is properly restored:
+       (if (eq leading-kill-ring-entry (cadr kill-ring))
+           ;; Aborted kill got pushed on front - ditch it:
+           (pop kill-ring)
+         ;; Aborted kill got appended to prior - resurrect prior:
+         (setcar kill-ring leading-kill-ring-entry))
+       ;; make last-command skip this failed command, so kill-appending
+       ;; conditions track:
+       (setq this-command last-command)
+       (error (concat "read-only text hit - use %s allout-kill-topic to"
+                      " discard collapsed stuff")
+              binding)))
+    )
+  )
 ;;;_    > allout-kill-topic ()
 (defun allout-kill-topic ()
   "Kill topic together with subtopics.
@@ -3236,14 +3541,14 @@
 		       (>= (allout-recent-depth) depth))))
 	    (forward-char 1)))
 
-    (kill-region beg (point))
+    (allout-unprotected (kill-region beg (point)))
     (sit-for 0)
     (save-excursion
       (allout-renumber-to-depth depth))))
 ;;;_    > allout-yank-processing ()
 (defun allout-yank-processing (&optional arg)
 
-  "Incidental outline specific business to be done just after text yanks.
+  "Incidental outline-specific business to be done just after text yanks.
 
 Does depth adjustment of yanked topics, when:
 
@@ -3259,7 +3564,7 @@
 
 The point is left in front of yanked, adjusted topics, rather than
 at the end (and vice-versa with the mark).  Non-adjusted yanks,
-however, are left exactly like normal, not outline specific yanks."
+however, are left exactly like normal, non-allout-specific yanks."
 
   (interactive "*P")
 					; Get to beginning, leaving
@@ -3463,6 +3768,60 @@
 ;;;_ #6 Exposure Control
 
 ;;;_  - Fundamental
+;;;_   > allout-flag-region (from to flag)
+(defun allout-flag-region (from to flag)
+  "Hide or show lines from FROM to TO, via Emacs selective-display FLAG char.
+Ie, text following flag C-m \(carriage-return) is hidden until the
+next C-j (newline) char.
+
+Returns the endpoint of the region."
+  ;; "OFR-" prefixes to avoid collisions with vars in code calling the macro.
+  ;; ie, elisp macro vars are not 'hygenic', so distinct names are necessary.
+  (let ((was-inhibit-r-o inhibit-read-only)
+        (was-undo-list buffer-undo-list)
+        (was-modified (buffer-modified-p))
+        trans)
+    (unwind-protect
+     (save-excursion
+       (setq inhibit-read-only t)
+       (setq buffer-undo-list t)
+       (if (> from to)
+           (setq trans from from to to trans))
+       (subst-char-in-region from to
+                             (if (= flag ?\n) ?\r ?\n)
+                             flag t)
+       ;; adjust character read-protection on all the affected lines.
+       ;; we handle the region line-by-line.
+       (goto-char to)
+       (end-of-line)
+       (setq to (min (+ 2 (point)) (point-max)))
+       (goto-char from)
+       (beginning-of-line)
+       (while (< (point) to)
+         ;; handle from start of exposed to beginning of hidden, or eol:
+         (remove-text-properties (point)
+                                 (progn (if (re-search-forward "[\r\n]"
+                                                               nil t)
+                                            (forward-char -1))
+                                        (point))
+                                 '(read-only nil))
+         ;; handle from start of hidden, if any, to eol:
+         (if (and (not (eobp)) (= (char-after (point)) ?\r))
+             (put-text-property (point) (progn (end-of-line) (point))
+                                'read-only t))
+         ;; Handle the end-of-line to beginning of next line:
+         (if (not (eobp))
+             (progn (forward-char 1)
+                    (remove-text-properties (1- (point)) (point)
+                                            '(read-only nil)))))
+       )
+     (if (not was-modified)
+         (set-buffer-modified-p nil))
+     (setq inhibit-read-only was-inhibit-r-o)
+     (setq buffer-undo-list was-undo-list)
+     )
+    )
+  )
 ;;;_   > allout-flag-current-subtree (flag)
 (defun allout-flag-current-subtree (flag)
   "Hide or show subtree of currently-visible topic.
@@ -3471,9 +3830,9 @@
 
   (save-excursion
     (allout-back-to-current-heading)
-    (allout-flag-region (point)
-			 (progn (allout-end-of-current-subtree) (1- (point)))
-			 flag)))
+    (let ((from (point))
+          (to (progn (allout-end-of-current-subtree) (1- (point)))))
+      (allout-flag-region from to flag))))
 
 ;;;_  - Topic-specific
 ;;;_   > allout-show-entry ()
@@ -3482,7 +3841,7 @@
 
 This is a way to give restricted peek at a concealed locality without the
 expense of exposing its context, but can leave the outline with aberrant
-exposure.  `allout-hide-current-entry-completely' or `allout-show-to-offshoot'
+exposure.  `allout-hide-current-entry-completely' or `allout-show-offshoot'
 should be used after the peek to rectify the exposure."
 
   (interactive)
@@ -3602,7 +3961,7 @@
   (allout-back-to-current-heading)
   (save-excursion
    (allout-flag-region (point)
-                        (progn (allout-end-of-current-entry) (point))
+                        (progn (allout-end-of-entry) (point))
                         ?\r)))
 ;;;_   > allout-show-current-entry (&optional arg)
 (defun allout-show-current-entry (&optional arg)
@@ -3614,8 +3973,9 @@
       (allout-hide-current-entry)
     (save-excursion
       (allout-flag-region (point)
-			   (progn (allout-end-of-current-entry) (point))
-			   ?\n))))
+			   (progn (allout-end-of-entry) (point))
+			   ?\n)
+      )))
 ;;;_   > allout-hide-current-entry-completely ()
 ; ... allout-hide-current-entry-completely also for isearch dynamic exposure:
 (defun allout-hide-current-entry-completely ()
@@ -3846,7 +4206,11 @@
       max-pos)))
 ;;;_   > allout-old-expose-topic (spec &rest followers)
 (defun allout-old-expose-topic (spec &rest followers)
-  "Dictate wholesale exposure scheme for current topic, according to SPEC.
+
+  "Deprecated.  Use `allout-expose-topic' \(with different schema
+format) instead.
+
+Dictate wholesale exposure scheme for current topic, according to SPEC.
 
 SPEC is either a number or a list.  Optional successive args
 dictate exposure for subsequent siblings of current topic.
@@ -3918,9 +4282,6 @@
       (allout-old-expose-topic (car followers))
       (setq followers (cdr followers)))
     max-pos))
-(make-obsolete 'allout-old-expose-topic
-               "use `allout-expose-topic' (with different schema format) instead."
-               "19.23")
 ;;;_   > allout-new-exposure '()
 (defmacro allout-new-exposure (&rest spec)
   "Literal frontend for `allout-expose-topic', doesn't evaluate arguments.
@@ -3929,6 +4290,8 @@
 
 Cursor is left at start position.
 
+Use this instead of obsolete `allout-exposure'.
+
 Examples:
 \(allout-new-exposure (-1 () () () 1) 0)
 	Close current topic at current level so only the immediate
@@ -4151,13 +4514,20 @@
 				 (cdr format)))))))
       ;; Put the list with first at front, to last at back:
       (nreverse result))))
+;;;_   > my-region-active-p ()
+(defmacro my-region-active-p ()
+  (if (fboundp 'region-active-p)
+      '(region-active-p)
+    'mark-active))
 ;;;_   > allout-process-exposed (&optional func from to frombuf
 ;;;					    tobuf format)
 (defun allout-process-exposed (&optional func from to frombuf tobuf
-					  format start-num)
+					  format &optional start-num)
   "Map function on exposed parts of current topic; results to another buffer.
 
-Apply FUNC to exposed portions FROM position TO position in buffer
+All args are options; default values itemized below.
+
+Apply FUNCTION to exposed portions FROM position TO position in buffer
 FROMBUF to buffer TOBUF.  Sixth optional arg, FORMAT, designates an
 alternate presentation form:
 
@@ -4170,7 +4540,7 @@
 		       except for distinctive bullets.
 
 Defaults:
-  FUNC:		`allout-insert-listified'
+  FUNCTION:	`allout-insert-listified'
   FROM:		region start, if region active, else start of buffer
   TO:		region end, if region active, else end of buffer
   FROMBUF:	current buffer
@@ -4219,9 +4589,7 @@
 
  \`(depth prefix text)'
 
-or
-
- \`(depth prefix text bullet-plus)'
+or \`(depth prefix text bullet-plus)'
 
 If `bullet-plus' is specified, it is inserted just after the entire prefix."
   (setq listified (cdr listified))
@@ -4237,7 +4605,7 @@
     (while text
       (insert (car text))
       (if (setq text (cdr text))
-	  (insert "\n")))
+	  (insert-string "\n")))
     (insert "\n")))
 ;;;_   > allout-copy-exposed-to-buffer (&optional arg tobuf format)
 (defun allout-copy-exposed-to-buffer (&optional arg tobuf format)
@@ -4440,14 +4808,14 @@
 	 body-content bop)
 					; Do the head line:
     (insert (concat "\\OneHeadLine{\\verb\1 "
-		    (allout-latex-verb-quote bullet)
-		    "\1}{"
-		    depth
-		    "}{\\verb\1 "
-		    (if head-line
-			(allout-latex-verb-quote head-line)
-		      "")
-		    "\1}\n"))
+                    (allout-latex-verb-quote bullet)
+                    "\1}{"
+                    depth
+                    "}{\\verb\1 "
+                    (if head-line
+                        (allout-latex-verb-quote head-line)
+                      "")
+                    "\1}\n"))
     (if (not body-lines)
 	nil
       ;;(insert "\\beginlines\n")
@@ -4509,7 +4877,614 @@
     (pop-to-buffer buf)
     (goto-char start-pt)))
 
-;;;_ #8 miscellaneous
+;;;_ #8 Encryption
+;;;_  > allout-toggle-current-subtree-encryption (&optional fetch-key)
+(defun allout-toggle-current-subtree-encryption (&optional fetch-key)
+  "Encrypt clear text or decrypt encoded contents of a topic.
+
+Contents includes body and subtopics.
+
+Currently only GnuPG encryption is supported.
+
+\**NOTE WELL** that the encrypted text must be ascii-armored.  For gnupg
+encryption, include the option ``armor'' in your ~/.gnupg/gpg.conf file.
+
+Both symmetric-key and key-pair encryption is implemented.  Symmetric is
+the default, use a single \(x4) universal argument for keypair mode.
+
+Encrypted topic's bullet is set to a `~' to signal that the contents of the
+topic \(body and subtopics, but not heading) is pending encryption or
+encrypted.  An `*' asterisk immediately after the bullet signals that the
+body is encrypted, its absence means it's meant to be encrypted but is not
+- it's \"disclosed\".  When a file with disclosed topics is saved, the user
+prompted for an ok to \(symmetric-key) encrypt the disclosed topics.  NOTE
+WELL that you must explicitly \(re)encrypt key-pair encrypted topics if you
+want them to continue to be in key-pair mode.
+
+Level-1 topics, with prefix consisting solely of an `*' asterisk, cannot be
+encrypted.  If you want to encrypt the contents of a top-level topic, use
+\\[allout-shift-in] to increase its depth.
+
+Failed transformation does not change the an entry being encrypted -
+instead, the key is re-solicited and the transformation is retried.
+\\[keyboard-quit] to abort.
+
+Decryption does symmetric or key-pair key mode depending on how the text
+was encrypted.  The encryption key is solicited if not currently available
+from the key cache from a recent prior encryption action.
+
+Optional FETCH-KEY universal argument is used for two purposes - to provoke
+key-pair instead of symmetric encryption, or to provoke clearing of the key
+cache so keys are freshly fetched.
+
+ - Without any universal arguments, then the appropriate key for the is
+   obtained from the cache, if available, else from the user.
+
+ - If FETCH-KEY is the result of one universal argument - ie, equal to 4 -
+   then key-pair encryption is used.
+
+ - With repeated universal argument - equal to 16 - then the key cache is
+   cleared before any encryption transformations, to force prompting of the
+   user for the key.
+
+The solicited key is retained for reuse in a buffer-specific cache for some
+set period of time \(default, 60 seconds), after which the string is
+nulled.  `mailcrypt' provides the key caching functionality.  You can
+adjust the key cache timeout by ajdusting the setting of the elisp variable
+`mc-passwd-timeout'.
+
+If the file previously had no associated key, or had a different key than
+specified, the user is prompted to repeat the new one for corroboration.  A
+random string encrypted by the new key is set on the buffer-specific
+variable `allout-key-verifier-string', for confirmation of the key when
+next obtained, before encrypting or decrypting anything with it.  This
+helps avoid mistakenly shifting between keys.
+
+If allout customization var `allout-key-verifier-handling' is non-nil, an
+entry for `allout-key-verifier-string' and its value is added to an Emacs
+'local variables' section at the end of the file, which is created if
+necessary.  That setting is for retention of the key verifier across emacs
+sessions.
+
+Similarly, `allout-key-hint-string' stores a user-provided reminder about
+their key, and `allout-key-hint-handling' specifies when the hint is
+presented, or if key hints are disabled.  If enabled \(see the
+`allout-key-hint-handling' docstring for details), the hint string is
+stored in the local-variables section of the file, and solicited whenever
+the key is changed."
+
+;;; This routine handles allout-specific business, dispatching
+;;; encryption-specific business to allout-encrypt-string.
+
+  (interactive "P")
+  (save-excursion
+    (allout-end-of-prefix t)
+
+    (if (= (allout-recent-depth) 1)
+        (error (concat "Cannot encrypt or decrypt level 1 topics -"
+                       " shift it in to make it encryptable")))
+
+    (if (and fetch-key
+             (not (equal fetch-key '(4))))
+        (mc-deactivate-passwd))
+
+    (let* ((allout-buffer (current-buffer))
+           ;; Asses location:
+           (after-bullet-pos (point))
+           (was-encrypted
+            (progn (if (= (point-max) after-bullet-pos)
+                       (error "no body to encrypt"))
+                   (looking-at "\\*")))
+           (was-collapsed (if (not (re-search-forward "[\n\r]" nil t))
+                              nil
+                            (backward-char 1)
+                            (looking-at "\r")))
+           (subtree-beg (1+ (point)))
+           (subtree-end (allout-end-of-subtree))
+           (subject-text (buffer-substring-no-properties subtree-beg
+                                                         subtree-end))
+           (subtree-end-char (char-after (1- subtree-end)))
+           (subtree-trailling-char (char-after subtree-end))
+           (place-holder (if (or (string= "" subject-text)
+                                 (string= "\n" subject-text))
+                             (error "No topic contents to %scrypt"
+                                    (if was-encrypted "de" "en"))))
+           ;; Assess key parameters:
+           (key-type (or
+                      ;; detect the type by which it is already encrypted
+                      (and was-encrypted
+                           (allout-encrypted-text-type subject-text))
+                      (and (member fetch-key '(4 (4)))
+                           (yes-or-no-p "Use key-pair encryption instead? ")
+                           'keypair)
+                      'symmetric))
+           (fetch-key (and fetch-key (not (member fetch-key '(16 (16))))))
+           result-text)
+
+      (setq result-text
+            (allout-encrypt-string subject-text was-encrypted
+                                    (current-buffer) key-type fetch-key))
+
+       ;; Replace the subtree with the processed product.
+      (allout-unprotected
+       (progn
+         (set-buffer allout-buffer)
+         (delete-region subtree-beg subtree-end)
+         (insert result-text)
+         (if was-collapsed
+             (allout-flag-region subtree-beg (1- (point)) ?\r))
+         ;; adjust trailling-blank-lines to preserve topic spacing:
+         (if (not was-encrypted)
+             (if (and (member subtree-end-char '(?\r ?\n))
+                      (member subtree-trailling-char '(?\r ?\n)))
+                 (insert subtree-trailling-char)))
+         ;; Ensure that the item has an encrypted-entry bullet:
+         (if (not (string= (buffer-substring-no-properties
+                            (1- after-bullet-pos) after-bullet-pos)
+                           allout-topic-encryption-bullet))
+             (progn (goto-char (1- after-bullet-pos))
+                    (delete-char 1)
+                    (insert allout-topic-encryption-bullet)))
+         (if was-encrypted
+             ;; Remove the is-encrypted bullet qualifier:
+             (progn (goto-char after-bullet-pos)
+                    (delete-char 1))
+           ;; Add the is-encrypted bullet qualifier:
+           (goto-char after-bullet-pos)
+           (insert "*"))
+         )
+       )
+      )
+    )
+  )
+;;;_  > allout-encrypt-string (text decrypt allout-buffer key-type rekey
+;;;                                  &optional retried verifying)
+(defun allout-encrypt-string (text decrypt allout-buffer key-type rekey
+                                    &optional retried verifying)
+  "Encrypt or decrypt a string TEXT using KEY.
+
+If optional DECRYPT is true (default false), then decrypt instead of
+encrypt.
+
+Optional REKEY (default false) provokes clearing of the key cache to force
+fresh prompting for the key.
+
+Optional RETRIED is for internal use - conveys the number of failed keys have
+been solicited in sequence leading to this current call.
+
+Optional VERIFYING is for internal use, signifying processing of text
+solely for verification of the cached key.
+
+Returns the resulting string, or nil if the transformation fails."
+
+  ;; Ensure that we have an alternate handle on the real mc-activate-passwd:
+  (if (not (fboundp 'real-mc-activate-passwd))
+      ;; Force loads of the primary mailcrypt packages, so flet below holds.
+      (progn (require 'mailcrypt)
+             (load "mc-toplev")
+             (fset 'real-mc-activate-passwd
+                   (symbol-function 'mc-activate-passwd))))
+
+  (if (and rekey (not verifying)) (mc-deactivate-passwd))
+
+  (catch 'encryption-failed
+    (save-excursion
+
+      (let* ((mc-default-scheme (or allout-encryption-scheme
+                                    allout-default-encryption-scheme))
+             (id (format "%s-%s" key-type
+                         (or (buffer-file-name allout-buffer)
+                             (buffer-name allout-buffer))))
+             (cached (real-mc-activate-passwd id nil))
+             (comment "Processed by allout driving mailcrypt")
+             key work-buffer result result-text encryption-process-status)
+
+        (unwind-protect
+
+            ;; Interject our mc-activate-passwd wrapper:
+            (flet ((mc-activate-passwd (id &optional prompt)
+                                       (allout-mc-activate-passwd id prompt)))
+
+              (setq work-buffer
+                    (set-buffer (allout-encryption-produce-work-buffer text)))
+
+              (cond
+
+               ;; symmetric:
+               ((equal key-type 'symmetric)
+                (setq key (if verifying
+                              (real-mc-activate-passwd id nil)
+                            (allout-mc-activate-passwd id)))
+                (setq encryption-process-status
+                      (crypt-encrypt-buffer key decrypt))
+                (if (zerop encryption-process-status)
+                    t
+                  (if verifying
+                      (throw 'encryption-failed nil)
+                    (mc-deactivate-passwd)
+                    (error "Symmetric-key encryption failed (%s) - wrong key?"
+                           encryption-process-status))))
+
+               ;; encrypt 'keypair:
+               ((not decrypt)
+                (condition-case result
+                    (mailcrypt-encrypt 1)
+                  (error (mc-deactivate-passwd)
+                         (error "encryption failed: %s"
+                                (cadr result)))))
+
+               ;; decrypt 'keypair:
+               (t (condition-case result
+                      (mc-decrypt)
+                    (error (mc-deactivate-passwd)
+                           (error "decryption failed: %s"
+                                  (cadr result))))))
+
+              (setq result-text (if (or (equal key-type 'keypair)
+                                        (not decrypt))
+                                    (buffer-substring 1 (1- (point-max)))
+                                  (buffer-string)))
+              ;; validate result - non-empty
+              (cond ((not result-text)
+                     (if verifying
+                         nil
+                       ;; Transformation was fruitless - retry with new key.
+                       (mc-deactivate-passwd)
+                       (allout-encrypt-string text allout-buffer decrypt nil
+                                               (if retried (1+ retried) 1)
+                                               verifying)))
+
+                    ;; Barf if encryption yields extraordinary control chars:
+                    ((and (not decrypt)
+                          (string-match "[\C-a\C-k\C-o-\C-z\C-@]" result-text))
+                     (error (concat "encryption produced unusable"
+                                    " non-armored text - reconfigure!")))
+
+                    ;; valid result and just verifying or non-symmetric:
+                    ((or verifying (not (equal key-type 'symmetric)))
+                     result-text)
+
+                    ;; valid result and regular symmetric - situate validator:
+                    (t
+                     ;; valid result and verifier needs to be situated in
+                     ;; allout-buffer:
+                     (set-buffer allout-buffer)
+                     (if (and (or rekey (not cached))
+                              (not (allout-verify-key key allout-buffer)))
+                         (allout-situate-encryption-key-verifier key id))
+                     result-text)
+                    )
+              )
+
+          ;; unwind-protect emergence:
+          (if work-buffer
+              (kill-buffer work-buffer))
+          )
+        )
+      )
+    )
+  )
+;;;_  > allout-mc-activate-passwd (id &optional prompt)
+(defun allout-mc-activate-passwd (id &optional prompt)
+  "Substituted for mc-activate-passwd during allout outline encryption.
+
+We add key-verification to vanilla mc-activate-passwd.
+
+We depend in some cases on values of the following allout-encrypt-string
+internal or prevailing variables:
+  - key-type - 'symmetric or 'keypair
+  - id - id associated with current key in key cache
+  - allout-buffer - where subject text resides
+  - retried - number of current attempts to obtain this key
+  - rekey - user asked to present a new key - needs to be confirmed"
+
+;;  - if we're doing non-symmetric key, just do normal mc-activate-passwd
+;;  - otherwise, if we are have a cached version of the key, then assume
+;;    it's verified and return it
+;;  - otherwise, prompt for a key, and:
+;;    - if we have a key verifier \(a string value which should decrypt
+;;      against a symmetric key), validate against the verifier
+;;      - if successful, return the verified key
+;;      - if unsuccessful:
+;;        - offer to use the new key
+;;          - if accepted, do confirm process
+;;          - if refused, try again until we get a correctly spelled one or the
+;;            user quits
+;;    - if no key verifier, resolicit the key to get corroboration and return
+;;      the corroborated key if spelled identically, or error if not.
+
+  (if (not (equal key-type 'symmetric))
+      ;; do regular mc-activate-passwd on non-symmetric key
+      (real-mc-activate-passwd id prompt)
+
+    ;; Symmetric hereon:
+
+    (save-excursion
+      (set-buffer allout-buffer)
+      (let* ((hint (if (and (not (string= allout-key-hint-string ""))
+                            (or (equal allout-key-hint-handling 'always)
+                                (and (equal allout-key-hint-handling 'needed)
+                                     retried)))
+                       (format " [%s]" allout-key-hint-string)
+                     ""))
+             (retry-message (if retried (format " (%s retry)" retried) ""))
+             (prompt-sans-hint (format "'%s' symmetric key%s: "
+                                       (buffer-name allout-buffer)
+                                       retry-message))
+             (full-prompt (format "'%s' symmetric key%s%s: "
+                                  (buffer-name allout-buffer)
+                                  hint retry-message))
+             (prompt full-prompt)
+             (verifier-string (allout-get-encryption-key-verifier))
+             ;; force retention of cached passwords for five minutes while
+             ;; we're in this particular routine:
+             (mc-passwd-timeout 300)
+             (cached (real-mc-activate-passwd id nil))
+             (got (or cached (real-mc-activate-passwd id full-prompt)))
+             confirmation)
+
+        (if (not got)
+            nil
+
+          ;; Duplicate our handle on the key so it's not clobbered by
+          ;; deactivate-passwd memory clearing:
+          (setq got (format "%s" got))
+
+          (cond (verifier-string
+                 (if (and (not (allout-encrypt-string
+                                verifier-string 'decrypt allout-buffer
+                                'symmetric nil 0 'verifying))
+                          (if (yes-or-no-p
+                               (concat "Key differs from established"
+                                       " - use new one instead? "))
+                              ;; deactivate password for subsequent
+                              ;; confirmation:
+                              (progn (mc-deactivate-passwd)
+                                     (setq prompt prompt-sans-hint)
+                                     nil)
+                            t))
+                     (progn (mc-deactivate-passwd)
+                            (error "Wrong key."))))
+                ;; Force confirmation by repetition for new key:
+                ((or rekey (not cached)) (mc-deactivate-passwd))))
+        ;; we have a key and it's either verified and cached.
+        ;; confirmation vs new input - doing mc-activate-passwd will do the
+        ;; right thing, in either case:
+        (setq confirmation
+              (real-mc-activate-passwd id (concat prompt
+                                                  " ... confirm spelling: ")))
+        (prog1
+            (if (equal got confirmation)
+                confirmation
+              (if (yes-or-no-p (concat "spelling of original and"
+                                       " confirmation differ - retry? "))
+                  (progn (setq retried (if retried (1+ retried) 1))
+                         (mc-deactivate-passwd)
+                         ;; recurse to this routine:
+                         (mc-activate-passwd id prompt-sans-hint))
+                (mc-deactivate-passwd)
+                (error "Confirmation failed.")))
+          ;; reduce opportunity for memory cherry-picking by zeroing duplicate:
+          (dotimes (i (length got))
+            (aset got i 0))
+          )
+        )
+      )
+    )
+  )
+;;;_  > allout-encryption-produce-work-buffer (text)
+(defun allout-encryption-produce-work-buffer (text)
+  "Establish a new buffer filled with TEXT, for outline encrypion processing.
+
+TEXT is massaged so outline collapsing, if any, is removed."
+  (let ((work-buffer (generate-new-buffer " *allout encryption*")))
+    (save-excursion
+      (set-buffer work-buffer)
+      (insert (subst-char-in-string ?\r ?\n text)))
+    work-buffer))
+;;;_  > allout-encrypted-topic-p ()
+(defun allout-encrypted-topic-p ()
+  "True if the current topic is encryptable and encrypted."
+  (save-excursion
+    (allout-end-of-prefix t)
+    (and (string= (buffer-substring-no-properties (1- (point)) (point))
+                  allout-topic-encryption-bullet)
+         (looking-at "\\*"))
+    )
+  )
+;;;_  > allout-encrypted-text-type (text)
+;;; XXX gpg-specific, not generic!
+(defun allout-encrypted-text-type (text)
+  "For gpg encrypted text, return 'symmetric or 'keypair."
+
+  ;; Ensure mc-gpg-path has a value:
+  (if (not (boundp 'mc-gpg-path))
+      (load-library "mc-gpg"))
+
+  (save-excursion
+    (let* ((work-buffer (set-buffer
+                         (allout-encryption-produce-work-buffer text)))
+           (result (mc-gpg-process-region (point-min) (point-max)
+                                          nil mc-gpg-path
+                                          '("--batch" "--decrypt")
+                                          'mc-gpg-decrypt-parser
+                                          work-buffer nil)))
+      (cond ((equal (nth 0 result) 'symmetric)
+             'symmetric)
+            ((equal (nth 0 result) t)
+             'keypair)
+            (t (error "Unrecognized/unsupported encryption type %S"
+                      (nth 0 result))))
+      )
+    )
+  )
+;;;_  > allout-create-encryption-key-verifier (key id)
+(defun allout-create-encryption-key-verifier (key id)
+  "Encrypt a random message for later validation of symmetric key."
+  ;; use 20 random ascii characters, across the entire ascii range.
+  (random t)
+  (let ((spew (make-string 20 ?\0)))
+    (dotimes (i (length spew))
+      (aset spew i (1+ (random 254))))
+    (allout-encrypt-string spew nil nil 'symmetric nil nil t))
+  )
+;;;_  > allout-situate-encryption-key-verifier (key id)
+(defun allout-situate-encryption-key-verifier (key id)
+  "Establish key verifier string on file variable.
+
+We also prompt for and situate a new reminder, if reminders are enabled.
+
+We massage the string to simplify programmatic adjustment.  File variable
+is `allout-file-key-verifier-string'."
+  (let ((verifier-string
+         ;; Collapse to a single line and enclose in string quotes:
+         (subst-char-in-string ?\n ?\C-a
+                               (allout-create-encryption-key-verifier
+                                key id)))
+        (reminder (if (not (equal allout-key-hint-handling 'disabled))
+                      (read-from-minibuffer
+                       "Key hint to jog your memory next time: "
+                       allout-key-hint-string))))
+    (setq allout-key-verifier-string verifier-string)
+    (allout-adjust-file-variable "allout-key-verifier-string"
+                                  verifier-string)
+    (cond ((equal allout-key-hint-handling 'disabled)
+           nil)
+          ((not (string= reminder allout-key-hint-string))
+           (setq allout-key-hint-string reminder)
+           (allout-adjust-file-variable "allout-key-hint-string"
+                                         reminder)))
+    )
+  )
+;;;_  > allout-get-encryption-key-verifier ()
+(defun allout-get-encryption-key-verifier ()
+  "Return the text of the encrypt key verifier, unmassaged, or nil if none.
+
+Derived from value of `allout-file-key-verifier-string'."
+
+  (let ((verifier-string (and (boundp 'allout-key-verifier-string)
+                              allout-key-verifier-string)))
+    (if verifier-string
+        ;; Return it uncollapsed
+        (subst-char-in-string ?\C-a ?\n verifier-string)
+      nil)
+   )
+  )
+;;;_  > allout-verify-key (key)
+(defun allout-verify-key (key allout-buffer)
+  "True if key successfully decrypts key verifier, nil otherwise.
+
+\"Otherwise\" includes absence of key verifier."
+  (save-excursion
+    (set-buffer allout-buffer)
+    (and (boundp 'allout-key-verifier-string)
+         allout-key-verifier-string
+         (allout-encrypt-string (allout-get-encryption-key-verifier)
+                                 'decrypt allout-buffer 'symmetric
+                                 nil nil 'verifying)
+         t)))
+;;;_  > allout-next-topic-pending-encryption (&optional except-mark)
+(defun allout-next-topic-pending-encryption (&optional except-mark)
+  "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."
+  (let (done got content-beg)
+    (while (not done)
+
+      (if (not (re-search-forward
+                (format "\\(\\`\\|[\n\r]\\)%s *%s[^*]"
+                        (regexp-quote allout-header-prefix)
+                        (regexp-quote allout-topic-encryption-bullet))
+                nil t))
+          (setq got nil
+                done t)
+        (goto-char (setq got (match-beginning 0)))
+        (if (looking-at "[\n\r]")
+            (forward-char 1))
+        (setq got (point)))
+
+      (cond ((not got)
+             (setq done t))
+
+            ((not (re-search-forward "[\n\r]"))
+             (setq got nil
+                   done t))
+
+            ((eobp)
+             (setq got nil
+                   done t))
+
+            (t
+             (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)))
+                 ;; Continue looking
+                 (setq got nil)
+               ;; Got it!
+               (setq done t)))
+            )
+      )
+    (if got
+        (goto-char got))
+    )
+  )
+;;;_  > allout-encrypt-decrypted (&optional except-mark)
+(defun allout-encrypt-decrypted (&optional except-mark)
+  "Encrypt topics pending encryption except those containing exemption point.
+
+EXCEPT-MARK identifies a point whose containing topics should be excluded
+from encryption.  This supports '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
+and exactly resituate the cursor if this is being done as part of a file
+save.  See `allout-encrypt-unencrypted-on-saves' for more info."
+
+  (interactive "p")
+  (save-excursion
+    (let ((current-mark (point-marker))
+          was-modified
+          editing-topic editing-point)
+      (goto-char (point-min))
+      (while (allout-next-topic-pending-encryption except-mark)
+        (setq was-modified (buffer-modified-p))
+        (if (save-excursion
+              (and (boundp 'allout-encrypt-unencrypted-on-saves)
+                   allout-encrypt-unencrypted-on-saves
+                   (setq bo-subtree (re-search-forward "[\n\r]"))
+                   ;; Not collapsed:
+                   (string= (match-string 0) "\n")
+                   (>= current-mark (point))
+                   (allout-end-of-current-subtree)
+                   (<= current-mark (point))))
+            (setq editing-topic (point)
+                  ;; we had to wait for this 'til now so prior topics are
+                  ;; encrypted, any relevant text shifts are in place:
+                  editing-point (marker-position current-mark)))
+        (allout-toggle-current-subtree-encryption)
+        (if (not was-modified)
+            (set-buffer-modified-p nil))
+        )
+      (if (not was-modified)
+         (set-buffer-modified-p nil))
+      (if editing-topic (list editing-topic editing-point))
+      )
+    )
+  )
+
+;;;_ #9 miscellaneous
 ;;;_  > allout-mark-topic ()
 (defun allout-mark-topic ()
   "Put the region around topic currently containing point."
@@ -4538,22 +5513,100 @@
 	t
       (allout-open-topic 2)
       (insert (concat "Dummy outline topic header - see"
-		      "`allout-mode' docstring: `^Hm'."))
-      (forward-line 1)
+                      "`allout-mode' docstring: `^Hm'."))
+      (allout-adjust-file-variable
+       "allout-layout" (format "%s" (or allout-layout '(-1 : 0)))))))
+;;;_  > allout-file-vars-section-data ()
+(defun allout-file-vars-section-data ()
+  "Return data identifying the file-vars section, or nil if none.
+
+Returns list `(beginning-point prefix-string suffix-string)'."
+  ;; minimally gleaned from emacs 21.4 files.el hack-local-variables function.
+  (let (beg prefix suffix)
+    (save-excursion
       (goto-char (point-max))
-      (open-line 1)
-      (allout-open-topic 0)
-      (insert "Local emacs vars.\n")
-      (allout-open-topic 1)
-      (insert "(`allout-layout' is for allout.el allout-mode)\n")
-      (allout-open-topic 0)
-      (insert "Local variables:\n")
-      (allout-open-topic 0)
-      (insert (format "allout-layout: %s\n"
-			     (or allout-layout
-				 '(-1 : 0))))
-      (allout-open-topic 0)
-      (insert "End:\n"))))
+      (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
+      (if (let ((case-fold-search t))
+	    (not (search-forward "Local Variables:" nil t)))
+          nil
+        (setq beg (- (point) 16))
+        (setq suffix (buffer-substring-no-properties
+                      (point)
+                      (progn (if (re-search-forward "[\n\r]" nil t)
+                                 (forward-char -1))
+                             (point))))
+        (setq prefix (buffer-substring-no-properties
+                      (progn (if (re-search-backward "[\n\r]" nil t)
+                                 (forward-char 1))
+                             (point))
+                      beg))
+        (list beg prefix suffix))
+      )
+    )
+  )
+;;;_  > allout-adjust-file-variable (varname value)
+(defun allout-adjust-file-variable (varname value)
+  "Adjust the setting of an emacs file variable named VARNAME to VALUE.
+
+This activity is inhibited if either `enable-local-variables'
+`allout-enable-file-variable-adjustment' are nil.
+
+When enabled, an entry for the variable is created if not already present,
+or changed if established with a different value.  The section for the file
+variables, itself, is created if not already present.  When created, the
+section lines \(including the section line) exist as second-level topics in
+a top-level topic at the end of the file.
+
+enable-local-variables must be true for any of this to happen."
+  (if (not (and enable-local-variables
+                allout-enable-file-variable-adjustment))
+      nil
+    (save-excursion
+      (let ((section-data (allout-file-vars-section-data))
+            beg prefix suffix)
+        (if section-data
+            (setq beg (car section-data)
+                  prefix (cadr section-data)
+                  suffix (car (cddr section-data)))
+          ;; create the section
+          (goto-char (point-max))
+          (open-line 1)
+          (allout-open-topic 0)
+          (end-of-line)
+          (insert "Local emacs vars.\n")
+          (allout-open-topic 1)
+          (setq beg (point)
+                suffix ""
+                prefix (buffer-substring-no-properties (progn
+                                                         (beginning-of-line)
+                                                         (point))
+                                                       beg))
+          (goto-char beg)
+          (insert "Local variables:\n")
+          (allout-open-topic 0)
+          (insert "End:\n")
+          )
+        ;; look for existing entry or create one, leaving point for insertion
+        ;; of new value:
+        (goto-char beg)
+        (allout-show-to-offshoot)
+        (if (search-forward (concat "\n" prefix varname ":") nil t)
+            (let* ((value-beg (point))
+                   (line-end (progn (if (re-search-forward "[\n\r]" nil t)
+                                        (forward-char -1))
+                                    (point)))
+                   (value-end (- line-end (length suffix))))
+              (if (> value-end value-beg)
+                  (delete-region value-beg value-end)))
+          (end-of-line)
+          (open-line 1)
+          (forward-line 1)
+          (insert (concat prefix varname ":")))
+        (insert (format " %S%s" value suffix))
+        )
+      )
+    )
+  )
 ;;;_  > solicit-char-in-string (prompt string &optional do-defaulting)
 (defun solicit-char-in-string (prompt string &optional do-defaulting)
   "Solicit (with first arg PROMPT) choice of a character from string STRING.
@@ -4594,8 +5647,7 @@
 Representations of actual backslashes - '\\\\\\\\' - are left as a
 single backslash.
 
-\(fn REGEXP)"
-;; Optional arg SUCCESSIVE-BACKSLASHES is used internally for recursion.
+Optional arg SUCCESSIVE-BACKSLASHES is used internally for recursion."
 
   (if (string= regexp "")
       ""
@@ -4611,11 +5663,6 @@
 		(regexp-sans-escapes (substring regexp 1)))
       ;; Exclude first char, but maintain count:
       (regexp-sans-escapes (substring regexp 1) successive-backslashes))))
-;;;_  > my-region-active-p ()
-(defmacro my-region-active-p ()
-  (if (fboundp 'region-active-p)
-      '(region-active-p)
-    'mark-active))
 ;;;_  - add-hook definition for divergent emacsen
 ;;;_   > add-hook (hook function &optional append)
 (if (not (fboundp 'add-hook))
@@ -4640,13 +5687,13 @@
 (defun my-mark-marker (&optional force buffer)
   "Accommodate the different signature for `mark-marker' across Emacsen.
 
-XEmacs takes two optional args, while GNU Emacs does not,
+XEmacs takes two optional args, while mainline GNU Emacs does not,
 so pass them along when appropriate."
-  (if (featurep 'xemacs)
+  (if (string-match " XEmacs " emacs-version)
       (mark-marker force buffer)
     (mark-marker)))
 
-;;;_ #9 Under development
+;;;_ #10 Under development
 ;;;_  > allout-bullet-isearch (&optional bullet)
 (defun allout-bullet-isearch (&optional bullet)
   "Isearch \(regexp) for topic with bullet BULLET."
@@ -4676,5 +5723,4 @@
 ;;;allout-layout: (0 : -1 -1 0)
 ;;;End:
 
-;;; arch-tag: cf38fbc3-c044-450f-8bff-afed8ba5681c
 ;;; allout.el ends here


[-- Attachment #3: allout-ChangeLog.txt --]
[-- Type: text/plain, Size: 3562 bytes --]

2005-09-30  Ken Manheimer  <ken.manheimer@gmail.com>

	* allout.el: omnibus changes

	  - new subsystem supporting easy gpg topic encryption/decryption.

	    salient features:

	    - both public- and symmetric-key modes are supported.
	    - encryption being on a per-topic basis means you can
	      intersperse encrypted and clear-text data in a single file
	      to your heart's content.
	    - user-provided symmetric-key hints, with consistency
	      verification to help user avoid confusion
	    - time-limited key reuse, a la (and using) mailcrypt's
	      mc-passwd-timeout
	    - write-file-hook and auto-save-hook activities to support auto
	      encryption of pending topics on save; provision to skip
	      currently-edited topic to avoid editing disturbance

	    topic encryption functionality depends on both mailcrypt and
	    crypt++ packages.  (non-encryption allout functionality is not
	    disrupted if either mailcrypt or crypt++ are absent.)

	    `allout-toggle-current-subtree-encryption' is the central
	    routine.

	    there are a five new encryption customization variables:

	    - allout-topic-encryption-bullet
	    - allout-default-encryption-scheme
	    - allout-key-verifier-handling
	    - allout-key-hint-handling
	    - allout-encrypt-unencrypted-on-saves

	    topic encryption is included in mouse menu

	    docstring for `allout-toggle-current-subtree-encryption'
	    and customization variables provide detailed description.

	  - repaired inhibition of concealed-text edits

	    this helps preserve the structural integrity of outlines, as
	    well as preventing insidiously invisible accidental edits

	    (it also noticably slows massive exposure changes, but i
	    consider the performance acceptable.  eg, i have blanket
	    auto-exposure set for my daily-notes log, which has real-world
	    intricacy in a 1.1 Mb, 7000 topic outline, and have no problems
	    working with it on a 200 MhZ windows laptop.)

	  - disallow manually shifting a topic deeper than the offspring
	    depth of the previous topic - avoiding confusing "containment
	    discontinuities"

	  - fixed retention of body relative hanging indent during
	    promotion of collapsed bodies

	  - made it easy to open new topic with same bullet as current
	    topic - topic creation functions provided with any universal
	    argument provokes now prompt for bullet, defaulting to the
	    bullet of the previous topic.  very ergonomic.

	  - plain bullet alternates '.' period and ',' comma only.  all
	    other bullets are relegated to special status (but customizable)

	  - comments and routine names better distinguish between:
	    - topic body - the text contained after a header
	    - topic header - the first line, before the body
	    - topic entry - the header, body, and offspring

	  - allout-beginning-of-current-entry now works as advertised

	  - allout-end-of-current-entry relieved of superfluous
	    allout-show-entry

	  - reconciled with distributed allout.el 1.61 (current CVS version
	    as of 09/30/2005), including interactive-p fixes, typo and
	    coding style fixes, change of function prefix to "allout-", etc,
	    and fixed problem created in outline yanking due to the
	    interactive-p fixes

	  - relocated some macros

	  - refined many docstrings, including anything from correcting
	    typos to conceptual clarification and correction

	  - corrected commentary 'keywords' to legitimate ones

	  - updated comentary author info (using my current email address,
            obscurified)

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-09-30 17:24 new version of allout.el - patch and ChangeLog Ken Manheimer
@ 2005-09-30 21:06 ` Sascha Wilde
  2005-09-30 21:52   ` Ken Manheimer
       [not found] ` <E1ELj0L-0000Pn-3T@fencepost.gnu.org>
  1 sibling, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-09-30 21:06 UTC (permalink / raw)
  Cc: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 1027 bytes --]

On Fri, Sep 30, 2005 at 01:24:14PM -0400, Ken Manheimer wrote:
> attached is a patch and ChangeLog for a substantial new version of
> allout.el, emacs' alternative (and much more extensive) outliner.  
[...]
> below is the synopsis of just the encryption features, from the ChangeLog entry.
[...]
> 	    - both public- and symmetric-key modes are supported.
> 	    - encryption being on a per-topic basis means you can
> 	      intersperse encrypted and clear-text data in a single file
> 	      to your heart's content.

I think this sounds great, but...

> 	    topic encryption functionality depends on both mailcrypt and
> 	    crypt++ packages.  (non-encryption allout functionality is not
> 	    disrupted if either mailcrypt or crypt++ are absent.)

why do you relay on these packages, which aren't part of gnu emacs,
when we have pgg?

cheers
sascha
-- 
Sascha Wilde   -.-. ..- .-. .. --- ... .. - -.-- 
               -.- .. .-.. .-.. . -.. 
               - .... .
               -.-. .- -

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-09-30 21:06 ` Sascha Wilde
@ 2005-09-30 21:52   ` Ken Manheimer
  2005-10-01  8:20     ` Andreas Schwab
  2005-10-01 16:28     ` Ken Manheimer
  0 siblings, 2 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-09-30 21:52 UTC (permalink / raw)


On 9/30/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> On Fri, Sep 30, 2005 at 01:24:14PM -0400, Ken Manheimer wrote:
> [...]
> >           - both public- and symmetric-key modes are supported.
> >           - encryption being on a per-topic basis means you can
> >             intersperse encrypted and clear-text data in a single file
> >             to your heart's content.
>
> I think this sounds great, but...
>
> >           topic encryption functionality depends on both mailcrypt and
> >           crypt++ packages.  (non-encryption allout functionality is not
> >           disrupted if either mailcrypt or crypt++ are absent.)
>
> why do you relay on these packages, which aren't part of gnu emacs,
> when we have pgg?

good question - i wasn't aware of pgg.  can you tell me more about it?
 i'd be very happy to find a single package that cleanly provides the
encryption interface that allout needs!

gentoo has an ebuild for it, but it involves xemacs dependencies,
making me think the build is xemacs-specific.  i gather, since you're
responding via the emacs-devel list, that it's available for the
mainline emacs - is that right?  google points me at only emacs-wiki
stuff (for a search on "emacs gpp") or xemacs-related stuff (for
"xemacs gpp")...

ken
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-09-30 21:52   ` Ken Manheimer
@ 2005-10-01  8:20     ` Andreas Schwab
  2005-10-01 12:41       ` Reiner Steib
  2005-10-01 16:28     ` Ken Manheimer
  1 sibling, 1 reply; 156+ messages in thread
From: Andreas Schwab @ 2005-10-01  8:20 UTC (permalink / raw)
  Cc: emacs-devel

Ken Manheimer <ken.manheimer@gmail.com> writes:

> good question - i wasn't aware of pgg.  can you tell me more about it?

pgg has been developed as part of Gnus.  It hasn't been distributed as
part of Emacs before, but Emacs 22 will contain it as part of the Gnus
subsystem.

> google points me at only emacs-wiki stuff (for a search on "emacs gpp")
> or xemacs-related stuff (for "xemacs gpp")...

http://www.gnupg.org/(en)/related_software/frontends.html#fend_mua-PGG

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-10-01  8:20     ` Andreas Schwab
@ 2005-10-01 12:41       ` Reiner Steib
  2005-10-01 23:54         ` James Cloos
  0 siblings, 1 reply; 156+ messages in thread
From: Reiner Steib @ 2005-10-01 12:41 UTC (permalink / raw)


On Sat, Oct 01 2005, Andreas Schwab wrote:

> Ken Manheimer <ken.manheimer@gmail.com> writes:
>
>> good question - i wasn't aware of pgg.  can you tell me more about it?

If you have Emacs 22 (CVS) or Gnus 5.10 installed, you should also
have the manual: (info "(pgg)Top").

> pgg has been developed as part of Gnus.  

PGG has been developed as a separate package (by Daiki Ueno, AFAICS).
It has later been include in Gnus (Gnus 5.10).

> It hasn't been distributed as part of Emacs before, but Emacs 22
> will contain it as part of the Gnus subsystem.

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-09-30 21:52   ` Ken Manheimer
  2005-10-01  8:20     ` Andreas Schwab
@ 2005-10-01 16:28     ` Ken Manheimer
  2005-10-02 10:48       ` Sascha Wilde
  2005-10-02 17:08       ` new version of allout.el - patch and ChangeLog Richard M. Stallman
  1 sibling, 2 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-01 16:28 UTC (permalink / raw)
  Cc: Sascha Wilde, Andreas Schwab

On 9/30/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> On 9/30/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> > On Fri, Sep 30, 2005 at 01:24:14PM -0400, Ken Manheimer wrote:
> > [...]
> > >           topic encryption functionality depends on both mailcrypt and
> > >           crypt++ packages.  (non-encryption allout functionality is not
> > >           disrupted if either mailcrypt or crypt++ are absent.)
> >
> > why do you relay on these packages, which aren't part of gnu emacs,
> > when we have pgg?
>
> good question - i wasn't aware of pgg.  can you tell me more about it?
>  i'd be very happy to find a single package that cleanly provides the
> encryption interface that allout needs!

andreas pointed me at pgg's bundling in gnus, for which gentoo has an
ebuild.  i emerged it and got access to gpp and the info file.  it
looks nice - clean - but appears to have the same drawback, for my
purposes, as mailcrypt.  it will decrypt messages encoded with a
symmetric key, but provides no api for encrypting with a symmetric
key.  that lack is a show-stopper for my purposes.

that mailcrypt and pgg would concentrate on public-key mode makes a
lot of sense, considering the ultimate purpose is encryption and/or
signing of messages to be exchanged between remote parties - email,
news, software packaging, etc.  my primary concern for encryption in
allout is with conveniently securing notes for oneself.  the lattitude
of symmetric keys offers much better convenience in that context.

i actually inquired on the mailcrypt developers list about the lack of
provision for symmetric-key encryption, and the general concensus was
that it just was an oversight, not a deliberate avoidance.  i presume
(as i suggest above) because it's not useful for the message-exchange
realm.

it may well be that pgg is preferable, somehow, to mailcrypt - they
both offer similar functionality, including key caching, as well as
the lack of an interface for encrypting with a symmetric key.  but the
changeover won't gain me anything i can yet see - i'll still need to
also use crypt++ for the symmetric key encoding.  and the cost in
effort of switching from working code would not be trivial, so
until/unless i see a compelling gain, or someone else does the
integration (and convinces me that pgg is more widespread than
mailcrypt), i'm think i'm fine with mailcrypt.

ken
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
       [not found] ` <E1ELj0L-0000Pn-3T@fencepost.gnu.org>
@ 2005-10-01 22:33   ` Ken Manheimer
  2005-10-20 13:57     ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-01 22:33 UTC (permalink / raw)
  Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 988 bytes --]

On 10/1/05, Richard M. Stallman <rms@gnu.org> wrote:
> Thanks very much for sending this update.  Now is a good time to
> install it.

great!  i'll be glad to see these improvements out there in the world...

> Could you be so kind as to itemize the change log, describing which
> functions/defuns have been changed, and how?  We need that in order
> to install the change.
>
> Also, we need to have an item for etc/NEWS.  Would you please write one?

i've attached new versions of the patch and ChangeLog, and an etc/NEWS snippet.

please use the new version of the patch, rather than the one i sent
yesterday.  it includes an xemacs compatibility provision for a
problem i hadn't noticed until after i sent the patch out yesterday. 
it also includes several small adjustments i noticed while doing the
detailed enumeration of the functions that were changed.

i'm cc'ing emacs-devel, figuring that's where the material will be used.

ken
ken.manheimer@gmail.com

[-- Attachment #2: allout-patch.txt --]
[-- Type: text/plain, Size: 113749 bytes --]

--- allout.el.~1.61.~	2005-08-06 18:13:41.000000000 -0400
+++ allout.el	2005-10-01 17:47:12.000000000 -0400
@@ -3,10 +3,11 @@
 ;; Copyright (C) 1992, 1993, 1994, 2001, 2002, 2003, 2004,
 ;;   2005 Free Software Foundation, Inc.
 
-;; Author: Ken Manheimer <klm@zope.com>
-;; Maintainer: Ken Manheimer <klm@zope.com>
+;; Author: Ken Manheimer <ken dot manheimer at gmail dot com>
+;; Maintainer: Ken Manheimer <ken dot manheimer at gmail dot com>
 ;; Created: Dec 1991 - first release to usenet
-;; Keywords: outlines mode wp languages
+;; Version: $Id: allout.el,v 1.68 2005/09/30 19:48:25 klm Exp $||
+;; Keywords: outlines wp languages
 
 ;; This file is part of GNU Emacs.
 
@@ -34,43 +35,68 @@
 ;; programming languages.  (For an example, see the allout code
 ;; itself, which is organized in ;; an outline framework.)
 ;;
-;; In addition to outline navigation and exposure, allout includes:
+;; Some features:
 ;;
-;;  - topic-oriented repositioning, cut, and paste
-;;  - integral outline exposure-layout
-;;  - incremental search with dynamic exposure and reconcealment of hidden text
+;;  - classic outline-mode topic-oriented navigation and exposure adjustment
+;;  - topic-oriented editing including coherent topic and subtopic
+;;    creation, promotion, demotion, cut/paste across depths, etc
+;;  - incremental search with dynamic exposure and reconcealment of text
+;;  - customizable bullet format enbles programming-language specific
+;;    outlining, for ultimate code-folding editing.  (allout code itself is
+;;    formatted as an outline - do ESC-x eval-current-buffer in allout.el
+;;    to try it out.)
+;;  - configurable per-file initial exposure settings
+;;  - symmetric-key and key-pair topic encryption, plus reliable key
+;;    verification and user-supplied hint maintenance.  (see
+;;    allout-toggle-current-subtree-encryption docstring.)
 ;;  - automatic topic-number maintenance
-;;  - "Hot-spot" operation, for single-keystroke maneuvering and
-;;    exposure control.  (See the `allout-mode' docstring.)
+;;  - "hot-spot" operation, for single-keystroke maneuvering and
+;;    exposure control (see the allout-mode docstring)
+;;  - easy rendering of exposed portions into numbered, latex, indented, etc
+;;    outline styles
 ;;
-;; and many other features.
+;; and more.
 ;;
 ;; The outline menubar additions provide quick reference to many of
-;; the features, and see the docstring of the function `allout-init'
-;; for instructions on priming your Emacs session for automatic
-;; activation of `allout-mode'.
+;; the features, and see the docstring of the variable `allout-init'
+;; for instructions on priming your emacs session for automatic
+;; activation of allout-mode.
 ;;
 ;; See the docstring of the variables `allout-layout' and
 ;; `allout-auto-activation' for details on automatic activation of
-;; allout `allout-mode' as a minor mode.  (It has changed since allout
+;; `allout-mode' as a minor mode.  (It has changed since allout
 ;; 3.x, for those of you that depend on the old method.)
 ;;
 ;; Note - the lines beginning with `;;;_' are outline topic headers.
 ;;        Just `ESC-x eval-current-buffer' to give it a whirl.
 
-;; Ken Manheimer	klm@zope.com
+;; ken manheimer (ken dot manheimer at gmail dot com)
 
 ;;; Code:
 
 ;;;_* Provide
+;(provide 'outline)
 (provide 'allout)
 
+;;;_* Dependency autoloads
+(eval-when-compile 'cl)                 ; otherwise, flet compilation fouls
+(autoload 'crypt-encrypt-buffer "crypt++")
+(setq-default crypt-encryption-type 'gpg)
+
+(autoload 'mc-encrypt "mailcrypt"
+  "*Encrypt the current buffer")
+(autoload 'mc-activate-passwd "mailcrypt"
+  "Activate the passphrase matching ID, using PROMPT for a prompt.
+Return the passphrase.  If PROMPT is nil, only return value if cached.")
+(autoload 'mc-gpg-process-region "mc-gpg")
+(autoload 'mc-dectivate-passwd "mailcrypt"
+  "*Deactivate the passphrase cache.")
+
 ;;;_* USER CUSTOMIZATION VARIABLES:
 (defgroup allout nil
   "Extensive outline mode for use alone and with other modes."
   :prefix "allout-"
-  :group 'editing
-  :version "22.1")
+  :group 'outlines)
 
 ;;;_ + Layout, Mode, and Topic Header Configuration
 
@@ -111,8 +137,8 @@
 
 A list value specifies a default layout for the current buffer, to be
 applied upon activation of `allout-mode'.  Any non-nil value will
-automatically trigger `allout-mode', provided `allout-init'
-has been called to enable it.
+automatically trigger `allout-mode' \(provided `allout-init' has been called
+to enable this behavior).
 
 See the docstring for `allout-init' for details on setting up for
 auto-mode-activation, and for `allout-expose-topic' for the format of
@@ -171,7 +197,7 @@
   :group 'allout)
 (make-variable-buffer-local 'allout-primary-bullet)
 ;;;_  = allout-plain-bullets-string
-(defcustom allout-plain-bullets-string ".:,;"
+(defcustom allout-plain-bullets-string ".,"
   "*The bullets normally used in outline topic prefixes.
 
 See `allout-distinctive-bullets-string' for the other kind of
@@ -185,7 +211,7 @@
   :group 'allout)
 (make-variable-buffer-local 'allout-plain-bullets-string)
 ;;;_  = allout-distinctive-bullets-string
-(defcustom allout-distinctive-bullets-string "*+-=>([{}&!?#%\"X@$~_\\"
+(defcustom allout-distinctive-bullets-string "*+-=>()[{}&!?#%\"X@$~_\\:;^"
   "*Persistent outline header bullets used to distinguish special topics.
 
 These bullets are used to distinguish topics from the run-of-the-mill
@@ -198,12 +224,13 @@
  `?' question topics
  `\(' parenthetic comment \(with a matching close paren inside)
  `[' meta-note \(with a matching close ] inside)
- `\"' a quote
+ `\"' a quotation
  `=' value settings
  `~' \"more or less\"
+ `^' see above
 
-... just for example.  (`#' typically has a special meaning to the
-software, according to the value of `allout-numbered-bullet'.)
+ ... for example.  (`#' typically has a special meaning to the software,
+according to the value of `allout-numbered-bullet'.)
 
 See `allout-plain-bullets-string' for the selection of
 alternating bullets.
@@ -337,7 +364,6 @@
 Set this var to the bullet you want to use for file cross-references."
   :type '(choice (const nil) string)
   :group 'allout)
-
 ;;;_  = allout-presentation-padding
 (defcustom allout-presentation-padding 2
   "*Presentation-format white-space padding factor, for greater indent."
@@ -381,7 +407,7 @@
   :type 'string
   :group 'allout)
 ;;;_  - allout-title
-(defcustom allout-title '(or buffer-file-name (current-buffer-name))
+(defcustom allout-title '(or buffer-file-name (buffer-name))
   "*Expression to be evaluated to determine the title for LaTeX
 formatted copy."
   :type 'sexp
@@ -397,6 +423,94 @@
   :type 'string
   :group 'allout)
 
+;;;_ + Topic encryption
+;;;_  = allout-topic-encryption-bullet
+(defcustom allout-topic-encryption-bullet "~"
+  "*Bullet signifying encryption of the entry's body."
+  :type '(choice (const nil) string)
+  :group 'allout)
+;;;_  = allout-default-encryption-scheme
+(defcustom allout-default-encryption-scheme 'mc-scheme-gpg
+  "*Default allout outline topic encryption mode.
+
+See mailcrypt variable `mc-schemes' and mailcrypt docs for encryption schemes."
+  :type 'symbol
+  :group 'allout)
+;;;_  = allout-key-verifier-handling
+(defcustom allout-key-verifier-handling 'situate
+  "*Dictate outline encryption key verifier handling.
+
+The key verifier is string associated with a file that is encrypted with
+the file's current symmetric encryption key.  It is used, if present, to
+confirm that the key entered by the user is the same as the established
+one, or explicitly presenting the user with the choice to go with a
+new key when a difference is encountered.
+
+The range of values are:
+
+ situate - include key verifier string as text in the file's local-vars
+           section
+ transient - establish the value as a variable in the file's buffer, but
+             don't preserve it as a file variable.
+ disabled - don't establish or do verification.
+
+See the docstring for the `allout-enable-file-variable-adjustment'
+variable for details about allout ajustment of file variables."
+  :type '(choice (const situate)
+                 (const transient)
+                 (const disabled))
+  :group 'allout)
+(make-variable-buffer-local 'allout-key-verifier-handling)
+;;;_  = allout-key-hint-handling
+(defcustom allout-key-hint-handling 'always
+  "*Dictate outline encryption key reminder handling:
+
+ always - always show reminder when prompting
+ needed - show reminder on key entry failure
+ manage - never present reminder, but still manage a file-var entry for it
+ disabled - don't even manage the file variable entry
+
+See the docstring for the `allout-enable-file-variable-adjustment'
+variable for details about allout ajustment of file variables."
+  :type '(choice (const always)
+                 (const needed)
+                 (const manage)
+                 (const disabled))
+  :group 'allout)
+(make-variable-buffer-local 'allout-key-hint-handling)
+;;;_  = allout-encrypt-unencrypted-on-saves
+(defcustom allout-encrypt-unencrypted-on-saves 'except-current
+  "*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
+       key 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 key 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))
+  :group 'allout)
+(make-variable-buffer-local 'allout-encrypt-unencrypted-on-saves)
+
 ;;;_ + Miscellaneous customization
 
 ;;;_  = allout-command-prefix
@@ -422,13 +536,15 @@
         ("\C-f" allout-forward-current-level)
         ("\C-b" allout-backward-current-level)
         ("\C-a" allout-beginning-of-current-entry)
-        ("\C-e" allout-end-of-current-entry)
+        ("\C-e" allout-end-of-entry)
                                         ; Exposure commands:
         ("\C-i" allout-show-children)
         ("\C-s" allout-show-current-subtree)
         ("\C-h" allout-hide-current-subtree)
+        ("h" allout-hide-current-subtree)
         ("\C-o" allout-show-current-entry)
         ("!" allout-show-all)
+        ("x" allout-toggle-current-subtree-encryption)
                                         ; Alteration commands:
         (" " allout-open-sibtopic)
         ("." allout-open-subtopic)
@@ -489,19 +605,22 @@
 
 (make-variable-buffer-local 'allout-reindent-bodies)
 
-;;;_  = allout-inhibit-protection
-(defcustom allout-inhibit-protection nil
-  "*Non-nil disables warnings and confirmation-checks for concealed-text edits.
-
-Outline mode uses Emacs change-triggered functions to detect unruly
-changes to concealed regions.  Set this var non-nil to disable the
-protection, potentially increasing text-entry responsiveness a bit.
-
-This var takes effect at `allout-mode' activation, so you may have to
-deactivate and then reactivate the mode if you want to toggle the
-behavior."
+;;;_  = allout-enable-file-variable-adjustment
+(defcustom allout-enable-file-variable-adjustment t
+  "*If non-nil, some allout outline actions can edit Emacs file variables text.
+
+This can range from changes to existing entries, addition of new ones,
+and creation of a new local variables section when necessary.
+
+Emacs file variables adjustments are also inhibited if `enable-local-variables'
+is nil.
+
+Operations potentially causing edits include allout encryption routines.
+See the docstring for `allout-toggle-current-subtree-encryption' for
+details."
   :type 'boolean
   :group 'allout)
+(make-variable-buffer-local 'allout-enable-file-variable-adjustment)
 
 ;;;_* CODE - no user customizations below.
 
@@ -509,7 +628,7 @@
 ;;;_  : Version
 ;;;_   = allout-version
 (defvar allout-version
-  (let ((rcs-rev "$Revision$"))
+  (let ((rcs-rev "$Revision: 1.68 $"))
     (condition-case err
 	(save-match-data
 	  (string-match "Revision: \\([0-9]+\\.[0-9]+\\)" rcs-rev)
@@ -728,7 +847,16 @@
 			      (car (cdr cell)))))))
 	    keymap-list)
     map))
-
+;;;_   = allout-prior-bindings - being deprecated.
+(defvar allout-prior-bindings nil
+  "Variable for use in V18, with allout-added-bindings, for
+resurrecting, on mode deactivation, bindings that existed before
+activation.  Being deprecated.")
+;;;_   = allout-added-bindings - being deprecated
+(defvar allout-added-bindings nil
+  "Variable for use in V18, with allout-prior-bindings, for
+resurrecting, on mode deactivation, bindings that existed before
+activation.  Being deprecated.")
 ;;;_  : Menu bar
 (defvar allout-mode-exposure-menu)
 (defvar allout-mode-editing-menu)
@@ -759,7 +887,11 @@
 		      ["Shift Topic Out" allout-shift-out t]
 		      ["Rebullet Topic" allout-rebullet-topic t]
 		      ["Rebullet Heading" allout-rebullet-current-heading t]
-		      ["Number Siblings" allout-number-siblings t]))
+		      ["Number Siblings" allout-number-siblings t]
+		      "----"
+                      ["Toggle Topic Encryption"
+                       allout-toggle-current-subtree-encryption
+                       (> (allout-current-depth) 1)]))
   (easy-menu-define allout-mode-navigation-menu
 		    allout-mode-map
 		    "Allout outline navigation menu."
@@ -775,7 +907,7 @@
 		      "----"
 		      ["Beginning of Entry"
 		       allout-beginning-of-current-entry t]
-		      ["End of Entry" allout-end-of-current-entry t]
+		      ["End of Entry" allout-end-of-entry t]
 		      ["End of Subtree" allout-end-of-current-subtree t]))
   (easy-menu-define allout-mode-misc-menu
 		    allout-mode-map
@@ -855,13 +987,6 @@
           (setq allout-mode-prior-settings rebuild)))))
   )
 ;;;_  : Mode-specific incidentals
-;;;_   = allout-during-write-cue nil
-(defvar allout-during-write-cue nil
-  "Used to inhibit outline change-protection during file write.
-
-See also `allout-post-command-business', `allout-write-file-hook',
-`allout-before-change-protect', and `allout-post-command-business'
-functions.")
 ;;;_   = allout-pre-was-isearching nil
 (defvar allout-pre-was-isearching nil
   "Cue for isearch-dynamic-exposure mechanism, implemented in
@@ -869,22 +994,28 @@
 (make-variable-buffer-local 'allout-pre-was-isearching)
 ;;;_   = allout-isearch-prior-pos nil
 (defvar allout-isearch-prior-pos nil
-  "Cue for isearch-dynamic-exposure tracking, used by `allout-isearch-expose'.")
+  "Cue for isearch-dynamic-exposure tracking, used by
+`allout-isearch-expose'.")
 (make-variable-buffer-local 'allout-isearch-prior-pos)
-;;;_   = allout-override-protect nil
-(defvar allout-override-protect nil
-  "Used in `allout-mode' for regulate of concealed-text protection mechanism.
-
-Allout outline mode regulates alteration of concealed text to protect
-against inadvertent, unnoticed changes.  This is for use by specific,
-native outline functions to temporarily override that protection.
-It's automatically reset to nil after every buffer modification.")
-(make-variable-buffer-local 'allout-override-protect)
+;;;_   = allout-isearch-did-quit
+(defvar allout-isearch-did-quit nil
+  "Distinguishes isearch conclusion and cancellation.
+
+Maintained by allout-isearch-abort \(which is wrapped around the real
+isearch-abort), and monitored by allout-isearch-expose for action.")
+(make-variable-buffer-local 'allout-isearch-did-quit)
 ;;;_   > allout-unprotected (expr)
-(defmacro allout-unprotected (expression)
-  "Evaluate EXPRESSION with `allout-override-protect' let-bound to t."
-  `(let ((allout-override-protect t))
-     ,expression))
+(defmacro allout-unprotected (expr)
+  "Enable internal outline operations to alter read-only text."
+  `(let ((was-inhibit-r-o inhibit-read-only))
+     (unwind-protect
+         (progn
+           (setq inhibit-read-only t)
+           ,expr)
+       (setq inhibit-read-only was-inhibit-r-o)
+       )
+     )
+  )
 ;;;_   = allout-undo-aggregation
 (defvar allout-undo-aggregation 30
   "Amount of successive self-insert actions to bunch together per undo.
@@ -897,14 +1028,109 @@
   "Horrible hack used to prevent invalid multiple triggering of outline
 mode from prop-line file-var activation.  Used by `allout-mode' function
 to track repeats.")
-;;;_   > allout-write-file-hook ()
-(defun allout-write-file-hook ()
-  "In `allout-mode', run as a `write-contents-functions' activity.
-
-Currently just sets `allout-during-write-cue', so outline change-protection
-knows to keep inactive during file write."
-  (setq allout-during-write-cue t)
-  nil)
+;;;_   = allout-file-key-verifier-string
+(defvar allout-file-key-verifier-string nil
+  "Name for use as a file variable for verifying encryption key across
+sessions.")
+(make-variable-buffer-local 'allout-file-key-verifier-string)
+;;;_   = allout-encryption-scheme
+(defvar allout-encryption-scheme nil
+  "*Allout outline topic encryption scheme pending for the current buffer.
+
+Intended as a file-specific (buffer local) setting, it defaults to the
+value of allout-default-encryption-scheme if nil.")
+(make-variable-buffer-local 'allout-encryption-scheme)
+;;;_   = allout-key-verifier-string
+(defvar allout-key-verifier-string nil
+  "Setting used to test solicited encryption keys against that already
+associated with a file.
+
+It consists of an encrypted random string useful only to verify that a key
+entered by the user is effective for decryption.  The key itself is \*not*
+recorded in the file anywhere, and the encrypted contents are random binary
+characters to avoid exposing greater susceptibility to search attacks.
+
+The verifier string is retained as an Emacs file variable, as well as in
+the emacs buffer state, if file variable adjustments are enabled.  See
+`allout-enable-file-variable-adjustment' for details about that.")
+(make-variable-buffer-local 'allout-key-verifier-string)
+(setq-default allout-key-verifier-string nil)
+;;;_   = allout-key-hint-string
+(defvar allout-key-hint-string ""
+  "Variable used to retain a reminder string for a file's encryption key.
+
+See the description of `allout-key-hint-handling' for details about how
+the reminder is deployed.
+
+The hint is retained as an Emacs file variable, as well as in the emacs buffer
+state, if file variable adjustments are enabled.  See
+`allout-enable-file-variable-adjustment' for details about that.")
+(make-variable-buffer-local 'allout-key-hint-string)
+(setq-default allout-key-hint-string "")
+;;;_   = allout-after-save-decrypt
+(defvar allout-after-save-decrypt nil
+  "Internal variable, is nil or has the value of two points:
+
+ - the location of a topic to be decrypted after saving is done
+ - where to situate the cursor after the decryption is performed
+
+This is used to decrypt the topic that was currently being edited, if it
+was encrypted automatically as part of a file write or autosave.")
+(make-variable-buffer-local 'allout-after-save-decrypt)
+;;;_   > allout-write-file-hook-handler ()
+(defun allout-write-file-hook-handler ()
+  "Implement `allout-encrypt-unencrypted-on-saves' policy for file writes."
+
+  (if (or (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 2)
+            (condition-case failure
+                (setq allout-after-save-decrypt
+                      (allout-encrypt-decrypted except-mark))
+              (error (progn
+                       (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 saves."
+
+  (if  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-after-saves-handler ()
+(defun allout-after-saves-handler ()
+  "Decrypt topic encrypted for save, if it's currently being edited.
+
+Ie, if it was pending encryption and contained the point in its body before
+the save.
+
+We use values stored in `allout-after-save-decrypt' to locate the topic
+and the place for the cursor after the decryption is done."
+  (if (not (and (allout-mode-p)
+                (boundp 'allout-after-save-decrypt)
+                allout-after-save-decrypt))
+      t
+    (goto-char (car allout-after-save-decrypt))
+    (let ((was-modified (buffer-modified-p)))
+      (allout-toggle-current-subtree-encryption)
+      (if (not was-modified)
+          (set-buffer-modified-p nil)))
+    (goto-char (cadr allout-after-save-decrypt))
+    (setq allout-after-save-decrypt nil))
+  )
 
 ;;;_ #2 Mode activation
 ;;;_  = allout-mode
@@ -916,11 +1142,10 @@
   'allout-mode)
 ;;;_  = allout-explicitly-deactivated
 (defvar allout-explicitly-deactivated nil
-  "Non-nil if `allout-mode' was last deliberately deactivated.
+  "If t, `allout-mode's last deactivation was deliberate.
 So `allout-post-command-business' should not reactivate it...")
 (make-variable-buffer-local 'allout-explicitly-deactivated)
 ;;;_  > allout-init (&optional mode)
-;;;###autoload
 (defun allout-init (&optional mode)
   "Prime `allout-mode' to enable/disable auto-activation, wrt `allout-layout'.
 
@@ -939,9 +1164,9 @@
 the `allout-layout' variable.  (See `allout-layout' and
 `allout-expose-topic' docstrings for more details on auto layout).
 
-`allout-init' works by setting up (or removing)
-`allout-find-file-hook' in `find-file-hook', and giving
-`allout-auto-activation' a suitable setting.
+`allout-init' works by setting up (or removing) the `allout-mode'
+find-file-hook, and giving `allout-auto-activation' a suitable
+setting.
 
 To prime your Emacs session for full auto-outline operation, include
 the following two lines in your Emacs init file:
@@ -949,32 +1174,35 @@
 \(require 'allout)
 \(allout-init t)"
 
-  (interactive
-   (let ((m (completing-read
-	     (concat "Select outline auto setup mode "
-		     "(empty for report, ? for options) ")
-	     '(("nil")("full")("activate")("deactivate")
-	       ("ask") ("report") (""))
-	     nil
-	     t)))
-     (if (string= m "") 'report
-       (intern-soft m))))
+  (interactive)
+  (if (interactive-p)
+      (progn
+	(setq mode
+	      (completing-read
+	       (concat "Select outline auto setup mode "
+		       "(empty for report, ? for options) ")
+	       '(("nil")("full")("activate")("deactivate")
+		 ("ask") ("report") (""))
+	       nil
+	       t))
+	(if (string= mode "")
+	    (setq mode 'report)
+	  (setq mode (intern-soft mode)))))
   (let
       ;; convenience aliases, for consistent ref to respective vars:
       ((hook 'allout-find-file-hook)
        (curr-mode 'allout-auto-activation))
 
     (cond ((not mode)
-	   (setq find-file-hook (delq hook find-file-hook))
+	   (setq find-file-hooks (delq hook find-file-hooks))
 	   (if (interactive-p)
 	       (message "Allout outline mode auto-activation inhibited.")))
 	  ((eq mode 'report)
-	   (if (memq hook find-file-hook)
-	       ;; Just punt and use the reports from each of the modes:
-	       (allout-init (symbol-value curr-mode))
-	     (allout-init nil)
-	     (message "Allout outline mode auto-activation inhibited.")))
-	  (t (add-hook 'find-file-hook hook)
+	   (if (not (memq hook find-file-hooks))
+	       (allout-init nil)
+	     ;; Just punt and use the reports from each of the modes:
+	     (allout-init (symbol-value curr-mode))))
+	  (t (add-hook 'find-file-hooks hook)
 	     (set curr-mode		; `set', not `setq'!
 		  (cond ((eq mode 'activate)
 			 (message
@@ -1022,10 +1250,11 @@
 
 In addition to outline navigation and exposure, allout includes:
 
- - topic-oriented repositioning, cut, and paste
+ - topic-oriented repositioning, promotion/demotion, cut, and paste
  - integral outline exposure-layout
  - incremental search with dynamic exposure and reconcealment of hidden text
  - automatic topic-number maintenance
+ - easy topic encryption and decryption
  - \"Hot-spot\" operation, for single-keystroke maneuvering and
     exposure control.  \(See the allout-mode docstring.)
 
@@ -1035,7 +1264,7 @@
 special `allout-mode' features and terminology.  See also the outline
 menubar additions for quick reference to many of the features, and see
 the docstring of the function `allout-init' for instructions on
-priming your Emacs session for automatic activation of `allout-mode'.
+priming your emacs session for automatic activation of `allout-mode'.
 
 
 The bindings are dictated by the `allout-keybindings-list' and
@@ -1048,7 +1277,7 @@
 C-c C-u allout-up-current-level         | C-c C-s allout-show-current-subtree
 C-c C-f allout-forward-current-level    | C-c C-o allout-show-current-entry
 C-c C-b allout-backward-current-level   | ^U C-c C-s allout-show-all
-C-c C-e allout-end-of-current-entry     |	   allout-hide-current-leaves
+C-c C-e allout-end-of-entry             |	   allout-hide-current-leaves
 C-c C-a allout-beginning-of-current-entry, alternately, goes to hot-spot
 
 	Topic Header Production:
@@ -1064,7 +1293,7 @@
 C-c<CR>	allout-rebullet-topic	Reconcile bullets of topic and its offspring
 				- distinctive bullets are not changed, others
 				  alternated according to nesting depth.
-C-c *	allout-rebullet-current-heading Prompt for alternate bullet for
+C-c b	allout-rebullet-current-heading Prompt for alternate bullet for
 					 current topic.
 C-c #	allout-number-siblings	Number bullets of topic and siblings - the
 				offspring are not affected.  With repeat
@@ -1087,8 +1316,8 @@
 C-c C-SPC allout-mark-topic
 C-c = c	allout-copy-exposed-to-buffer
 				Duplicate outline, sans concealed text, to
-				buffer with name derived from derived from
-				that of current buffer - \"*XXX exposed*\".
+				buffer with name derived from derived from that
+				of current buffer - \"*BUFFERNAME exposed*\".
 C-c = p	allout-flatten-exposed-to-buffer
 				Like above 'copy-exposed', but convert topic
 				prefixes to section.subsection... numeric
@@ -1096,6 +1325,19 @@
 ESC ESC (allout-init t)	Setup Emacs session for outline mode
 				auto-activation.
 
+                  Encrypted Entries
+
+Outline mode supports easily togglable gpg encryption of topics, with
+niceities like support for symmetric and key-pair modes, key timeout, key
+consistency checking, user-provided hinting for symmetric key mode, and
+auto-encryption of topics pending encryption on save.  The aim is to enable
+reliable topic privacy while preventing accidents like neglected
+encryption, encryption with a mistaken key, forgetting which key was used,
+and other practical pitfalls.
+
+See the `allout-toggle-current-subtree-encryption' function and
+`allout-encrypt-unencrypted-on-saves' customization variable for details.
+
 		 HOT-SPOT Operation
 
 Hot-spot operation provides a means for easy, single-keystroke outline
@@ -1148,11 +1390,11 @@
 
 HEADER:	The first line of a topic, include the topic PREFIX and header
 	text.
-PREFIX: The leading text of a topic which distinguishes it from
-	normal text.  It has a strict form, which consists of a
-	prefix-lead string, padding, and a bullet.  The bullet may be
-	followed by a number, indicating the ordinal number of the
-	topic among its siblings, a space, and then the header text.
+PREFIX: The leading text of a topic which distinguishes it from normal
+        text.  It has a strict form, which consists of a prefix-lead
+        string, padding, and a bullet.  The bullet may be followed by a
+        number, indicating the ordinal number of the topic among its
+        siblings, a space, and then the header text.
 
 	The relative length of the PREFIX determines the nesting depth
 	of the topic.
@@ -1223,7 +1465,7 @@
      ;; off on second invocation, so we detect it as best we can, and
      ;; skip everything.
      ((and same-complex-command		; Still in same complex command
-					; as last time `allout-mode' invoked.
+                                        ; as last time `allout-mode' invoked.
 	  active			; Already activated.
 	  (not explicit-activation)	; Prop-line file-vars don't have args.
 	  (string-match "^19.1[89]"	; Bug only known to be in v19.18 and
@@ -1238,6 +1480,19 @@
 				       ; active state or *de*activation
 				       ; specifically requested:
       (setq allout-explicitly-deactivated t)
+      (if (string-match "^18\." emacs-version)
+				       ; Revoke those keys that remain
+				       ; as we set them:
+	  (let ((curr-loc (current-local-map)))
+	   (mapcar (function
+		    (lambda (cell)
+		      (if (eq (lookup-key curr-loc (car cell))
+			      (car (cdr cell)))
+			  (define-key curr-loc (car cell)
+			    (assq (car cell) allout-prior-bindings)))))
+		   allout-added-bindings)
+	   (allout-resumptions 'allout-added-bindings)
+	   (allout-resumptions 'allout-prior-bindings)))
 
       (if allout-old-style-prefixes
 	  (progn
@@ -1246,9 +1501,12 @@
       (allout-resumptions 'selective-display)
       (if (and (boundp 'before-change-functions) before-change-functions)
 	  (allout-resumptions 'before-change-functions))
-      (setq write-contents-functions
-	    (delq 'allout-write-file-hook
-		  write-contents-functions))
+      (setq local-write-file-hooks
+	   (delq 'allout-write-file-hook-handler
+		 local-write-file-hooks))
+      (setq auto-save-hook
+	   (delq 'allout-auto-save-hook-handler
+		 auto-save-hook))
       (allout-resumptions 'paragraph-start)
       (allout-resumptions 'paragraph-separate)
       (allout-resumptions (if (string-match "^18" emacs-version)
@@ -1288,25 +1546,27 @@
 		     (cons '(allout-mode . allout-mode-map)
 			   minor-mode-map-alist))))
 
+				       ; V18 minor-mode key bindings:
+				       ; Stash record of added bindings
+				       ; for later revocation:
+	(allout-resumptions 'allout-added-bindings
+			    (list allout-keybindings-list))
+	(allout-resumptions 'allout-prior-bindings
+			    (list (current-local-map)))
 				       ; and add them:
 	(use-local-map (produce-allout-mode-map allout-keybindings-list
 						(current-local-map)))
 	)
 
 				       ; selective-display is the
-				       ; Emacs conditional exposure
+				       ; emacs conditional exposure
 				       ; mechanism:
       (allout-resumptions 'selective-display '(t))
-      (if allout-inhibit-protection
-	  t
-	(allout-resumptions 'before-change-functions
-			    '(allout-before-change-protect)))
       (add-hook 'pre-command-hook 'allout-pre-command-business)
       (add-hook 'post-command-hook 'allout-post-command-business)
-				       ; Temporarily set by any outline
-				       ; functions that can be trusted to
-				       ; deal properly with concealed text.
-      (add-hook 'write-contents-functions 'allout-write-file-hook)
+      (add-hook 'local-write-file-hooks 'allout-write-file-hook-handler)
+      (make-variable-buffer-local 'auto-save-hook)
+      (add-hook 'auto-save-hook 'allout-auto-save-hook-handler)
 				       ; Custom auto-fill func, to support
 				       ; respect for topic headline,
 				       ; hanging-indents, etc:
@@ -1337,7 +1597,8 @@
       (if allout-layout
 	  (setq do-layout t))
 
-      (if allout-isearch-dynamic-expose
+      (if (and allout-isearch-dynamic-expose
+	       (not (fboundp 'allout-real-isearch-abort)))
 	  (allout-enwrap-isearch))
 
       (run-hooks 'allout-mode-hook)
@@ -1376,7 +1637,6 @@
     )					; let*
   )  					; defun
 ;;;_  > allout-minor-mode
-;;; XXX released verion doesn't do this?
 (defalias 'allout-minor-mode 'allout-mode)
 
 ;;;_ #3 Internal Position State-Tracking - "allout-recent-*" funcs
@@ -1400,12 +1660,12 @@
   "Buffer point last returned by `allout-end-of-current-subtree'.")
 (make-variable-buffer-local 'allout-recent-end-of-subtree)
 ;;;_  > allout-prefix-data (beg end)
-(defmacro allout-prefix-data (beginning end)
+(defmacro allout-prefix-data (beg end)
   "Register allout-prefix state data - BEGINNING and END of prefix.
 
 For reference by `allout-recent' funcs.  Returns BEGINNING."
   `(setq allout-recent-prefix-end ,end
-         allout-recent-prefix-beginning ,beginning))
+         allout-recent-prefix-beginning ,beg))
 ;;;_  > allout-recent-depth ()
 (defmacro allout-recent-depth ()
   "Return depth of last heading encountered by an outline maneuvering function.
@@ -1612,9 +1872,12 @@
   "Produce a location \"chart\" of subtopics of the containing topic.
 
 Optional argument LEVELS specifies the depth \(relative to start
-depth) for the chart.
+depth) for the chart.  Subsequent optional args are not for public
+use.
+
+Point is left at the end of the subtree.
 
-Charts are used to capture outline structure, so that outline altering
+Charts are used to capture outline structure, so that outline-altering
 routines need assess the structure only once, and then use the chart
 for their elaborate manipulations.
 
@@ -1625,11 +1888,9 @@
 The chart for a topics' offspring precedes the entry for the topic
 itself.
 
-\(fn &optional LEVELS)"
-
-  ;; The other function parameters are for internal recursion, and should
-  ;; not be specified by external callers.  ORIG-DEPTH is depth of topic at
-  ;; starting point, and PREV-DEPTH is depth of prior topic."
+The other function parameters are for internal recursion, and should
+not be specified by external callers.  ORIG-DEPTH is depth of topic at
+starting point, and PREV-DEPTH is depth of prior topic."
 
   (let ((original (not orig-depth))	; `orig-depth' set only in recursion.
 	chart curr-depth)
@@ -1835,11 +2096,18 @@
   (if (re-search-forward allout-line-boundary-regexp nil 'move)
       (prog1 (goto-char (match-beginning 0))
              (allout-prefix-data (match-beginning 2)(match-end 2)))))
-;;;_   > allout-end-of-current-subtree ()
-(defun allout-end-of-current-subtree ()
-  "Put point at the end of the last leaf in the currently visible topic."
-  (interactive)
-  (allout-back-to-current-heading)
+;;;_   > allout-end-of-subtree (&optional current)
+(defun allout-end-of-subtree (&optional current)
+  "Put point at the end of the last leaf in the containing topic.
+
+If optional CURRENT is true (default false), then put point at the end of
+the containing visible topic.
+
+Returns the value of point."
+  (interactive "P")
+  (if current
+      (allout-back-to-current-heading)
+    (allout-goto-prefix))
   (let ((level (allout-recent-depth)))
     (allout-next-heading)
     (while (and (not (eobp))
@@ -1851,9 +2119,16 @@
                '(?\n ?\r))
          (forward-char -1))
     (setq allout-recent-end-of-subtree (point))))
+;;;_   > allout-end-of-current-subtree ()
+(defun allout-end-of-current-subtree ()
+  "Put point at end of last leaf in currently visible containing topic.
+
+Returns the value of point."
+  (interactive)
+  (allout-end-of-subtree t))
 ;;;_   > allout-beginning-of-current-entry ()
 (defun allout-beginning-of-current-entry ()
-  "When not already there, position point at beginning of current topic's body.
+  "When not already there, position point at beginning of current topic header.
 
 If already there, move cursor to bullet for hot-spot operation.
 \(See `allout-mode' doc string for details on hot-spot operation.)"
@@ -1863,11 +2138,10 @@
     (if (and (interactive-p)
 	     (= (point) start-point))
 	(goto-char (allout-current-bullet-pos)))))
-;;;_   > allout-end-of-current-entry ()
-(defun allout-end-of-current-entry ()
+;;;_   > allout-end-of-entry ()
+(defun allout-end-of-entry ()
   "Position the point at the end of the current topics' entry."
   (interactive)
-  (allout-show-entry)
   (prog1 (allout-pre-next-preface)
     (if (and (not (bobp))(looking-at "^$"))
         (forward-char -1))))
@@ -1875,9 +2149,27 @@
 (defun allout-end-of-current-heading ()
   (interactive)
   (allout-beginning-of-current-entry)
-  (forward-line -1)
-  (end-of-line))
+  (re-search-forward "[\n\r]" nil t)
+  (forward-char -1))
 (defalias 'allout-end-of-heading 'allout-end-of-current-heading)
+;;;_   > allout-get-body-text ()
+(defun allout-get-body-text ()
+  "Return the unmangled body text of the topic immediately containing point."
+  (save-excursion
+    (allout-end-of-prefix)
+    (if (not (re-search-forward "[\n\r]" nil t))
+        nil
+      (backward-char 1)
+      (let ((pre-body (point)))
+        (if (not pre-body)
+            nil
+          (allout-end-of-entry)
+          (if (not (= pre-body (point)))
+              (buffer-substring-no-properties (1+ pre-body) (point))))
+        )
+      )
+    )
+  )
 
 ;;;_  - Depth-wise
 ;;;_   > allout-ascend-to-depth (depth)
@@ -1892,12 +2184,16 @@
         (if (= (allout-recent-depth) depth)
             (progn (goto-char allout-recent-prefix-beginning)
                    depth)
-          (goto-char last-good)))))
+          (goto-char last-good)
+          nil))
+    (if (interactive-p) (allout-end-of-prefix))))
 ;;;_   > allout-ascend ()
 (defun allout-ascend ()
   "Ascend one level, returning t if successful, nil if not."
-  (if (allout-beginning-of-level)
-      (allout-previous-heading)))
+  (prog1
+      (if (allout-beginning-of-level)
+	  (allout-previous-heading))
+    (if (interactive-p) (allout-end-of-prefix))))
 ;;;_   > allout-descend-to-depth (depth)
 (defun allout-descend-to-depth (depth)
   "Descend to depth DEPTH within current topic.
@@ -1917,13 +2213,13 @@
       nil))
   )
 ;;;_   > allout-up-current-level (arg &optional dont-complain)
-(defun allout-up-current-level (arg &optional dont-complain interactive)
+(defun allout-up-current-level (arg &optional dont-complain)
   "Move out ARG levels from current visible topic.
 
 Positions on heading line of containing topic.  Error if unable to
 ascend that far, or nil if unable to ascend but optional arg
 DONT-COMPLAIN is non-nil."
-  (interactive "p\np")
+  (interactive "p")
   (allout-back-to-current-heading)
   (let ((present-level (allout-recent-depth))
 	(last-good (point))
@@ -1944,12 +2240,12 @@
     (if (or failed
 	    (> arg 0))
 	(progn (goto-char last-good)
-	       (if interactive (allout-end-of-prefix))
+	       (if (interactive-p) (allout-end-of-prefix))
 	       (if (not dont-complain)
 		   (error "Can't ascend past outermost level")
-		 (if interactive (allout-end-of-prefix))
+		 (if (interactive-p) (allout-end-of-prefix))
 		 nil))
-      (if interactive (allout-end-of-prefix))
+      (if (interactive-p) (allout-end-of-prefix))
       allout-recent-prefix-beginning)))
 
 ;;;_  - Linear
@@ -1981,7 +2277,7 @@
         nil))))
 ;;;_   > allout-previous-sibling (&optional depth backward)
 (defun allout-previous-sibling (&optional depth backward)
-  "Like `allout-forward-current-level', but backwards & respect invisible topics.
+  "Like `allout-forward-current-level' backwards, respecting invisible topics.
 
 Optional DEPTH specifies depth to traverse, default current depth.
 
@@ -2015,7 +2311,7 @@
   (let ((depth (allout-depth)))
     (while (allout-previous-sibling depth nil))
     (prog1 (allout-recent-depth)
-      (allout-end-of-prefix))))
+      (if (interactive-p) (allout-end-of-prefix)))))
 ;;;_   > allout-next-visible-heading (arg)
 (defun allout-next-visible-heading (arg)
   "Move to the next ARG'th visible heading line, backward if arg is negative.
@@ -2053,13 +2349,13 @@
   (interactive "p")
   (allout-next-visible-heading (- arg)))
 ;;;_   > allout-forward-current-level (arg)
-(defun allout-forward-current-level (arg &optional interactive)
+(defun allout-forward-current-level (arg)
   "Position point at the next heading of the same level.
 
 Takes optional repeat-count, goes backward if count is negative.
 
 Returns resulting position, else nil if none found."
-  (interactive "p\np")
+  (interactive "p")
   (let ((start-depth (allout-current-depth))
 	(start-point (point))
 	(start-arg arg)
@@ -2087,7 +2383,7 @@
 		  (= (allout-recent-depth) start-depth)))
 	allout-recent-prefix-beginning
       (goto-char last-good)
-      (if (not interactive)
+      (if (not (interactive-p))
 	  nil
 	(allout-end-of-prefix)
 	(error "Hit %s level %d topic, traversed %d of %d requested"
@@ -2096,10 +2392,10 @@
 	       (- (abs start-arg) arg)
 	       (abs start-arg))))))
 ;;;_   > allout-backward-current-level (arg)
-(defun allout-backward-current-level (arg &optional interactive)
+(defun allout-backward-current-level (arg)
   "Inverse of `allout-forward-current-level'."
-  (interactive "p\np")
-  (if interactive
+  (interactive "p")
+  (if (interactive-p)
       (let ((current-prefix-arg (* -1 arg)))
 	(call-interactively 'allout-forward-current-level))
     (allout-forward-current-level (* -1 arg))))
@@ -2107,121 +2403,6 @@
 ;;;_ #5 Alteration
 
 ;;;_  - Fundamental
-;;;_   > allout-before-change-protect (beg end)
-(defun allout-before-change-protect (beg end)
-  "Outline before-change hook, regulates changes to concealed text.
-
-Reveal concealed text that would be changed by current command, and
-offer user choice to commit or forego the change.  Unchanged text is
-reconcealed.  User has option to have changed text reconcealed.
-
-Undo commands are specially treated - the user is not prompted for
-choice, the undoes are always committed (based on presumption that the
-things being undone were already subject to this regulation routine),
-and undoes always leave the changed stuff exposed.
-
-Changes to concealed regions are ignored while file is being written.
-\(This is for the sake of functions that do change the file during
-writes, like crypt and zip modes.)
-
-Locally bound in outline buffers to `before-change-functions', which
-in Emacs 19 is run before any change to the buffer.
-
-Any functions which set [`this-command' to `undo', or which set]
-`allout-override-protect' non-nil (as does, eg, allout-flag-chars)
-are exempt from this restriction."
-  (if (and (allout-mode-p)
-					; allout-override-protect
-					; set by functions that know what
-					; they're doing, eg outline internals:
-	   (not allout-override-protect)
-	   (not allout-during-write-cue)
-	   (save-match-data		; Preserve operation position state.
-					; Both beginning and end chars must
-					; be exposed:
-	     (save-excursion (if (memq this-command '(newline open-line))
-				 ;; Compensate for stupid Emacs {new,
-				 ;; open-}line display optimization:
-				 (setq beg (1+ beg)
-				       end (1+ end)))
-			     (goto-char beg)
-			     (or (allout-hidden-p)
-				 (and (not (= beg end))
-				      (goto-char end)
-				      (allout-hidden-p))))))
-      (save-match-data
-	(if (equal this-command 'undo)
-		 ;; Allow undo without inhibition.
-		 ;; - Undoing new and open-line hits stupid Emacs redisplay
-		 ;;   optimization (em 19 cmds.c, ~ line 200).
-		 ;; - Presumably, undoing what was properly protected when
-		 ;;   done.
-		 ;; - Undo may be users' only recourse in protection faults.
-		 ;; So, expose what getting changed:
-	    (progn (message "Undo! - exposing concealed target...")
-		   (if (allout-hidden-p)
-		       (allout-show-children))
-		   (message "Undo!"))
-	  (let (response
-		(rehide-completely (save-excursion (allout-goto-prefix)
-						   (allout-hidden-p)))
-		rehide-place)
-
-	    (save-excursion
-	      (if (condition-case err
-		      ;; Condition case to catch keyboard quits during reads.
-		      (progn
-					; Give them a peek where
-			(save-excursion
-			  (if (eolp) (setq rehide-place
-					   (allout-goto-prefix)))
-			  (allout-show-entry))
-					; Present the message, but...
-					; leave the cursor at the location
-					; until they respond:
-					; Then interpret the response:
-			(while
-			    (progn
-			      (message (concat "Change inside concealed"
-					       " region - do it? "
-					       "(n or 'y'/'r'eclose)"))
-			      (setq response (read-char))
-			      (not
-			       (cond ((memq response '(?r ?R))
-				      (setq response 'reclose))
-				     ((memq response '(?y ?Y ? ))
-				      (setq response t))
-				     ((memq response '(?n ?N 127))
-				      (setq response nil)
-				      t)
-				     ((eq response ??)
-				      (message
-				       "`r' means `yes, then reclose'")
-				      nil)
-				     (t (message "Please answer y, n, or r")
-					(sit-for 1)
-					nil)))))
-			response)
-		    ('quit nil))
-					; Continue:
-		  (if (eq response 'reclose)
-		      (save-excursion
-			(if rehide-place (goto-char rehide-place))
-			(if rehide-completely
-			    (allout-hide-current-entry-completely)
-			  (allout-hide-current-entry)))
-		    (if (allout-ascend-to-depth (1- (allout-recent-depth)))
-			(allout-show-children)
-		      (allout-show-to-offshoot)))
-					; Prevent:
-		(if rehide-completely
-		    (save-excursion
-		      (if rehide-place (goto-char rehide-place))
-		      (allout-hide-current-entry-completely))
-		  (allout-hide-current-entry))
-		(error "Change within concealed region prevented"))))))
-    )	; if
-  )	; defun
 ;;;_   = allout-post-goto-bullet
 (defvar allout-post-goto-bullet nil
   "Outline internal var, for `allout-pre-command-business' hot-spot operation.
@@ -2236,24 +2417,20 @@
 (defun allout-post-command-business ()
   "Outline `post-command-hook' function.
 
-- Null `allout-override-protect', so it's not left open.
-
 - Implement (and clear) `allout-post-goto-bullet', for hot-spot
   outline commands.
 
-- Massages `buffer-undo-list' so successive, standard character self-inserts
-  are aggregated.  This kludge compensates for lack of undo bunching when
-  `before-change-functions' is used."
+- Decrypt topic currently being edited if it was encrypted for a save.
+
+- Massage buffer-undo-list so successive, standard character self-inserts are
+  aggregated.  This kludge compensates for lack of undo bunching when
+  before-change-functions is used."
 
 					; Apply any external change func:
   (if (not (allout-mode-p))		; In allout-mode.
       nil
-    (setq allout-override-protect nil)
     (if allout-isearch-dynamic-expose
 	(allout-isearch-rectification))
-    (if allout-during-write-cue
-	;; Was used by allout-before-change-protect, done with it now:
-	(setq allout-during-write-cue nil))
     ;; Undo bunching business:
     (if (and (listp buffer-undo-list)	; Undo history being kept.
 	     (equal this-command 'self-insert-command)
@@ -2282,6 +2459,11 @@
 	      (setq buffer-undo-list
 		    (cons (cons prev-from cur-to)
 			  (cdr (cdr (cdr buffer-undo-list))))))))
+
+    (if (and (boundp 'allout-after-save-decrypt)
+             allout-after-save-decrypt)
+        (allout-after-saves-handler))
+
     ;; Implement -post-goto-bullet, if set: (must be after undo business)
     (if (and allout-post-goto-bullet
 	     (allout-current-bullet-pos))
@@ -2304,8 +2486,9 @@
 char.  When in this mode you can use regular cursor-positioning
 command/keystrokes to relocate the cursor off of a bullet character to
 return to regular interpretation of self-insert characters."
+
   (if (not (allout-mode-p))
-      ;; Shouldn't be invoked if not in allout allout-mode, but just in case:
+      ;; Shouldn't be invoked if not in allout-mode, but just in case:
       nil
     ;; Register isearch status:
     (if (and (boundp  'isearch-mode) isearch-mode)
@@ -2317,7 +2500,9 @@
 	(let* ((this-key-num (cond
 			      ((numberp last-command-char)
 			       last-command-char)
-			      ((fboundp 'char-to-int)
+			      ;; Only xemacs has characterp.
+			      ((and (fboundp 'characterp)
+				    (characterp last-command-char))
 			       (char-to-int last-command-char))
 			      (t 0)))
 	       mapped-binding)
@@ -2340,7 +2525,7 @@
 		      this-command mapped-binding)))))))
 ;;;_   > allout-find-file-hook ()
 (defun allout-find-file-hook ()
-  "Activate `allout-mode' when `allout-auto-activation' & `allout-layout' are non-nil.
+  "Activate `allout-mode' when `allout-auto-activation', `allout-layout' non-nil.
 
 See `allout-init' for setup instructions."
   (if (and allout-auto-activation
@@ -2353,7 +2538,7 @@
 
 Called as part of `allout-post-command-business'."
 
-  (let ((isearching isearch-mode))
+  (let ((isearching (and (boundp 'isearch-mode) isearch-mode)))
     (cond ((and isearching (not allout-pre-was-isearching))
 	   (allout-isearch-expose 'start))
 	  ((and isearching allout-pre-was-isearching)
@@ -2361,24 +2546,11 @@
 	  ((and (not isearching) allout-pre-was-isearching)
 	   (allout-isearch-expose 'final))
 	  ;; Not and wasn't isearching:
-	  (t (setq allout-isearch-prior-pos nil)))))
+	  (t (setq allout-isearch-prior-pos nil)
+	     (setq allout-isearch-did-quit nil)))))
 ;;;_   = allout-isearch-was-font-lock
 (defvar allout-isearch-was-font-lock
   (and (boundp 'font-lock-mode) font-lock-mode))
-
-;;;_   > allout-flag-region (from to flag)
-(defmacro allout-flag-region (from to flag)
-  "Hide or show lines from FROM to TO, via Emacs `selective-display' FLAG char.
-Ie, text following flag C-m \(carriage-return) is hidden until the
-next C-j (newline) char.
-
-Returns the endpoint of the region."
-  `(let ((buffer-read-only nil)
-	   (allout-override-protect t))
-       (subst-char-in-region ,from ,to
-			     (if (= ,flag ?\n) ?\r ?\n)
-			     ,flag t)))
-
 ;;;_   > allout-isearch-expose (mode)
 (defun allout-isearch-expose (mode)
   "MODE is either 'clear, 'start, 'continue, or 'final."
@@ -2403,21 +2575,56 @@
       (setq allout-isearch-prior-pos nil)
     (if (not (eq mode 'final))
 	(setq allout-isearch-prior-pos (cons (point) (allout-show-entry)))
-      (if isearch-mode-end-hook-quit
+      (if allout-isearch-did-quit
 	  nil
 	(setq allout-isearch-prior-pos nil)
-	(allout-show-children)))))
+	(allout-show-children))))
+  (setq allout-isearch-did-quit nil))
 ;;;_   > allout-enwrap-isearch ()
 (defun allout-enwrap-isearch ()
-  "Impose `isearch-abort' wrapper for dynamic exposure in isearch.
+  "Impose `allout-mode' isearch-abort wrapper for dynamic exposure in isearch.
 
 The function checks to ensure that the rebinding is done only once."
-  (add-hook 'isearch-mode-end-hook 'allout-isearch-rectification))
+
+  (add-hook 'isearch-mode-end-hook 'allout-isearch-rectification)
+  (if (fboundp 'allout-real-isearch-abort)
+      ;;
+      nil
+                                        ; Ensure load of isearch-mode:
+    (if (or (and (fboundp 'isearch-mode)
+                 (fboundp 'isearch-abort))
+            (condition-case error
+                (load-library "isearch-mode")
+              ('file-error (message
+			    "Skipping isearch-mode provisions - %s '%s'"
+			    (car (cdr error))
+			    (car (cdr (cdr error))))
+			   (sit-for 1)
+			   ;; Inhibit subsequent tries and return nil:
+			   (setq allout-isearch-dynamic-expose nil))))
+        ;; Isearch-mode loaded, encapsulate specific entry points for
+        ;; outline dynamic-exposure business:
+        (progn
+	  ;; stash crucial isearch-mode funcs under known, private
+	  ;; names, then register wrapper functions under the old
+	  ;; names, in their stead:
+          (fset 'allout-real-isearch-abort (symbol-function 'isearch-abort))
+          (fset 'isearch-abort 'allout-isearch-abort)))))
+;;;_   > allout-isearch-abort ()
+(defun allout-isearch-abort ()
+  "Wrapper for allout-real-isearch-abort \(which see), to register
+actual quits."
+  (interactive)
+  (setq allout-isearch-did-quit nil)
+  (condition-case what
+      (allout-real-isearch-abort)
+    ('quit (setq allout-isearch-did-quit t)
+	  (signal 'quit nil))))
 
 ;;; Prevent unnecessary font-lock while isearching!
 (defvar isearch-was-font-locking nil)
 (defun isearch-inhibit-font-lock ()
-  "Inhibit `font-lock-mode' while isearching - for use on `isearch-mode-hook'."
+  "Inhibit `font-lock' while isearching - for use on `isearch-mode-hook'."
   (if (and (allout-mode-p) (boundp 'font-lock-mode) font-lock-mode)
       (setq isearch-was-font-locking t
 	    font-lock-mode nil)))
@@ -2465,6 +2672,14 @@
                  (if prefix
                      (allout-get-prefix-bullet prefix)
                    (allout-get-bullet)))))
+;;;_   > allout-encrypted-type-prefix (&optional prefix)
+(defun allout-encrypted-type-prefix (&optional prefix)
+  "True if current header prefix bullet is for an encrypted entry \(body)."
+  (and allout-topic-encryption-bullet
+        (string= allout-topic-encryption-bullet
+                 (if prefix
+                     (allout-get-prefix-bullet prefix)
+                   (allout-get-bullet)))))
 ;;;_   > allout-bullet-for-depth (&optional depth)
 (defun allout-bullet-for-depth (&optional depth)
   "Return outline topic bullet suited to optional DEPTH, or current depth."
@@ -2625,15 +2840,15 @@
                                    ((allout-sibling-index))))))
     )
   )
-;;;_   > allout-open-topic (relative-depth &optional before use-sib-bullet)
-(defun allout-open-topic (relative-depth &optional before use-sib-bullet)
-  "Open a new topic at depth RELATIVE-DEPTH.
+;;;_   > allout-open-topic (relative-depth &optional before use_recent_bullet)
+(defun allout-open-topic (relative-depth &optional before use_recent_bullet)
+  "Open a new topic at depth DEPTH.
 
 New topic is situated after current one, unless optional flag BEFORE
 is non-nil, or unless current line is complete empty (not even
 whitespace), in which case open is done on current line.
 
-If USE-SIB-BULLET is true, use the bullet of the prior sibling.
+If USE_RECENT_BULLET is true, offer to use the bullet of the prior sibling.
 
 Nuances:
 
@@ -2660,9 +2875,11 @@
   (let* ((depth (+ (allout-current-depth) relative-depth))
          (opening-on-blank (if (looking-at "^\$")
                                (not (setq before nil))))
-         opening-numbered	; Will get while computing ref-topic, below
-         ref-depth		; Will get while computing ref-topic, below
-         ref-bullet		; Will get while computing ref-topic, next
+         ;; bunch o vars set while computing ref-topic
+         opening-numbered
+         opening-encrypted
+         ref-depth
+         ref-bullet
          (ref-topic (save-excursion
                       (cond ((< relative-depth 0)
                              (allout-ascend-to-depth depth))
@@ -2680,6 +2897,13 @@
                                        (allout-descend-to-depth depth))
                                    (if (allout-numbered-type-prefix)
                                        allout-numbered-bullet))))
+                      (setq opening-encrypted
+                            (save-excursion
+                              (and allout-topic-encryption-bullet
+                                   (or (<= relative-depth 0)
+                                       (allout-descend-to-depth depth))
+                                   (if (allout-numbered-type-prefix)
+                                       allout-numbered-bullet))))
                       (point)))
          dbl-space
          doing-beginning)
@@ -2718,19 +2942,24 @@
                             (if (not (bobp))
                                 (allout-previous-heading)))
 	    (if (and before (bobp))
-		(allout-unprotected (open-line 1))))
+		(allout-unprotected (allout-open-line-not-read-only))))
 
           (if (<= relative-depth 0)
               ;; Not going inwards, don't snug up:
               (if doing-beginning
-		  (allout-unprotected (open-line (if dbl-space 2 1)))
+                  (allout-unprotected
+                   (if (not dbl-space)
+                       (allout-open-line-not-read-only)
+                     (allout-open-line-not-read-only)
+                     (allout-open-line-not-read-only)))
 		(if before
 		    (progn (end-of-line)
 			   (allout-pre-next-preface)
 			   (while (= ?\r (following-char))
                              (forward-char 1))
 			   (if (not (looking-at "^$"))
-			       (allout-unprotected (open-line 1))))
+			       (allout-unprotected
+                                (allout-open-line-not-read-only))))
 		  (allout-end-of-current-subtree)))
             ;; Going inwards - double-space if first offspring is,
             ;; otherwise snug up.
@@ -2748,38 +2977,47 @@
                       (progn (forward-line -1)
                              (looking-at "^\\s-*$"))))
                 (progn (forward-line 1)
-                       (allout-unprotected (open-line 1))))
+                       (allout-unprotected
+                        (allout-open-line-not-read-only))
+                       (forward-line 1)))
             (end-of-line))
           ;;(if doing-beginning (goto-char doing-beginning))
           (if (not (bobp))
+              ;; We insert a newline char rather than using open-line to
+              ;; avoid rear-stickiness inheritence of read-only property.
               (progn (if (and (not (> depth ref-depth))
                               (not before))
-                         (allout-unprotected (open-line 1))
+                         (allout-unprotected
+                          (allout-open-line-not-read-only))
 		       (if (> depth ref-depth)
-			   (allout-unprotected (newline 1))
+                         (allout-unprotected
+                          (allout-open-line-not-read-only))
 			 (if dbl-space
-			     (allout-unprotected (open-line 1))
+                             (allout-unprotected
+                              (allout-open-line-not-read-only))
 			   (if (not before)
 			       (allout-unprotected (newline 1))))))
                      (if dbl-space
-			 (allout-unprotected (newline  1)))
+			 (allout-unprotected (newline 1)))
                      (if (and (not (eobp))
                               (not (bolp)))
                          (forward-char 1))))
           ))
     (insert (concat (allout-make-topic-prefix opening-numbered
-					       t
-					       depth)
-		    " "))
+                                              t
+                                              depth)
+                           " "))
 
     ;;(if doing-beginning (save-excursion (newline (if dbl-space 2 1))))
 
 
-    (allout-rebullet-heading (and use-sib-bullet ref-bullet);;; solicit
+    (allout-rebullet-heading (and use_recent_bullet         ;;; solicit
+                                   ref-bullet)
                               depth			     ;;; depth
                               nil 			     ;;; number-control
                               nil			     ;;; index
-                              t)     (end-of-line)
+                              t)
+    (end-of-line)
     )
   )
 ;;;_    . open-topic contingencies
@@ -2795,6 +3033,13 @@
 ;;;_     ; buffer boundaries - special provisions for beginning and end ob
 ;;;_     ; level 1 topics have special provisions also - double space.
 ;;;_     ; location of new topic
+;;;_   > allout-open-line-not-read-only ()
+(defun allout-open-line-not-read-only ()
+  "Open line and remove inherited read-only text prop from new char, if any."
+  (open-line 1)
+  (if (plist-get (text-properties-at (point)) 'read-only)
+      (allout-unprotected
+       (remove-text-properties (point) (+ 1 (point)) '(read-only nil)))))
 ;;;_   > allout-open-subtopic (arg)
 (defun allout-open-subtopic (arg)
   "Open new topic header at deeper level than the current one.
@@ -2802,7 +3047,7 @@
 Negative universal arg means to open deeper, but place the new topic
 prior to the current one."
   (interactive "p")
-  (allout-open-topic 1 (> 0 arg)))
+  (allout-open-topic 1 (> 0 arg) (< 1 arg)))
 ;;;_   > allout-open-sibtopic (arg)
 (defun allout-open-sibtopic (arg)
   "Open new topic header at same level as the current one.
@@ -2812,7 +3057,7 @@
 Negative universal arg means to place the new topic prior to the current
 one."
   (interactive "p")
-  (allout-open-topic 0 (> 0 arg) (< 1 arg)))
+  (allout-open-topic 0 (> 0 arg) (not (= 1 arg))))
 ;;;_   > allout-open-supertopic (arg)
 (defun allout-open-supertopic (arg)
   "Open new topic header at shallower level than the current one.
@@ -2821,7 +3066,7 @@
 topic prior to the current one."
 
   (interactive "p")
-  (allout-open-topic -1 (> 0 arg)))
+  (allout-open-topic -1 (> 0 arg) (< 1 arg)))
 
 ;;;_  - Outline Alteration
 ;;;_   : Topic Modification
@@ -2877,15 +3122,15 @@
 		  (setq old-indent-begin (match-beginning 1)
 			old-indent-end (match-end 1))
 		  (not (looking-at allout-regexp)))
-	   (if (> 0 (setq excess (- (current-column)
-				     old-margin)))
+	   (if (> 0 (setq excess (- (- old-indent-end old-indent-begin)
+                                    old-margin)))
 	       ;; Text starts left of old margin - don't adjust:
 	       nil
 	     ;; Text was hanging at or right of old left margin -
 	     ;; reindent it, preserving its existing indentation
 	     ;; beyond the old margin:
 	     (delete-region old-indent-begin old-indent-end)
-	     (indent-to (+ new-margin excess)))))))))
+             (indent-to (+ new-margin excess (current-column))))))))))
 ;;;_    > allout-rebullet-current-heading (arg)
 (defun allout-rebullet-current-heading (arg)
   "Solicit new bullet for current visible heading."
@@ -2922,28 +3167,30 @@
 
   "Adjust bullet of current topic prefix.
 
+All args are optional.
+
 If SOLICIT is non-nil, then the choice of bullet is solicited from
 user.  If it's a character, then that character is offered as the
 default, otherwise the one suited to the context \(according to
 distinction or depth) is offered.  If non-nil, then the
 context-specific bullet is just used.
 
-Second arg NEW-DEPTH forces the topic prefix to that depth, regardless
+Second arg DEPTH forces the topic prefix to that depth, regardless
 of the topic's current depth.
 
 Third arg NUMBER-CONTROL can force the prefix to or away from
 numbered form.  It has effect only if `allout-numbered-bullet' is
 non-nil and soliciting was not explicitly invoked (via first arg).
 Its effect, numbering or denumbering, then depends on the setting
-of the fourth arg, INDEX.
+of the forth arg, INDEX.
 
-If NUMBER-CONTROL is non-nil and fourth arg INDEX is nil, then the
+If NUMBER-CONTROL is non-nil and forth arg INDEX is nil, then the
 prefix of the topic is forced to be non-numbered.  Null index and
 non-nil NUMBER-CONTROL forces denumbering.  Non-nil INDEX (and
 non-nil NUMBER-CONTROL) forces a numbered-prefix form.  If non-nil
 INDEX is a number, then that number is used for the numbered
 prefix.  Non-nil and non-number means that the index for the
-numbered prefix will be derived by `allout-make-topic-prefix'.
+numbered prefix will be derived by allout-make-topic-prefix.
 
 Fifth arg DO-SUCCESSORS t means re-resolve count on succeeding
 siblings.
@@ -2986,9 +3233,10 @@
 					; Put in new prefix:
       (allout-unprotected (insert new-prefix))
 
-      ;; Reindent the body if elected and margin changed:
+      ;; Reindent the body if elected, margin changed, and not encrypted body:
       (if (and allout-reindent-bodies
-	       (not (= new-depth current-depth)))
+	       (not (= new-depth current-depth))
+               (not (allout-encrypted-topic-p)))
 	  (allout-reindent-body current-depth new-depth))
 
       ;; Recursively rectify successive siblings of orig topic if
@@ -3010,7 +3258,7 @@
   ) ; defun
 ;;;_    > allout-rebullet-topic (arg)
 (defun allout-rebullet-topic (arg)
-  "Like `allout-rebullet-topic-grunt', but start from topic visible at point.
+  "Rebullet the visible topic containing point and all contained subtopics.
 
 Descends into invisible as well as visible topics, however.
 
@@ -3036,18 +3284,18 @@
                                                starting-point
                                                index
                                                do-successors)
+  "Like `allout-rebullet-topic', but on nearest containing topic
+\(visible or not).
 
-  "Rebullet the topic at point, visible or invisible, and all
-contained subtopics.  See `allout-rebullet-heading' for rebulleting
-behavior.
+See `allout-rebullet-heading' for rebulleting behavior.
 
-Arg RELATIVE-DEPTH means to shift the depth of the entire
-topic that amount.
+All arguments are optional.
 
-\(fn &optional RELATIVE-DEPTH)"
+First arg RELATIVE-DEPTH means to shift the depth of the entire
+topic that amount.
 
-  ;; All args except the first one are for internal recursive use by the
-  ;; function itself.
+The rest of the args are for internal recursive use by the function
+itself.  The are STARTING-DEPTH, STARTING-POINT, and INDEX."
 
   (let* ((relative-depth (or relative-depth 0))
          (new-depth (allout-depth))
@@ -3177,13 +3425,42 @@
         (setq more (allout-next-sibling depth nil))))))
 ;;;_    > allout-shift-in (arg)
 (defun allout-shift-in (arg)
-  "Increase depth of current heading and any topics collapsed within it."
+  "Increase depth of current heading and any topics collapsed within it.
+
+We disallow shifts that would result in the topic having a depth more than
+one level greater than the immediately previous topic, to avoid containment
+discontinuity.  The first topic in the file can be adjusted to any positive
+depth, however."
   (interactive "p")
+  (if (> arg 0)
+      (save-excursion
+        (allout-back-to-current-heading)
+        (if (not (bobp))
+            (let* ((current-depth (allout-recent-depth))
+                   (start-point (point))
+                   (predecessor-depth (progn
+                                        (forward-char -1)
+                                        (allout-goto-prefix)
+                                        (if (< (point) start-point)
+                                            (allout-recent-depth)
+                                          0))))
+              (if (and (> predecessor-depth 0)
+                       (> (+ current-depth arg)
+                          (1+ predecessor-depth)))
+                  (error (concat "May not shift deeper than offspring depth"
+                                 " of previous topic")))))))
   (allout-rebullet-topic arg))
 ;;;_    > allout-shift-out (arg)
 (defun allout-shift-out (arg)
-  "Decrease depth of current heading and any topics collapsed within it."
+  "Decrease depth of current heading and any topics collapsed within it.
+
+We disallow shifts that would result in the topic having a depth more than
+one level greater than the immediately previous topic, to avoid containment
+discontinuity.  The first topic in the file can be adjusted to any positive
+depth, however."
   (interactive "p")
+  (if (< arg 0)
+      (allout-shift-in (* arg -1)))
   (allout-rebullet-topic (* arg -1)))
 ;;;_   : Surgery (kill-ring) functions with special provisions for outlines:
 ;;;_    > allout-kill-line (&optional arg)
@@ -3191,24 +3468,56 @@
   "Kill line, adjusting subsequent lines suitably for outline mode."
 
   (interactive "*P")
-  (if (not (and (allout-mode-p)		; active outline mode,
-		allout-numbered-bullet		; numbers may need adjustment,
-		(bolp)				; may be clipping topic head,
-		(looking-at allout-regexp)))	; are clipping topic head.
-      ;; Above conditions do not obtain - just do a regular kill:
-      (kill-line arg)
-    ;; Ah, have to watch out for adjustments:
-    (let* ((depth (allout-depth)))
-                                        ; Do the kill:
-      (kill-line arg)
+
+  (let ((start-point (point))
+        (leading-kill-ring-entry (car kill-ring))
+        binding)
+
+    (condition-case err
+
+        (if (not (and (allout-mode-p)        ; active outline mode,
+                      allout-numbered-bullet ; numbers may need adjustment,
+                      (bolp)                  ; may be clipping topic head,
+                      (looking-at allout-regexp))) ; are clipping topic head.
+            ;; Above conditions do not obtain - just do a regular kill:
+            (kill-line arg)
+          ;; Ah, have to watch out for adjustments:
+          (let* ((depth (allout-depth))
+                 (start-point (point))
+                 binding)
+                                        ; Do the kill, presenting option
+                                        ; for read-only text:
+            (kill-line arg)
                                         ; Provide some feedback:
-      (sit-for 0)
-      (save-excursion
+          (sit-for 0)
+          (save-excursion
                                         ; Start with the topic
                                         ; following killed line:
-        (if (not (looking-at allout-regexp))
-            (allout-next-heading))
-        (allout-renumber-to-depth depth)))))
+            (if (not (looking-at allout-regexp))
+                (allout-next-heading))
+            (allout-renumber-to-depth depth))))
+      ;; condition case handler:
+      (text-read-only
+       (goto-char start-point)
+       (setq binding (where-is-internal 'allout-kill-topic nil t))
+       (cond ((not binding) (setq binding ""))
+             ((arrayp binding)
+              (setq binding (mapconcat 'key-description (list binding) ", ")))
+             (t (setq binding (format "%s" binding))))
+       ;; ensure prior kill-ring leader is properly restored:
+       (if (eq leading-kill-ring-entry (cadr kill-ring))
+           ;; Aborted kill got pushed on front - ditch it:
+           (pop kill-ring)
+         ;; Aborted kill got appended to prior - resurrect prior:
+         (setcar kill-ring leading-kill-ring-entry))
+       ;; make last-command skip this failed command, so kill-appending
+       ;; conditions track:
+       (setq this-command last-command)
+       (error (concat "read-only text hit - use %s allout-kill-topic to"
+                      " discard collapsed stuff")
+              binding)))
+    )
+  )
 ;;;_    > allout-kill-topic ()
 (defun allout-kill-topic ()
   "Kill topic together with subtopics.
@@ -3236,14 +3545,14 @@
 		       (>= (allout-recent-depth) depth))))
 	    (forward-char 1)))
 
-    (kill-region beg (point))
+    (allout-unprotected (kill-region beg (point)))
     (sit-for 0)
     (save-excursion
       (allout-renumber-to-depth depth))))
 ;;;_    > allout-yank-processing ()
 (defun allout-yank-processing (&optional arg)
 
-  "Incidental outline specific business to be done just after text yanks.
+  "Incidental outline-specific business to be done just after text yanks.
 
 Does depth adjustment of yanked topics, when:
 
@@ -3259,7 +3568,7 @@
 
 The point is left in front of yanked, adjusted topics, rather than
 at the end (and vice-versa with the mark).  Non-adjusted yanks,
-however, are left exactly like normal, not outline specific yanks."
+however, are left exactly like normal, non-allout-specific yanks."
 
   (interactive "*P")
 					; Get to beginning, leaving
@@ -3463,6 +3772,60 @@
 ;;;_ #6 Exposure Control
 
 ;;;_  - Fundamental
+;;;_   > allout-flag-region (from to flag)
+(defun allout-flag-region (from to flag)
+  "Hide or show lines from FROM to TO, via Emacs selective-display FLAG char.
+Ie, text following flag C-m \(carriage-return) is hidden until the
+next C-j (newline) char.
+
+Returns the endpoint of the region."
+  ;; "OFR-" prefixes to avoid collisions with vars in code calling the macro.
+  ;; ie, elisp macro vars are not 'hygenic', so distinct names are necessary.
+  (let ((was-inhibit-r-o inhibit-read-only)
+        (was-undo-list buffer-undo-list)
+        (was-modified (buffer-modified-p))
+        trans)
+    (unwind-protect
+     (save-excursion
+       (setq inhibit-read-only t)
+       (setq buffer-undo-list t)
+       (if (> from to)
+           (setq trans from from to to trans))
+       (subst-char-in-region from to
+                             (if (= flag ?\n) ?\r ?\n)
+                             flag t)
+       ;; adjust character read-protection on all the affected lines.
+       ;; we handle the region line-by-line.
+       (goto-char to)
+       (end-of-line)
+       (setq to (min (+ 2 (point)) (point-max)))
+       (goto-char from)
+       (beginning-of-line)
+       (while (< (point) to)
+         ;; handle from start of exposed to beginning of hidden, or eol:
+         (remove-text-properties (point)
+                                 (progn (if (re-search-forward "[\r\n]"
+                                                               nil t)
+                                            (forward-char -1))
+                                        (point))
+                                 '(read-only nil))
+         ;; handle from start of hidden, if any, to eol:
+         (if (and (not (eobp)) (= (char-after (point)) ?\r))
+             (put-text-property (point) (progn (end-of-line) (point))
+                                'read-only t))
+         ;; Handle the end-of-line to beginning of next line:
+         (if (not (eobp))
+             (progn (forward-char 1)
+                    (remove-text-properties (1- (point)) (point)
+                                            '(read-only nil)))))
+       )
+     (if (not was-modified)
+         (set-buffer-modified-p nil))
+     (setq inhibit-read-only was-inhibit-r-o)
+     (setq buffer-undo-list was-undo-list)
+     )
+    )
+  )
 ;;;_   > allout-flag-current-subtree (flag)
 (defun allout-flag-current-subtree (flag)
   "Hide or show subtree of currently-visible topic.
@@ -3471,9 +3834,9 @@
 
   (save-excursion
     (allout-back-to-current-heading)
-    (allout-flag-region (point)
-			 (progn (allout-end-of-current-subtree) (1- (point)))
-			 flag)))
+    (let ((from (point))
+          (to (progn (allout-end-of-current-subtree) (1- (point)))))
+      (allout-flag-region from to flag))))
 
 ;;;_  - Topic-specific
 ;;;_   > allout-show-entry ()
@@ -3482,7 +3845,7 @@
 
 This is a way to give restricted peek at a concealed locality without the
 expense of exposing its context, but can leave the outline with aberrant
-exposure.  `allout-hide-current-entry-completely' or `allout-show-to-offshoot'
+exposure.  `allout-hide-current-entry-completely' or `allout-show-offshoot'
 should be used after the peek to rectify the exposure."
 
   (interactive)
@@ -3602,7 +3965,7 @@
   (allout-back-to-current-heading)
   (save-excursion
    (allout-flag-region (point)
-                        (progn (allout-end-of-current-entry) (point))
+                        (progn (allout-end-of-entry) (point))
                         ?\r)))
 ;;;_   > allout-show-current-entry (&optional arg)
 (defun allout-show-current-entry (&optional arg)
@@ -3614,8 +3977,9 @@
       (allout-hide-current-entry)
     (save-excursion
       (allout-flag-region (point)
-			   (progn (allout-end-of-current-entry) (point))
-			   ?\n))))
+			   (progn (allout-end-of-entry) (point))
+			   ?\n)
+      )))
 ;;;_   > allout-hide-current-entry-completely ()
 ; ... allout-hide-current-entry-completely also for isearch dynamic exposure:
 (defun allout-hide-current-entry-completely ()
@@ -3846,7 +4210,11 @@
       max-pos)))
 ;;;_   > allout-old-expose-topic (spec &rest followers)
 (defun allout-old-expose-topic (spec &rest followers)
-  "Dictate wholesale exposure scheme for current topic, according to SPEC.
+
+  "Deprecated.  Use `allout-expose-topic' \(with different schema
+format) instead.
+
+Dictate wholesale exposure scheme for current topic, according to SPEC.
 
 SPEC is either a number or a list.  Optional successive args
 dictate exposure for subsequent siblings of current topic.
@@ -3918,9 +4286,6 @@
       (allout-old-expose-topic (car followers))
       (setq followers (cdr followers)))
     max-pos))
-(make-obsolete 'allout-old-expose-topic
-               "use `allout-expose-topic' (with different schema format) instead."
-               "19.23")
 ;;;_   > allout-new-exposure '()
 (defmacro allout-new-exposure (&rest spec)
   "Literal frontend for `allout-expose-topic', doesn't evaluate arguments.
@@ -3929,6 +4294,8 @@
 
 Cursor is left at start position.
 
+Use this instead of obsolete `allout-exposure'.
+
 Examples:
 \(allout-new-exposure (-1 () () () 1) 0)
 	Close current topic at current level so only the immediate
@@ -4151,13 +4518,20 @@
 				 (cdr format)))))))
       ;; Put the list with first at front, to last at back:
       (nreverse result))))
+;;;_   > my-region-active-p ()
+(defmacro my-region-active-p ()
+  (if (fboundp 'region-active-p)
+      '(region-active-p)
+    'mark-active))
 ;;;_   > allout-process-exposed (&optional func from to frombuf
 ;;;					    tobuf format)
 (defun allout-process-exposed (&optional func from to frombuf tobuf
-					  format start-num)
+					  format &optional start-num)
   "Map function on exposed parts of current topic; results to another buffer.
 
-Apply FUNC to exposed portions FROM position TO position in buffer
+All args are options; default values itemized below.
+
+Apply FUNCTION to exposed portions FROM position TO position in buffer
 FROMBUF to buffer TOBUF.  Sixth optional arg, FORMAT, designates an
 alternate presentation form:
 
@@ -4170,7 +4544,7 @@
 		       except for distinctive bullets.
 
 Defaults:
-  FUNC:		`allout-insert-listified'
+  FUNCTION:	`allout-insert-listified'
   FROM:		region start, if region active, else start of buffer
   TO:		region end, if region active, else end of buffer
   FROMBUF:	current buffer
@@ -4219,9 +4593,7 @@
 
  \`(depth prefix text)'
 
-or
-
- \`(depth prefix text bullet-plus)'
+or \`(depth prefix text bullet-plus)'
 
 If `bullet-plus' is specified, it is inserted just after the entire prefix."
   (setq listified (cdr listified))
@@ -4237,7 +4609,7 @@
     (while text
       (insert (car text))
       (if (setq text (cdr text))
-	  (insert "\n")))
+	  (insert-string "\n")))
     (insert "\n")))
 ;;;_   > allout-copy-exposed-to-buffer (&optional arg tobuf format)
 (defun allout-copy-exposed-to-buffer (&optional arg tobuf format)
@@ -4440,14 +4812,14 @@
 	 body-content bop)
 					; Do the head line:
     (insert (concat "\\OneHeadLine{\\verb\1 "
-		    (allout-latex-verb-quote bullet)
-		    "\1}{"
-		    depth
-		    "}{\\verb\1 "
-		    (if head-line
-			(allout-latex-verb-quote head-line)
-		      "")
-		    "\1}\n"))
+                    (allout-latex-verb-quote bullet)
+                    "\1}{"
+                    depth
+                    "}{\\verb\1 "
+                    (if head-line
+                        (allout-latex-verb-quote head-line)
+                      "")
+                    "\1}\n"))
     (if (not body-lines)
 	nil
       ;;(insert "\\beginlines\n")
@@ -4509,7 +4881,615 @@
     (pop-to-buffer buf)
     (goto-char start-pt)))
 
-;;;_ #8 miscellaneous
+;;;_ #8 Encryption
+;;;_  > allout-toggle-current-subtree-encryption (&optional fetch-key)
+(defun allout-toggle-current-subtree-encryption (&optional fetch-key)
+  "Encrypt clear text or decrypt encoded contents of a topic.
+
+Contents includes body and subtopics.
+
+Currently only GnuPG encryption is supported.
+
+\**NOTE WELL** that the encrypted text must be ascii-armored.  For gnupg
+encryption, include the option ``armor'' in your ~/.gnupg/gpg.conf file.
+
+Both symmetric-key and key-pair encryption is implemented.  Symmetric is
+the default, use a single \(x4) universal argument for keypair mode.
+
+Encrypted topic's bullet is set to a `~' to signal that the contents of the
+topic \(body and subtopics, but not heading) is pending encryption or
+encrypted.  An `*' asterisk immediately after the bullet signals that the
+body is encrypted, its absence means it's meant to be encrypted but is not
+- it's \"disclosed\".  When a file with disclosed topics is saved, the user
+prompted for an ok to \(symmetric-key) encrypt the disclosed topics.  NOTE
+WELL that you must explicitly \(re)encrypt key-pair encrypted topics if you
+want them to continue to be in key-pair mode.
+
+Level-1 topics, with prefix consisting solely of an `*' asterisk, cannot be
+encrypted.  If you want to encrypt the contents of a top-level topic, use
+\\[allout-shift-in] to increase its depth.
+
+Failed transformation does not change the an entry being encrypted -
+instead, the key is re-solicited and the transformation is retried.
+\\[keyboard-quit] to abort.
+
+Decryption does symmetric or key-pair key mode depending on how the text
+was encrypted.  The encryption key is solicited if not currently available
+from the key cache from a recent prior encryption action.
+
+Optional FETCH-KEY universal argument is used for two purposes - to provoke
+key-pair instead of symmetric encryption, or to provoke clearing of the key
+cache so keys are freshly fetched.
+
+ - Without any universal arguments, then the appropriate key for the is
+   obtained from the cache, if available, else from the user.
+
+ - If FETCH-KEY is the result of one universal argument - ie, equal to 4 -
+   then key-pair encryption is used.
+
+ - With repeated universal argument - equal to 16 - then the key cache is
+   cleared before any encryption transformations, to force prompting of the
+   user for the key.
+
+The solicited key is retained for reuse in a buffer-specific cache for some
+set period of time \(default, 60 seconds), after which the string is
+nulled.  `mailcrypt' provides the key caching functionality.  You can
+adjust the key cache timeout by ajdusting the setting of the elisp variable
+`mc-passwd-timeout'.
+
+If the file previously had no associated key, or had a different key than
+specified, the user is prompted to repeat the new one for corroboration.  A
+random string encrypted by the new key is set on the buffer-specific
+variable `allout-key-verifier-string', for confirmation of the key when
+next obtained, before encrypting or decrypting anything with it.  This
+helps avoid mistakenly shifting between keys.
+
+If allout customization var `allout-key-verifier-handling' is non-nil, an
+entry for `allout-key-verifier-string' and its value is added to an Emacs
+'local variables' section at the end of the file, which is created if
+necessary.  That setting is for retention of the key verifier across emacs
+sessions.
+
+Similarly, `allout-key-hint-string' stores a user-provided reminder about
+their key, and `allout-key-hint-handling' specifies when the hint is
+presented, or if key hints are disabled.  If enabled \(see the
+`allout-key-hint-handling' docstring for details), the hint string is
+stored in the local-variables section of the file, and solicited whenever
+the key is changed."
+
+;;; This routine handles allout-specific business, dispatching
+;;; encryption-specific business to allout-encrypt-string.
+
+  (interactive "P")
+  (save-excursion
+    (allout-end-of-prefix t)
+
+    (if (= (allout-recent-depth) 1)
+        (error (concat "Cannot encrypt or decrypt level 1 topics -"
+                       " shift it in to make it encryptable")))
+
+    (if (and fetch-key
+             (not (equal fetch-key '(4))))
+        (mc-deactivate-passwd))
+
+    (let* ((allout-buffer (current-buffer))
+           ;; Asses location:
+           (after-bullet-pos (point))
+           (was-encrypted
+            (progn (if (= (point-max) after-bullet-pos)
+                       (error "no body to encrypt"))
+                   (looking-at "\\*")))
+           (was-collapsed (if (not (re-search-forward "[\n\r]" nil t))
+                              nil
+                            (backward-char 1)
+                            (looking-at "\r")))
+           (subtree-beg (1+ (point)))
+           (subtree-end (allout-end-of-subtree))
+           (subject-text (buffer-substring-no-properties subtree-beg
+                                                         subtree-end))
+           (subtree-end-char (char-after (1- subtree-end)))
+           (subtree-trailling-char (char-after subtree-end))
+           (place-holder (if (or (string= "" subject-text)
+                                 (string= "\n" subject-text))
+                             (error "No topic contents to %scrypt"
+                                    (if was-encrypted "de" "en"))))
+           ;; Assess key parameters:
+           (key-type (or
+                      ;; detect the type by which it is already encrypted
+                      (and was-encrypted
+                           (allout-encrypted-text-type subject-text))
+                      (and (member fetch-key '(4 (4)))
+                           (yes-or-no-p "Use key-pair encryption instead? ")
+                           'keypair)
+                      'symmetric))
+           (fetch-key (and fetch-key (not (member fetch-key '(16 (16))))))
+           result-text)
+
+      (setq result-text
+            (allout-encrypt-string subject-text was-encrypted
+                                    (current-buffer) key-type fetch-key))
+
+       ;; Replace the subtree with the processed product.
+      (allout-unprotected
+       (progn
+         (set-buffer allout-buffer)
+         (delete-region subtree-beg subtree-end)
+         (insert result-text)
+         (if was-collapsed
+             (allout-flag-region subtree-beg (1- (point)) ?\r))
+         ;; adjust trailling-blank-lines to preserve topic spacing:
+         (if (not was-encrypted)
+             (if (and (member subtree-end-char '(?\r ?\n))
+                      (member subtree-trailling-char '(?\r ?\n)))
+                 (insert subtree-trailling-char)))
+         ;; Ensure that the item has an encrypted-entry bullet:
+         (if (not (string= (buffer-substring-no-properties
+                            (1- after-bullet-pos) after-bullet-pos)
+                           allout-topic-encryption-bullet))
+             (progn (goto-char (1- after-bullet-pos))
+                    (delete-char 1)
+                    (insert allout-topic-encryption-bullet)))
+         (if was-encrypted
+             ;; Remove the is-encrypted bullet qualifier:
+             (progn (goto-char after-bullet-pos)
+                    (delete-char 1))
+           ;; Add the is-encrypted bullet qualifier:
+           (goto-char after-bullet-pos)
+           (insert "*"))
+         )
+       )
+      )
+    )
+  )
+;;;_  > allout-encrypt-string (text decrypt allout-buffer key-type rekey
+;;;                                  &optional retried verifying)
+(defun allout-encrypt-string (text decrypt allout-buffer key-type rekey
+                                    &optional retried verifying)
+  "Encrypt or decrypt a string TEXT using KEY.
+
+If optional DECRYPT is true (default false), then decrypt instead of
+encrypt.
+
+Optional REKEY (default false) provokes clearing of the key cache to force
+fresh prompting for the key.
+
+Optional RETRIED is for internal use - conveys the number of failed keys have
+been solicited in sequence leading to this current call.
+
+Optional VERIFYING is for internal use, signifying processing of text
+solely for verification of the cached key.
+
+Returns the resulting string, or nil if the transformation fails."
+
+  ;; Ensure that we have an alternate handle on the real mc-activate-passwd:
+  (if (not (fboundp 'real-mc-activate-passwd))
+      ;; Force loads of the primary mailcrypt packages, so flet below holds.
+      (progn (require 'mailcrypt)
+             (load "mc-toplev")
+             (fset 'real-mc-activate-passwd
+                   (symbol-function 'mc-activate-passwd))))
+
+  (if (and rekey (not verifying)) (mc-deactivate-passwd))
+
+  (catch 'encryption-failed
+    (save-excursion
+
+      (let* ((mc-default-scheme (or allout-encryption-scheme
+                                    allout-default-encryption-scheme))
+             (id (format "%s-%s" key-type
+                         (or (buffer-file-name allout-buffer)
+                             (buffer-name allout-buffer))))
+             (cached (real-mc-activate-passwd id nil))
+             (comment "Processed by allout driving mailcrypt")
+             key work-buffer result result-text encryption-process-status)
+
+        (unwind-protect
+
+            ;; Interject our mc-activate-passwd wrapper:
+            (flet ((mc-activate-passwd (id &optional prompt)
+                                       (allout-mc-activate-passwd id prompt)))
+
+              (setq work-buffer
+                    (set-buffer (allout-encryption-produce-work-buffer text)))
+
+              (cond
+
+               ;; symmetric:
+               ((equal key-type 'symmetric)
+                (setq key (if verifying
+                              (real-mc-activate-passwd id nil)
+                            (allout-mc-activate-passwd id)))
+                (setq encryption-process-status
+                      (crypt-encrypt-buffer key decrypt))
+                (if (zerop encryption-process-status)
+                    t
+                  (if verifying
+                      (throw 'encryption-failed nil)
+                    (mc-deactivate-passwd)
+                    (error "Symmetric-key encryption failed (%s) - wrong key?"
+                           encryption-process-status))))
+
+               ;; encrypt 'keypair:
+               ((not decrypt)
+                (condition-case result
+                    (mailcrypt-encrypt 1)
+                  (error (mc-deactivate-passwd)
+                         (error "encryption failed: %s"
+                                (cadr result)))))
+
+               ;; decrypt 'keypair:
+               (t (condition-case result
+                      (mc-decrypt)
+                    (error (mc-deactivate-passwd)
+                           (error "decryption failed: %s"
+                                  (cadr result))))))
+
+              (setq result-text (if (or (equal key-type 'keypair)
+                                        (not decrypt))
+                                    (buffer-substring 1 (1- (point-max)))
+                                  (buffer-string)))
+              ;; validate result - non-empty
+              (cond ((not result-text)
+                     (if verifying
+                         nil
+                       ;; Transformation was fruitless - retry with new key.
+                       (mc-deactivate-passwd)
+                       (allout-encrypt-string text allout-buffer decrypt nil
+                                               (if retried (1+ retried) 1)
+                                               verifying)))
+
+                    ;; Barf if encryption yields extraordinary control chars:
+                    ((and (not decrypt)
+                          (string-match "[\C-a\C-k\C-o-\C-z\C-@]" result-text))
+                     (error (concat "encryption produced unusable"
+                                    " non-armored text - reconfigure!")))
+
+                    ;; valid result and just verifying or non-symmetric:
+                    ((or verifying (not (equal key-type 'symmetric)))
+                     result-text)
+
+                    ;; valid result and regular symmetric - situate validator:
+                    (t
+                     ;; valid result and verifier needs to be situated in
+                     ;; allout-buffer:
+                     (set-buffer allout-buffer)
+                     (if (and (or rekey (not cached))
+                              (not (allout-verify-key key allout-buffer)))
+                         (allout-situate-encryption-key-verifier key id))
+                     result-text)
+                    )
+              )
+
+          ;; unwind-protect emergence:
+          (if work-buffer
+              (kill-buffer work-buffer))
+          )
+        )
+      )
+    )
+  )
+;;;_  > allout-mc-activate-passwd (id &optional prompt)
+(defun allout-mc-activate-passwd (id &optional prompt)
+  "Substituted for mc-activate-passwd during allout outline encryption.
+
+We add key-verification to vanilla mc-activate-passwd.
+
+We depend in some cases on values of the following allout-encrypt-string
+internal or prevailing variables:
+  - key-type - 'symmetric or 'keypair
+  - id - id associated with current key in key cache
+  - allout-buffer - where subject text resides
+  - retried - number of current attempts to obtain this key
+  - rekey - user asked to present a new key - needs to be confirmed"
+
+;;  - if we're doing non-symmetric key, just do normal mc-activate-passwd
+;;  - otherwise, if we are have a cached version of the key, then assume
+;;    it's verified and return it
+;;  - otherwise, prompt for a key, and:
+;;    - if we have a key verifier \(a string value which should decrypt
+;;      against a symmetric key), validate against the verifier
+;;      - if successful, return the verified key
+;;      - if unsuccessful:
+;;        - offer to use the new key
+;;          - if accepted, do confirm process
+;;          - if refused, try again until we get a correctly spelled one or the
+;;            user quits
+;;    - if no key verifier, resolicit the key to get corroboration and return
+;;      the corroborated key if spelled identically, or error if not.
+
+  (if (not (equal key-type 'symmetric))
+      ;; do regular mc-activate-passwd on non-symmetric key
+      (real-mc-activate-passwd id prompt)
+
+    ;; Symmetric hereon:
+
+    (save-excursion
+      (set-buffer allout-buffer)
+      (let* ((hint (if (and (not (string= allout-key-hint-string ""))
+                            (or (equal allout-key-hint-handling 'always)
+                                (and (equal allout-key-hint-handling 'needed)
+                                     retried)))
+                       (format " [%s]" allout-key-hint-string)
+                     ""))
+             (retry-message (if retried (format " (%s retry)" retried) ""))
+             (prompt-sans-hint (format "'%s' symmetric key%s: "
+                                       (buffer-name allout-buffer)
+                                       retry-message))
+             (full-prompt (format "'%s' symmetric key%s%s: "
+                                  (buffer-name allout-buffer)
+                                  hint retry-message))
+             (prompt full-prompt)
+             (verifier-string (allout-get-encryption-key-verifier))
+             ;; force retention of cached passwords for five minutes while
+             ;; we're in this particular routine:
+             (mc-passwd-timeout 300)
+             (cached (real-mc-activate-passwd id nil))
+             (got (or cached (real-mc-activate-passwd id full-prompt)))
+             confirmation)
+
+        (if (not got)
+            nil
+
+          ;; Duplicate our handle on the key so it's not clobbered by
+          ;; deactivate-passwd memory clearing:
+          (setq got (format "%s" got))
+
+          (cond (verifier-string
+                 (if (and (not (allout-encrypt-string
+                                verifier-string 'decrypt allout-buffer
+                                'symmetric nil 0 'verifying))
+                          (if (yes-or-no-p
+                               (concat "Key differs from established"
+                                       " - use new one instead? "))
+                              ;; deactivate password for subsequent
+                              ;; confirmation:
+                              (progn (mc-deactivate-passwd)
+                                     (setq prompt prompt-sans-hint)
+                                     nil)
+                            t))
+                     (progn (mc-deactivate-passwd)
+                            (error "Wrong key."))))
+                ;; Force confirmation by repetition for new key:
+                ((or rekey (not cached)) (mc-deactivate-passwd))))
+        ;; we have a key and it's either verified and cached.
+        ;; confirmation vs new input - doing mc-activate-passwd will do the
+        ;; right thing, in either case:
+        (setq confirmation
+              (real-mc-activate-passwd id (concat prompt
+                                                  " ... confirm spelling: ")))
+        (prog1
+            (if (equal got confirmation)
+                confirmation
+              (if (yes-or-no-p (concat "spelling of original and"
+                                       " confirmation differ - retry? "))
+                  (progn (setq retried (if retried (1+ retried) 1))
+                         (mc-deactivate-passwd)
+                         ;; recurse to this routine:
+                         (mc-activate-passwd id prompt-sans-hint))
+                (mc-deactivate-passwd)
+                (error "Confirmation failed.")))
+          ;; reduce opportunity for memory cherry-picking by zeroing duplicate:
+          (dotimes (i (length got))
+            (aset got i 0))
+          )
+        )
+      )
+    )
+  )
+;;;_  > allout-encryption-produce-work-buffer (text)
+(defun allout-encryption-produce-work-buffer (text)
+  "Establish a new buffer filled with TEXT, for outline encrypion processing.
+
+TEXT is massaged so outline collapsing, if any, is removed."
+  (let ((work-buffer (generate-new-buffer " *allout encryption*")))
+    (save-excursion
+      (set-buffer work-buffer)
+      (insert (subst-char-in-string ?\r ?\n text)))
+    work-buffer))
+;;;_  > allout-encrypted-topic-p ()
+(defun allout-encrypted-topic-p ()
+  "True if the current topic is encryptable and encrypted."
+  (save-excursion
+    (allout-end-of-prefix t)
+    (and (string= (buffer-substring-no-properties (1- (point)) (point))
+                  allout-topic-encryption-bullet)
+         (looking-at "\\*"))
+    )
+  )
+;;;_  > allout-encrypted-text-type (text)
+;;; XXX gpg-specific, not generic!
+(defun allout-encrypted-text-type (text)
+  "For gpg encrypted text, return 'symmetric or 'keypair."
+
+  ;; Ensure mc-gpg-path has a value:
+  (if (not (boundp 'mc-gpg-path))
+      (load-library "mc-gpg"))
+
+  (save-excursion
+    (let* ((work-buffer (set-buffer
+                         (allout-encryption-produce-work-buffer text)))
+           (result (mc-gpg-process-region (point-min) (point-max)
+                                          nil mc-gpg-path
+                                          '("--batch" "--decrypt")
+                                          'mc-gpg-decrypt-parser
+                                          work-buffer nil)))
+      (cond ((equal (nth 0 result) 'symmetric)
+             'symmetric)
+            ((equal (nth 0 result) t)
+             'keypair)
+            (t (error "Unrecognized/unsupported encryption type %S"
+                      (nth 0 result))))
+      )
+    )
+  )
+;;;_  > allout-create-encryption-key-verifier (key id)
+(defun allout-create-encryption-key-verifier (key id)
+  "Encrypt a random message for later validation of symmetric key."
+  ;; use 20 random ascii characters, across the entire ascii range.
+  (random t)
+  (let ((spew (make-string 20 ?\0)))
+    (dotimes (i (length spew))
+      (aset spew i (1+ (random 254))))
+    (allout-encrypt-string spew nil nil 'symmetric nil nil t))
+  )
+;;;_  > allout-situate-encryption-key-verifier (key id)
+(defun allout-situate-encryption-key-verifier (key id)
+  "Establish key verifier string on file variable.
+
+We also prompt for and situate a new reminder, if reminders are enabled.
+
+We massage the string to simplify programmatic adjustment.  File variable
+is `allout-file-key-verifier-string'."
+  (let ((verifier-string
+         ;; Collapse to a single line and enclose in string quotes:
+         (subst-char-in-string ?\n ?\C-a
+                               (allout-create-encryption-key-verifier
+                                key id)))
+        (reminder (if (not (equal allout-key-hint-handling 'disabled))
+                      (read-from-minibuffer
+                       "Key hint to jog your memory next time: "
+                       allout-key-hint-string))))
+    (setq allout-key-verifier-string verifier-string)
+    (allout-adjust-file-variable "allout-key-verifier-string"
+                                  verifier-string)
+    (cond ((equal allout-key-hint-handling 'disabled)
+           nil)
+          ((not (string= reminder allout-key-hint-string))
+           (setq allout-key-hint-string reminder)
+           (allout-adjust-file-variable "allout-key-hint-string"
+                                         reminder)))
+    )
+  )
+;;;_  > allout-get-encryption-key-verifier ()
+(defun allout-get-encryption-key-verifier ()
+  "Return the text of the encrypt key verifier, unmassaged, or nil if none.
+
+Derived from value of `allout-file-key-verifier-string'."
+
+  (let ((verifier-string (and (boundp 'allout-key-verifier-string)
+                              allout-key-verifier-string)))
+    (if verifier-string
+        ;; Return it uncollapsed
+        (subst-char-in-string ?\C-a ?\n verifier-string)
+      nil)
+   )
+  )
+;;;_  > allout-verify-key (key)
+(defun allout-verify-key (key allout-buffer)
+  "True if key successfully decrypts key verifier, nil otherwise.
+
+\"Otherwise\" includes absence of key verifier."
+  (save-excursion
+    (set-buffer allout-buffer)
+    (and (boundp 'allout-key-verifier-string)
+         allout-key-verifier-string
+         (allout-encrypt-string (allout-get-encryption-key-verifier)
+                                 'decrypt allout-buffer 'symmetric
+                                 nil nil 'verifying)
+         t)))
+;;;_  > allout-next-topic-pending-encryption (&optional except-mark)
+(defun allout-next-topic-pending-encryption (&optional except-mark)
+  "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."
+  (let (done got content-beg)
+    (while (not done)
+
+      (if (not (re-search-forward
+                (format "\\(\\`\\|[\n\r]\\)%s *%s[^*]"
+                        (regexp-quote allout-header-prefix)
+                        (regexp-quote allout-topic-encryption-bullet))
+                nil t))
+          (setq got nil
+                done t)
+        (goto-char (setq got (match-beginning 0)))
+        (if (looking-at "[\n\r]")
+            (forward-char 1))
+        (setq got (point)))
+
+      (cond ((not got)
+             (setq done t))
+
+            ((not (re-search-forward "[\n\r]"))
+             (setq got nil
+                   done t))
+
+            ((eobp)
+             (setq got nil
+                   done t))
+
+            (t
+             (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)))
+                 ;; Continue looking
+                 (setq got nil)
+               ;; Got it!
+               (setq done t)))
+            )
+      )
+    (if got
+        (goto-char got))
+    )
+  )
+;;;_  > allout-encrypt-decrypted (&optional except-mark)
+(defun allout-encrypt-decrypted (&optional except-mark)
+  "Encrypt topics pending encryption except those containing exemption point.
+
+EXCEPT-MARK identifies a point whose containing topics should be excluded
+from encryption.  This supports '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
+and exactly resituate the cursor if this is being done as part of a file
+save.  See `allout-encrypt-unencrypted-on-saves' for more info."
+
+  (interactive "p")
+  (save-excursion
+    (let ((current-mark (point-marker))
+          was-modified
+          bo-subtree
+          editing-topic editing-point)
+      (goto-char (point-min))
+      (while (allout-next-topic-pending-encryption except-mark)
+        (setq was-modified (buffer-modified-p))
+        (if (save-excursion
+              (and (boundp 'allout-encrypt-unencrypted-on-saves)
+                   allout-encrypt-unencrypted-on-saves
+                   (setq bo-subtree (re-search-forward "[\n\r]"))
+                   ;; Not collapsed:
+                   (string= (match-string 0) "\n")
+                   (>= current-mark (point))
+                   (allout-end-of-current-subtree)
+                   (<= current-mark (point))))
+            (setq editing-topic (point)
+                  ;; we had to wait for this 'til now so prior topics are
+                  ;; encrypted, any relevant text shifts are in place:
+                  editing-point (marker-position current-mark)))
+        (allout-toggle-current-subtree-encryption)
+        (if (not was-modified)
+            (set-buffer-modified-p nil))
+        )
+      (if (not was-modified)
+         (set-buffer-modified-p nil))
+      (if editing-topic (list editing-topic editing-point))
+      )
+    )
+  )
+
+;;;_ #9 miscellaneous
 ;;;_  > allout-mark-topic ()
 (defun allout-mark-topic ()
   "Put the region around topic currently containing point."
@@ -4538,22 +5518,100 @@
 	t
       (allout-open-topic 2)
       (insert (concat "Dummy outline topic header - see"
-		      "`allout-mode' docstring: `^Hm'."))
-      (forward-line 1)
+                      "`allout-mode' docstring: `^Hm'."))
+      (allout-adjust-file-variable
+       "allout-layout" (format "%s" (or allout-layout '(-1 : 0)))))))
+;;;_  > allout-file-vars-section-data ()
+(defun allout-file-vars-section-data ()
+  "Return data identifying the file-vars section, or nil if none.
+
+Returns list `(beginning-point prefix-string suffix-string)'."
+  ;; minimally gleaned from emacs 21.4 files.el hack-local-variables function.
+  (let (beg prefix suffix)
+    (save-excursion
       (goto-char (point-max))
-      (open-line 1)
-      (allout-open-topic 0)
-      (insert "Local emacs vars.\n")
-      (allout-open-topic 1)
-      (insert "(`allout-layout' is for allout.el allout-mode)\n")
-      (allout-open-topic 0)
-      (insert "Local variables:\n")
-      (allout-open-topic 0)
-      (insert (format "allout-layout: %s\n"
-			     (or allout-layout
-				 '(-1 : 0))))
-      (allout-open-topic 0)
-      (insert "End:\n"))))
+      (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
+      (if (let ((case-fold-search t))
+	    (not (search-forward "Local Variables:" nil t)))
+          nil
+        (setq beg (- (point) 16))
+        (setq suffix (buffer-substring-no-properties
+                      (point)
+                      (progn (if (re-search-forward "[\n\r]" nil t)
+                                 (forward-char -1))
+                             (point))))
+        (setq prefix (buffer-substring-no-properties
+                      (progn (if (re-search-backward "[\n\r]" nil t)
+                                 (forward-char 1))
+                             (point))
+                      beg))
+        (list beg prefix suffix))
+      )
+    )
+  )
+;;;_  > allout-adjust-file-variable (varname value)
+(defun allout-adjust-file-variable (varname value)
+  "Adjust the setting of an emacs file variable named VARNAME to VALUE.
+
+This activity is inhibited if either `enable-local-variables'
+`allout-enable-file-variable-adjustment' are nil.
+
+When enabled, an entry for the variable is created if not already present,
+or changed if established with a different value.  The section for the file
+variables, itself, is created if not already present.  When created, the
+section lines \(including the section line) exist as second-level topics in
+a top-level topic at the end of the file.
+
+enable-local-variables must be true for any of this to happen."
+  (if (not (and enable-local-variables
+                allout-enable-file-variable-adjustment))
+      nil
+    (save-excursion
+      (let ((section-data (allout-file-vars-section-data))
+            beg prefix suffix)
+        (if section-data
+            (setq beg (car section-data)
+                  prefix (cadr section-data)
+                  suffix (car (cddr section-data)))
+          ;; create the section
+          (goto-char (point-max))
+          (open-line 1)
+          (allout-open-topic 0)
+          (end-of-line)
+          (insert "Local emacs vars.\n")
+          (allout-open-topic 1)
+          (setq beg (point)
+                suffix ""
+                prefix (buffer-substring-no-properties (progn
+                                                         (beginning-of-line)
+                                                         (point))
+                                                       beg))
+          (goto-char beg)
+          (insert "Local variables:\n")
+          (allout-open-topic 0)
+          (insert "End:\n")
+          )
+        ;; look for existing entry or create one, leaving point for insertion
+        ;; of new value:
+        (goto-char beg)
+        (allout-show-to-offshoot)
+        (if (search-forward (concat "\n" prefix varname ":") nil t)
+            (let* ((value-beg (point))
+                   (line-end (progn (if (re-search-forward "[\n\r]" nil t)
+                                        (forward-char -1))
+                                    (point)))
+                   (value-end (- line-end (length suffix))))
+              (if (> value-end value-beg)
+                  (delete-region value-beg value-end)))
+          (end-of-line)
+          (open-line 1)
+          (forward-line 1)
+          (insert (concat prefix varname ":")))
+        (insert (format " %S%s" value suffix))
+        )
+      )
+    )
+  )
 ;;;_  > solicit-char-in-string (prompt string &optional do-defaulting)
 (defun solicit-char-in-string (prompt string &optional do-defaulting)
   "Solicit (with first arg PROMPT) choice of a character from string STRING.
@@ -4594,8 +5652,7 @@
 Representations of actual backslashes - '\\\\\\\\' - are left as a
 single backslash.
 
-\(fn REGEXP)"
-;; Optional arg SUCCESSIVE-BACKSLASHES is used internally for recursion.
+Optional arg SUCCESSIVE-BACKSLASHES is used internally for recursion."
 
   (if (string= regexp "")
       ""
@@ -4611,11 +5668,6 @@
 		(regexp-sans-escapes (substring regexp 1)))
       ;; Exclude first char, but maintain count:
       (regexp-sans-escapes (substring regexp 1) successive-backslashes))))
-;;;_  > my-region-active-p ()
-(defmacro my-region-active-p ()
-  (if (fboundp 'region-active-p)
-      '(region-active-p)
-    'mark-active))
 ;;;_  - add-hook definition for divergent emacsen
 ;;;_   > add-hook (hook function &optional append)
 (if (not (fboundp 'add-hook))
@@ -4636,17 +5688,30 @@
 	       (if append
 		   (nconc (symbol-value hook) (list function))
 		 (cons function (symbol-value hook)))))))
+;;;_  > subst-char-in-string if necessary
+(if (not (fboundp 'subst-char-in-string))
+    (defun subst-char-in-string (fromchar tochar string &optional inplace)
+      "Replace FROMCHAR with TOCHAR in STRING each time it occurs.
+Unless optional argument INPLACE is non-nil, return a new string."
+      (let ((i (length string))
+            (newstr (if inplace string (copy-sequence string))))
+        (while (> i 0)
+          (setq i (1- i))
+          (if (eq (aref newstr i) fromchar)
+              (aset newstr i tochar)))
+        newstr)))
+
 ;;;_  : my-mark-marker to accommodate divergent emacsen:
 (defun my-mark-marker (&optional force buffer)
   "Accommodate the different signature for `mark-marker' across Emacsen.
 
-XEmacs takes two optional args, while GNU Emacs does not,
+XEmacs takes two optional args, while mainline GNU Emacs does not,
 so pass them along when appropriate."
-  (if (featurep 'xemacs)
+  (if (string-match " XEmacs " emacs-version)
       (mark-marker force buffer)
     (mark-marker)))
 
-;;;_ #9 Under development
+;;;_ #10 Under development
 ;;;_  > allout-bullet-isearch (&optional bullet)
 (defun allout-bullet-isearch (&optional bullet)
   "Isearch \(regexp) for topic with bullet BULLET."

[-- Attachment #3: allout-ChangeLog.txt --]
[-- Type: text/plain, Size: 6893 bytes --]

2005-09-30  Ken Manheimer  <ken.manheimer@gmail.com>

	* allout.el: omnibus changes

	  - new subsystem supporting easy gpg topic encryption/decryption.

	    salient features:

	    - both public- and symmetric-key modes are supported.
	    - encryption being on a per-topic basis means you can
	      intersperse encrypted and clear-text data in a single file
	      to your heart's content.
	    - user-provided symmetric-key hints, with consistency
	      verification to help user avoid confusion
	    - time-limited key reuse, a la (and using) mailcrypt's
	      mc-passwd-timeout
	    - write-file-hook and auto-save-hook activities to support auto
	      encryption of pending topics on save; provision to skip
	      currently-edited topic to avoid editing disturbance

	    topic encryption functionality depends on both mailcrypt and
	    crypt++ packages.  (non-encryption allout functionality is not
	    disrupted if either mailcrypt or crypt++ are absent.)

	    docstring for `allout-toggle-current-subtree-encryption'
	    and customization variables provide detailed description.

	    code changes:

	    new autoloads of crypt++ and mailcrypt routines, all for
	    encryption functionality.

	    'allout customization subgroup now positioned in 'outlines
	    group (instead of prior 'editing group)

	    central topic-encryption entry point:
	    (outline-toggle-current-subtree-encryption)

	    other new encryption routines:
	    (allout-encrypt-string, allout-encryption-produce-work-buffer,
	    allout-encrypted-topic-p, allout-encrypted-text-type,
	    allout-mc-activate-passwd,
	    allout-create-encryption-key-verifier,
	    allout-situate-encryption-key-verifier,
	    allout-get-encryption-key-verifier, allout-verify-key,
	    allout-next-topic-pending-encryption,
	    allout-encrypt-decrypted, allout-encrypted-type-prefix)

	    new customization variables:
	    (outline-topic-encryption-bullet,
	    outline-default-encryption-scheme,
	    outline-key-verifier-handling, outline-key-hint-handling,
	    outline-encrypt-unencrypted-on-saves)

	    new operational variables:
	    (allout-file-key-verifier-string, allout-encryption-scheme,
	    allout-key-verifier-string, allout-key-hint-string,
	    allout-after-save-decrypt)

	    new hook functions for auto-encryption of pending topics:
	    (allout-write-file-hook-handler, allout-auto-save-hook-handler,
	    allout-after-saves-handler)

	    (allout-post-command-business): do allout-after-save-decrypt

	  - added mechanism for adding and adjusting settings of Emacs file
	    variables.

	    (allout-enable-file-variable-adjustment): custom var to enable
	    mechanism
	    (allout-adjust-file-variable, allout-file-vars-section-data):
	    mechanism implementation
	    (outlineify-sticky): use file vars mechanism

	  - replaced broken mechanism for inhibition of concealed-text edits

	    using read-only text instead of before-change-functions,
	    because the latter can no longer veto the changes without being
	    disabled.  read-only text is more suitable and less
	    complicated, anyway.

	    (it also noticably slows massive exposure changes, but i
	    consider the performance acceptable.  eg, i have blanket
	    auto-exposure set for my daily-notes log, which has real-world
	    intricacy in a 1.1 Mb, 7000 topic outline, and have no problems
	    working with it on a 200 MhZ windows laptop.)

	    (allout-inhibit-protection, allout-during-write-cue,
	    allout-override-protect, allout-before-change-protect): removed

	    (allout-flag-region, allout-open-topic): revised to adjust
	    read-only text

	    (allout-open-line-not-read-only): added to facilitate read-only
	    text based protection

	    (allout-kill-line): revised to adjust read-only text, clue the
	    user about the inhibition

	  - (allout-unprotected): robustified with an unwind-protect

	  - disallow manually shifting a topic deeper than the offspring
	    depth of the previous topic - avoiding confusing "containment
	    discontinuities"

	    (allout-shift-in, allout-shift-out)

	  - fixed retention of body relative hanging indent during
	    promotion of collapsed bodies

	    (allout-reindent-bodies)

	  - made it easy to open new topic with same bullet as current
	    topic - topic creation functions provided with any universal
	    argument provokes now prompt for bullet, defaulting to the
	    bullet of the previous topic.  very ergonomic.

	    (allout-open-topic)

	  - (allout-plain-bullets-string, allout-distinctive-bullets-string):
	    plain bullet alternates '.'	 period and ',' comma only.  all
	    other bullets are relegated to special status (but
	    customizable)

	  - (allout-end-of-entry): renamed from 'allout-end-of-current-entry
	    since it actually operates w.r.t. most immediately containing
	    entry, visible or not

	    (allout-hide-current-entry, allout-show-current-entry): use the
	    revised version

	  - (allout-old-expose-topic): solidify deprecation.

	  - (allout-end-of-subtree): added, so we can span concealed as
	    well as visible topics.
	    (allout-end-of-current-subtree): use `allout-end-of-subtree'.

	  - (allout-end-of-current-heading): tweaked to just respect the
	    first line

	  - (allout-get-body-text): added

	  - (allout-ascend-to-depth, allout-ascend): position at end of
	    prefix when invoked interactively

	  - (allout-up-current-level): use `interactive-p'

	  - (allout-mode, allout-init): miscellaneous docstring and
	    operational refinements, as well as hookups of new encryption
	    stuff

	  - comments and routine names better distinguish between:
	    - topic body - the text contained after a header
	    - topic header - the first line, before the body
	    - topic entry - the header, body, and offspring

	  - (allout-beginning-of-current-entry): now works as advertised

	  - (allout-end-of-current-entry): relieved of superfluous
	    allout-show-entry

	  - (allout-isearch-rectification): refine condition for isearching
	    (allout-isearch-abort, allout-enwrap-isearch)

	  - reconciled with distributed allout.el 1.61 (current CVS version
	    as of 09/30/2005), including interactive-p fixes, typo and
	    coding style fixes, change of function prefix to "allout-", etc,
	    and fixed problem created in outline yanking due to the
	    interactive-p fixes

	  - relocated some macros
	    (allout-flag-region, my-region-active-p)

	  - refined many docstrings, including anything from correcting
	    typos to conceptual clarification and correction

	  - (allout-title): fallback title is '(buffer-name)', not
	    non-existing '(current-buffer-name)'

	  - (subst-char-in-string): define if absent (for some xemacs versions)

	  - corrected commentary 'keywords' to legitimate ones

	  - updated comentary author info (using my current email address,
	    obscurified)

[-- Attachment #4: allout-news.txt --]
[-- Type: text/plain, Size: 1154 bytes --]

** allout (extensive outline navigation and authoring mode), significantly
   updated:

 - topic cryptography added, enabling easy gpg topic encryption and
   decryption.  per-topic basis enables interspersing encrypted-text and
   clear-text within a single file to your hearts content, using symmetric
   and/or public key modes.  time-limited key caching, user-provided
   symmetric key hinting and consitency verification, auto-encryption of
   pending topics on save, and more, make it easy to use encryption in
   powerful ways.

 - many substantial fixes and refinements, including:

   - repaired inhibition of inadvertant edits to concealed text
   - repaired retention of topic body hanging indent upon topic depth shifts
   - prevent "containment discontinuities" where a topic is shifted deeper
     than the offspring-depth of its' container
   - easy to adopt the distinctive bullet of a topic in a topic created
     relative to it, or select a new one, or use the common topic bullet
   - plain bullets, by default, now alternate between only two characters
     ('.' and ','), yielding less cluttered outlines.
   - many internal fixes.

[-- Attachment #5: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-10-01 12:41       ` Reiner Steib
@ 2005-10-01 23:54         ` James Cloos
  0 siblings, 0 replies; 156+ messages in thread
From: James Cloos @ 2005-10-01 23:54 UTC (permalink / raw)
  Cc: Ken Manheimer

>>>>> "Reiner" == Reiner Steib <reinersteib+gmane@imap.cc> writes:

> good question - i wasn't aware of pgg.  can you tell me more about it?

Reiner> If you have Emacs 22 (CVS) or Gnus 5.10 installed, you should
Reiner> also have the manual: (info "(pgg)Top").

For gentoo, that means any of the app-editors/emacs-cvs, app-emacs/gnus
and/or app-emacs/gnus-cvs ebuilds should contain that info manual.

-JimC
-- 
James H. Cloos, Jr. <cloos@jhcloos.com>

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-10-01 16:28     ` Ken Manheimer
@ 2005-10-02 10:48       ` Sascha Wilde
  2005-10-02 14:23         ` Ken Manheimer
  2005-10-02 20:31         ` Richard M. Stallman
  2005-10-02 17:08       ` new version of allout.el - patch and ChangeLog Richard M. Stallman
  1 sibling, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2005-10-02 10:48 UTC (permalink / raw)
  Cc: Andreas Schwab, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 1139 bytes --]

On Sat, Oct 01, 2005 at 12:28:17PM -0400, Ken Manheimer wrote:

> I emerged it and got access to gpp and the info file.  it
> looks nice - clean - but appears to have the same drawback, for my
> purposes, as mailcrypt.  it will decrypt messages encoded with a
> symmetric key, but provides no api for encrypting with a symmetric
> key.  that lack is a show-stopper for my purposes.

So you would consider switching to pgg, if it would provide an
interface to symmetric encryption?

> it may well be that pgg is preferable, somehow, to mailcrypt - they
> both offer similar functionality, including key caching, as well as
> the lack of an interface for encrypting with a symmetric key.  but the
> changeover won't gain me anything i can yet see - i'll still need to
> also use crypt++ for the symmetric key encoding.

The reason I asked is, that pgg is, just like allout, part of GNU 
Emacs 22 -- so IMO it would be desirable to have the howl
functionality of allout "out of the box" with GNU emacs.

cheers
sascha
-- 
Sascha Wilde 
Hi! I'm a .signature *virus*! Copy me into your ~/.signature to help me spread!

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-10-02 10:48       ` Sascha Wilde
@ 2005-10-02 14:23         ` Ken Manheimer
  2005-10-02 20:31         ` Richard M. Stallman
  1 sibling, 0 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-02 14:23 UTC (permalink / raw)


On 10/2/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> On Sat, Oct 01, 2005 at 12:28:17PM -0400, Ken Manheimer wrote:
>
> > I emerged it and got access to gpp and the info file.  it
> > looks nice - clean - but appears to have the same drawback, for my
> > purposes, as mailcrypt.  it will decrypt messages encoded with a
> > symmetric key, but provides no api for encrypting with a symmetric
> > key.  that lack is a show-stopper for my purposes.
>
> So you would consider switching to pgg, if it would provide an
> interface to symmetric encryption?

yes.  it would probably be a relief - allout goes through different
contortions to use crypt++ than it does for mailcrypt.  i expect my
code could simplify, overall, if it used a single, fairly clean
encryption interface.

> > it may well be that pgg is preferable, somehow, to mailcrypt - they
> > both offer similar functionality, including key caching, as well as
> > the lack of an interface for encrypting with a symmetric key.  but the
> > changeover won't gain me anything i can yet see - i'll still need to
> > also use crypt++ for the symmetric key encoding.
>
> The reason I asked is, that pgg is, just like allout, part of GNU
> Emacs 22 -- so IMO it would be desirable to have the howl
> functionality of allout "out of the box" with GNU emacs.

that would be a compelling reason.  i could allocate some time to
incorporate pgg into allout, ditching the dependencies on crypt++ and
mailcrypt, if pgg provided for encrypting with symmetric keys.  i
don't think i have the time to develop that extension of pgg  however.
 do you think someone else might do that?  that would be cool...

ken
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-10-01 16:28     ` Ken Manheimer
  2005-10-02 10:48       ` Sascha Wilde
@ 2005-10-02 17:08       ` Richard M. Stallman
  1 sibling, 0 replies; 156+ messages in thread
From: Richard M. Stallman @ 2005-10-02 17:08 UTC (permalink / raw)
  Cc: wilde, schwab, emacs-devel

PGG is a good thing, but it doesn't replace Mailcrypt, not by itself,
because its interface is designed for Lisp programs instead of for
users.

I think we should do two things:

1. Move PGG out of Gnus and into the rest of Emacs.

2. Write a user-level interface to PGG which can be used
instead of Mailcrypt.

#1 is simple and harmless; let's do that now.

Would anyone like to do #2?  We would install it after the coming
release.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-10-02 10:48       ` Sascha Wilde
  2005-10-02 14:23         ` Ken Manheimer
@ 2005-10-02 20:31         ` Richard M. Stallman
  2005-10-03 19:25           ` pgg symmetric encryption patch (was: new version of allout.el - patch and ChangeLog) Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Richard M. Stallman @ 2005-10-02 20:31 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, emacs-devel

    So you would consider switching to pgg, if it would provide an
    interface to symmetric encryption?

If someone wants to do it, and assuming the result is clean, it would 
be a good thing to do.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* pgg symmetric encryption patch (was: new version of allout.el - patch and ChangeLog)
  2005-10-02 20:31         ` Richard M. Stallman
@ 2005-10-03 19:25           ` Sascha Wilde
  2005-10-03 19:50             ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-03 19:25 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, ueno, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 4341 bytes --]

On Sun, Oct 02, 2005 at 04:31:10PM -0400, Richard M. Stallman wrote:
>     So you would consider switching to pgg, if it would provide an
>     interface to symmetric encryption?
> 
> If someone wants to do it, and assuming the result is clean, it would 
> be a good thing to do.

Enclosed you'll find my preliminary patch to make symmetric encryption
possible with pgg.

The new function pgg-encrypt-symmetric-region asks for a passphrase
and uses it to symmetrically encrypt the given region.

Please note, this is by no means complete, just a small proof of concept.

Ken, would something along this lines be sufficient for use with allout?

cheers
sascha

cvs server: Diffing .
Index: pgg-gpg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg-gpg.el,v
retrieving revision 1.6
diff -u -r1.6 pgg-gpg.el
--- pgg-gpg.el	6 Aug 2005 19:51:42 -0000	1.6
+++ pgg-gpg.el	3 Oct 2005 19:13:34 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -141,24 +142,32 @@
 
 (defun pgg-gpg-encrypt-region (start end recipients &optional sign)
   "Encrypt the current region between START and END.
+If recipients is :symmetric do symmetric encryption
 If optional argument SIGN is non-nil, do a combined sign and encrypt."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
+	 (symmetric-encryption (eq recipients :symmetric))
 	 (passphrase
-	  (when sign
-	    (pgg-read-passphrase
-	     (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	     pgg-gpg-user-id)))
+	  (if symmetric-encryption
+	      (pgg-read-passphrase
+	       "GnuPG passphrase for symmetric encryption: ")
+	    (when sign
+	      (pgg-read-passphrase
+	       (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
+	       pgg-gpg-user-id))))
 	 (args
 	  (append
-	   (list "--batch" "--armor" "--always-trust" "--encrypt")
+	   (list "--batch" "--armor" "--always-trust" 
+		 (if symmetric-encryption "--symmetric" "--encrypt"))
 	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
-	   (if recipients
-	       (apply #'nconc
-		      (mapcar (lambda (rcpt)
-				(list pgg-gpg-recipient-argument rcpt))
-			      (append recipients
-				      (if pgg-encrypt-for-me
-					  (list pgg-gpg-user-id)))))))))
+	   (if symmetric-encryption
+	       nil
+	       (if recipients
+		   (apply #'nconc
+			  (mapcar (lambda (rcpt)
+				    (list pgg-gpg-recipient-argument rcpt))
+				  (append recipients
+					  (if pgg-encrypt-for-me
+					      (list pgg-gpg-user-id))))))))))
     (pgg-as-lbt start end 'CRLF
       (pgg-gpg-process-region start end passphrase pgg-gpg-program args))
     (when sign
Index: pgg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg.el,v
retrieving revision 1.8
diff -u -r1.8 pgg.el
--- pgg.el	26 Aug 2005 00:02:05 -0000	1.8
+++ pgg.el	3 Oct 2005 19:13:34 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP
 
@@ -232,6 +233,18 @@
 	 (pgg-save-coding-system start end
 	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
 		       (point-min) (point-max) rcpts sign))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric-region (start end)
+  "Encrypt the current region between START and END symmetric with passphrase."
+  (interactive "r")
+  (let ((status
+	 (pgg-save-coding-system start end
+	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
+		       (point-min) (point-max) :symmetric))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))


-- 
Sascha Wilde : The most exciting phrase to hear in science, the one
             : that heralds new discoveries, is not "Eureka!" (I found
             : it!) but "That's funny ..." -- Isaac Asimov

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch (was: new version of allout.el - patch and ChangeLog)
  2005-10-03 19:25           ` pgg symmetric encryption patch (was: new version of allout.el - patch and ChangeLog) Sascha Wilde
@ 2005-10-03 19:50             ` Ken Manheimer
  2005-10-04 10:53               ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-03 19:50 UTC (permalink / raw)


On 10/3/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> On Sun, Oct 02, 2005 at 04:31:10PM -0400, Richard M. Stallman wrote:
> >     So you would consider switching to pgg, if it would provide an
> >     interface to symmetric encryption?
> >
> > If someone wants to do it, and assuming the result is clean, it would
> > be a good thing to do.
>
> Enclosed you'll find my preliminary patch to make symmetric encryption
> possible with pgg.
>
> The new function pgg-encrypt-symmetric-region asks for a passphrase
> and uses it to symmetrically encrypt the given region.
>
> Please note, this is by no means complete, just a small proof of concept.
>
> Ken, would something along this lines be sufficient for use with allout?
> [...]
> Sascha Wilde : The most exciting phrase to hear in science, the one
>              : that heralds new discoveries, is not "Eureka!" (I found
>              : it!) but "That's funny ..." -- Isaac Asimov

sounds like it, yes!  i can't try it right now, but whether or not it
works as is, if you're willing to continue ironing it out with me to
get it working properly, i'll it to work with allout.  (i hope to have
some time this evening or else tomorrow afternoon to devote attention
to it.)

!

(as you may realize, i like the quote!-)

ken
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch (was: new version of allout.el - patch and ChangeLog)
  2005-10-03 19:50             ` Ken Manheimer
@ 2005-10-04 10:53               ` Sascha Wilde
  2005-10-04 12:46                 ` pgg symmetric encryption patch Stefan Monnier
  2005-10-05 16:19                 ` Sascha Wilde
  0 siblings, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2005-10-04 10:53 UTC (permalink / raw)
  Cc: schwab, ueno, Richard M. Stallman, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 1287 bytes --]

On Mon, Oct 03, 2005 at 03:50:25PM -0400, Ken Manheimer wrote:
> On 10/3/05, Sascha Wilde <wilde@sha-bang.de> wrote:

> > Enclosed you'll find my preliminary patch to make symmetric encryption
> > possible with pgg.
[...]
> > Ken, would something along this lines be sufficient for use with allout?
> 
> sounds like it, yes!  i can't try it right now, but whether or not it
> works as is, if you're willing to continue ironing it out with me to
> get it working properly, i'll it to work with allout.

I'll try to find the time to make this a proper feature of pgg.  (I
also added the original author to the cc, so he might add his
thoughts)

Ken, please let me know if it works for you, and what features you are
missing.

One problem, though: pgg supports, besides gnupg, pgp and pgp5 -- I
don't have any version of pgp on my box, and I'm not willing to buy a
proprietary product to write these patches.  So, to make the symmetric
encryption feature work with these backends, I would need help by
people, who can tell me about the needed switches for pgp and test the
patches with different versions of pgp...

cheers
sascha
-- 
Sascha Wilde : "There are 10 types of people in the world. 
             : Those who understand binary and those who don't."

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-04 10:53               ` Sascha Wilde
@ 2005-10-04 12:46                 ` Stefan Monnier
  2005-10-05 16:19                 ` Sascha Wilde
  1 sibling, 0 replies; 156+ messages in thread
From: Stefan Monnier @ 2005-10-04 12:46 UTC (permalink / raw)
  Cc: schwab, ueno, Richard M. Stallman, emacs-devel

> One problem, though: pgg supports, besides gnupg, pgp and pgp5 -- I
> don't have any version of pgp on my box, and I'm not willing to buy a
> proprietary product to write these patches.  So, to make the symmetric
> encryption feature work with these backends, I would need help by
> people, who can tell me about the needed switches for pgp and test the
> patches with different versions of pgp...

I wouldn't worry about that: for non-gpg users it currently doesn't work
either, so it's not like you're making life worse for them.  If they want
symmetric crypto to work for their product, they'll have to provide the
patches themselves.


        Stefan

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-04 10:53               ` Sascha Wilde
  2005-10-04 12:46                 ` pgg symmetric encryption patch Stefan Monnier
@ 2005-10-05 16:19                 ` Sascha Wilde
  2005-10-05 19:16                   ` Ken Manheimer
  2005-10-06  2:18                   ` Daiki Ueno
  1 sibling, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2005-10-05 16:19 UTC (permalink / raw)



[-- Attachment #1.1.1: Type: text/plain, Size: 568 bytes --]

On Tue, Oct 04, 2005 at 12:53:30PM +0200, Sascha Wilde wrote:

> I'll try to find the time to make this a proper feature of pgg.  (I
> also added the original author to the cc, so he might add his
> thoughts)

I attached a more complete patch, including documentation and
changelog entries.

Any comments, bug-fixes, flames are highly appreciated.

cheers
sascha

ps. I have no write access to CVS, so if there are no objections,
please commit.
-- 
Sascha Wilde
    "Liebet eure Feinde, vielleicht schadet das ihrem Ruf" 
    (Stanislaw Jerzy Lec)

[-- Attachment #1.1.2: emacs-pgg-symmetric.patch-02 --]
[-- Type: text/plain, Size: 9344 bytes --]

Index: man/pgg.texi
===================================================================
RCS file: /cvsroot/emacs/emacs/man/pgg.texi,v
retrieving revision 1.5
diff -u -r1.5 pgg.texi
--- man/pgg.texi	16 Sep 2005 22:11:00 -0000	1.5
+++ man/pgg.texi	5 Oct 2005 16:09:13 -0000
@@ -98,6 +98,8 @@
 @lisp
 (autoload 'pgg-encrypt-region "pgg"
   "Encrypt the current region." t)
+(autoload 'pgg-encrypt-symmetric-region "pgg"
+  "Encrypt the current region with symmetric algorithm." t)
 (autoload 'pgg-decrypt-region "pgg"
   "Decrypt the current region." t)
 (autoload 'pgg-sign-region "pgg"
@@ -140,6 +142,13 @@
 with GnuPG.
 @end deffn
 
+@deffn Command pgg-encrypt-symmetric-region start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher.  After invocation you are asked for a passphrase.
+
+This is currently only implemented for GnuPG.
+@end deffn
+
 @deffn Command pgg-decrypt-region start end
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it replaces the current region contents (in
@@ -305,6 +314,10 @@
 @var{recipients}.  If @var{sign} is non-@code{nil}, do a combined sign
 and encrypt.  If encryption is successful, it returns @code{t},
 otherwise @code{nil}.
+
+If @var{recipients} equals @code{:symmetric} a symmetric cipher together
+with a passphrase is used and @var{sign} is ignored.  This feature is
+currently only implemented for GnuPG.
 @end deffn
 
 @deffn Method pgg-scheme-decrypt-region scheme start end
Index: man/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/man/ChangeLog,v
retrieving revision 1.681
diff -u -r1.681 ChangeLog
--- man/ChangeLog	4 Oct 2005 22:52:16 -0000	1.681
+++ man/ChangeLog	5 Oct 2005 16:09:16 -0000
@@ -1,3 +1,11 @@
+2005-10-05  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg.texi (How to use): Added autoload line for
+	`pgg-encrypt-symmetric-region'.
+	(User Commands): Description of `pgg-encrypt-symmetric-region'.
+	(Backend methods): Describe new symmetric encryption feature in
+	`pgg-scheme-encrypt-region'.
+
 2005-10-05  Nick Roberts  <nickrob@snap.net.nz>
 
 	* speedbar.texi (GDB): Describe use of watch expressions.
Index: lisp/gnus/pgg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg.el,v
retrieving revision 1.8
diff -u -r1.8 pgg.el
--- lisp/gnus/pgg.el	26 Aug 2005 00:02:05 -0000	1.8
+++ lisp/gnus/pgg.el	5 Oct 2005 16:09:17 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP
 
@@ -232,6 +233,34 @@
 	 (pgg-save-coding-system start end
 	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
 		       (point-min) (point-max) rcpts sign))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric-region (start end)
+  "Encrypt the current region between START and END symmetric with passphrase."
+  (interactive "r")
+  (when (not (member (or pgg-scheme pgg-default-scheme)
+		     pgg-symmetric-encryption-schemes))
+    (error "Symmetric encryption is not implemented for selected scheme."))
+  (let ((status
+	 (pgg-save-coding-system start end
+	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
+		       (point-min) (point-max) :symmetric))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric (&optional start end)
+  "Encrypt the current buffer symmetric with passphrase.
+If optional arguments START and END are specified, only encrypt within
+the region."
+  (interactive)
+  (let* ((start (or start (point-min)))
+	 (end (or end (point-max)))
+	 (status (pgg-encrypt-symmetric-region start end)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
Index: lisp/gnus/pgg-gpg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg-gpg.el,v
retrieving revision 1.6
diff -u -r1.6 pgg-gpg.el
--- lisp/gnus/pgg-gpg.el	6 Aug 2005 19:51:42 -0000	1.6
+++ lisp/gnus/pgg-gpg.el	5 Oct 2005 16:09:17 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -141,24 +142,32 @@
 
 (defun pgg-gpg-encrypt-region (start end recipients &optional sign)
   "Encrypt the current region between START and END.
+If recipients is :symmetric do symmetric encryption
 If optional argument SIGN is non-nil, do a combined sign and encrypt."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
+	 (symmetric-encryption (eq recipients :symmetric))
 	 (passphrase
-	  (when sign
-	    (pgg-read-passphrase
-	     (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	     pgg-gpg-user-id)))
+	  (if symmetric-encryption
+	      (pgg-read-passphrase
+	       "GnuPG passphrase for symmetric encryption: ")
+	    (when sign
+	      (pgg-read-passphrase
+	       (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
+	       pgg-gpg-user-id))))
 	 (args
 	  (append
-	   (list "--batch" "--armor" "--always-trust" "--encrypt")
+	   (list "--batch" "--armor" "--always-trust" 
+		 (if symmetric-encryption "--symmetric" "--encrypt"))
 	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
-	   (if recipients
-	       (apply #'nconc
-		      (mapcar (lambda (rcpt)
-				(list pgg-gpg-recipient-argument rcpt))
-			      (append recipients
-				      (if pgg-encrypt-for-me
-					  (list pgg-gpg-user-id)))))))))
+	   (if symmetric-encryption
+	       nil
+	       (if recipients
+		   (apply #'nconc
+			  (mapcar (lambda (rcpt)
+				    (list pgg-gpg-recipient-argument rcpt))
+				  (append recipients
+					  (if pgg-encrypt-for-me
+					      (list pgg-gpg-user-id))))))))))
     (pgg-as-lbt start end 'CRLF
       (pgg-gpg-process-region start end passphrase pgg-gpg-program args))
     (when sign
@@ -180,7 +189,10 @@
 	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase
 	  (pgg-read-passphrase
-	   (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
+	   (format (if (pgg-gpg-symmetric-key-p message-keys)
+		       "Passphrase for symmetric dencryption: "
+		       "GnuPG passphrase for %s: ")
+		   pgg-gpg-user-id)
 	   pgg-gpg-user-id))
 	 (args '("--batch" "--decrypt")))
     (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
@@ -188,6 +200,13 @@
       (pgg-gpg-possibly-cache-passphrase passphrase pgg-gpg-user-id)
       (goto-char (point-min))
       (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
+
+(defun pgg-gpg-symmetric-key-p (message-keys)
+  "Check if MESSAGE-KEYS contains a symmetric encryption indicator."
+  (dolist (key message-keys result)
+    (when (and (eq (car key) 3)
+	       (member '(symmetric-key-algorithm) key))
+      (setq result key))))
 
 (defun pgg-gpg-select-matching-key (message-keys secret-keys)
   "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."
Index: lisp/gnus/pgg-def.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg-def.el,v
retrieving revision 1.7
diff -u -r1.7 pgg-def.el
--- lisp/gnus/pgg-def.el	6 Aug 2005 19:51:42 -0000	1.7
+++ lisp/gnus/pgg-def.el	5 Oct 2005 16:09:17 -0000
@@ -3,6 +3,7 @@
 ;; Copyright (C) 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/11/02
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -83,6 +84,9 @@
 
 (defvar pgg-scheme nil
   "Current scheme of PGP implementation.")
+
+(defconst pgg-symmetric-encryption-schemes '(gpg)
+  "Schemes of PGP implementation for which symmetric encrypt is implemented.")
 
 (defmacro pgg-truncate-key-identifier (key)
   `(if (> (length ,key) 8) (substring ,key 8) ,key))
Index: lisp/gnus/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/ChangeLog,v
retrieving revision 1.388
diff -u -r1.388 ChangeLog
--- lisp/gnus/ChangeLog	4 Oct 2005 22:51:06 -0000	1.388
+++ lisp/gnus/ChangeLog	5 Oct 2005 16:09:19 -0000
@@ -1,3 +1,15 @@
+2005-10-05  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg-def.el (pgg-symmetric-encryption-schemes): List of schemes
+	with symmetric encryption support.
+
+	* pgg-gpg.el (pgg-gpg-encrypt-region): Added symmetric encryption.
+	(pgg-gpg-symmetric-key-p): New function to check for an symmetric
+	encrypted session key.
+
+	* pgg.el (pgg-encrypt-symmetric,pgg-encrypt-symmetric-region):
+	New user commands for symmetric encryption.
+
 2005-10-04  Reiner Steib  <Reiner.Steib@gmx.de>
 
 	* mm-url.el (mm-url-predefined-programs): Add switches for curl.

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-05 16:19                 ` Sascha Wilde
@ 2005-10-05 19:16                   ` Ken Manheimer
  2005-10-10  4:15                     ` Richard M. Stallman
  2005-10-06  2:18                   ` Daiki Ueno
  1 sibling, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-05 19:16 UTC (permalink / raw)


On 10/5/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> On Tue, Oct 04, 2005 at 12:53:30PM +0200, Sascha Wilde wrote:
>
> > I'll try to find the time to make this a proper feature of pgg.  (I
> > also added the original author to the cc, so he might add his
> > thoughts)
>
> I attached a more complete patch, including documentation and
> changelog entries.
>
> Any comments, bug-fixes, flames are highly appreciated.

i have some questions regarding my switching allout over to use pgg. 
i've been looking over the impact, and it's complicated by the
intricate way i use mailcrypt's key caching mechanism.  i would have
to change pgg's key caching stuff to enable me, for instance, to query
for the presence of a key, and also change the encryption/decryption
function signatures to take explictly passed-in keys.  it will not be
trivial, and i don't want to launch into the work if there's no chance
the pgg changes will be accepted.

i know there's no way in advance to know whether my changes will or
won't be acceptible, but i would like to know whether there will be
attention available to evaluate them and the possibility that they'll
be accepted?  my time frame is also a little  daunting - i think i
have at least a few days of work, and am going to be away for a week
in the middle of next week, so may not have anything finished until a
few weeks from now.  any thoughts?

ken manheimer
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-05 16:19                 ` Sascha Wilde
  2005-10-05 19:16                   ` Ken Manheimer
@ 2005-10-06  2:18                   ` Daiki Ueno
  2005-10-06  9:01                     ` Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2005-10-06  2:18 UTC (permalink / raw)
  Cc: schwab, Simon Josefsson, Richard M. Stallman, emacs-devel

Hello Sascha,

>>>>> In <20051005161905.GA6208@kenny.sha-bang.local> 
>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> I attached a more complete patch, including documentation and
> changelog entries.

> Any comments, bug-fixes, flames are highly appreciated.

> +;;;###autoload
> +(defun pgg-encrypt-symmetric-region (start end)
> +  "Encrypt the current region between START and END symmetric with passphrase."
> +  (interactive "r")
> +  (when (not (member (or pgg-scheme pgg-default-scheme)
> +		     pgg-symmetric-encryption-schemes))
> +    (error "Symmetric encryption is not implemented for selected scheme."))

It might be better to split pgg-gpg-encrypt-symmetric-region from
pgg-gpg-encrypt-region rather than maintaining
pgg-symmetric-encryption-schemes.

When pgg-invoke calls "encrypt-symmetric-region" on pgp or pgp5
backend, a void-function error is signaled.  Therefore, the user will
see that "encrypt-symmetric-region" is not implemented.

And also, is it still necessary to give special meaning to the 1st
argument (recipients) of pgg-encrypt-region?

> ps. I have no write access to CVS, so if there are no objections,
> please commit.

Currently, PGG in Emacs CVS is a part of Gnus.  So I added
Simon Josefsson to the Cc: list.  He is one of Gnus maintainers and he
has taken care of PGG in Gnus CVS.

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-06  2:18                   ` Daiki Ueno
@ 2005-10-06  9:01                     ` Sascha Wilde
  2005-10-06 22:41                       ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-06  9:01 UTC (permalink / raw)
  Cc: schwab, Ken Manheimer, emacs-devel, Richard M. Stallman,
	Simon Josefsson


[-- Attachment #1.1.1: Type: text/plain, Size: 1077 bytes --]

On Thu, Oct 06, 2005 at 11:18:48AM +0900, Daiki Ueno wrote:

> It might be better to split pgg-gpg-encrypt-symmetric-region from
> pgg-gpg-encrypt-region rather than maintaining
> pgg-symmetric-encryption-schemes.

Yes, I think you are right, after in all this would be a cleaner
approach.  (I had reasons for my original design, but reconsidering
them, they didn't hold...)

> And also, is it still necessary to give special meaning to the 1st
> argument (recipients) of pgg-encrypt-region?

I guess you mean pgg-gpg-encrypt-region?  No, after moving symmetric
encryption in a dedicated function the special meaning of recipients
is no longer needed.

> > ps. I have no write access to CVS, so if there are no objections,
> > please commit.
> 
> Currently, PGG in Emacs CVS is a part of Gnus.  So I added
> Simon Josefsson to the Cc: list.  He is one of Gnus maintainers and he
> has taken care of PGG in Gnus CVS.

Thanks.

Attached you'll find a revised version of the patch.

cheers
-- 
Sascha Wilde
To become a Jedi, use Emacs you have to.

[-- Attachment #1.1.2: emacs-pgg-symmetric.patch-03 --]
[-- Type: text/plain, Size: 7422 bytes --]

Index: man/pgg.texi
===================================================================
RCS file: /cvsroot/emacs/emacs/man/pgg.texi,v
retrieving revision 1.5
diff -u -r1.5 pgg.texi
--- man/pgg.texi	16 Sep 2005 22:11:00 -0000	1.5
+++ man/pgg.texi	6 Oct 2005 09:00:13 -0000
@@ -98,6 +98,8 @@
 @lisp
 (autoload 'pgg-encrypt-region "pgg"
   "Encrypt the current region." t)
+(autoload 'pgg-encrypt-symmetric-region "pgg"
+  "Encrypt the current region with symmetric algorithm." t)
 (autoload 'pgg-decrypt-region "pgg"
   "Decrypt the current region." t)
 (autoload 'pgg-sign-region "pgg"
@@ -140,6 +142,13 @@
 with GnuPG.
 @end deffn
 
+@deffn Command pgg-encrypt-symmetric-region start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher.  After invocation you are asked for a passphrase.
+
+This is currently only implemented for GnuPG.
+@end deffn
+
 @deffn Command pgg-decrypt-region start end
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it replaces the current region contents (in
@@ -305,6 +314,13 @@
 @var{recipients}.  If @var{sign} is non-@code{nil}, do a combined sign
 and encrypt.  If encryption is successful, it returns @code{t},
 otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-encrypt-symmetric-region scheme start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher and a passphrases.  If encryption is successful, it
+returns @code{t}, otherwise @code{nil}.  This function is currently only
+implemented for GnuPG.
 @end deffn
 
 @deffn Method pgg-scheme-decrypt-region scheme start end
Index: man/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/man/ChangeLog,v
retrieving revision 1.681
diff -u -r1.681 ChangeLog
--- man/ChangeLog	4 Oct 2005 22:52:16 -0000	1.681
+++ man/ChangeLog	6 Oct 2005 09:00:16 -0000
@@ -1,3 +1,11 @@
+2005-10-06  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg.texi (How to use): Added autoload line for
+	`pgg-encrypt-symmetric-region'.
+	(User Commands): Description of `pgg-encrypt-symmetric-region'.
+	(Backend methods): Describe new funktion
+	`pgg-scheme-encrypt-symmetric-region'.
+
 2005-10-05  Nick Roberts  <nickrob@snap.net.nz>
 
 	* speedbar.texi (GDB): Describe use of watch expressions.
Index: lisp/gnus/pgg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg.el,v
retrieving revision 1.8
diff -u -r1.8 pgg.el
--- lisp/gnus/pgg.el	26 Aug 2005 00:02:05 -0000	1.8
+++ lisp/gnus/pgg.el	6 Oct 2005 09:00:17 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP
 
@@ -232,6 +233,32 @@
 	 (pgg-save-coding-system start end
 	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
 		       (point-min) (point-max) rcpts sign))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric-region (start end)
+  "Encrypt the current region between START and END symmetric with passphrase."
+  (interactive "r")
+  (let ((status
+	 (pgg-save-coding-system start end
+	   (pgg-invoke "encrypt-symmetric-region" 
+		       (or pgg-scheme pgg-default-scheme)
+		       (point-min) (point-max)))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric (&optional start end)
+  "Encrypt the current buffer symmetric with passphrase.
+If optional arguments START and END are specified, only encrypt within
+the region."
+  (interactive)
+  (let* ((start (or start (point-min)))
+	 (end (or end (point-max)))
+	 (status (pgg-encrypt-symmetric-region start end)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
Index: lisp/gnus/pgg-gpg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg-gpg.el,v
retrieving revision 1.6
diff -u -r1.6 pgg-gpg.el
--- lisp/gnus/pgg-gpg.el	6 Aug 2005 19:51:42 -0000	1.6
+++ lisp/gnus/pgg-gpg.el	6 Oct 2005 09:00:17 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -169,6 +170,16 @@
 	(pgg-gpg-possibly-cache-passphrase passphrase)))
     (pgg-process-when-success)))
 
+(defun pgg-gpg-encrypt-symmetric-region (start end)
+  "Encrypt the current region between START and END with symmetric cipher."
+  (let* ((passphrase
+	  (pgg-read-passphrase "GnuPG passphrase for symmetric encryption: "))
+	 (args
+	  (append (list "--batch" "--armor" "--symmetric" ))))
+    (pgg-as-lbt start end 'CRLF
+      (pgg-gpg-process-region start end passphrase pgg-gpg-program args))    
+    (pgg-process-when-success)))
+
 (defun pgg-gpg-decrypt-region (start end)
   "Decrypt the current region between START and END."
   (let* ((current-buffer (current-buffer))
@@ -180,7 +191,10 @@
 	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase
 	  (pgg-read-passphrase
-	   (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
+	   (format (if (pgg-gpg-symmetric-key-p message-keys)
+		       "Passphrase for symmetric dencryption: "
+		       "GnuPG passphrase for %s: ")
+		   pgg-gpg-user-id)
 	   pgg-gpg-user-id))
 	 (args '("--batch" "--decrypt")))
     (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
@@ -188,6 +202,13 @@
       (pgg-gpg-possibly-cache-passphrase passphrase pgg-gpg-user-id)
       (goto-char (point-min))
       (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
+
+(defun pgg-gpg-symmetric-key-p (message-keys)
+  "Check if MESSAGE-KEYS contains a symmetric encryption indicator."
+  (dolist (key message-keys result)
+    (when (and (eq (car key) 3)
+	       (member '(symmetric-key-algorithm) key))
+      (setq result key))))
 
 (defun pgg-gpg-select-matching-key (message-keys secret-keys)
   "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."
Index: lisp/gnus/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/ChangeLog,v
retrieving revision 1.388
diff -u -r1.388 ChangeLog
--- lisp/gnus/ChangeLog	4 Oct 2005 22:51:06 -0000	1.388
+++ lisp/gnus/ChangeLog	6 Oct 2005 09:00:20 -0000
@@ -1,3 +1,15 @@
+2005-10-06  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg-gpg.el (pgg-gpg-encrypt-symmetric-region): New function for
+	symmetric encryption.
+	(pgg-gpg-symmetric-key-p): New function to check for an symmetric
+	encrypted session key.
+	(pgg-gpg-decrypt-region): When decrypting a symmetric encrypted
+	message ask for the passphrase in a proper way.
+
+	* pgg.el (pgg-encrypt-symmetric,pgg-encrypt-symmetric-region):
+	New user commands for symmetric encryption.
+
 2005-10-04  Reiner Steib  <Reiner.Steib@gmx.de>
 
 	* mm-url.el (mm-url-predefined-programs): Add switches for curl.

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-06  9:01                     ` Sascha Wilde
@ 2005-10-06 22:41                       ` Ken Manheimer
  2005-10-07 10:00                         ` Sascha Wilde
  2005-12-09 15:43                         ` pgg symmetric encryption patch Simon Josefsson
  0 siblings, 2 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-06 22:41 UTC (permalink / raw)


i'm attempting to incorporate sascha's modified pgg in allout, instead
of using a combination of mailcrypt and crypt++, and encountering some
serious problems.  the problems include some fundamental problems with
pgg operation, independent of the patch, that are show-stoppers for
me.  i'd like to run my assessment of these things by you all and see
if you can help me understand them.  it's possible i'm mistaken about
some, i don't understand what appear to be the choices made.

all of my experiments involve the current pgg code found in the
gnu.org lisp/gnus CVS.  some of them (i'll try to be clear about
which) involve this pgg code with sascha's most recent symmetric-key
extensions patch (emacs-pgg-symmetric.patch-03) applied (by hand -
couldn't get it to work using 'patch').

1. my most serious concern is with the unpatched pgg code.  the text that
   it encrypts is altered from the original, in order to append \r carriage
   returns to the text (using pgg-as-lbt / pgg-convert-lbt).

   the problem with this is that decryption on unix-ish platforms with
   anything other than pgg will result in text that is different than the
   original.  for example, text that is encrypted with pgg-gpg and then
   decrypted directly using the gpg program (using the command-line, for
   instance) will be distorted in this way.  likewise if decrypted using
   mailcrypt in emacs, or pgp5 or pgp in any way, etc.

   this is not acceptable for my purposes (and i can't figure out where it
   would be acceptable, but i'm not familiar with the encryption concerns
   for message exchange, eg for email or news).

2. i also have some fundamental problems with the way unaltered pgg's
   passphrase caching system is wired.  i am not sure about my analysis,
   and would love to be corrected, and filled in about how it actually does
   work.  (the passphrase cache routines could really use some informative
   docstrings.)

   as far as i can tell, on decryption it keys on the value of
   pgg-default-user-id, rather than the actual recipients of the message.
   this is generally useless for any messages but those encrypted with the
   user's public-key.  and it depends on the user having set
   pgg-default-user-id, which seems like an unnecessary and complicating
   limitation.

3. this key caching problem of #2 is compounded in the context of sascha's
   patches, because i really can't figure what the right thing is.  plus,
   it's not hooked up quite right in the patches:

  - the patched version will use the prompt for the symmetric key even when
    doing a public-key decryption.

  - pgg-gpp-encrypt-symmetric-region does not do do any key caching.  this
    is the right thing modulo the pgg-default-user-id misorientation of the
    caching mechanism - but is unacceptable for my purposes, where users
    can particularly need the convenience of key caching for symmetric-key
    operation, in order to encrypt and decrypt multiple entries.

4. in the patched version, the symmetric encryption does not replace the
   original text with the encrypted text - it's only available in the
   hidden " *PGG output*" buffer, but not put in place.

5. last, another small problem with the unaltered pgg code.

   i stumbled and was confused when pgg failed to do a public-key
   encryption due to the default value of pgg-default-user-id.  only on
   reading the code did i learn i needed to set pgg-default-user-id to the
   identity of my primary key.  it may be that i should use my user login
   for that key's identity, so the default would work, i dunno.

it took me a while to unravel these problems, and i stopped at that
point - i don't think i can use pgg, as it stands, according to this
assessment.  i don't understand the reasons for the choices - maybe
just because i'm unfamiliar with the regular context where it's used. 
i may be mistaken about my assessment in some of these items, and
would welcome correction and/or clarification!

ken manheimer
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-06 22:41                       ` Ken Manheimer
@ 2005-10-07 10:00                         ` Sascha Wilde
  2005-10-07 18:06                           ` Ken Manheimer
  2005-12-09 15:43                         ` pgg symmetric encryption patch Simon Josefsson
  1 sibling, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-07 10:00 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), emacs-devel, Richard M. Stallman,
	Simon Josefsson (gnus maintainer of pgg)


[-- Attachment #1.1.1: Type: text/plain, Size: 2242 bytes --]

On Thu, Oct 06, 2005 at 06:41:14PM -0400, Ken Manheimer wrote:

> which) involve this pgg code with sascha's most recent symmetric-key
> extensions patch (emacs-pgg-symmetric.patch-03) applied (by hand -
> couldn't get it to work using 'patch').

hmm, strange, I just applied the patch to a fresh GNU emacs cvs
checkout w/o any problems -- only one changelog hunk failed, no
wonder, the changelogs are constantly changing...  ;-)
 
> 1. my most serious concern is with the unpatched pgg code.  the text that
>    it encrypts is altered from the original, in order to append \r carriage
>    returns to the text (using pgg-as-lbt / pgg-convert-lbt).
> 
>    the problem with this is that decryption on unix-ish platforms with
>    anything other than pgg will result in text that is different than the
>    original.

This is supposed to be a feature, not a bug. 
But read on, there actually _is_ a bug in PGG...

Please note RfC 2440  5.9.:

The last sentence gives a short summary on the subject

   Text data is stored with <CR><LF> text endings (i.e. network-normal
   line endings).  These should be converted to native line endings by
   the receiving software.

As PGG tries to implement RfC conform OpenPGP, and it handles is text,
not binary data, this always applies.

Please read also on the `--textmode' option of gpg.

THE BUG: pgg does the newline conversion by it self (I'm not quite
sure why) but fails to tell the backend (gpg) that it should operate
in textmode, so the Data Packet is tagged as binary, not text data...

Please try if the appended patch (only against pgg-gpg.el) fixes this
issue.

[passphrase caching]

As I'm short of time, I'll look into this issues later, sorry...

> 4. in the patched version, the symmetric encryption does not replace the
>    original text with the encrypted text - it's only available in the
>    hidden " *PGG output*" buffer, but not put in place.

I think, you want to use `pgg-encrypt-symmetric-region', which
encapsulates the backend function `pgg-gpg-encrypt-symmetric-region'
and puts the encrypted text in place.

cheers
sascha
-- 
Sascha Wilde

A conclusion is simply the place where someone got tired of thinking.

[-- Attachment #1.1.2: pgg-gpg_textmode.patch --]
[-- Type: text/plain, Size: 3075 bytes --]

*** pgg-gpg.el	09 Aug 2005 12:53:45 +0200	1.6
--- pgg-gpg.el	07 Okt 2005 11:47:44 +0200	
***************
*** 4,9 ****
--- 4,10 ----
  ;;   2005 Free Software Foundation, Inc.
  
  ;; Author: Daiki Ueno <ueno@unixuser.org>
+ ;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
  ;; Created: 1999/10/28
  ;; Keywords: PGP, OpenPGP, GnuPG
  
***************
*** 150,156 ****
  	     pgg-gpg-user-id)))
  	 (args
  	  (append
! 	   (list "--batch" "--armor" "--always-trust" "--encrypt")
  	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
  	   (if recipients
  	       (apply #'nconc
--- 151,157 ----
  	     pgg-gpg-user-id)))
  	 (args
  	  (append
! 	   (list "--batch" "--textmode" "--armor" "--always-trust" "--encrypt")
  	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
  	   (if recipients
  	       (apply #'nconc
***************
*** 169,174 ****
--- 170,185 ----
  	(pgg-gpg-possibly-cache-passphrase passphrase)))
      (pgg-process-when-success)))
  
+ (defun pgg-gpg-encrypt-symmetric-region (start end)
+   "Encrypt the current region between START and END with symmetric cipher."
+   (let* ((passphrase
+ 	  (pgg-read-passphrase "GnuPG passphrase for symmetric encryption: "))
+ 	 (args
+ 	  (append (list "--batch" "--textmode" "--armor" "--symmetric" ))))
+     (pgg-as-lbt start end 'CRLF
+       (pgg-gpg-process-region start end passphrase pgg-gpg-program args))    
+     (pgg-process-when-success)))
+ 
  (defun pgg-gpg-decrypt-region (start end)
    "Decrypt the current region between START and END."
    (let* ((current-buffer (current-buffer))
***************
*** 180,186 ****
  	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
  	 (passphrase
  	  (pgg-read-passphrase
! 	   (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
  	   pgg-gpg-user-id))
  	 (args '("--batch" "--decrypt")))
      (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
--- 191,200 ----
  	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
  	 (passphrase
  	  (pgg-read-passphrase
! 	   (format (if (pgg-gpg-symmetric-key-p message-keys)
! 		       "Passphrase for symmetric dencryption: "
! 		       "GnuPG passphrase for %s: ")
! 		   pgg-gpg-user-id)
  	   pgg-gpg-user-id))
  	 (args '("--batch" "--decrypt")))
      (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
***************
*** 189,194 ****
--- 203,215 ----
        (goto-char (point-min))
        (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
  
+ (defun pgg-gpg-symmetric-key-p (message-keys)
+   "Check if MESSAGE-KEYS contains a symmetric encryption indicator."
+   (dolist (key message-keys result)
+     (when (and (eq (car key) 3)
+ 	       (member '(symmetric-key-algorithm) key))
+       (setq result key))))
+ 
  (defun pgg-gpg-select-matching-key (message-keys secret-keys)
    "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."
    (loop for message-key in message-keys

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-07 10:00                         ` Sascha Wilde
@ 2005-10-07 18:06                           ` Ken Manheimer
  2005-10-07 21:49                             ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-07 18:06 UTC (permalink / raw)


On 10/7/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> On Thu, Oct 06, 2005 at 06:41:14PM -0400, Ken Manheimer wrote:
>
> > which) involve this pgg code with sascha's most recent symmetric-key
> > extensions patch (emacs-pgg-symmetric.patch-03) applied (by hand -
> > couldn't get it to work using 'patch').
>
> hmm, strange, I just applied the patch to a fresh GNU emacs cvs
> checkout w/o any problems -- only one changelog hunk failed, no
> wonder, the changelogs are constantly changing...  ;-)

ironically, this was a due to the patch file having DOS-style line
endings.  i didn't notice the "(DOS)" indicator on the emacs mode line
- but did notice it when i just looked at the .rej files.  i visited
the file "literally" ('find-file-literally') and stripped the ^Ms, and
the patch worked.

(to complicate matters a little, 'patch' compensated for the ^M line
endings in the new patch you sent (pgg-gpg_textmode.patch).  i don't know why
that compensation didn't happen with the other patch - maybe something to
do with this one being for a single file and the other being multi?
aargh.)

> > 1. my most serious concern is with the unpatched pgg code.  the text that
> >    it encrypts is altered from the original, in order to append \r carriage
> >    returns to the text (using pgg-as-lbt / pgg-convert-lbt).
> >
> >    the problem with this is that decryption on unix-ish platforms with
> >    anything other than pgg will result in text that is different than the
> >    original.
>
> This is supposed to be a feature, not a bug.
> But read on, there actually _is_ a bug in PGG...
>
> Please note RfC 2440  5.9.:
>
> The last sentence gives a short summary on the subject
>
>    Text data is stored with <CR><LF> text endings (i.e. network-normal
>    line endings).  These should be converted to native line endings by
>    the receiving software.
>
> As PGG tries to implement RfC conform OpenPGP, and it handles is text,
> not binary data, this always applies.
>
> Please read also on the `--textmode' option of gpg.
>
> THE BUG: pgg does the newline conversion by it self (I'm not quite
> sure why) but fails to tell the backend (gpg) that it should operate
> in textmode, so the Data Packet is tagged as binary, not text data...

pgg is definitely doing the wrong thing in converting the text to DOS
format, itself.  that requires that pgg be the decryption program used
if the platform where the message is being decrypted does not use DOS
file-encoding.

> Please try if the appended patch (only against pgg-gpg.el) fixes this
> issue.

that didn't work, but lead me in the right direction to what looks like the fix.

it does work if you also remove the invocation of the pgg-as-lbt macro
which encloses the pgg-gpg-process-region call.  i'm including a patch
which does that for all of the pgg-gpg.el routines which use
pgg-as-lbt.

once again, i'm not *sure* that's the right thing, but i'm pretty sure
that the way pgg-as-lbt is being used is the wrong thing.  maybe that
was done to try to provide for versions of gpg that lacked the
--textmode option. i don't think that would be a good idea.

(since pgg-as-lbt is a macro, its effect is a little beguiling.  it
does its processing _before_ the call to pgg-gpg-process-region,
despite the fact that the latter is placed as an argument to the
former, and in contrast to what would happen in regular functions,
where the innermost call would be conducted first...)

> [passphrase caching]
>
> As I'm short of time, I'll look into this issues later, sorry...

i've resolved part of the problem in my patch, specifically:

> > 3. this key caching problem of #2 is compounded in the context of sascha's
> > [...]
> > - the patched version will use the prompt for the symmetric key even when
> >   doing a public-key decryption.

the problem was that the 'result' value in dolist was being setq'd,
but not made local, so the previous result is used in the case that no
new result is found.  i added a '(let (result) ...)' around the
dolist, and it's now behaving properly.  that's in my version of your
patch.

caching of the symmetric passphrase is going to take some more thought.

what i did in allout is to manipulate mailcrypt's caching mechanism to
cache the symmetric key according to the file path, if any, else the
buffer name.  that way, there's one symmetric key cached per file.  on
top of that, there's allowance in the password reading mechanism for
new or varying symmetric keys for a file, with provision for
presenting a user-supplied key hint in the prompt, as well.  i would
like to refine pgg's password prompting mechanism to make it easy for
allout to provide the prompt and other behaviors without making it too
specialized and complicated.  i'm going to leave that for a separate
patch, once i get it done.

finally (with regard to the passphrase stuff), pgg should be caching
the key-pair mode passphrases according to the actual identity of the
key being addressed, and not the default user id.  that info is
available explicitly when encrypting, and i suspect that your
pgg-gpg-symmetric-key-p demonstrates that it's available (via
pgg-decode-armor-region) when decrypting.  the caching should
discriminate, and the decryption prompt should indicate, on the basis
of that info, but i'll leave it to someone else to make those
refinements to the pgg code.  i'm going to just try to make sure the
caching and password reading mechanisms are general enough.

> > 4. in the patched version, the symmetric encryption does not replace the
> >    original text with the encrypted text - it's only available in the
> >    hidden " *PGG output*" buffer, but not put in place.
>
> I think, you want to use `pgg-encrypt-symmetric-region', which
> encapsulates the backend function `pgg-gpg-encrypt-symmetric-region'
> and puts the encrypted text in place.

you're correct, that was my mistake.

we're making some good progress here.  the --textmode fact was crucial
- it's looking like the use of pgg-as-lbt is somehow misguided.  i'm
hoping that the major things are taken care of, and i can refine the
passphrase caching mechanism as i see necessary.

thanks for your help!

ken manheimer
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-07 18:06                           ` Ken Manheimer
@ 2005-10-07 21:49                             ` Sascha Wilde
  2005-10-08  8:48                               ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-07 21:49 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), emacs-devel, Richard M. Stallman,
	Simon Josefsson (gnus maintainer of pgg)


[-- Attachment #1.1.1: Type: text/plain, Size: 3118 bytes --]

On Fri, Oct 07, 2005 at 02:06:55PM -0400, Ken Manheimer wrote:
> On 10/7/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> > On Thu, Oct 06, 2005 at 06:41:14PM -0400, Ken Manheimer wrote:

> > > 1. my most serious concern is with the unpatched pgg code.  the text that
> > >    it encrypts is altered from the original, in order to append \r carriage
> > >    returns to the text (using pgg-as-lbt / pgg-convert-lbt).
> > >
> > >    the problem with this is that decryption on unix-ish platforms with
> > >    anything other than pgg will result in text that is different than the
> > >    original.
> >
> > This is supposed to be a feature, not a bug.
> > But read on, there actually _is_ a bug in PGG...
[...]
> > THE BUG: pgg does the newline conversion by it self (I'm not quite
> > sure why) but fails to tell the backend (gpg) that it should operate
> > in textmode, so the Data Packet is tagged as binary, not text data...
> 
> pgg is definitely doing the wrong thing in converting the text to DOS
> format, itself.  that requires that pgg be the decryption program used
> if the platform where the message is being decrypted does not use DOS
> file-encoding.

While I agree, that it is unnecessary (at least with gpg as backend) I
wouldn't say, that it is wrong.  When the content of the data packet
is tag as text, _any_ decrypting application is required to convert
the <CR><LF> to the type of linebreak matching the local system.

> > Please try if the appended patch (only against pgg-gpg.el) fixes this
> > issue.
> 
> that didn't work, but lead me in the right direction to what looks
> like the fix.
> 
> it does work if you also remove the invocation of the pgg-as-lbt macro
> which encloses the pgg-gpg-process-region call. 

As explained it shouldn't make any difference if the conversion is
done by pgg or gpg, as long as the data is tagged as text.

I tried it here with my latest patches and gpg and I was able to
encrypt a text using pgg and decrypt it with gpg on the command line
as well as with pgg within emacs and getting the right result (unix
like linebreakes, that is) in both cases.  What happens when you try
it?



> i'm including a patch which does that for all of the pgg-gpg.el
> routines which use pgg-as-lbt.

hmm, I don't think you did...  ;-)  And, as explained, I think this
shouldn't be needed.

Anyway I found another (unrelated) bug in my code, please see the
attached patch.

> the problem was that the 'result' value in dolist was being setq'd,
> but not made local, so the previous result is used in the case that no
> new result is found.  i added a '(let (result) ...)' around the
> dolist, and it's now behaving properly.  that's in my version of your
> patch.

Yes, this was a bug.  (Funny enough, I just found it m self)

Everybody: please attache the provided patch...

[...]
> we're making some good progress here.

yes, seems so!  :-)

Thanks for your work.

cheers
sascha
-- 
Sascha Wilde : "Lies, was ich meine, nicht, was ich schreibe."
             : (Urs Traenkner in de.alt.admin)

[-- Attachment #1.1.2: pgg-gpg_symmetric-key-p.patch --]
[-- Type: text/plain, Size: 794 bytes --]

--- /usr/share/emacs/22.0.50/lisp/gnus/pgg-gpg.el	2005-10-07 11:47:44.000000000 +0200
+++ /home/wilde/src/std-src/emacs/lisp/gnus/pgg-gpg.el	2005-10-07 23:29:57.000000000 +0200
@@ -205,10 +205,11 @@
 
 (defun pgg-gpg-symmetric-key-p (message-keys)
   "Check if MESSAGE-KEYS contains a symmetric encryption indicator."
-  (dolist (key message-keys result)
-    (when (and (eq (car key) 3)
-	       (member '(symmetric-key-algorithm) key))
-      (setq result key))))
+  (let ((result))
+    (dolist (key message-keys result)
+      (when (and (eq (car key) 3)
+		 (member '(symmetric-key-algorithm) key))
+	(setq result key)))))
 
 (defun pgg-gpg-select-matching-key (message-keys secret-keys)
   "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."


[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-07 21:49                             ` Sascha Wilde
@ 2005-10-08  8:48                               ` Simon Josefsson
  2005-10-08 10:36                                 ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2005-10-08  8:48 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel

It seems you are making some progress here.  For simplicity, could you
post the complete patch (preferably in unified diff format) against
Emacs CVS you want to have installed?  Unless somebody else has
already taken care of this...

Btw, I have merged some bug fixes of PGG from No Gnus CVS into Emacs
CVS.  The changes between PGG in Emacs CVS and No Gnus are now only
related to password.el, which I believe we agreed to not install in
Emacs because it was too close to the release.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08  8:48                               ` Simon Josefsson
@ 2005-10-08 10:36                                 ` Sascha Wilde
  2005-10-08 11:14                                   ` Simon Josefsson
  2005-10-08 18:31                                   ` Ken Manheimer
  0 siblings, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2005-10-08 10:36 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches), Ken Manheimer,
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 655 bytes --]

On Sat, Oct 08, 2005 at 10:48:27AM +0200, Simon Josefsson wrote:
> It seems you are making some progress here.  For simplicity, could you
> post the complete patch (preferably in unified diff format) against
> Emacs CVS you want to have installed?  Unless somebody else has
> already taken care of this...

I attached the complete patch against the latest cvs checkout.

Thanks for your help.

cheers
sascha
-- 
Sascha Wilde
"Structure is _nothing_ if it is all you got.  Skeletons _spook_ people if
 thwy try to walk around on their own.  I really wonder why XML does
 not."            -- Erik Naggum <erik@naggum.net> in comp.lang.lisp

[-- Attachment #1.1.2: emacs-pgg-symmetric.patch-04 --]
[-- Type: text/plain, Size: 7885 bytes --]

Index: man/pgg.texi
===================================================================
RCS file: /cvsroot/emacs/emacs/man/pgg.texi,v
retrieving revision 1.5
diff -u -r1.5 pgg.texi
--- man/pgg.texi	16 Sep 2005 22:11:00 -0000	1.5
+++ man/pgg.texi	8 Oct 2005 10:31:09 -0000
@@ -98,6 +98,8 @@
 @lisp
 (autoload 'pgg-encrypt-region "pgg"
   "Encrypt the current region." t)
+(autoload 'pgg-encrypt-symmetric-region "pgg"
+  "Encrypt the current region with symmetric algorithm." t)
 (autoload 'pgg-decrypt-region "pgg"
   "Decrypt the current region." t)
 (autoload 'pgg-sign-region "pgg"
@@ -140,6 +142,13 @@
 with GnuPG.
 @end deffn
 
+@deffn Command pgg-encrypt-symmetric-region start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher.  After invocation you are asked for a passphrase.
+
+This is currently only implemented for GnuPG.
+@end deffn
+
 @deffn Command pgg-decrypt-region start end
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it replaces the current region contents (in
@@ -305,6 +314,13 @@
 @var{recipients}.  If @var{sign} is non-@code{nil}, do a combined sign
 and encrypt.  If encryption is successful, it returns @code{t},
 otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-encrypt-symmetric-region scheme start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher and a passphrases.  If encryption is successful, it
+returns @code{t}, otherwise @code{nil}.  This function is currently only
+implemented for GnuPG.
 @end deffn
 
 @deffn Method pgg-scheme-decrypt-region scheme start end
Index: man/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/man/ChangeLog,v
retrieving revision 1.683
diff -u -r1.683 ChangeLog
--- man/ChangeLog	8 Oct 2005 02:55:16 -0000	1.683
+++ man/ChangeLog	8 Oct 2005 10:31:12 -0000
@@ -10,6 +10,14 @@
 	* building.texi (GDB Graphical Interface): Add variables and
 	functions to indices.  Be more precise.
 
+2005-10-06  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg.texi (How to use): Added autoload line for
+	`pgg-encrypt-symmetric-region'.
+	(User Commands): Description of `pgg-encrypt-symmetric-region'.
+	(Backend methods): Describe new funktion
+	`pgg-scheme-encrypt-symmetric-region'.
+
 2005-10-05  Nick Roberts  <nickrob@snap.net.nz>
 
 	* speedbar.texi (GDB): Describe use of watch expressions.
Index: lisp/gnus/pgg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg.el,v
retrieving revision 1.8
diff -u -r1.8 pgg.el
--- lisp/gnus/pgg.el	26 Aug 2005 00:02:05 -0000	1.8
+++ lisp/gnus/pgg.el	8 Oct 2005 10:31:13 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP
 
@@ -232,6 +233,32 @@
 	 (pgg-save-coding-system start end
 	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
 		       (point-min) (point-max) rcpts sign))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric-region (start end)
+  "Encrypt the current region between START and END symmetric with passphrase."
+  (interactive "r")
+  (let ((status
+	 (pgg-save-coding-system start end
+	   (pgg-invoke "encrypt-symmetric-region" 
+		       (or pgg-scheme pgg-default-scheme)
+		       (point-min) (point-max)))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric (&optional start end)
+  "Encrypt the current buffer symmetric with passphrase.
+If optional arguments START and END are specified, only encrypt within
+the region."
+  (interactive)
+  (let* ((start (or start (point-min)))
+	 (end (or end (point-max)))
+	 (status (pgg-encrypt-symmetric-region start end)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
Index: lisp/gnus/pgg-gpg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg-gpg.el,v
retrieving revision 1.7
diff -u -r1.7 pgg-gpg.el
--- lisp/gnus/pgg-gpg.el	8 Oct 2005 08:43:33 -0000	1.7
+++ lisp/gnus/pgg-gpg.el	8 Oct 2005 10:31:14 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -150,7 +151,7 @@
 	     pgg-gpg-user-id)))
 	 (args
 	  (append
-	   (list "--batch" "--armor" "--always-trust" "--encrypt")
+	   (list "--batch" "--textmode" "--armor" "--always-trust" "--encrypt")
 	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
 	   (if recipients
 	       (apply #'nconc
@@ -169,6 +170,16 @@
 	(pgg-gpg-possibly-cache-passphrase passphrase)))
     (pgg-process-when-success)))
 
+(defun pgg-gpg-encrypt-symmetric-region (start end)
+  "Encrypt the current region between START and END with symmetric cipher."
+  (let* ((passphrase
+	  (pgg-read-passphrase "GnuPG passphrase for symmetric encryption: "))
+	 (args
+	  (append (list "--batch" "--textmode" "--armor" "--symmetric" ))))
+    (pgg-as-lbt start end 'CRLF
+      (pgg-gpg-process-region start end passphrase pgg-gpg-program args))    
+    (pgg-process-when-success)))
+
 (defun pgg-gpg-decrypt-region (start end)
   "Decrypt the current region between START and END."
   (let* ((current-buffer (current-buffer))
@@ -180,7 +191,10 @@
 	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase
 	  (pgg-read-passphrase
-	   (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
+	   (format (if (pgg-gpg-symmetric-key-p message-keys)
+		       "Passphrase for symmetric dencryption: "
+		       "GnuPG passphrase for %s: ")
+		   pgg-gpg-user-id)
 	   pgg-gpg-user-id))
 	 (args '("--batch" "--decrypt")))
     (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
@@ -188,6 +202,14 @@
       (pgg-gpg-possibly-cache-passphrase passphrase pgg-gpg-user-id)
       (goto-char (point-min))
       (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
+
+(defun pgg-gpg-symmetric-key-p (message-keys)
+  "Check if MESSAGE-KEYS contains a symmetric encryption indicator."
+  (let ((result))
+    (dolist (key message-keys result)
+      (when (and (eq (car key) 3)
+		 (member '(symmetric-key-algorithm) key))
+	(setq result key)))))
 
 (defun pgg-gpg-select-matching-key (message-keys secret-keys)
   "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."
Index: lisp/gnus/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/ChangeLog,v
retrieving revision 1.392
diff -u -r1.392 ChangeLog
--- lisp/gnus/ChangeLog	8 Oct 2005 08:45:31 -0000	1.392
+++ lisp/gnus/ChangeLog	8 Oct 2005 10:31:16 -0000
@@ -1,3 +1,15 @@
+2005-10-06  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg-gpg.el (pgg-gpg-encrypt-symmetric-region): New function for
+	symmetric encryption.
+	(pgg-gpg-symmetric-key-p): New function to check for an symmetric
+	encrypted session key.
+	(pgg-gpg-decrypt-region): When decrypting a symmetric encrypted
+	message ask for the passphrase in a proper way.
+
+	* pgg.el (pgg-encrypt-symmetric,pgg-encrypt-symmetric-region):
+	New user commands for symmetric encryption.
+
 2005-01-21  Derek Atkins <warlord@MIT.EDU>  (tiny change)
 
 	* pgg-pgp.el (pgg-pgp-decrypt-region): Use passphrase cache.

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08 10:36                                 ` Sascha Wilde
@ 2005-10-08 11:14                                   ` Simon Josefsson
  2005-10-08 12:56                                     ` Ken Manheimer
  2005-10-08 13:43                                     ` Sascha Wilde
  2005-10-08 18:31                                   ` Ken Manheimer
  1 sibling, 2 replies; 156+ messages in thread
From: Simon Josefsson @ 2005-10-08 11:14 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel

Sascha Wilde <wilde@sha-bang.de> writes:

> On Sat, Oct 08, 2005 at 10:48:27AM +0200, Simon Josefsson wrote:
>> It seems you are making some progress here.  For simplicity, could you
>> post the complete patch (preferably in unified diff format) against
>> Emacs CVS you want to have installed?  Unless somebody else has
>> already taken care of this...
>
> I attached the complete patch against the latest cvs checkout.
>
> Thanks for your help.

Thanks!  The patch looks good.  I think this is a non-trivial change,
though, so installing it would require signing papers to transfer the
copyright to the FSF.  Have all the authors done this?  Would you be
willing to do it?  Thanks.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08 11:14                                   ` Simon Josefsson
@ 2005-10-08 12:56                                     ` Ken Manheimer
  2005-10-08 22:56                                       ` Richard M. Stallman
  2005-10-08 13:43                                     ` Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-08 12:56 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel

On 10/8/05, Simon Josefsson <jas@extundo.com> wrote:
> Sascha Wilde <wilde@sha-bang.de> writes:
>
> > On Sat, Oct 08, 2005 at 10:48:27AM +0200, Simon Josefsson wrote:
> >> It seems you are making some progress here.  For simplicity, could you
> >> post the complete patch (preferably in unified diff format) against
> >> Emacs CVS you want to have installed?  Unless somebody else has
> >> already taken care of this...
> >
> > I attached the complete patch against the latest cvs checkout.
> >
> > Thanks for your help.
>
> Thanks!  The patch looks good.  I think this is a non-trivial change,
> though, so installing it would require signing papers to transfer the
> copyright to the FSF.  Have all the authors done this?  Would you be
> willing to do it?  Thanks.

how imminent is the release?  i have an initial revision of the code,
on top of sascha's patches, to enable explicit management of
passphrase caching by the calling code.  that still might change as i
develop my code that uses it, though.  so i'm unsure whether i have
toto post those revisions immediately, so i can get them into the
release, or whether i have a few days to develop the other code and
resolve the changes i'd ideally like in the pgg code.

as for the copyright assignment, i have papers on file from a long
time ago, for allout and icomplete, but i believe it covers whatever i
want to contribute.  all the lines in the current patch were written
by sascha, anyway, my suggestions just motivated some of them.

ken manheimer
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08 11:14                                   ` Simon Josefsson
  2005-10-08 12:56                                     ` Ken Manheimer
@ 2005-10-08 13:43                                     ` Sascha Wilde
  1 sibling, 0 replies; 156+ messages in thread
From: Sascha Wilde @ 2005-10-08 13:43 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches), Ken Manheimer,
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 830 bytes --]

On Sat, Oct 08, 2005 at 01:14:59PM +0200, Simon Josefsson wrote:
> Sascha Wilde <wilde@sha-bang.de> writes:
> 
> > On Sat, Oct 08, 2005 at 10:48:27AM +0200, Simon Josefsson wrote:

> > I attached the complete patch against the latest cvs checkout.
> >
> > Thanks for your help.
> 
> Thanks!  The patch looks good.  I think this is a non-trivial
> change, though, so installing it would require signing papers to
> transfer the copyright to the FSF.  Have all the authors done this?

No, I haven't yet.

> Would you be willing to do it?  Thanks.

Sure.  Could you please guide me how to do this?

cheers
sascha
-- 
Sascha Wilde : xedit? Das sieht zwar wie vi aus als könne es nix, aber im
             : Gegensatz zu vi kann es wirklich nix und nix ist noch geschönt!
             : (Michael Core in dafc)

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08 10:36                                 ` Sascha Wilde
  2005-10-08 11:14                                   ` Simon Josefsson
@ 2005-10-08 18:31                                   ` Ken Manheimer
  2005-10-08 19:16                                     ` Ken Manheimer
  2005-10-10 21:15                                     ` Ken Manheimer
  1 sibling, 2 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-08 18:31 UTC (permalink / raw)


On 10/8/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> On Sat, Oct 08, 2005 at 10:48:27AM +0200, Simon Josefsson wrote:
> > It seems you are making some progress here.  For simplicity, could you
> > post the complete patch (preferably in unified diff format) against
> > Emacs CVS you want to have installed?  Unless somebody else has
> > already taken care of this...
>
> I attached the complete patch against the latest cvs checkout.

i've got another take on the cumulative patch, with the addition of
some refinements i would like to add.

the patch is against the gnu.org repository, and incorporates recent
checkins there as of a few minutes ago.

here are the details of my further refinements, which are included in
this patch.   their purpose is to enable external management of the
passphrases, including prompting and caching, while still using the
pgg encryption and cache mechanisms.  the changes have two thrusts:

  - extend the (generic pgg and gpg scheme) encryption and decryption
    routines to take an optional passphrase argument, and when provided,
    use its value instead of prompting for the passphrase

  - extend the passphrase caching and prompting routines to take an optional
    'notruncate' argument, to enable caching of passphrases for keys besides
    those that have the format of the short pgp packet key id.

i think that these, together, will enable me to do the passphrase
handling and extend it to symmetric keys, while still leveraging the
features of the pgg mechanism (in particular, passphrase expiration). 
i am pretty sure it's all backwards compatible - all the additional
functionality hinges on using the new optional arguments, there should
be no operational changes if you don't use them.

(i am very puzzled about why the passphrase cache was restricted to
the length of the short pgp packet key ids.  seems like you want to
couple the passphrases with the user identity for which the message is
being encoded, in the case of key-pair ciphers, or some arbitrary
string for symmetric ciphers - eg, file name is what i want to use for
symmetric keys in allout, since the symmetric keys are associated with
the files.  but once again i don't know the pgp territory well enough
to wade in, and want to minimize the chance of inadvertantly breaking
anything.

if this approach is deemed to be fine, i can easily provide an
additional patch to adjust the pgg-pgp and pgg-pgp5 modules similarly.

ken
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08 18:31                                   ` Ken Manheimer
@ 2005-10-08 19:16                                     ` Ken Manheimer
  2005-10-10 21:15                                     ` Ken Manheimer
  1 sibling, 0 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-08 19:16 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 3189 bytes --]

damn!  i'm absolutely sure i attached it that time.  (i even ditched
the first attachment and reattached a new copy, when i noticed a
revision to add.)  i'm going to try again as an attachment, and if it
doesn't go through i'll send it inline.

---------- Forwarded message ----------
From: Ken Manheimer <ken.manheimer@gmail.com>
Date: Oct 8, 2005 2:31 PM
Subject: Re: pgg symmetric encryption patch
To: Simon Josefsson <jas@extundo.com>, Ken Manheimer
<ken.manheimer@gmail.com>, "sascha schwab (symmetric encryption
patches)" <schwab@suse.de>, "Daiki Ueno (pgg author)"
<ueno@unixuser.org>, "Richard M. Stallman" <rms@gnu.org>,
emacs-devel@gnu.org


On 10/8/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> On Sat, Oct 08, 2005 at 10:48:27AM +0200, Simon Josefsson wrote:
> > It seems you are making some progress here.  For simplicity, could you
> > post the complete patch (preferably in unified diff format) against
> > Emacs CVS you want to have installed?  Unless somebody else has
> > already taken care of this...
>
> I attached the complete patch against the latest cvs checkout.

i've got another take on the cumulative patch, with the addition of
some refinements i would like to add.

the patch is against the gnu.org repository, and incorporates recent
checkins there as of a few minutes ago.

here are the details of my further refinements, which are included in
this patch.   their purpose is to enable external management of the
passphrases, including prompting and caching, while still using the
pgg encryption and cache mechanisms.  the changes have two thrusts:

  - extend the (generic pgg and gpg scheme) encryption and decryption
    routines to take an optional passphrase argument, and when provided,
    use its value instead of prompting for the passphrase

  - extend the passphrase caching and prompting routines to take an optional
    'notruncate' argument, to enable caching of passphrases for keys besides
    those that have the format of the short pgp packet key id.

i think that these, together, will enable me to do the passphrase
handling and extend it to symmetric keys, while still leveraging the
features of the pgg mechanism (in particular, passphrase expiration).
i am pretty sure it's all backwards compatible - all the additional
functionality hinges on using the new optional arguments, there should
be no operational changes if you don't use them.

(i am very puzzled about why the passphrase cache was restricted to
the length of the short pgp packet key ids.  seems like you want to
couple the passphrases with the user identity for which the message is
being encoded, in the case of key-pair ciphers, or some arbitrary
string for symmetric ciphers - eg, file name is what i want to use for
symmetric keys in allout, since the symmetric keys are associated with
the files.  but once again i don't know the pgp territory well enough
to wade in, and want to minimize the chance of inadvertantly breaking
anything.

if this approach is deemed to be fine, i can easily provide an
additional patch to adjust the pgg-pgp and pgg-pgp5 modules similarly.

ken
ken.manheimer@gmail.com

[-- Attachment #2: emacs-pgg-symmetric.patch-05 --]
[-- Type: application/octet-stream, Size: 17286 bytes --]

Index: man/pgg.texi
===================================================================
RCS file: /cvsroot/emacs/emacs/man/pgg.texi,v
retrieving revision 1.5
diff -u -r1.5 pgg.texi
--- man/pgg.texi	16 Sep 2005 22:11:00 -0000	1.5
+++ man/pgg.texi	8 Oct 2005 10:31:09 -0000
@@ -98,6 +98,8 @@
 @lisp
 (autoload 'pgg-encrypt-region "pgg"
   "Encrypt the current region." t)
+(autoload 'pgg-encrypt-symmetric-region "pgg"
+  "Encrypt the current region with symmetric algorithm." t)
 (autoload 'pgg-decrypt-region "pgg"
   "Decrypt the current region." t)
 (autoload 'pgg-sign-region "pgg"
@@ -140,6 +142,13 @@
 with GnuPG.
 @end deffn
 
+@deffn Command pgg-encrypt-symmetric-region start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher.  After invocation you are asked for a passphrase.
+
+This is currently only implemented for GnuPG.
+@end deffn
+
 @deffn Command pgg-decrypt-region start end
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it replaces the current region contents (in
@@ -305,6 +314,13 @@
 @var{recipients}.  If @var{sign} is non-@code{nil}, do a combined sign
 and encrypt.  If encryption is successful, it returns @code{t},
 otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-encrypt-symmetric-region scheme start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher and a passphrases.  If encryption is successful, it
+returns @code{t}, otherwise @code{nil}.  This function is currently only
+implemented for GnuPG.
 @end deffn
 
 @deffn Method pgg-scheme-decrypt-region scheme start end
Index: man/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/man/ChangeLog,v
retrieving revision 1.683
diff -u -r1.683 ChangeLog
--- man/ChangeLog	8 Oct 2005 02:55:16 -0000	1.683
+++ man/ChangeLog	8 Oct 2005 10:31:12 -0000
@@ -10,6 +10,14 @@
 	* building.texi (GDB Graphical Interface): Add variables and
 	functions to indices.  Be more precise.
 
+2005-10-06  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg.texi (How to use): Added autoload line for
+	`pgg-encrypt-symmetric-region'.
+	(User Commands): Description of `pgg-encrypt-symmetric-region'.
+	(Backend methods): Describe new funktion
+	`pgg-scheme-encrypt-symmetric-region'.
+
 2005-10-05  Nick Roberts  <nickrob@snap.net.nz>
 
 	* speedbar.texi (GDB): Describe use of watch expressions.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/ChangeLog,v
retrieving revision 1.392
diff -u -r1.392 ChangeLog
--- ChangeLog	8 Oct 2005 08:45:31 -0000	1.392
+++ ChangeLog	8 Oct 2005 17:58:09 -0000
@@ -1,3 +1,41 @@
+
+2005-10-08  Ken Manheimer <ken.manheimer+emacs@gmail.com>
+
+	* pgg.el (pgg-encrypt-region, pgg-encrypt-symmetric-region,
+	pgg-encrypt-symmetric, pgg-encrypt, pgg-decrypt-region,
+	pgg-decrypt, pgg-sign-region, pgg-sign):
+	add optional 'passphrase' argument to all these routines, so the
+	passphrase can be managed externally and then passed in to the
+	system.
+
+	* pgg.el (pgg-read-passphrase, pgg-add-passphrase-cache,
+	pgg-remove-passphrase-cache): add optional 'notruncate' argument,
+	so the passphrase cache can be used reliably with identifiers
+	besides a pgp packet's key id.
+
+	* pgg-gpg.el (pgg-pgp-encrypt-region,
+	pgg-pgp-encrypt-symmetric-region, pgg-pgp-encrypt-symmetric,
+	pgg-pgp-encrypt, pgg-pgp-decrypt-region, pgg-pgp-decrypt,
+	pgg-pgp-sign-region, pgg-pgp-sign): add optional 'passphrase'
+	argument to all these routines, so the passphrase can be managed
+	externally and passed in to the system.
+
+	* pgg-gpg.el (pgg-gpg-possibly-cache-passphrase): add optional
+	'notruncate' argument, so the passphrase cache can be used
+	reliably with identifiers besides a pgp packet's key id.
+
+2005-10-06  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg-gpg.el (pgg-gpg-encrypt-symmetric-region): New function for
+	symmetric encryption.
+	(pgg-gpg-symmetric-key-p): New function to check for an symmetric
+	encrypted session key.
+	(pgg-gpg-decrypt-region): When decrypting a symmetric encrypted
+	message ask for the passphrase in a proper way.
+
+	* pgg.el (pgg-encrypt-symmetric,pgg-encrypt-symmetric-region):
+	New user commands for symmetric encryption.
+
 2005-01-21  Derek Atkins <warlord@MIT.EDU>  (tiny change)
 
 	* pgg-pgp.el (pgg-pgp-decrypt-region): Use passphrase cache.
Index: pgg-gpg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg-gpg.el,v
retrieving revision 1.7
diff -u -r1.7 pgg-gpg.el
--- pgg-gpg.el	8 Oct 2005 08:43:33 -0000	1.7
+++ pgg-gpg.el	8 Oct 2005 17:58:09 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -96,7 +97,7 @@
 	  (delete-file output-file-name))
       (set-default-file-modes orig-mode))))
 
-(defun pgg-gpg-possibly-cache-passphrase (passphrase &optional key)
+(defun pgg-gpg-possibly-cache-passphrase (passphrase &optional key notruncate)
   (if (and pgg-cache-passphrase
 	   (progn
 	     (goto-char (point-min))
@@ -108,7 +109,8 @@
 	     (if (re-search-forward
 		  "^\\[GNUPG:] NEED_PASSPHRASE\\(_PIN\\)? \\w+ ?\\w*" nil t)
 		 (substring (match-string 0) -8))))
-       passphrase)))
+       passphrase
+       notruncate)))
 
 (defvar pgg-gpg-all-secret-keys 'unknown)
 
@@ -139,18 +141,23 @@
 			     nil t)
 	  (substring (match-string 2) 8)))))
 
-(defun pgg-gpg-encrypt-region (start end recipients &optional sign)
+(defun pgg-gpg-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END.
-If optional argument SIGN is non-nil, do a combined sign and encrypt."
+
+If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
-	 (passphrase
-	  (when sign
-	    (pgg-read-passphrase
-	     (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	     pgg-gpg-user-id)))
+	 (passphrase (or passphrase
+                         (when sign
+                           (pgg-read-passphrase
+                            (format "GnuPG passphrase for %s: "
+                                    pgg-gpg-user-id)
+                            pgg-gpg-user-id))))
 	 (args
 	  (append
-	   (list "--batch" "--armor" "--always-trust" "--encrypt")
+	   (list "--batch" "--textmode" "--armor" "--always-trust" "--encrypt")
 	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
 	   (if recipients
 	       (apply #'nconc
@@ -169,8 +176,25 @@
 	(pgg-gpg-possibly-cache-passphrase passphrase)))
     (pgg-process-when-success)))
 
-(defun pgg-gpg-decrypt-region (start end)
-  "Decrypt the current region between START and END."
+(defun pgg-gpg-encrypt-symmetric-region (start end &optional passphrase)
+  "Encrypt the current region between START and END with symmetric cipher.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
+  (let* ((passphrase (or passphrase
+                         (pgg-read-passphrase
+                          "GnuPG passphrase for symmetric encryption: ")))
+	 (args
+	  (append (list "--batch" "--textmode" "--armor" "--symmetric" ))))
+    (pgg-as-lbt start end 'CRLF
+      (pgg-gpg-process-region start end passphrase pgg-gpg-program args))    
+    (pgg-process-when-success)))
+
+(defun pgg-gpg-decrypt-region (start end &optional passphrase)
+  "Decrypt the current region between START and END.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((current-buffer (current-buffer))
 	 (message-keys (with-temp-buffer
 			 (insert-buffer-substring current-buffer)
@@ -178,16 +202,27 @@
 	 (secret-keys (pgg-gpg-lookup-all-secret-keys))
 	 (key (pgg-gpg-select-matching-key message-keys secret-keys))
 	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
-	 (passphrase
-	  (pgg-read-passphrase
-	   (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	   pgg-gpg-user-id))
+	 (passphrase (or passphrase
+                         (pgg-read-passphrase
+                          (format (if (pgg-gpg-symmetric-key-p message-keys)
+                                      "Passphrase for symmetric decryption: "
+                                    "GnuPG passphrase for %s: ")
+                                  pgg-gpg-user-id)
+                          pgg-gpg-user-id)))
 	 (args '("--batch" "--decrypt")))
     (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
     (with-current-buffer pgg-errors-buffer
       (pgg-gpg-possibly-cache-passphrase passphrase pgg-gpg-user-id)
       (goto-char (point-min))
       (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
+
+(defun pgg-gpg-symmetric-key-p (message-keys)
+  "Check if MESSAGE-KEYS contains a symmetric encryption indicator."
+  (let (result)
+    (dolist (key message-keys result)
+      (when (and (eq (car key) 3)
+		 (member '(symmetric-key-algorithm) key))
+	(setq result key)))))
 
 (defun pgg-gpg-select-matching-key (message-keys secret-keys)
   "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."
Index: pgg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg.el,v
retrieving revision 1.8
diff -u -r1.8 pgg.el
--- pgg.el	26 Aug 2005 00:02:05 -0000	1.8
+++ pgg.el	8 Oct 2005 17:58:10 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP
 
@@ -81,9 +82,10 @@
 
 (defvar pgg-passphrase-cache (make-vector 7 0))
 
-(defun pgg-read-passphrase (prompt &optional key)
+(defun pgg-read-passphrase (prompt &optional key notruncate)
   (or (and pgg-cache-passphrase
-	   key (setq key (pgg-truncate-key-identifier key))
+	   key (or (not notruncate)
+                   (setq key (pgg-truncate-key-identifier key)))
 	   (symbol-value (intern-soft key pgg-passphrase-cache)))
       (read-passwd prompt)))
 
@@ -159,15 +161,15 @@
 	(pgg-run-at-time-1 time repeat function args))
     (defalias 'pgg-run-at-time 'run-at-time)))
 
-(defun pgg-add-passphrase-cache (key passphrase)
-  (setq key (pgg-truncate-key-identifier key))
+(defun pgg-add-passphrase-cache (key passphrase &optional notruncate)
+  (if (not notruncate) (setq key (pgg-truncate-key-identifier key)))
   (set (intern key pgg-passphrase-cache)
        passphrase)
   (pgg-run-at-time pgg-passphrase-cache-expiry nil
 		   #'pgg-remove-passphrase-cache
 		   key))
 
-(defun pgg-remove-passphrase-cache (key)
+(defun pgg-remove-passphrase-cache (key &optional notruncate)
   (let ((passphrase (symbol-value (intern-soft key pgg-passphrase-cache))))
     (when passphrase
       (fillarray passphrase ?_)
@@ -222,52 +224,101 @@
 ;;;
 
 ;;;###autoload
-(defun pgg-encrypt-region (start end rcpts &optional sign)
+(defun pgg-encrypt-region (start end rcpts &optional sign passphrase)
   "Encrypt the current region between START and END for RCPTS.
-If optional argument SIGN is non-nil, do a combined sign and encrypt."
+
+If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive
    (list (region-beginning)(region-end)
 	 (split-string (read-string "Recipients: ") "[ \t,]+")))
   (let ((status
 	 (pgg-save-coding-system start end
 	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
-		       (point-min) (point-max) rcpts sign))))
+		       (point-min) (point-max) rcpts sign passphrase))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric-region (start end &optional passphrase)
+  "Encrypt the current region between START and END symmetric with passphrase.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+cache or user."
+  (interactive "r")
+  (let ((status
+	 (pgg-save-coding-system start end
+	   (pgg-invoke "encrypt-symmetric-region" 
+		       (or pgg-scheme pgg-default-scheme)
+		       (point-min) (point-max) passphrase))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric (&optional start end passphrase)
+  "Encrypt the current buffer using a symmetric, rather than key-pair, cipher.
+
+If optional arguments START and END are specified, only encrypt within
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
+  (interactive)
+  (let* ((start (or start (point-min)))
+	 (end (or end (point-max)))
+	 (status (pgg-encrypt-symmetric-region start end passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-encrypt (rcpts &optional sign start end)
+(defun pgg-encrypt (rcpts &optional sign start end passphrase)
   "Encrypt the current buffer for RCPTS.
+
 If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
 If optional arguments START and END are specified, only encrypt within
-the region."
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive (list (split-string (read-string "Recipients: ") "[ \t,]+")))
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
-	 (status (pgg-encrypt-region start end rcpts sign)))
+	 (status (pgg-encrypt-region start end rcpts sign passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-decrypt-region (start end)
-  "Decrypt the current region between START and END."
+(defun pgg-decrypt-region (start end &optional passphrase)
+  "Decrypt the current region between START and END.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "r")
   (let* ((buf (current-buffer))
 	 (status
 	  (pgg-save-coding-system start end
 	    (pgg-invoke "decrypt-region" (or pgg-scheme pgg-default-scheme)
-			(point-min) (point-max)))))
+			(point-min) (point-max) passphrase))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-decrypt (&optional start end)
+(defun pgg-decrypt (&optional start end passphrase)
   "Decrypt the current buffer.
+
 If optional arguments START and END are specified, only decrypt within
-the region."
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "")
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
@@ -277,38 +328,52 @@
     status))
 
 ;;;###autoload
-(defun pgg-sign-region (start end &optional cleartext)
+(defun pgg-sign-region (start end &optional cleartext passphrase)
   "Make the signature from text between START and END.
+
 If the optional 3rd argument CLEARTEXT is non-nil, it does not create
 a detached signature.
+
 If this function is called interactively, CLEARTEXT is enabled
-and the the output is displayed."
+and the the output is displayed.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "r")
   (let ((status (pgg-save-coding-system start end
 		  (pgg-invoke "sign-region" (or pgg-scheme pgg-default-scheme)
 			      (point-min) (point-max)
-			      (or (interactive-p) cleartext)))))
+			      (or (interactive-p) cleartext)
+                              passphrase))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-sign (&optional cleartext start end)
+(defun pgg-sign (&optional cleartext start end passphrase)
   "Sign the current buffer.
+
 If the optional argument CLEARTEXT is non-nil, it does not create a
 detached signature.
+
 If optional arguments START and END are specified, only sign data
 within the region.
+
 If this function is called interactively, CLEARTEXT is enabled
-and the the output is displayed."
+and the the output is displayed.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "")
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
-	 (status (pgg-sign-region start end (or (interactive-p) cleartext))))
+	 (status (pgg-sign-region start end
+                                  (or (interactive-p) cleartext)
+                                  passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
-  
+
 ;;;###autoload
 (defun pgg-verify-region (start end &optional signature fetch)
   "Verify the current region between START and END.



[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08 12:56                                     ` Ken Manheimer
@ 2005-10-08 22:56                                       ` Richard M. Stallman
  2005-10-10 21:50                                         ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Richard M. Stallman @ 2005-10-08 22:56 UTC (permalink / raw)
  Cc: schwab, ueno, emacs-devel, jas

Pretesting surely won't start in the next few weeks.

Your papers cover only the specific files you assigned,
but they do cover changes to those files.  So if you change
the code in allout.el to work with pgg, we will have no trouble
using that change.

But we do need papers from Sascha Wilde.  I will start arranging that.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-05 19:16                   ` Ken Manheimer
@ 2005-10-10  4:15                     ` Richard M. Stallman
  0 siblings, 0 replies; 156+ messages in thread
From: Richard M. Stallman @ 2005-10-10  4:15 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, ueno, emacs-devel

      i would have
    to change pgg's key caching stuff to enable me, for instance, to query
    for the presence of a key, and also change the encryption/decryption
    function signatures to take explictly passed-in keys.  it will not be
    trivial, and i don't want to launch into the work if there's no chance
    the pgg changes will be accepted.

I see no reason to reject them, assuming you do a good job writing
them, provided you preserve upward-compatibility for the existing PGG
interface functions.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08 18:31                                   ` Ken Manheimer
  2005-10-08 19:16                                     ` Ken Manheimer
@ 2005-10-10 21:15                                     ` Ken Manheimer
  2005-10-10 21:16                                       ` Ken Manheimer
  2005-10-12 23:47                                       ` Ken Manheimer
  1 sibling, 2 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-10 21:15 UTC (permalink / raw)


for those of you following the developments at home (:-), here's an
incremental patch on top of what i sent out a few days ago.  i fixed a
small stack of bugs in pgg-gpg.el that settles my complaint about
prompting with the secret key identity, and also filled in a small
oversight in the changes i sent out a few days ago.

while this could be the last pgg patch, i'm still developing, hence
the incremental.  i plan to send out a full patch when i've finished
transitioning allout to pgg, at which point i expect my mucking with
pgg to be settled.  so, repository maintainers may want to wait for
that, while i'm hoping those actively involved (eg, sascha) will
scrutinize and, ideally, exercise these patches.

we'll see if the attached patch makes it through this time.  (i
haven't re-attached it, which i think was the problem last time.)  if
not, look forward to a followup...

thanks.
ken
ken.manheimer@gmail.com

On 10/8/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> On 10/8/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> > On Sat, Oct 08, 2005 at 10:48:27AM +0200, Simon Josefsson wrote:
> > > It seems you are making some progress here.  For simplicity, could you
> > > post the complete patch (preferably in unified diff format) against
> > > Emacs CVS you want to have installed?  Unless somebody else has
> > > already taken care of this...
> >
> > I attached the complete patch against the latest cvs checkout.
>
> i've got another take on the cumulative patch, with the addition of
> some refinements i would like to add.
>
> the patch is against the gnu.org repository, and incorporates recent
> checkins there as of a few minutes ago.
>
> here are the details of my further refinements, which are included in
> this patch.   their purpose is to enable external management of the
> passphrases, including prompting and caching, while still using the
> pgg encryption and cache mechanisms.  the changes have two thrusts:
>
>   - extend the (generic pgg and gpg scheme) encryption and decryption
>     routines to take an optional passphrase argument, and when provided,
>     use its value instead of prompting for the passphrase
>
>   - extend the passphrase caching and prompting routines to take an optional
>     'notruncate' argument, to enable caching of passphrases for keys besides
>     those that have the format of the short pgp packet key id.
>
> i think that these, together, will enable me to do the passphrase
> handling and extend it to symmetric keys, while still leveraging the
> features of the pgg mechanism (in particular, passphrase expiration).
> i am pretty sure it's all backwards compatible - all the additional
> functionality hinges on using the new optional arguments, there should
> be no operational changes if you don't use them.
>
> (i am very puzzled about why the passphrase cache was restricted to
> the length of the short pgp packet key ids.  seems like you want to
> couple the passphrases with the user identity for which the message is
> being encoded, in the case of key-pair ciphers, or some arbitrary
> string for symmetric ciphers - eg, file name is what i want to use for
> symmetric keys in allout, since the symmetric keys are associated with
> the files.  but once again i don't know the pgp territory well enough
> to wade in, and want to minimize the chance of inadvertantly breaking
> anything.
>
> if this approach is deemed to be fine, i can easily provide an
> additional patch to adjust the pgg-pgp and pgg-pgp5 modules similarly.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-10 21:15                                     ` Ken Manheimer
@ 2005-10-10 21:16                                       ` Ken Manheimer
  2005-10-12 23:47                                       ` Ken Manheimer
  1 sibling, 0 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-10 21:16 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 3862 bytes --]

shit.  the attachment was dropped.  shit.  trying again.  sorry about
the clutter.

On 10/10/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> for those of you following the developments at home (:-), here's an
> incremental patch on top of what i sent out a few days ago.  i fixed a
> small stack of bugs in pgg-gpg.el that settles my complaint about
> prompting with the secret key identity, and also filled in a small
> oversight in the changes i sent out a few days ago.
>
> while this could be the last pgg patch, i'm still developing, hence
> the incremental.  i plan to send out a full patch when i've finished
> transitioning allout to pgg, at which point i expect my mucking with
> pgg to be settled.  so, repository maintainers may want to wait for
> that, while i'm hoping those actively involved (eg, sascha) will
> scrutinize and, ideally, exercise these patches.
>
> we'll see if the attached patch makes it through this time.  (i
> haven't re-attached it, which i think was the problem last time.)  if
> not, look forward to a followup...
>
> thanks.
> ken
> ken.manheimer@gmail.com
>
> On 10/8/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> > On 10/8/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> > > On Sat, Oct 08, 2005 at 10:48:27AM +0200, Simon Josefsson wrote:
> > > > It seems you are making some progress here.  For simplicity, could you
> > > > post the complete patch (preferably in unified diff format) against
> > > > Emacs CVS you want to have installed?  Unless somebody else has
> > > > already taken care of this...
> > >
> > > I attached the complete patch against the latest cvs checkout.
> >
> > i've got another take on the cumulative patch, with the addition of
> > some refinements i would like to add.
> >
> > the patch is against the gnu.org repository, and incorporates recent
> > checkins there as of a few minutes ago.
> >
> > here are the details of my further refinements, which are included in
> > this patch.   their purpose is to enable external management of the
> > passphrases, including prompting and caching, while still using the
> > pgg encryption and cache mechanisms.  the changes have two thrusts:
> >
> >   - extend the (generic pgg and gpg scheme) encryption and decryption
> >     routines to take an optional passphrase argument, and when provided,
> >     use its value instead of prompting for the passphrase
> >
> >   - extend the passphrase caching and prompting routines to take an optional
> >     'notruncate' argument, to enable caching of passphrases for keys besides
> >     those that have the format of the short pgp packet key id.
> >
> > i think that these, together, will enable me to do the passphrase
> > handling and extend it to symmetric keys, while still leveraging the
> > features of the pgg mechanism (in particular, passphrase expiration).
> > i am pretty sure it's all backwards compatible - all the additional
> > functionality hinges on using the new optional arguments, there should
> > be no operational changes if you don't use them.
> >
> > (i am very puzzled about why the passphrase cache was restricted to
> > the length of the short pgp packet key ids.  seems like you want to
> > couple the passphrases with the user identity for which the message is
> > being encoded, in the case of key-pair ciphers, or some arbitrary
> > string for symmetric ciphers - eg, file name is what i want to use for
> > symmetric keys in allout, since the symmetric keys are associated with
> > the files.  but once again i don't know the pgp territory well enough
> > to wade in, and want to minimize the chance of inadvertantly breaking
> > anything.
> >
> > if this approach is deemed to be fine, i can easily provide an
> > additional patch to adjust the pgg-pgp and pgg-pgp5 modules similarly.
>

[-- Attachment #2: pgg-symmetric_incremental_05_1.patch --]
[-- Type: application/octet-stream, Size: 3987 bytes --]

Index: ChangeLog
===================================================================
RCS file: /home/klm/.cvs/aside/src/gnus/ChangeLog,v
retrieving revision 1.5
diff -u -r1.5 ChangeLog
--- ChangeLog	8 Oct 2005 17:58:23 -0000	1.5
+++ ChangeLog	10 Oct 2005 20:56:06 -0000
@@ -1,3 +1,17 @@
+2005-10-15  Ken Manheimer  <ken.manheimer@gmail.com>
+
+	* pgg-gpe.el
+	(pgg-gpg-select-matching-key): fixed: look at the right part of the
+	decoded armor to find the key-identifier
+	(pgg-gpg-lookup-key-owner): new function to return the
+	human-readable identifier of a key owner.
+	(pgg-gpg-decrypt-region): prompt with the key owner (rather
+	than the key value) if we have a key and can match it against a
+	secret key.  also, added an XXX note pointing out fact that the
+	prompt only indicates the first matching key.
+
+	* pgg.el (pgg-decrypt): passing along 'passphrase' in call to
+	pgg-decrypt-region; i overlooked this one in my previous patch.
 
 2005-10-08  Ken Manheimer <ken.manheimer+emacs@gmail.com>
 
Index: pgg-gpg.el
===================================================================
RCS file: /home/klm/.cvs/aside/src/gnus/pgg-gpg.el,v
retrieving revision 1.6
diff -u -r1.6 pgg-gpg.el
--- pgg-gpg.el	8 Oct 2005 17:36:41 -0000	1.6
+++ pgg-gpg.el	10 Oct 2005 20:56:06 -0000
@@ -141,6 +141,24 @@
 			     nil t)
 	  (substring (match-string 2) 8)))))
 
+(defun pgg-gpg-lookup-key-owner (string &optional all)
+  "Search keys associated with STRING and return owner of identified key.
+
+Optional ALL non-nil means search all keys, including secret keys."
+  (let ((args (list "--with-colons" "--no-greeting" "--batch"
+		    (if all "--list-secret-keys" "--list-keys")
+		    string))
+        (key-regexp (concat "^\\(sec\\|pub\\)"
+                            ":[^:]*:[^:]*:[^:]*:\\([^:]*\\):[^:]*"
+                            ":[^:]*:[^:]*:[^:]*:\\([^:]*\\):"))
+        )
+    (with-temp-buffer
+      (apply #'call-process pgg-gpg-program nil t nil args)
+      (goto-char (point-min))
+      (if (re-search-forward key-regexp
+			     nil t)
+          (match-string 3)))))
+
 (defun pgg-gpg-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END.
 
@@ -200,8 +218,14 @@
 			 (insert-buffer-substring current-buffer)
 			 (pgg-decode-armor-region (point-min) (point-max))))
 	 (secret-keys (pgg-gpg-lookup-all-secret-keys))
+         ;; XXX the user is stuck if they have the passphrase for the
+         ;;     second or later secret key for which the message is
+         ;;     encrypted.  ideally, we would incrementally give them a
+         ;;     chance with subsequent keys each time they fail with one.
 	 (key (pgg-gpg-select-matching-key message-keys secret-keys))
-	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
+	 (key-owner (and key (pgg-gpg-lookup-key-owner key t)))
+	 (pgg-gpg-user-id (or key-owner key
+	                      pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase (or passphrase
                          (pgg-read-passphrase
                           (format (if (pgg-gpg-symmetric-key-p message-keys)
@@ -217,7 +241,7 @@
       (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
 
 (defun pgg-gpg-symmetric-key-p (message-keys)
-  "Check if MESSAGE-KEYS contains a symmetric encryption indicator."
+  "True if decoded armor MESSAGE-KEYS has symmetric encryption indicator."
   (let (result)
     (dolist (key message-keys result)
       (when (and (eq (car key) 3)
@@ -228,7 +252,8 @@
   "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."
   (loop for message-key in message-keys
 	for message-key-id = (and (equal (car message-key) 1)
-				  (cdr (assq 'key-identifier message-key)))
+				  (cdr (assq 'key-identifier
+                                             (cdr message-key))))
 	for key = (and message-key-id (pgg-lookup-key message-key-id 'encrypt))
 	when (and key (member key secret-keys)) return key))
 

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-08 22:56                                       ` Richard M. Stallman
@ 2005-10-10 21:50                                         ` Ken Manheimer
  2005-10-11 14:44                                           ` Richard M. Stallman
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-10 21:50 UTC (permalink / raw)
  Cc: schwab, ueno, emacs-devel, jas

On 10/8/05, Richard M. Stallman <rms@gnu.org> wrote:
> Pretesting surely won't start in the next few weeks.

i'll continue on, happy to have breathing room.

> Your papers cover only the specific files you assigned,
> but they do cover changes to those files.  So if you change
> the code in allout.el to work with pgg, we will have no trouble
> using that change.

in the pgg patchs i've sent so far, there's probably around 70 lines
of mine in pgg.el and around 37 in pgg-gpe.el.  i don't think there
will be too many more changes, but these are essential.  is that small
enough that no copyright assignment is required?

ken
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-10 21:50                                         ` Ken Manheimer
@ 2005-10-11 14:44                                           ` Richard M. Stallman
  0 siblings, 0 replies; 156+ messages in thread
From: Richard M. Stallman @ 2005-10-11 14:44 UTC (permalink / raw)
  Cc: schwab, ueno, emacs-devel, jas

    in the pgg patchs i've sent so far, there's probably around 70 lines
    of mine in pgg.el and around 37 in pgg-gpe.el.  i don't think there
    will be too many more changes, but these are essential.  is that small
    enough that no copyright assignment is required?

Over 10 to 15 lines needs papers.  I will send you what you need.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-10 21:15                                     ` Ken Manheimer
  2005-10-10 21:16                                       ` Ken Manheimer
@ 2005-10-12 23:47                                       ` Ken Manheimer
  2005-10-20 14:08                                         ` Ken Manheimer
  1 sibling, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-12 23:47 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 2751 bytes --]

as threatened, here is a complete patch against the current gnu.org
lisp/gnus repository.  i've migrated all the allout encryption
functionality to pgg and exercised this stuff pretty substantially,
and am very comfortable with the way it works.

there are a bunch of fixes, as well as extensions so the passphrases
can be managed by the calling functions, as well as refinement of the
passphrase caching mechanism (so multiple timeouts don't pileup for a
single passphrase - the last one replaces the prior ones).   lotsa
goodies.  the patch includes sascha wilde's symmetric-encryption
additions - basically, the whole deal.

what it does not include is revision of the pgg-pgp.el and pgg-pgp5.el
modules, to track changes to the pgg api.  i started in on that, only
to discover that they were already broken by the addition of a 'sign'
parameter to some of the encryption functions.  there's no way to
repair that short of implementing the feature for the other packages,
and i'm not in a position to do that.  (plus, i'm not sure i am
comfortable with the way it was done for pgg-gpg.)

so it looks like pgg-pgp.el and pgg-pgp5.el are disfunctional already,
without my changes.  i'm hoping that's not going to prevent the
introduction of my changes.

i'm going to be heading offline for five days, starting tomorrow, so
it'll be a bit before i can respond to questions.  i hope the patch
i'm sending (which  includes detaild ChangeLog entries) will be
helpful to anyone that wishes to navigate them.

and once again, i'm not sure the attachment will be delivered this
time.  (it wasn't on a recent try, but then was on a subsequent
message.  this is the first awkward gmail bug i've hit...)

ken
ken.manheimer@gmail.com

On 10/10/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> for those of you following the developments at home (:-), here's an
> incremental patch on top of what i sent out a few days ago.  i fixed a
> small stack of bugs in pgg-gpg.el that settles my complaint about
> prompting with the secret key identity, and also filled in a small
> oversight in the changes i sent out a few days ago.
>
> while this could be the last pgg patch, i'm still developing, hence
> the incremental.  i plan to send out a full patch when i've finished
> transitioning allout to pgg, at which point i expect my mucking with
> pgg to be settled.  so, repository maintainers may want to wait for
> that, while i'm hoping those actively involved (eg, sascha) will
> scrutinize and, ideally, exercise these patches.
>
> we'll see if the attached patch makes it through this time.  (i
> haven't re-attached it, which i think was the problem last time.)  if
> not, look forward to a followup...

[-- Attachment #2: emacs-pgg-omnnibus.patch-06 --]
[-- Type: application/octet-stream, Size: 24517 bytes --]

Index: ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/ChangeLog,v
retrieving revision 1.393
diff -u -r1.393 ChangeLog
--- ChangeLog	9 Oct 2005 15:39:09 -0000	1.393
+++ ChangeLog	12 Oct 2005 23:31:39 -0000
@@ -1,3 +1,78 @@
+2005-10-12  Ken Manheimer  <ken.manheimer@gmail.com>
+
+	* pgg-gpg.el
+	(pgg-gpg-select-matching-key): fixed: look at the right part of the
+	decoded armor to find the key-identifier
+	(pgg-gpg-lookup-key-owner): new function to return the
+	human-readable identifier of a key owner.
+	(pgg-gpg-lookup-id-from-key-owner): make it easy to identify the
+	key itself.
+	(pgg-gpg-decrypt-region): prompt with the key owner (rather
+	than the key value) if we have a key and can match it against a
+	secret key.  also, added an XXX note pointing out fact that the
+	prompt only indicates the first matching key.
+	(pgg-add-passphrase-to-cache): <= pgg-add-passphrase-cache
+	(pgg-remove-passphrase-from-cache) <= pgg-remove-passphrase-cache
+
+	* pgg.el (pgg-decrypt): passing along 'passphrase' in call to
+	pgg-decrypt-region; i overlooked this one in my previous patch.
+	(pgg-pending-timers): a new hash for tracking the passphrase cache
+	timers, so that new ones supercede old ones.
+	(pgg-add-passphrase-to-cache): renamed from
+	`pgg-add-passphrase-cache' to reduce confusion.  and modified to
+	cancel old timers when new ones are added.
+	(pgg-remove-passphrase-from-cache): renamed from
+	`pgg-remove-passphrase-cache' to reduce confusion.  and modified
+	to cancel old timers when their keys are removed from the cache.
+	(pgg-cancel-timer): in mainline gnu emacs, an alias for
+	cancel-timer; in xemacs, an indirection to delete-itimer.
+	(pgg-read-passphrase-from-cache, pgg-read-passphrase): extracted 
+	pgg-read-passphrase-from-cache from pgg-read-passphrase so users
+	can only check cache without risk of prompting.  corrected bug in
+	notruncate  behavior.
+	(pgg-read-passphrase-from-cache, pgg-read-passphrase,
+	pgg-add-passphrase-cache, pgg-remove-passphrase-cache): added
+	informative docstrings.
+	(pgg-decrypt): convey provided passphrase in subordinate call to
+	pgg-decrypt-region (missed that in a prior patch)
+
+2005-10-08  Ken Manheimer <ken.manheimer+emacs@gmail.com>
+
+	* pgg.el (pgg-encrypt-region, pgg-encrypt-symmetric-region,
+	pgg-encrypt-symmetric, pgg-encrypt, pgg-decrypt-region,
+	pgg-decrypt, pgg-sign-region, pgg-sign):
+	add optional 'passphrase' argument to all these routines, so the
+	passphrase can be managed externally and then passed in to the
+	system.
+
+	* pgg.el (pgg-read-passphrase, pgg-add-passphrase-cache,
+	pgg-remove-passphrase-cache): add optional 'notruncate' argument,
+	so the passphrase cache can be used reliably with identifiers
+	besides a pgp packet's key id.
+
+	* pgg-gpg.el (pgg-pgp-encrypt-region,
+	pgg-pgp-encrypt-symmetric-region, pgg-pgp-encrypt-symmetric,
+	pgg-pgp-encrypt, pgg-pgp-decrypt-region, pgg-pgp-decrypt,
+	pgg-pgp-sign-region, pgg-pgp-sign): add optional 'passphrase'
+	argument to all these routines, so the passphrase can be managed
+	externally and passed in to the system.
+
+	* pgg-gpg.el (pgg-gpg-possibly-cache-passphrase): add optional
+	'notruncate' argument, so the passphrase cache can be used
+	reliably with identifiers besides a pgp packet's key id.
+
+2005-10-06  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg-gpg.el (pgg-gpg-encrypt-symmetric-region): New function for
+	symmetric encryption.
+	(pgg-gpg-symmetric-key-p): New function to check for an symmetric
+	encrypted session key.
+	(pgg-gpg-decrypt-region): When decrypting a symmetric encrypted
+	message ask for the passphrase in a proper way.
+
+	* pgg.el (pgg-encrypt-symmetric,pgg-encrypt-symmetric-region):
+	New user commands for symmetric encryption.
+
 2005-10-09  Daniel Brockman <daniel@brockman.se>
 
 	* format-spec.el (format-spec): Propagate text properties of % spec.
Index: pgg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg.el,v
retrieving revision 1.8
diff -u -r1.8 pgg.el
--- pgg.el	26 Aug 2005 00:02:05 -0000	1.8
+++ pgg.el	12 Oct 2005 23:31:39 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP
 
@@ -67,26 +68,110 @@
     (set-window-buffer window buffer)
     (shrink-window-if-larger-than-buffer window)))
 
+;; XXX `pgg-display-output-buffer' is a horrible name for this function.
+;;     It should be something like `pgg-situate-output-or-display-error'.
 (defun pgg-display-output-buffer (start end status)
+  "Situate en/decryption results or pop up an error buffer.
+
+Text from START to END is replaced by contents of output buffer if STATUS
+is true, or else the output buffer is displayed."
   (if status
-      (progn
-	(delete-region start end)
-	(insert-buffer-substring pgg-output-buffer)
-	(decode-coding-region start (point) buffer-file-coding-system))
-    (let ((temp-buffer-show-function
-	   (function pgg-temp-buffer-show-function)))
-      (with-output-to-temp-buffer pgg-echo-buffer
-	(set-buffer standard-output)
-	(insert-buffer-substring pgg-errors-buffer)))))
+      (pgg-situate-output start end)
+    (pgg-display-error-buffer)))
+
+(defun pgg-situate-output (start end)
+  "Place en/decryption result in place of current text from START to END."
+  (delete-region start end)
+  (insert-buffer-substring pgg-output-buffer)
+  (decode-coding-region start (point) buffer-file-coding-system))
+
+(defun pgg-display-error-buffer ()
+  "Pop up an error buffer indicating the reason for an en/decryption failure."
+  (let ((temp-buffer-show-function
+         (function pgg-temp-buffer-show-function)))
+    (with-output-to-temp-buffer pgg-echo-buffer
+      (set-buffer standard-output)
+      (insert-buffer-substring pgg-errors-buffer))))
 
 (defvar pgg-passphrase-cache (make-vector 7 0))
 
-(defun pgg-read-passphrase (prompt &optional key)
-  (or (and pgg-cache-passphrase
-	   key (setq key (pgg-truncate-key-identifier key))
-	   (symbol-value (intern-soft key pgg-passphrase-cache)))
+(defvar pgg-pending-timers (make-vector 7 0)
+  "Hash table for managing scheduled pgg cache management timers.
+
+We associate key and timer, so the timer can be cancelled if a new
+timeout for the key is set while an old one is still pending.")
+
+(defun pgg-read-passphrase (prompt &optional key notruncate)
+  "Using PROMPT, obtain passphrase for KEY from cache or user.
+
+Truncate the key to 8 trailing characters unless NOTRUNCATE is true
+\(default false).
+
+Custom variables `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry'
+regulate cache behavior."
+  (or (pgg-read-passphrase-from-cache key notruncate)
       (read-passwd prompt)))
 
+(defun pgg-read-passphrase-from-cache (key &optional notruncate)
+  "Obtain passphrase for KEY from time-limited passphrase cache.
+
+Truncate the key to 8 trailing characters unless NOTRUNCATE is true
+\(default false).
+
+Custom variables `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry'
+regulate cache behavior."
+  (and pgg-cache-passphrase
+       key (or notruncate
+                (setq key (pgg-truncate-key-identifier key)))
+       (symbol-value (intern-soft key pgg-passphrase-cache))))
+
+(defun pgg-add-passphrase-to-cache (key passphrase &optional notruncate)
+  "Associate KEY with PASSPHRASE in time-limited passphrase cache.
+
+Truncate the key to 8 trailing characters unless NOTRUNCATE is true
+\(default false).
+
+Custom variables `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry'
+regulate cache behavior."
+
+  (let* ((key (if notruncate key (pgg-truncate-key-identifier key)))
+         (interned-timer-key (intern-soft key pgg-pending-timers))
+         (old-timer (symbol-value interned-timer-key))
+         new-timer)
+    (when old-timer
+        (cancel-timer old-timer)
+        (unintern interned-timer-key pgg-pending-timers))
+    (set (intern key pgg-passphrase-cache)
+         passphrase)
+    (set (intern key pgg-pending-timers)
+         (pgg-run-at-time pgg-passphrase-cache-expiry nil
+                           #'pgg-remove-passphrase-from-cache
+                           key notruncate))))
+
+(defun pgg-remove-passphrase-from-cache (key &optional notruncate)
+  "Omit passphrase associated with KEY in time-limited passphrase cache.
+
+Truncate the key to 8 trailing characters unless NOTRUNCATE is true
+\(default false).
+
+This is a no-op if there is not entry for KEY (eg, it's already expired.
+
+The memory for the passphrase is filled with underscores to clear any
+references to it.
+
+Custom variables `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry'
+regulate cache behavior."
+  (let* ((passphrase (pgg-read-passphrase-from-cache key notruncate))
+         (key (if notruncate key (pgg-truncate-key-identifier key)))
+         (interned-timer-key (intern-soft key pgg-pending-timers))
+         (old-timer (symbol-value interned-timer-key)))
+    (when passphrase
+      (fillarray passphrase ?_)
+      (unintern key pgg-passphrase-cache))
+    (when old-timer
+      (pgg-cancel-timer old-timer)
+      (unintern interned-timer-key pgg-pending-timers))))
+
 (eval-when-compile
   (defmacro pgg-run-at-time-1 (time repeat function args)
     (when (featurep 'xemacs)
@@ -151,27 +236,19 @@
 
 (eval-and-compile
   (if (featurep 'xemacs)
-      (defun pgg-run-at-time (time repeat function &rest args)
-	"Emulating function run as `run-at-time'.
+      (progn
+        (defun pgg-run-at-time (time repeat function &rest args)
+          "Emulating function run as `run-at-time'.
 TIME should be nil meaning now, or a number of seconds from now.
 Return an itimer object which can be used in either `delete-itimer'
 or `cancel-timer'."
-	(pgg-run-at-time-1 time repeat function args))
-    (defalias 'pgg-run-at-time 'run-at-time)))
-
-(defun pgg-add-passphrase-cache (key passphrase)
-  (setq key (pgg-truncate-key-identifier key))
-  (set (intern key pgg-passphrase-cache)
-       passphrase)
-  (pgg-run-at-time pgg-passphrase-cache-expiry nil
-		   #'pgg-remove-passphrase-cache
-		   key))
-
-(defun pgg-remove-passphrase-cache (key)
-  (let ((passphrase (symbol-value (intern-soft key pgg-passphrase-cache))))
-    (when passphrase
-      (fillarray passphrase ?_)
-      (unintern key pgg-passphrase-cache))))
+          (pgg-run-at-time-1 time repeat function args))
+        (defun pgg-cancel-timer (timer)
+          "Emulate cancel-timer for xemacs."
+          (delete-itimer timer))
+        )
+    (defalias 'pgg-run-at-time 'run-at-time)
+    (defalias 'pgg-cancel-timer 'cancel-timer)))
 
 (defmacro pgg-convert-lbt-region (start end lbt)
   `(let ((pgg-conversion-end (set-marker (make-marker) ,end)))
@@ -222,93 +299,156 @@
 ;;;
 
 ;;;###autoload
-(defun pgg-encrypt-region (start end rcpts &optional sign)
+(defun pgg-encrypt-region (start end rcpts &optional sign passphrase)
   "Encrypt the current region between START and END for RCPTS.
-If optional argument SIGN is non-nil, do a combined sign and encrypt."
+
+If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive
    (list (region-beginning)(region-end)
 	 (split-string (read-string "Recipients: ") "[ \t,]+")))
   (let ((status
 	 (pgg-save-coding-system start end
 	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
-		       (point-min) (point-max) rcpts sign))))
+		       (point-min) (point-max) rcpts sign passphrase))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-encrypt (rcpts &optional sign start end)
+(defun pgg-encrypt-symmetric-region (start end &optional passphrase)
+  "Encrypt the current region between START and END symmetric with passphrase.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+cache or user."
+  (interactive "r")
+  (let ((status
+	 (pgg-save-coding-system start end
+	   (pgg-invoke "encrypt-symmetric-region" 
+		       (or pgg-scheme pgg-default-scheme)
+		       (point-min) (point-max) passphrase))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric (&optional start end passphrase)
+  "Encrypt the current buffer using a symmetric, rather than key-pair, cipher.
+
+If optional arguments START and END are specified, only encrypt within
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
+  (interactive)
+  (let* ((start (or start (point-min)))
+	 (end (or end (point-max)))
+	 (status (pgg-encrypt-symmetric-region start end passphrase)))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt (rcpts &optional sign start end passphrase)
   "Encrypt the current buffer for RCPTS.
+
 If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
 If optional arguments START and END are specified, only encrypt within
-the region."
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive (list (split-string (read-string "Recipients: ") "[ \t,]+")))
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
-	 (status (pgg-encrypt-region start end rcpts sign)))
+	 (status (pgg-encrypt-region start end rcpts sign passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-decrypt-region (start end)
-  "Decrypt the current region between START and END."
+(defun pgg-decrypt-region (start end &optional passphrase)
+  "Decrypt the current region between START and END.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "r")
   (let* ((buf (current-buffer))
 	 (status
 	  (pgg-save-coding-system start end
 	    (pgg-invoke "decrypt-region" (or pgg-scheme pgg-default-scheme)
-			(point-min) (point-max)))))
+			(point-min) (point-max) passphrase))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-decrypt (&optional start end)
+(defun pgg-decrypt (&optional start end passphrase)
   "Decrypt the current buffer.
+
 If optional arguments START and END are specified, only decrypt within
-the region."
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "")
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
-	 (status (pgg-decrypt-region start end)))
+	 (status (pgg-decrypt-region start end passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-sign-region (start end &optional cleartext)
+(defun pgg-sign-region (start end &optional cleartext passphrase)
   "Make the signature from text between START and END.
+
 If the optional 3rd argument CLEARTEXT is non-nil, it does not create
 a detached signature.
+
 If this function is called interactively, CLEARTEXT is enabled
-and the the output is displayed."
+and the the output is displayed.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "r")
   (let ((status (pgg-save-coding-system start end
 		  (pgg-invoke "sign-region" (or pgg-scheme pgg-default-scheme)
 			      (point-min) (point-max)
-			      (or (interactive-p) cleartext)))))
+			      (or (interactive-p) cleartext)
+                              passphrase))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-sign (&optional cleartext start end)
+(defun pgg-sign (&optional cleartext start end passphrase)
   "Sign the current buffer.
+
 If the optional argument CLEARTEXT is non-nil, it does not create a
 detached signature.
+
 If optional arguments START and END are specified, only sign data
 within the region.
+
 If this function is called interactively, CLEARTEXT is enabled
-and the the output is displayed."
+and the the output is displayed.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "")
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
-	 (status (pgg-sign-region start end (or (interactive-p) cleartext))))
+	 (status (pgg-sign-region start end
+                                  (or (interactive-p) cleartext)
+                                  passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
-  
+
 ;;;###autoload
 (defun pgg-verify-region (start end &optional signature fetch)
   "Verify the current region between START and END.
Index: pgg-gpg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/pgg-gpg.el,v
retrieving revision 1.7
diff -u -r1.7 pgg-gpg.el
--- pgg-gpg.el	8 Oct 2005 08:43:33 -0000	1.7
+++ pgg-gpg.el	12 Oct 2005 23:31:39 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -96,19 +97,20 @@
 	  (delete-file output-file-name))
       (set-default-file-modes orig-mode))))
 
-(defun pgg-gpg-possibly-cache-passphrase (passphrase &optional key)
+(defun pgg-gpg-possibly-cache-passphrase (passphrase &optional key notruncate)
   (if (and pgg-cache-passphrase
 	   (progn
 	     (goto-char (point-min))
 	     (re-search-forward "^\\[GNUPG:] \\(GOOD_PASSPHRASE\\>\\)\\|\\(SIG_CREATED\\)" nil t)))
-      (pgg-add-passphrase-cache
+      (pgg-add-passphrase-to-cache
        (or key
 	   (progn
 	     (goto-char (point-min))
 	     (if (re-search-forward
 		  "^\\[GNUPG:] NEED_PASSPHRASE\\(_PIN\\)? \\w+ ?\\w*" nil t)
 		 (substring (match-string 0) -8))))
-       passphrase)))
+       passphrase
+       notruncate)))
 
 (defvar pgg-gpg-all-secret-keys 'unknown)
 
@@ -139,18 +141,53 @@
 			     nil t)
 	  (substring (match-string 2) 8)))))
 
-(defun pgg-gpg-encrypt-region (start end recipients &optional sign)
+(defun pgg-gpg-lookup-key-owner (string &optional all)
+  "Search keys associated with STRING and return owner of identified key.
+
+The value may be just the bare key id, or it may be a combination of the
+user name associated with the key and the key id, with the key id enclosed
+in \"<...>\" angle brackets.
+
+Optional ALL non-nil means search all keys, including secret keys."
+  (let ((args (list "--with-colons" "--no-greeting" "--batch"
+		    (if all "--list-secret-keys" "--list-keys")
+		    string))
+        (key-regexp (concat "^\\(sec\\|pub\\)"
+                            ":[^:]*:[^:]*:[^:]*:\\([^:]*\\):[^:]*"
+                            ":[^:]*:[^:]*:[^:]*:\\([^:]*\\):"))
+        )
+    (with-temp-buffer
+      (apply #'call-process pgg-gpg-program nil t nil args)
+      (goto-char (point-min))
+      (if (re-search-forward key-regexp
+                             nil t)
+          (match-string 3)))))
+
+(defun pgg-gpg-key-id-from-key-owner (key-owner)
+  (cond ((not key-owner) nil)
+        ;; Extract bare key id from outermost paired angle brackets, if any:
+        ((string-match "[^<]*<\\(.+\\)>[^>]*" key-owner)
+         (substring key-owner (match-beginning 1)(match-end 1)))
+        (key-owner))
+  )
+
+(defun pgg-gpg-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END.
-If optional argument SIGN is non-nil, do a combined sign and encrypt."
+
+If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
-	 (passphrase
-	  (when sign
-	    (pgg-read-passphrase
-	     (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	     pgg-gpg-user-id)))
+	 (passphrase (or passphrase
+                         (when sign
+                           (pgg-read-passphrase
+                            (format "GnuPG passphrase for %s: "
+                                    pgg-gpg-user-id)
+                            pgg-gpg-user-id))))
 	 (args
 	  (append
-	   (list "--batch" "--armor" "--always-trust" "--encrypt")
+	   (list "--batch" "--textmode" "--armor" "--always-trust" "--encrypt")
 	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
 	   (if recipients
 	       (apply #'nconc
@@ -169,19 +206,46 @@
 	(pgg-gpg-possibly-cache-passphrase passphrase)))
     (pgg-process-when-success)))
 
-(defun pgg-gpg-decrypt-region (start end)
-  "Decrypt the current region between START and END."
+(defun pgg-gpg-encrypt-symmetric-region (start end &optional passphrase)
+  "Encrypt the current region between START and END with symmetric cipher.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
+  (let* ((passphrase (or passphrase
+                         (pgg-read-passphrase
+                          "GnuPG passphrase for symmetric encryption: ")))
+	 (args
+	  (append (list "--batch" "--textmode" "--armor" "--symmetric" ))))
+    (pgg-as-lbt start end 'CRLF
+      (pgg-gpg-process-region start end passphrase pgg-gpg-program args))
+    (pgg-process-when-success)))
+
+(defun pgg-gpg-decrypt-region (start end &optional passphrase)
+  "Decrypt the current region between START and END.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((current-buffer (current-buffer))
 	 (message-keys (with-temp-buffer
 			 (insert-buffer-substring current-buffer)
 			 (pgg-decode-armor-region (point-min) (point-max))))
 	 (secret-keys (pgg-gpg-lookup-all-secret-keys))
+         ;; XXX the user is stuck if they need to use the passphrase for
+         ;;     any but the first secret key for which the message is
+         ;;     encrypted.  ideally, we would incrementally give them a
+         ;;     chance with subsequent keys each time they fail with one.
 	 (key (pgg-gpg-select-matching-key message-keys secret-keys))
-	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
-	 (passphrase
-	  (pgg-read-passphrase
-	   (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	   pgg-gpg-user-id))
+         (key-owner (and key (pgg-gpg-lookup-key-owner key t)))
+	 (key-id (pgg-gpg-key-id-from-key-owner key-owner))
+	 (pgg-gpg-user-id (or key-id key
+	                      pgg-gpg-user-id pgg-default-user-id))
+	 (passphrase (or passphrase
+                         (pgg-read-passphrase
+                          (format (if (pgg-gpg-symmetric-key-p message-keys)
+                                      "Passphrase for symmetric decryption: "
+                                    "GnuPG passphrase for %s: ")
+                                  (or key-owner "??"))
+                          pgg-gpg-user-id)))
 	 (args '("--batch" "--decrypt")))
     (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
     (with-current-buffer pgg-errors-buffer
@@ -189,11 +253,20 @@
       (goto-char (point-min))
       (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
 
+(defun pgg-gpg-symmetric-key-p (message-keys)
+  "True if decoded armor MESSAGE-KEYS has symmetric encryption indicator."
+  (let (result)
+    (dolist (key message-keys result)
+      (when (and (eq (car key) 3)
+		 (member '(symmetric-key-algorithm) key))
+	(setq result key)))))
+
 (defun pgg-gpg-select-matching-key (message-keys secret-keys)
   "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."
   (loop for message-key in message-keys
 	for message-key-id = (and (equal (car message-key) 1)
-				  (cdr (assq 'key-identifier message-key)))
+				  (cdr (assq 'key-identifier
+                                             (cdr message-key))))
 	for key = (and message-key-id (pgg-lookup-key message-key-id 'encrypt))
 	when (and key (member key secret-keys)) return key))
 

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: new version of allout.el - patch and ChangeLog
  2005-10-01 22:33   ` Ken Manheimer
@ 2005-10-20 13:57     ` Ken Manheimer
  0 siblings, 0 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-20 13:57 UTC (permalink / raw)
  Cc: rms

[-- Attachment #1: Type: text/plain, Size: 612 bytes --]

This is a patch, ChangeLog, and NEWS file for a new version of allout.
 the allout version differs from the version i submitted recently in
that it bases it's new encryption features on pgg instead of
mailcrypt/crypt++ - mailcrypt/crypt++ are out of the picture.

the new encryption features depend on the new pgg version of my recent
pgg patches, also posted here.  i'm hoping the upgrades can be
coordinated so it all comes out harmoniously with the next release. 
(i'm going to post something in the pgg thread asking about the
disposition of those patches.)

tnx!

ken
ken.manheimer@gmail.com

[-- Attachment #2: allout-news.txt --]
[-- Type: text/plain, Size: 1176 bytes --]

** allout (extensive outline navigation and authoring mode), significantly
   updated:

 - topic cryptography added, enabling easy gpg topic encryption and
   decryption.  per-topic basis enables interspersing encrypted-text and
   clear-text within a single file to your hearts content, using symmetric
   and/or public key modes.  time-limited key caching, user-provided
   symmetric key hinting and consitency verification, auto-encryption of
   pending topics on save, and more, make it easy to use encryption in
   powerful ways.

 - many substantial fixes and refinements, including:

   - repaired inhibition of inadvertant edits to concealed text
   - repaired retention of topic body hanging indent upon topic depth shifts
   - prevent "containment discontinuities" where a topic is shifted deeper
     than the offspring-depth of its' container
   - easy to adopt the distinctive bullet of a topic in a topic created
     relative to it, or else select a new one, or else use the common topic
     bullet
   - plain bullets, by default, now alternate between only two characters
     ('.' and ','), yielding less cluttered outlines.
   - many internal fixes.








[-- Attachment #3: allout-ChangeLog.txt --]
[-- Type: text/plain, Size: 6996 bytes --]

2005-09-30  Ken Manheimer  <ken.manheimer@gmail.com>

	* allout.el: omnibus changes

	  - new subsystem supporting easy gpg topic encryption/decryption.

	    (function-specific change details are below the following
	    synopsis)

	    salient features:

	    - both public- and symmetric-key modes are supported.
	    - encryption being on a per-topic basis means you can
	      intersperse encrypted and clear-text data in a single file
	      to your heart's content.
	    - user-provided symmetric-key hints, with consistency
	      verification to help user avoid confusion
	    - time-limited passphrase reuse, a la (and using) pgg's
	      passphrase cache
	    - write-file-hook and auto-save-hook activities to support auto
	      encryption of pending topics on save; provision to skip
	      currently-edited topic to avoid editing disturbance

	    topic encryption functionality depends on the latst verion of
	    pgg.  (non-encryption allout functionality does not depend on
	    them.)

	    docstring for `allout-toggle-current-subtree-encryption'
	    and customization variables provide detailed description.

	    code changes:

	    'allout customization subgroup now positioned in 'outlines
	    group (instead of prior 'editing group)

	    central topic-encryption entry point:
	    (outline-toggle-current-subtree-encryption)

	    other new encryption routines:
	    (allout-encrypt-string, allout-encrypted-topic-p,
            allout-encrypted-text-type, allout-obtain-passphrase,
	    allout-create-encryption-passphrase-verifier,
	    allout-update-passphrase-mnemonic-aids,
	    allout-get-encryption-passphrase-verifier,
            allout-verify-passphrase, allout-next-topic-pending-encryption,
	    allout-encrypt-decrypted, allout-encrypted-type-prefix)

	    new customization variables:
	    (outline-topic-encryption-bullet,
	    outline-passphrase-verifier-handling,
	    outline-passphrase-hint-handling,
	    outline-encrypt-unencrypted-on-saves)

	    new operational variables:
	    (allout-file-passphrase-verifier-string, allout-encryption-scheme,
	    allout-passphrase-verifier-string, allout-passphrase-hint-string,
	    allout-after-save-decrypt)

	    new hook functions for auto-encryption of pending topics:
	    (allout-write-file-hook-handler, allout-auto-save-hook-handler,
	    allout-after-saves-handler)

	    (allout-post-command-business): do allout-after-save-decrypt

	  - added mechanism for adding and adjusting settings of Emacs file
	    variables.

	    (allout-enable-file-variable-adjustment): custom var to enable
	    mechanism
	    (allout-adjust-file-variable, allout-file-vars-section-data):
	    mechanism implementation
	    (outlineify-sticky): use file vars mechanism

	  - replaced broken mechanism for inhibition of concealed-text edits

	    using read-only text instead of before-change-functions,
	    because the latter can no longer veto the changes without being
	    disabled.  read-only text is more suitable and less
	    complicated, anyway.

	    (it also noticably slows massive exposure changes, but i
	    consider the performance acceptable.  eg, i have blanket
	    auto-exposure set for my daily-notes log, which has real-world
	    intricacy in a 1.1 Mb, 7000 topic outline, and have no problems
	    working with it on a 200 MhZ windows laptop.)

	    (allout-inhibit-protection, allout-during-write-cue,
	    allout-override-protect, allout-before-change-protect): removed

	    (allout-flag-region, allout-open-topic): revised to adjust
	    read-only text

	    (allout-open-line-not-read-only): added to facilitate read-only
	    text based protection

	    (allout-kill-line): revised to adjust read-only text, clue the
	    user about the inhibition

	  - (allout-unprotected): robustified with an unwind-protect

	  - disallow manually shifting a topic deeper than the offspring
	    depth of the previous topic - avoiding confusing "containment
	    discontinuities"

	    (allout-shift-in, allout-shift-out)

	  - fixed retention of body relative hanging indent during
	    promotion of collapsed bodies

	    (allout-reindent-bodies)

	  - made it easy to open new topic with same bullet as current
	    topic - topic creation functions provided with any universal
	    argument provokes now prompt for bullet, defaulting to the
	    bullet of the previous topic.  very ergonomic.

	    (allout-open-topic)

	  - (allout-plain-bullets-string, allout-distinctive-bullets-string):
	    plain bullet alternates '.'	 period and ',' comma only.  all
	    other bullets are relegated to special status (but
	    customizable)

	  - (allout-end-of-entry): renamed from 'allout-end-of-current-entry
	    since it actually operates w.r.t. most immediately containing
	    entry, visible or not

	    (allout-hide-current-entry, allout-show-current-entry): use the
	    revised version

	  - (allout-old-expose-topic): solidify deprecation.

	  - (allout-end-of-subtree): added, so we can span concealed as
	    well as visible topics.
	    (allout-end-of-current-subtree): use `allout-end-of-subtree'.

	  - (allout-end-of-current-heading): tweaked to just respect the
	    first line

	  - (allout-get-body-text): added

	  - (allout-ascend-to-depth, allout-ascend): position at end of
	    prefix when invoked interactively

	  - (allout-up-current-level): use `interactive-p'

	  - (allout-mode, allout-init): miscellaneous docstring and
	    operational refinements, as well as hookups of new encryption
	    stuff

	  - comments and routine names better distinguish between:
	    - topic body - the text contained after a header
	    - topic header - the first line, before the body
	    - topic entry - the header, body, and offspring

	  - (allout-beginning-of-current-entry): now works as advertised

	  - (allout-end-of-current-entry): relieved of superfluous
	    allout-show-entry

	  - (allout-isearch-rectification): refine condition for isearching
	    (allout-isearch-abort, allout-enwrap-isearch)

	  - reconciled with distributed allout.el 1.61 (current CVS version
	    as of 09/30/2005), including interactive-p fixes, typo and
	    coding style fixes, change of function prefix to "allout-", etc,
	    and fixed problem created in outline yanking due to the
	    interactive-p fixes

          - using key substitution placeholders in allout-mode decstring.

	  - relocated some macros
	    (allout-flag-region, my-region-active-p)

	  - refined many docstrings, including anything from correcting
	    typos to conceptual clarification and correction

	  - (allout-title): fallback title is '(buffer-name)', not
	    non-existing '(current-buffer-name)'

	  - (subst-char-in-string): define if absent (for some xemacs versions)

          - using `(featurep 'xemacs)' to distinguish between emacs and
            xemacs.

	  - corrected commentary 'keywords' to legitimate ones

	  - updated comentary author info (using my current email address,
	    obscurified)








[-- Attachment #4: allout.el-patch --]
[-- Type: application/octet-stream, Size: 119044 bytes --]

Index: allout.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/allout.el,v
retrieving revision 1.61
diff -u -r1.61 allout.el
--- allout.el	6 Aug 2005 22:13:41 -0000	1.61
+++ allout.el	20 Oct 2005 13:47:00 -0000
@@ -3,10 +3,11 @@
 ;; Copyright (C) 1992, 1993, 1994, 2001, 2002, 2003, 2004,
 ;;   2005 Free Software Foundation, Inc.
 
-;; Author: Ken Manheimer <klm@zope.com>
-;; Maintainer: Ken Manheimer <klm@zope.com>
+;; Author: Ken Manheimer <ken dot manheimer at gmail dot com>
+;; Maintainer: Ken Manheimer <ken dot manheimer at gmail dot com>
 ;; Created: Dec 1991 - first release to usenet
-;; Keywords: outlines mode wp languages
+;; Version: $Id: allout.el,v 1.76 2005/10/20 05:26:32 klm Exp $||
+;; Keywords: outlines wp languages
 
 ;; This file is part of GNU Emacs.
 
@@ -34,43 +35,60 @@
 ;; programming languages.  (For an example, see the allout code
 ;; itself, which is organized in ;; an outline framework.)
 ;;
-;; In addition to outline navigation and exposure, allout includes:
+;; Some features:
 ;;
-;;  - topic-oriented repositioning, cut, and paste
-;;  - integral outline exposure-layout
-;;  - incremental search with dynamic exposure and reconcealment of hidden text
+;;  - classic outline-mode topic-oriented navigation and exposure adjustment
+;;  - topic-oriented editing including coherent topic and subtopic
+;;    creation, promotion, demotion, cut/paste across depths, etc
+;;  - incremental search with dynamic exposure and reconcealment of text
+;;  - customizable bullet format enbles programming-language specific
+;;    outlining, for ultimate code-folding editing.  (allout code itself is
+;;    formatted as an outline - do ESC-x eval-current-buffer in allout.el
+;;    to try it out.)
+;;  - configurable per-file initial exposure settings
+;;  - symmetric-key and key-pair topic encryption, plus symmetric passphrase
+;;    mnemonic support, with verification against an established passphrase
+;;    (using a stashed encrypted dummy string) and user-supplied hint
+;;    maintenance.  (see allout-toggle-current-subtree-encryption docstring.)
 ;;  - automatic topic-number maintenance
-;;  - "Hot-spot" operation, for single-keystroke maneuvering and
-;;    exposure control.  (See the `allout-mode' docstring.)
+;;  - "hot-spot" operation, for single-keystroke maneuvering and
+;;    exposure control (see the allout-mode docstring)
+;;  - easy rendering of exposed portions into numbered, latex, indented, etc
+;;    outline styles
 ;;
-;; and many other features.
+;; and more.
 ;;
 ;; The outline menubar additions provide quick reference to many of
-;; the features, and see the docstring of the function `allout-init'
-;; for instructions on priming your Emacs session for automatic
-;; activation of `allout-mode'.
+;; the features, and see the docstring of the variable `allout-init'
+;; for instructions on priming your emacs session for automatic
+;; activation of allout-mode.
 ;;
 ;; See the docstring of the variables `allout-layout' and
 ;; `allout-auto-activation' for details on automatic activation of
-;; allout `allout-mode' as a minor mode.  (It has changed since allout
+;; `allout-mode' as a minor mode.  (It has changed since allout
 ;; 3.x, for those of you that depend on the old method.)
 ;;
 ;; Note - the lines beginning with `;;;_' are outline topic headers.
 ;;        Just `ESC-x eval-current-buffer' to give it a whirl.
 
-;; Ken Manheimer	klm@zope.com
+;; ken manheimer (ken dot manheimer at gmail dot com)
 
 ;;; Code:
 
 ;;;_* Provide
+;(provide 'outline)
 (provide 'allout)
 
+;;;_* Dependency autoloads
+(eval-when-compile 'cl)                 ; otherwise, flet compilation fouls
+(autoload 'pgg-gpg-symmetric-key-p "pgg-gpg"
+  "True if decoded armor MESSAGE-KEYS has symmetric encryption indicator.")
+
 ;;;_* USER CUSTOMIZATION VARIABLES:
 (defgroup allout nil
   "Extensive outline mode for use alone and with other modes."
   :prefix "allout-"
-  :group 'editing
-  :version "22.1")
+  :group 'outlines)
 
 ;;;_ + Layout, Mode, and Topic Header Configuration
 
@@ -111,8 +129,8 @@
 
 A list value specifies a default layout for the current buffer, to be
 applied upon activation of `allout-mode'.  Any non-nil value will
-automatically trigger `allout-mode', provided `allout-init'
-has been called to enable it.
+automatically trigger `allout-mode' \(provided `allout-init' has been called
+to enable this behavior).
 
 See the docstring for `allout-init' for details on setting up for
 auto-mode-activation, and for `allout-expose-topic' for the format of
@@ -171,7 +189,7 @@
   :group 'allout)
 (make-variable-buffer-local 'allout-primary-bullet)
 ;;;_  = allout-plain-bullets-string
-(defcustom allout-plain-bullets-string ".:,;"
+(defcustom allout-plain-bullets-string ".,"
   "*The bullets normally used in outline topic prefixes.
 
 See `allout-distinctive-bullets-string' for the other kind of
@@ -185,7 +203,7 @@
   :group 'allout)
 (make-variable-buffer-local 'allout-plain-bullets-string)
 ;;;_  = allout-distinctive-bullets-string
-(defcustom allout-distinctive-bullets-string "*+-=>([{}&!?#%\"X@$~_\\"
+(defcustom allout-distinctive-bullets-string "*+-=>()[{}&!?#%\"X@$~_\\:;^"
   "*Persistent outline header bullets used to distinguish special topics.
 
 These bullets are used to distinguish topics from the run-of-the-mill
@@ -198,12 +216,13 @@
  `?' question topics
  `\(' parenthetic comment \(with a matching close paren inside)
  `[' meta-note \(with a matching close ] inside)
- `\"' a quote
+ `\"' a quotation
  `=' value settings
  `~' \"more or less\"
+ `^' see above
 
-... just for example.  (`#' typically has a special meaning to the
-software, according to the value of `allout-numbered-bullet'.)
+ ... for example.  (`#' typically has a special meaning to the software,
+according to the value of `allout-numbered-bullet'.)
 
 See `allout-plain-bullets-string' for the selection of
 alternating bullets.
@@ -337,7 +356,6 @@
 Set this var to the bullet you want to use for file cross-references."
   :type '(choice (const nil) string)
   :group 'allout)
-
 ;;;_  = allout-presentation-padding
 (defcustom allout-presentation-padding 2
   "*Presentation-format white-space padding factor, for greater indent."
@@ -381,7 +399,7 @@
   :type 'string
   :group 'allout)
 ;;;_  - allout-title
-(defcustom allout-title '(or buffer-file-name (current-buffer-name))
+(defcustom allout-title '(or buffer-file-name (buffer-name))
   "*Expression to be evaluated to determine the title for LaTeX
 formatted copy."
   :type 'sexp
@@ -397,6 +415,69 @@
   :type 'string
   :group 'allout)
 
+;;;_ + Topic encryption
+;;;_  = allout-topic-encryption-bullet
+(defcustom allout-topic-encryption-bullet "~"
+  "*Bullet signifying encryption of the entry's body."
+  :type '(choice (const nil) string)
+  :group 'allout)
+;;;_  = allout-passphrase-verifier-handling
+(defcustom allout-passphrase-verifier-handling t
+  "*Enable use of symmetric encryption passphrase verifier if non-nil.
+
+See the docstring for the `allout-enable-file-variable-adjustment'
+variable for details about allout ajustment of file variables."
+  :type 'boolean
+  :group 'allout)
+(make-variable-buffer-local 'allout-passphrase-verifier-handling)
+;;;_  = allout-passphrase-hint-handling
+(defcustom allout-passphrase-hint-handling 'always
+  "*Dictate outline encryption passphrase reminder handling:
+
+ always - always show reminder when prompting
+ needed - show reminder on passphrase entry failure
+ disabled - never present or adjust reminder
+
+See the docstring for the `allout-enable-file-variable-adjustment'
+variable for details about allout ajustment of file variables."
+  :type '(choice (const always)
+                 (const needed)
+                 (const disabled))
+  :group 'allout)
+(make-variable-buffer-local 'allout-passphrase-hint-handling)
+;;;_  = allout-encrypt-unencrypted-on-saves
+(defcustom allout-encrypt-unencrypted-on-saves 'except-current
+  "*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))
+  :group 'allout)
+(make-variable-buffer-local 'allout-encrypt-unencrypted-on-saves)
+
 ;;;_ + Miscellaneous customization
 
 ;;;_  = allout-command-prefix
@@ -422,13 +503,15 @@
         ("\C-f" allout-forward-current-level)
         ("\C-b" allout-backward-current-level)
         ("\C-a" allout-beginning-of-current-entry)
-        ("\C-e" allout-end-of-current-entry)
+        ("\C-e" allout-end-of-entry)
                                         ; Exposure commands:
         ("\C-i" allout-show-children)
         ("\C-s" allout-show-current-subtree)
         ("\C-h" allout-hide-current-subtree)
+        ("h" allout-hide-current-subtree)
         ("\C-o" allout-show-current-entry)
         ("!" allout-show-all)
+        ("x" allout-toggle-current-subtree-encryption)
                                         ; Alteration commands:
         (" " allout-open-sibtopic)
         ("." allout-open-subtopic)
@@ -489,19 +572,22 @@
 
 (make-variable-buffer-local 'allout-reindent-bodies)
 
-;;;_  = allout-inhibit-protection
-(defcustom allout-inhibit-protection nil
-  "*Non-nil disables warnings and confirmation-checks for concealed-text edits.
-
-Outline mode uses Emacs change-triggered functions to detect unruly
-changes to concealed regions.  Set this var non-nil to disable the
-protection, potentially increasing text-entry responsiveness a bit.
-
-This var takes effect at `allout-mode' activation, so you may have to
-deactivate and then reactivate the mode if you want to toggle the
-behavior."
+;;;_  = allout-enable-file-variable-adjustment
+(defcustom allout-enable-file-variable-adjustment t
+  "*If non-nil, some allout outline actions edit Emacs local file var text.
+
+This can range from changes to existing entries, addition of new ones,
+and creation of a new local variables section when necessary.
+
+Emacs file variables adjustments are also inhibited if `enable-local-variables'
+is nil.
+
+Operations potentially causing edits include allout encryption routines.
+See the docstring for `allout-toggle-current-subtree-encryption' for
+details."
   :type 'boolean
   :group 'allout)
+(make-variable-buffer-local 'allout-enable-file-variable-adjustment)
 
 ;;;_* CODE - no user customizations below.
 
@@ -509,7 +595,7 @@
 ;;;_  : Version
 ;;;_   = allout-version
 (defvar allout-version
-  (let ((rcs-rev "$Revision$"))
+  (let ((rcs-rev "$Revision: 1.76 $"))
     (condition-case err
 	(save-match-data
 	  (string-match "Revision: \\([0-9]+\\.[0-9]+\\)" rcs-rev)
@@ -728,7 +814,16 @@
 			      (car (cdr cell)))))))
 	    keymap-list)
     map))
-
+;;;_   = allout-prior-bindings - being deprecated.
+(defvar allout-prior-bindings nil
+  "Variable for use in V18, with allout-added-bindings, for
+resurrecting, on mode deactivation, bindings that existed before
+activation.  Being deprecated.")
+;;;_   = allout-added-bindings - being deprecated
+(defvar allout-added-bindings nil
+  "Variable for use in V18, with allout-prior-bindings, for
+resurrecting, on mode deactivation, bindings that existed before
+activation.  Being deprecated.")
 ;;;_  : Menu bar
 (defvar allout-mode-exposure-menu)
 (defvar allout-mode-editing-menu)
@@ -759,7 +854,11 @@
 		      ["Shift Topic Out" allout-shift-out t]
 		      ["Rebullet Topic" allout-rebullet-topic t]
 		      ["Rebullet Heading" allout-rebullet-current-heading t]
-		      ["Number Siblings" allout-number-siblings t]))
+		      ["Number Siblings" allout-number-siblings t]
+		      "----"
+                      ["Toggle Topic Encryption"
+                       allout-toggle-current-subtree-encryption
+                       (> (allout-current-depth) 1)]))
   (easy-menu-define allout-mode-navigation-menu
 		    allout-mode-map
 		    "Allout outline navigation menu."
@@ -775,7 +874,7 @@
 		      "----"
 		      ["Beginning of Entry"
 		       allout-beginning-of-current-entry t]
-		      ["End of Entry" allout-end-of-current-entry t]
+		      ["End of Entry" allout-end-of-entry t]
 		      ["End of Subtree" allout-end-of-current-subtree t]))
   (easy-menu-define allout-mode-misc-menu
 		    allout-mode-map
@@ -855,13 +954,6 @@
           (setq allout-mode-prior-settings rebuild)))))
   )
 ;;;_  : Mode-specific incidentals
-;;;_   = allout-during-write-cue nil
-(defvar allout-during-write-cue nil
-  "Used to inhibit outline change-protection during file write.
-
-See also `allout-post-command-business', `allout-write-file-hook',
-`allout-before-change-protect', and `allout-post-command-business'
-functions.")
 ;;;_   = allout-pre-was-isearching nil
 (defvar allout-pre-was-isearching nil
   "Cue for isearch-dynamic-exposure mechanism, implemented in
@@ -869,22 +961,28 @@
 (make-variable-buffer-local 'allout-pre-was-isearching)
 ;;;_   = allout-isearch-prior-pos nil
 (defvar allout-isearch-prior-pos nil
-  "Cue for isearch-dynamic-exposure tracking, used by `allout-isearch-expose'.")
+  "Cue for isearch-dynamic-exposure tracking, used by
+`allout-isearch-expose'.")
 (make-variable-buffer-local 'allout-isearch-prior-pos)
-;;;_   = allout-override-protect nil
-(defvar allout-override-protect nil
-  "Used in `allout-mode' for regulate of concealed-text protection mechanism.
-
-Allout outline mode regulates alteration of concealed text to protect
-against inadvertent, unnoticed changes.  This is for use by specific,
-native outline functions to temporarily override that protection.
-It's automatically reset to nil after every buffer modification.")
-(make-variable-buffer-local 'allout-override-protect)
+;;;_   = allout-isearch-did-quit
+(defvar allout-isearch-did-quit nil
+  "Distinguishes isearch conclusion and cancellation.
+
+Maintained by allout-isearch-abort \(which is wrapped around the real
+isearch-abort), and monitored by allout-isearch-expose for action.")
+(make-variable-buffer-local 'allout-isearch-did-quit)
 ;;;_   > allout-unprotected (expr)
-(defmacro allout-unprotected (expression)
-  "Evaluate EXPRESSION with `allout-override-protect' let-bound to t."
-  `(let ((allout-override-protect t))
-     ,expression))
+(defmacro allout-unprotected (expr)
+  "Enable internal outline operations to alter read-only text."
+  `(let ((was-inhibit-r-o inhibit-read-only))
+     (unwind-protect
+         (progn
+           (setq inhibit-read-only t)
+           ,expr)
+       (setq inhibit-read-only was-inhibit-r-o)
+       )
+     )
+  )
 ;;;_   = allout-undo-aggregation
 (defvar allout-undo-aggregation 30
   "Amount of successive self-insert actions to bunch together per undo.
@@ -897,14 +995,102 @@
   "Horrible hack used to prevent invalid multiple triggering of outline
 mode from prop-line file-var activation.  Used by `allout-mode' function
 to track repeats.")
-;;;_   > allout-write-file-hook ()
-(defun allout-write-file-hook ()
-  "In `allout-mode', run as a `write-contents-functions' activity.
-
-Currently just sets `allout-during-write-cue', so outline change-protection
-knows to keep inactive during file write."
-  (setq allout-during-write-cue t)
-  nil)
+;;;_   = allout-file-passphrase-verifier-string
+(defvar allout-file-passphrase-verifier-string nil
+  "Name for use as a file variable for verifying encryption passphrase
+across sessions.")
+(make-variable-buffer-local 'allout-file-passphrase-verifier-string)
+;;;_   = allout-passphrase-verifier-string
+(defvar allout-passphrase-verifier-string nil
+  "Setting used to test solicited encryption passphrases against the one
+already associated with a file.
+
+It consists of an encrypted random string useful only to verify that a
+passphrase entered by the user is effective for decryption.  The passphrase
+itself is \*not* recorded in the file anywhere, and the encrypted contents
+are random binary characters to avoid exposing greater susceptibility to
+search attacks.
+
+The verifier string is retained as an Emacs file variable, as well as in
+the emacs buffer state, if file variable adjustments are enabled.  See
+`allout-enable-file-variable-adjustment' for details about that.")
+(make-variable-buffer-local 'allout-passphrase-verifier-string)
+;;;_   = allout-passphrase-hint-string
+(defvar allout-passphrase-hint-string ""
+  "Variable used to retain reminder string for file's encryption passphrase.
+
+See the description of `allout-passphrase-hint-handling' for details about how
+the reminder is deployed.
+
+The hint is retained as an Emacs file variable, as well as in the emacs buffer
+state, if file variable adjustments are enabled.  See
+`allout-enable-file-variable-adjustment' for details about that.")
+(make-variable-buffer-local 'allout-passphrase-hint-string)
+(setq-default allout-passphrase-hint-string "")
+;;;_   = allout-after-save-decrypt
+(defvar allout-after-save-decrypt nil
+  "Internal variable, is nil or has the value of two points:
+
+ - the location of a topic to be decrypted after saving is done
+ - where to situate the cursor after the decryption is performed
+
+This is used to decrypt the topic that was currently being edited, if it
+was encrypted automatically as part of a file write or autosave.")
+(make-variable-buffer-local 'allout-after-save-decrypt)
+;;;_   > allout-write-file-hook-handler ()
+(defun allout-write-file-hook-handler ()
+  "Implement `allout-encrypt-unencrypted-on-saves' policy for file writes."
+
+  (if (or (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 2)
+            (condition-case failure
+                (setq allout-after-save-decrypt
+                      (allout-encrypt-decrypted except-mark))
+              (error (progn
+                       (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 saves."
+
+  (if  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-after-saves-handler ()
+(defun allout-after-saves-handler ()
+  "Decrypt topic encrypted for save, if it's currently being edited.
+
+Ie, if it was pending encryption and contained the point in its body before
+the save.
+
+We use values stored in `allout-after-save-decrypt' to locate the topic
+and the place for the cursor after the decryption is done."
+  (if (not (and (allout-mode-p)
+                (boundp 'allout-after-save-decrypt)
+                allout-after-save-decrypt))
+      t
+    (goto-char (car allout-after-save-decrypt))
+    (let ((was-modified (buffer-modified-p)))
+      (allout-toggle-current-subtree-encryption)
+      (if (not was-modified)
+          (set-buffer-modified-p nil)))
+    (goto-char (cadr allout-after-save-decrypt))
+    (setq allout-after-save-decrypt nil))
+  )
 
 ;;;_ #2 Mode activation
 ;;;_  = allout-mode
@@ -916,11 +1102,10 @@
   'allout-mode)
 ;;;_  = allout-explicitly-deactivated
 (defvar allout-explicitly-deactivated nil
-  "Non-nil if `allout-mode' was last deliberately deactivated.
+  "If t, `allout-mode's last deactivation was deliberate.
 So `allout-post-command-business' should not reactivate it...")
 (make-variable-buffer-local 'allout-explicitly-deactivated)
 ;;;_  > allout-init (&optional mode)
-;;;###autoload
 (defun allout-init (&optional mode)
   "Prime `allout-mode' to enable/disable auto-activation, wrt `allout-layout'.
 
@@ -939,9 +1124,9 @@
 the `allout-layout' variable.  (See `allout-layout' and
 `allout-expose-topic' docstrings for more details on auto layout).
 
-`allout-init' works by setting up (or removing)
-`allout-find-file-hook' in `find-file-hook', and giving
-`allout-auto-activation' a suitable setting.
+`allout-init' works by setting up (or removing) the `allout-mode'
+find-file-hook, and giving `allout-auto-activation' a suitable
+setting.
 
 To prime your Emacs session for full auto-outline operation, include
 the following two lines in your Emacs init file:
@@ -949,32 +1134,35 @@
 \(require 'allout)
 \(allout-init t)"
 
-  (interactive
-   (let ((m (completing-read
-	     (concat "Select outline auto setup mode "
-		     "(empty for report, ? for options) ")
-	     '(("nil")("full")("activate")("deactivate")
-	       ("ask") ("report") (""))
-	     nil
-	     t)))
-     (if (string= m "") 'report
-       (intern-soft m))))
+  (interactive)
+  (if (interactive-p)
+      (progn
+	(setq mode
+	      (completing-read
+	       (concat "Select outline auto setup mode "
+		       "(empty for report, ? for options) ")
+	       '(("nil")("full")("activate")("deactivate")
+		 ("ask") ("report") (""))
+	       nil
+	       t))
+	(if (string= mode "")
+	    (setq mode 'report)
+	  (setq mode (intern-soft mode)))))
   (let
       ;; convenience aliases, for consistent ref to respective vars:
       ((hook 'allout-find-file-hook)
        (curr-mode 'allout-auto-activation))
 
     (cond ((not mode)
-	   (setq find-file-hook (delq hook find-file-hook))
+	   (setq find-file-hooks (delq hook find-file-hooks))
 	   (if (interactive-p)
 	       (message "Allout outline mode auto-activation inhibited.")))
 	  ((eq mode 'report)
-	   (if (memq hook find-file-hook)
-	       ;; Just punt and use the reports from each of the modes:
-	       (allout-init (symbol-value curr-mode))
-	     (allout-init nil)
-	     (message "Allout outline mode auto-activation inhibited.")))
-	  (t (add-hook 'find-file-hook hook)
+	   (if (not (memq hook find-file-hooks))
+	       (allout-init nil)
+	     ;; Just punt and use the reports from each of the modes:
+	     (allout-init (symbol-value curr-mode))))
+	  (t (add-hook 'find-file-hooks hook)
 	     (set curr-mode		; `set', not `setq'!
 		  (cond ((eq mode 'activate)
 			 (message
@@ -1006,6 +1194,7 @@
       (easy-menu-add cur))))
 ;;;_  > allout-mode (&optional toggle)
 ;;;_   : Defun:
+;;;###autoload
 (defun allout-mode (&optional toggle)
 ;;;_    . Doc string:
   "Toggle minor mode for controlling exposure and editing of text outlines.
@@ -1022,10 +1211,11 @@
 
 In addition to outline navigation and exposure, allout includes:
 
- - topic-oriented repositioning, cut, and paste
+ - topic-oriented repositioning, promotion/demotion, cut, and paste
  - integral outline exposure-layout
  - incremental search with dynamic exposure and reconcealment of hidden text
  - automatic topic-number maintenance
+ - easy topic encryption and decryption
  - \"Hot-spot\" operation, for single-keystroke maneuvering and
     exposure control.  \(See the allout-mode docstring.)
 
@@ -1035,7 +1225,7 @@
 special `allout-mode' features and terminology.  See also the outline
 menubar additions for quick reference to many of the features, and see
 the docstring of the function `allout-init' for instructions on
-priming your Emacs session for automatic activation of `allout-mode'.
+priming your emacs session for automatic activation of `allout-mode'.
 
 
 The bindings are dictated by the `allout-keybindings-list' and
@@ -1043,59 +1233,72 @@
 
 	Navigation:				   Exposure Control:
 	----------                                 ----------------
-C-c C-n allout-next-visible-heading     | C-c C-h allout-hide-current-subtree
-C-c C-p allout-previous-visible-heading | C-c C-i allout-show-children
-C-c C-u allout-up-current-level         | C-c C-s allout-show-current-subtree
-C-c C-f allout-forward-current-level    | C-c C-o allout-show-current-entry
-C-c C-b allout-backward-current-level   | ^U C-c C-s allout-show-all
-C-c C-e allout-end-of-current-entry     |	   allout-hide-current-leaves
-C-c C-a allout-beginning-of-current-entry, alternately, goes to hot-spot
+\\[allout-next-visible-heading] allout-next-visible-heading     | \\[allout-hide-current-subtree] allout-hide-current-subtree
+\\[allout-previous-visible-heading] allout-previous-visible-heading | \\[allout-show-children] allout-show-children
+\\[allout-up-current-level] allout-up-current-level         | \\[allout-show-current-subtree] allout-show-current-subtree
+\\[allout-forward-current-level] allout-forward-current-level    | \\[allout-show-current-entry] allout-show-current-entry
+\\[allout-backward-current-level] allout-backward-current-level   | \\[allout-show-all] allout-show-all
+\\[allout-end-of-entry] allout-end-of-entry
+\\[allout-beginning-of-current-entry,] allout-beginning-of-current-entry, alternately, goes to hot-spot
 
 	Topic Header Production:
 	-----------------------
-C-c<SP>	allout-open-sibtopic	Create a new sibling after current topic.
-C-c .	allout-open-subtopic	... an offspring of current topic.
-C-c ,	allout-open-supertopic	... a sibling of the current topic's parent.
+\\[allout-open-sibtopic]  allout-open-sibtopic	Create a new sibling after current topic.
+\\[allout-open-subtopic]  allout-open-subtopic	... an offspring of current topic.
+\\[allout-open-supertopic]  allout-open-supertopic	... a sibling of the current topic's parent.
 
 	Topic Level and Prefix Adjustment:
 	---------------------------------
-C-c >	allout-shift-in	Shift current topic and all offspring deeper.
-C-c <	allout-shift-out	... less deep.
-C-c<CR>	allout-rebullet-topic	Reconcile bullets of topic and its offspring
+\\[allout-shift-in]  allout-shift-in	Shift current topic and all offspring deeper.
+\\[allout-shift-out]  allout-shift-out	... less deep.
+\\[allout-rebullet-current-heading]  allout-rebullet-current-heading Prompt for alternate bullet for
+					 current topic.
+\\[allout-rebullet-topic]	allout-rebullet-topic	Reconcile bullets of topic and its offspring
 				- distinctive bullets are not changed, others
 				  alternated according to nesting depth.
-C-c *	allout-rebullet-current-heading Prompt for alternate bullet for
-					 current topic.
-C-c #	allout-number-siblings	Number bullets of topic and siblings - the
+\\[allout-number-siblings]  allout-number-siblings	Number bullets of topic and siblings - the
 				offspring are not affected.  With repeat
 				count, revoke numbering.
 
 	Topic-oriented Killing and Yanking:
 	----------------------------------
-C-c C-k	allout-kill-topic	Kill current topic, including offspring.
-C-k	allout-kill-line	Like kill-line, but reconciles numbering, etc.
-C-y	allout-yank		Yank, adjusting depth of yanked topic to
+\\[allout-kill-topic]     allout-kill-topic	Kill current topic, including offspring.
+\\[allout-kill-line]     allout-kill-line	Like kill-line, but reconciles numbering, etc.
+\\[allout-yank]     allout-yank		Yank, adjusting depth of yanked topic to
 				depth of heading if yanking into bare topic
 				heading (ie, prefix sans text).
-M-y	allout-yank-pop	Is to allout-yank as yank-pop is to yank
+\\[allout-yank-pop]     allout-yank-pop	Is to allout-yank as yank-pop is to yank
 
 	Misc commands:
 	-------------
 M-x outlineify-sticky		Activate outline mode for current buffer,
 				and establish a default file-var setting
 				for `allout-layout'.
-C-c C-SPC allout-mark-topic
-C-c = c	allout-copy-exposed-to-buffer
+\\[allout-mark-topic]     allout-mark-topic
+\\[allout-copy-exposed-to-buffer]     allout-copy-exposed-to-buffer
 				Duplicate outline, sans concealed text, to
-				buffer with name derived from derived from
-				that of current buffer - \"*XXX exposed*\".
-C-c = p	allout-flatten-exposed-to-buffer
+				buffer with name derived from derived from that
+				of current buffer - \"*BUFFERNAME exposed*\".
+\\[allout-flatten-exposed-to-buffer]     allout-flatten-exposed-to-buffer
 				Like above 'copy-exposed', but convert topic
 				prefixes to section.subsection... numeric
 				format.
 ESC ESC (allout-init t)	Setup Emacs session for outline mode
 				auto-activation.
 
+                  Encrypted Entries
+
+Outline mode supports easily togglable gpg encryption of topics, with
+niceties like support for symmetric and key-pair modes, passphrase timeout,
+passphrase consistency checking, user-provided hinting for symmetric key
+mode, and auto-encryption of topics pending encryption on save.  The aim is
+to enable reliable topic privacy while preventing accidents like neglected
+encryption, encryption with a mistaken passphrase, forgetting which
+passphrase was used, and other practical pitfalls.
+
+See the `allout-toggle-current-subtree-encryption' function and
+`allout-encrypt-unencrypted-on-saves' customization variable for details.
+
 		 HOT-SPOT Operation
 
 Hot-spot operation provides a means for easy, single-keystroke outline
@@ -1148,11 +1351,11 @@
 
 HEADER:	The first line of a topic, include the topic PREFIX and header
 	text.
-PREFIX: The leading text of a topic which distinguishes it from
-	normal text.  It has a strict form, which consists of a
-	prefix-lead string, padding, and a bullet.  The bullet may be
-	followed by a number, indicating the ordinal number of the
-	topic among its siblings, a space, and then the header text.
+PREFIX: The leading text of a topic which distinguishes it from normal
+        text.  It has a strict form, which consists of a prefix-lead
+        string, padding, and a bullet.  The bullet may be followed by a
+        number, indicating the ordinal number of the topic among its
+        siblings, a space, and then the header text.
 
 	The relative length of the PREFIX determines the nesting depth
 	of the topic.
@@ -1223,7 +1426,7 @@
      ;; off on second invocation, so we detect it as best we can, and
      ;; skip everything.
      ((and same-complex-command		; Still in same complex command
-					; as last time `allout-mode' invoked.
+                                        ; as last time `allout-mode' invoked.
 	  active			; Already activated.
 	  (not explicit-activation)	; Prop-line file-vars don't have args.
 	  (string-match "^19.1[89]"	; Bug only known to be in v19.18 and
@@ -1238,6 +1441,19 @@
 				       ; active state or *de*activation
 				       ; specifically requested:
       (setq allout-explicitly-deactivated t)
+      (if (string-match "^18\." emacs-version)
+				       ; Revoke those keys that remain
+				       ; as we set them:
+	  (let ((curr-loc (current-local-map)))
+	   (mapcar (function
+		    (lambda (cell)
+		      (if (eq (lookup-key curr-loc (car cell))
+			      (car (cdr cell)))
+			  (define-key curr-loc (car cell)
+			    (assq (car cell) allout-prior-bindings)))))
+		   allout-added-bindings)
+	   (allout-resumptions 'allout-added-bindings)
+	   (allout-resumptions 'allout-prior-bindings)))
 
       (if allout-old-style-prefixes
 	  (progn
@@ -1246,9 +1462,12 @@
       (allout-resumptions 'selective-display)
       (if (and (boundp 'before-change-functions) before-change-functions)
 	  (allout-resumptions 'before-change-functions))
-      (setq write-contents-functions
-	    (delq 'allout-write-file-hook
-		  write-contents-functions))
+      (setq local-write-file-hooks
+	   (delq 'allout-write-file-hook-handler
+		 local-write-file-hooks))
+      (setq auto-save-hook
+	   (delq 'allout-auto-save-hook-handler
+		 auto-save-hook))
       (allout-resumptions 'paragraph-start)
       (allout-resumptions 'paragraph-separate)
       (allout-resumptions (if (string-match "^18" emacs-version)
@@ -1288,25 +1507,27 @@
 		     (cons '(allout-mode . allout-mode-map)
 			   minor-mode-map-alist))))
 
+				       ; V18 minor-mode key bindings:
+				       ; Stash record of added bindings
+				       ; for later revocation:
+	(allout-resumptions 'allout-added-bindings
+			    (list allout-keybindings-list))
+	(allout-resumptions 'allout-prior-bindings
+			    (list (current-local-map)))
 				       ; and add them:
 	(use-local-map (produce-allout-mode-map allout-keybindings-list
 						(current-local-map)))
 	)
 
 				       ; selective-display is the
-				       ; Emacs conditional exposure
+				       ; emacs conditional exposure
 				       ; mechanism:
       (allout-resumptions 'selective-display '(t))
-      (if allout-inhibit-protection
-	  t
-	(allout-resumptions 'before-change-functions
-			    '(allout-before-change-protect)))
       (add-hook 'pre-command-hook 'allout-pre-command-business)
       (add-hook 'post-command-hook 'allout-post-command-business)
-				       ; Temporarily set by any outline
-				       ; functions that can be trusted to
-				       ; deal properly with concealed text.
-      (add-hook 'write-contents-functions 'allout-write-file-hook)
+      (add-hook 'local-write-file-hooks 'allout-write-file-hook-handler)
+      (make-variable-buffer-local 'auto-save-hook)
+      (add-hook 'auto-save-hook 'allout-auto-save-hook-handler)
 				       ; Custom auto-fill func, to support
 				       ; respect for topic headline,
 				       ; hanging-indents, etc:
@@ -1337,7 +1558,8 @@
       (if allout-layout
 	  (setq do-layout t))
 
-      (if allout-isearch-dynamic-expose
+      (if (and allout-isearch-dynamic-expose
+	       (not (fboundp 'allout-real-isearch-abort)))
 	  (allout-enwrap-isearch))
 
       (run-hooks 'allout-mode-hook)
@@ -1376,7 +1598,6 @@
     )					; let*
   )  					; defun
 ;;;_  > allout-minor-mode
-;;; XXX released verion doesn't do this?
 (defalias 'allout-minor-mode 'allout-mode)
 
 ;;;_ #3 Internal Position State-Tracking - "allout-recent-*" funcs
@@ -1400,12 +1621,12 @@
   "Buffer point last returned by `allout-end-of-current-subtree'.")
 (make-variable-buffer-local 'allout-recent-end-of-subtree)
 ;;;_  > allout-prefix-data (beg end)
-(defmacro allout-prefix-data (beginning end)
+(defmacro allout-prefix-data (beg end)
   "Register allout-prefix state data - BEGINNING and END of prefix.
 
 For reference by `allout-recent' funcs.  Returns BEGINNING."
   `(setq allout-recent-prefix-end ,end
-         allout-recent-prefix-beginning ,beginning))
+         allout-recent-prefix-beginning ,beg))
 ;;;_  > allout-recent-depth ()
 (defmacro allout-recent-depth ()
   "Return depth of last heading encountered by an outline maneuvering function.
@@ -1612,9 +1833,12 @@
   "Produce a location \"chart\" of subtopics of the containing topic.
 
 Optional argument LEVELS specifies the depth \(relative to start
-depth) for the chart.
+depth) for the chart.  Subsequent optional args are not for public
+use.
+
+Point is left at the end of the subtree.
 
-Charts are used to capture outline structure, so that outline altering
+Charts are used to capture outline structure, so that outline-altering
 routines need assess the structure only once, and then use the chart
 for their elaborate manipulations.
 
@@ -1625,11 +1849,9 @@
 The chart for a topics' offspring precedes the entry for the topic
 itself.
 
-\(fn &optional LEVELS)"
-
-  ;; The other function parameters are for internal recursion, and should
-  ;; not be specified by external callers.  ORIG-DEPTH is depth of topic at
-  ;; starting point, and PREV-DEPTH is depth of prior topic."
+The other function parameters are for internal recursion, and should
+not be specified by external callers.  ORIG-DEPTH is depth of topic at
+starting point, and PREV-DEPTH is depth of prior topic."
 
   (let ((original (not orig-depth))	; `orig-depth' set only in recursion.
 	chart curr-depth)
@@ -1835,11 +2057,18 @@
   (if (re-search-forward allout-line-boundary-regexp nil 'move)
       (prog1 (goto-char (match-beginning 0))
              (allout-prefix-data (match-beginning 2)(match-end 2)))))
-;;;_   > allout-end-of-current-subtree ()
-(defun allout-end-of-current-subtree ()
-  "Put point at the end of the last leaf in the currently visible topic."
-  (interactive)
-  (allout-back-to-current-heading)
+;;;_   > allout-end-of-subtree (&optional current)
+(defun allout-end-of-subtree (&optional current)
+  "Put point at the end of the last leaf in the containing topic.
+
+If optional CURRENT is true (default false), then put point at the end of
+the containing visible topic.
+
+Returns the value of point."
+  (interactive "P")
+  (if current
+      (allout-back-to-current-heading)
+    (allout-goto-prefix))
   (let ((level (allout-recent-depth)))
     (allout-next-heading)
     (while (and (not (eobp))
@@ -1851,9 +2080,16 @@
                '(?\n ?\r))
          (forward-char -1))
     (setq allout-recent-end-of-subtree (point))))
+;;;_   > allout-end-of-current-subtree ()
+(defun allout-end-of-current-subtree ()
+  "Put point at end of last leaf in currently visible containing topic.
+
+Returns the value of point."
+  (interactive)
+  (allout-end-of-subtree t))
 ;;;_   > allout-beginning-of-current-entry ()
 (defun allout-beginning-of-current-entry ()
-  "When not already there, position point at beginning of current topic's body.
+  "When not already there, position point at beginning of current topic header.
 
 If already there, move cursor to bullet for hot-spot operation.
 \(See `allout-mode' doc string for details on hot-spot operation.)"
@@ -1863,11 +2099,10 @@
     (if (and (interactive-p)
 	     (= (point) start-point))
 	(goto-char (allout-current-bullet-pos)))))
-;;;_   > allout-end-of-current-entry ()
-(defun allout-end-of-current-entry ()
+;;;_   > allout-end-of-entry ()
+(defun allout-end-of-entry ()
   "Position the point at the end of the current topics' entry."
   (interactive)
-  (allout-show-entry)
   (prog1 (allout-pre-next-preface)
     (if (and (not (bobp))(looking-at "^$"))
         (forward-char -1))))
@@ -1875,9 +2110,27 @@
 (defun allout-end-of-current-heading ()
   (interactive)
   (allout-beginning-of-current-entry)
-  (forward-line -1)
-  (end-of-line))
+  (re-search-forward "[\n\r]" nil t)
+  (forward-char -1))
 (defalias 'allout-end-of-heading 'allout-end-of-current-heading)
+;;;_   > allout-get-body-text ()
+(defun allout-get-body-text ()
+  "Return the unmangled body text of the topic immediately containing point."
+  (save-excursion
+    (allout-end-of-prefix)
+    (if (not (re-search-forward "[\n\r]" nil t))
+        nil
+      (backward-char 1)
+      (let ((pre-body (point)))
+        (if (not pre-body)
+            nil
+          (allout-end-of-entry)
+          (if (not (= pre-body (point)))
+              (buffer-substring-no-properties (1+ pre-body) (point))))
+        )
+      )
+    )
+  )
 
 ;;;_  - Depth-wise
 ;;;_   > allout-ascend-to-depth (depth)
@@ -1892,12 +2145,16 @@
         (if (= (allout-recent-depth) depth)
             (progn (goto-char allout-recent-prefix-beginning)
                    depth)
-          (goto-char last-good)))))
+          (goto-char last-good)
+          nil))
+    (if (interactive-p) (allout-end-of-prefix))))
 ;;;_   > allout-ascend ()
 (defun allout-ascend ()
   "Ascend one level, returning t if successful, nil if not."
-  (if (allout-beginning-of-level)
-      (allout-previous-heading)))
+  (prog1
+      (if (allout-beginning-of-level)
+	  (allout-previous-heading))
+    (if (interactive-p) (allout-end-of-prefix))))
 ;;;_   > allout-descend-to-depth (depth)
 (defun allout-descend-to-depth (depth)
   "Descend to depth DEPTH within current topic.
@@ -1917,13 +2174,13 @@
       nil))
   )
 ;;;_   > allout-up-current-level (arg &optional dont-complain)
-(defun allout-up-current-level (arg &optional dont-complain interactive)
+(defun allout-up-current-level (arg &optional dont-complain)
   "Move out ARG levels from current visible topic.
 
 Positions on heading line of containing topic.  Error if unable to
 ascend that far, or nil if unable to ascend but optional arg
 DONT-COMPLAIN is non-nil."
-  (interactive "p\np")
+  (interactive "p")
   (allout-back-to-current-heading)
   (let ((present-level (allout-recent-depth))
 	(last-good (point))
@@ -1944,12 +2201,12 @@
     (if (or failed
 	    (> arg 0))
 	(progn (goto-char last-good)
-	       (if interactive (allout-end-of-prefix))
+	       (if (interactive-p) (allout-end-of-prefix))
 	       (if (not dont-complain)
 		   (error "Can't ascend past outermost level")
-		 (if interactive (allout-end-of-prefix))
+		 (if (interactive-p) (allout-end-of-prefix))
 		 nil))
-      (if interactive (allout-end-of-prefix))
+      (if (interactive-p) (allout-end-of-prefix))
       allout-recent-prefix-beginning)))
 
 ;;;_  - Linear
@@ -1981,7 +2238,7 @@
         nil))))
 ;;;_   > allout-previous-sibling (&optional depth backward)
 (defun allout-previous-sibling (&optional depth backward)
-  "Like `allout-forward-current-level', but backwards & respect invisible topics.
+  "Like `allout-forward-current-level' backwards, respecting invisible topics.
 
 Optional DEPTH specifies depth to traverse, default current depth.
 
@@ -2015,7 +2272,7 @@
   (let ((depth (allout-depth)))
     (while (allout-previous-sibling depth nil))
     (prog1 (allout-recent-depth)
-      (allout-end-of-prefix))))
+      (if (interactive-p) (allout-end-of-prefix)))))
 ;;;_   > allout-next-visible-heading (arg)
 (defun allout-next-visible-heading (arg)
   "Move to the next ARG'th visible heading line, backward if arg is negative.
@@ -2053,13 +2310,13 @@
   (interactive "p")
   (allout-next-visible-heading (- arg)))
 ;;;_   > allout-forward-current-level (arg)
-(defun allout-forward-current-level (arg &optional interactive)
+(defun allout-forward-current-level (arg)
   "Position point at the next heading of the same level.
 
 Takes optional repeat-count, goes backward if count is negative.
 
 Returns resulting position, else nil if none found."
-  (interactive "p\np")
+  (interactive "p")
   (let ((start-depth (allout-current-depth))
 	(start-point (point))
 	(start-arg arg)
@@ -2087,7 +2344,7 @@
 		  (= (allout-recent-depth) start-depth)))
 	allout-recent-prefix-beginning
       (goto-char last-good)
-      (if (not interactive)
+      (if (not (interactive-p))
 	  nil
 	(allout-end-of-prefix)
 	(error "Hit %s level %d topic, traversed %d of %d requested"
@@ -2096,10 +2353,10 @@
 	       (- (abs start-arg) arg)
 	       (abs start-arg))))))
 ;;;_   > allout-backward-current-level (arg)
-(defun allout-backward-current-level (arg &optional interactive)
+(defun allout-backward-current-level (arg)
   "Inverse of `allout-forward-current-level'."
-  (interactive "p\np")
-  (if interactive
+  (interactive "p")
+  (if (interactive-p)
       (let ((current-prefix-arg (* -1 arg)))
 	(call-interactively 'allout-forward-current-level))
     (allout-forward-current-level (* -1 arg))))
@@ -2107,121 +2364,6 @@
 ;;;_ #5 Alteration
 
 ;;;_  - Fundamental
-;;;_   > allout-before-change-protect (beg end)
-(defun allout-before-change-protect (beg end)
-  "Outline before-change hook, regulates changes to concealed text.
-
-Reveal concealed text that would be changed by current command, and
-offer user choice to commit or forego the change.  Unchanged text is
-reconcealed.  User has option to have changed text reconcealed.
-
-Undo commands are specially treated - the user is not prompted for
-choice, the undoes are always committed (based on presumption that the
-things being undone were already subject to this regulation routine),
-and undoes always leave the changed stuff exposed.
-
-Changes to concealed regions are ignored while file is being written.
-\(This is for the sake of functions that do change the file during
-writes, like crypt and zip modes.)
-
-Locally bound in outline buffers to `before-change-functions', which
-in Emacs 19 is run before any change to the buffer.
-
-Any functions which set [`this-command' to `undo', or which set]
-`allout-override-protect' non-nil (as does, eg, allout-flag-chars)
-are exempt from this restriction."
-  (if (and (allout-mode-p)
-					; allout-override-protect
-					; set by functions that know what
-					; they're doing, eg outline internals:
-	   (not allout-override-protect)
-	   (not allout-during-write-cue)
-	   (save-match-data		; Preserve operation position state.
-					; Both beginning and end chars must
-					; be exposed:
-	     (save-excursion (if (memq this-command '(newline open-line))
-				 ;; Compensate for stupid Emacs {new,
-				 ;; open-}line display optimization:
-				 (setq beg (1+ beg)
-				       end (1+ end)))
-			     (goto-char beg)
-			     (or (allout-hidden-p)
-				 (and (not (= beg end))
-				      (goto-char end)
-				      (allout-hidden-p))))))
-      (save-match-data
-	(if (equal this-command 'undo)
-		 ;; Allow undo without inhibition.
-		 ;; - Undoing new and open-line hits stupid Emacs redisplay
-		 ;;   optimization (em 19 cmds.c, ~ line 200).
-		 ;; - Presumably, undoing what was properly protected when
-		 ;;   done.
-		 ;; - Undo may be users' only recourse in protection faults.
-		 ;; So, expose what getting changed:
-	    (progn (message "Undo! - exposing concealed target...")
-		   (if (allout-hidden-p)
-		       (allout-show-children))
-		   (message "Undo!"))
-	  (let (response
-		(rehide-completely (save-excursion (allout-goto-prefix)
-						   (allout-hidden-p)))
-		rehide-place)
-
-	    (save-excursion
-	      (if (condition-case err
-		      ;; Condition case to catch keyboard quits during reads.
-		      (progn
-					; Give them a peek where
-			(save-excursion
-			  (if (eolp) (setq rehide-place
-					   (allout-goto-prefix)))
-			  (allout-show-entry))
-					; Present the message, but...
-					; leave the cursor at the location
-					; until they respond:
-					; Then interpret the response:
-			(while
-			    (progn
-			      (message (concat "Change inside concealed"
-					       " region - do it? "
-					       "(n or 'y'/'r'eclose)"))
-			      (setq response (read-char))
-			      (not
-			       (cond ((memq response '(?r ?R))
-				      (setq response 'reclose))
-				     ((memq response '(?y ?Y ? ))
-				      (setq response t))
-				     ((memq response '(?n ?N 127))
-				      (setq response nil)
-				      t)
-				     ((eq response ??)
-				      (message
-				       "`r' means `yes, then reclose'")
-				      nil)
-				     (t (message "Please answer y, n, or r")
-					(sit-for 1)
-					nil)))))
-			response)
-		    ('quit nil))
-					; Continue:
-		  (if (eq response 'reclose)
-		      (save-excursion
-			(if rehide-place (goto-char rehide-place))
-			(if rehide-completely
-			    (allout-hide-current-entry-completely)
-			  (allout-hide-current-entry)))
-		    (if (allout-ascend-to-depth (1- (allout-recent-depth)))
-			(allout-show-children)
-		      (allout-show-to-offshoot)))
-					; Prevent:
-		(if rehide-completely
-		    (save-excursion
-		      (if rehide-place (goto-char rehide-place))
-		      (allout-hide-current-entry-completely))
-		  (allout-hide-current-entry))
-		(error "Change within concealed region prevented"))))))
-    )	; if
-  )	; defun
 ;;;_   = allout-post-goto-bullet
 (defvar allout-post-goto-bullet nil
   "Outline internal var, for `allout-pre-command-business' hot-spot operation.
@@ -2236,24 +2378,20 @@
 (defun allout-post-command-business ()
   "Outline `post-command-hook' function.
 
-- Null `allout-override-protect', so it's not left open.
-
 - Implement (and clear) `allout-post-goto-bullet', for hot-spot
   outline commands.
 
-- Massages `buffer-undo-list' so successive, standard character self-inserts
-  are aggregated.  This kludge compensates for lack of undo bunching when
-  `before-change-functions' is used."
+- Decrypt topic currently being edited if it was encrypted for a save.
+
+- Massage buffer-undo-list so successive, standard character self-inserts are
+  aggregated.  This kludge compensates for lack of undo bunching when
+  before-change-functions is used."
 
 					; Apply any external change func:
   (if (not (allout-mode-p))		; In allout-mode.
       nil
-    (setq allout-override-protect nil)
     (if allout-isearch-dynamic-expose
 	(allout-isearch-rectification))
-    (if allout-during-write-cue
-	;; Was used by allout-before-change-protect, done with it now:
-	(setq allout-during-write-cue nil))
     ;; Undo bunching business:
     (if (and (listp buffer-undo-list)	; Undo history being kept.
 	     (equal this-command 'self-insert-command)
@@ -2282,6 +2420,11 @@
 	      (setq buffer-undo-list
 		    (cons (cons prev-from cur-to)
 			  (cdr (cdr (cdr buffer-undo-list))))))))
+
+    (if (and (boundp 'allout-after-save-decrypt)
+             allout-after-save-decrypt)
+        (allout-after-saves-handler))
+
     ;; Implement -post-goto-bullet, if set: (must be after undo business)
     (if (and allout-post-goto-bullet
 	     (allout-current-bullet-pos))
@@ -2304,8 +2447,9 @@
 char.  When in this mode you can use regular cursor-positioning
 command/keystrokes to relocate the cursor off of a bullet character to
 return to regular interpretation of self-insert characters."
+
   (if (not (allout-mode-p))
-      ;; Shouldn't be invoked if not in allout allout-mode, but just in case:
+      ;; Shouldn't be invoked if not in allout-mode, but just in case:
       nil
     ;; Register isearch status:
     (if (and (boundp  'isearch-mode) isearch-mode)
@@ -2317,8 +2461,11 @@
 	(let* ((this-key-num (cond
 			      ((numberp last-command-char)
 			       last-command-char)
-			      ((fboundp 'char-to-int)
-			       (char-to-int last-command-char))
+			      ;; Only xemacs has characterp.
+			      ((and (fboundp 'characterp)
+				    (apply 'characterp
+                                           (list last-command-char)))
+			       (apply 'char-to-int (list last-command-char)))
 			      (t 0)))
 	       mapped-binding)
 	  (if (zerop this-key-num)
@@ -2340,7 +2487,7 @@
 		      this-command mapped-binding)))))))
 ;;;_   > allout-find-file-hook ()
 (defun allout-find-file-hook ()
-  "Activate `allout-mode' when `allout-auto-activation' & `allout-layout' are non-nil.
+  "Activate `allout-mode' when `allout-auto-activation', `allout-layout' non-nil.
 
 See `allout-init' for setup instructions."
   (if (and allout-auto-activation
@@ -2353,7 +2500,7 @@
 
 Called as part of `allout-post-command-business'."
 
-  (let ((isearching isearch-mode))
+  (let ((isearching (and (boundp 'isearch-mode) isearch-mode)))
     (cond ((and isearching (not allout-pre-was-isearching))
 	   (allout-isearch-expose 'start))
 	  ((and isearching allout-pre-was-isearching)
@@ -2361,24 +2508,11 @@
 	  ((and (not isearching) allout-pre-was-isearching)
 	   (allout-isearch-expose 'final))
 	  ;; Not and wasn't isearching:
-	  (t (setq allout-isearch-prior-pos nil)))))
+	  (t (setq allout-isearch-prior-pos nil)
+	     (setq allout-isearch-did-quit nil)))))
 ;;;_   = allout-isearch-was-font-lock
 (defvar allout-isearch-was-font-lock
   (and (boundp 'font-lock-mode) font-lock-mode))
-
-;;;_   > allout-flag-region (from to flag)
-(defmacro allout-flag-region (from to flag)
-  "Hide or show lines from FROM to TO, via Emacs `selective-display' FLAG char.
-Ie, text following flag C-m \(carriage-return) is hidden until the
-next C-j (newline) char.
-
-Returns the endpoint of the region."
-  `(let ((buffer-read-only nil)
-	   (allout-override-protect t))
-       (subst-char-in-region ,from ,to
-			     (if (= ,flag ?\n) ?\r ?\n)
-			     ,flag t)))
-
 ;;;_   > allout-isearch-expose (mode)
 (defun allout-isearch-expose (mode)
   "MODE is either 'clear, 'start, 'continue, or 'final."
@@ -2403,21 +2537,56 @@
       (setq allout-isearch-prior-pos nil)
     (if (not (eq mode 'final))
 	(setq allout-isearch-prior-pos (cons (point) (allout-show-entry)))
-      (if isearch-mode-end-hook-quit
+      (if allout-isearch-did-quit
 	  nil
 	(setq allout-isearch-prior-pos nil)
-	(allout-show-children)))))
+	(allout-show-children))))
+  (setq allout-isearch-did-quit nil))
 ;;;_   > allout-enwrap-isearch ()
 (defun allout-enwrap-isearch ()
-  "Impose `isearch-abort' wrapper for dynamic exposure in isearch.
+  "Impose `allout-mode' isearch-abort wrapper for dynamic exposure in isearch.
 
 The function checks to ensure that the rebinding is done only once."
-  (add-hook 'isearch-mode-end-hook 'allout-isearch-rectification))
+
+  (add-hook 'isearch-mode-end-hook 'allout-isearch-rectification)
+  (if (fboundp 'allout-real-isearch-abort)
+      ;;
+      nil
+                                        ; Ensure load of isearch-mode:
+    (if (or (and (fboundp 'isearch-mode)
+                 (fboundp 'isearch-abort))
+            (condition-case error
+                (load-library "isearch-mode")
+              ('file-error (message
+			    "Skipping isearch-mode provisions - %s '%s'"
+			    (car (cdr error))
+			    (car (cdr (cdr error))))
+			   (sit-for 1)
+			   ;; Inhibit subsequent tries and return nil:
+			   (setq allout-isearch-dynamic-expose nil))))
+        ;; Isearch-mode loaded, encapsulate specific entry points for
+        ;; outline dynamic-exposure business:
+        (progn
+	  ;; stash crucial isearch-mode funcs under known, private
+	  ;; names, then register wrapper functions under the old
+	  ;; names, in their stead:
+          (fset 'allout-real-isearch-abort (symbol-function 'isearch-abort))
+          (fset 'isearch-abort 'allout-isearch-abort)))))
+;;;_   > allout-isearch-abort ()
+(defun allout-isearch-abort ()
+  "Wrapper for allout-real-isearch-abort \(which see), to register
+actual quits."
+  (interactive)
+  (setq allout-isearch-did-quit nil)
+  (condition-case what
+      (allout-real-isearch-abort)
+    ('quit (setq allout-isearch-did-quit t)
+	  (signal 'quit nil))))
 
 ;;; Prevent unnecessary font-lock while isearching!
 (defvar isearch-was-font-locking nil)
 (defun isearch-inhibit-font-lock ()
-  "Inhibit `font-lock-mode' while isearching - for use on `isearch-mode-hook'."
+  "Inhibit `font-lock' while isearching - for use on `isearch-mode-hook'."
   (if (and (allout-mode-p) (boundp 'font-lock-mode) font-lock-mode)
       (setq isearch-was-font-locking t
 	    font-lock-mode nil)))
@@ -2465,6 +2634,14 @@
                  (if prefix
                      (allout-get-prefix-bullet prefix)
                    (allout-get-bullet)))))
+;;;_   > allout-encrypted-type-prefix (&optional prefix)
+(defun allout-encrypted-type-prefix (&optional prefix)
+  "True if current header prefix bullet is for an encrypted entry \(body)."
+  (and allout-topic-encryption-bullet
+        (string= allout-topic-encryption-bullet
+                 (if prefix
+                     (allout-get-prefix-bullet prefix)
+                   (allout-get-bullet)))))
 ;;;_   > allout-bullet-for-depth (&optional depth)
 (defun allout-bullet-for-depth (&optional depth)
   "Return outline topic bullet suited to optional DEPTH, or current depth."
@@ -2625,15 +2802,15 @@
                                    ((allout-sibling-index))))))
     )
   )
-;;;_   > allout-open-topic (relative-depth &optional before use-sib-bullet)
-(defun allout-open-topic (relative-depth &optional before use-sib-bullet)
-  "Open a new topic at depth RELATIVE-DEPTH.
+;;;_   > allout-open-topic (relative-depth &optional before use_recent_bullet)
+(defun allout-open-topic (relative-depth &optional before use_recent_bullet)
+  "Open a new topic at depth DEPTH.
 
 New topic is situated after current one, unless optional flag BEFORE
 is non-nil, or unless current line is complete empty (not even
 whitespace), in which case open is done on current line.
 
-If USE-SIB-BULLET is true, use the bullet of the prior sibling.
+If USE_RECENT_BULLET is true, offer to use the bullet of the prior sibling.
 
 Nuances:
 
@@ -2660,9 +2837,11 @@
   (let* ((depth (+ (allout-current-depth) relative-depth))
          (opening-on-blank (if (looking-at "^\$")
                                (not (setq before nil))))
-         opening-numbered	; Will get while computing ref-topic, below
-         ref-depth		; Will get while computing ref-topic, below
-         ref-bullet		; Will get while computing ref-topic, next
+         ;; bunch o vars set while computing ref-topic
+         opening-numbered
+         opening-encrypted
+         ref-depth
+         ref-bullet
          (ref-topic (save-excursion
                       (cond ((< relative-depth 0)
                              (allout-ascend-to-depth depth))
@@ -2680,6 +2859,13 @@
                                        (allout-descend-to-depth depth))
                                    (if (allout-numbered-type-prefix)
                                        allout-numbered-bullet))))
+                      (setq opening-encrypted
+                            (save-excursion
+                              (and allout-topic-encryption-bullet
+                                   (or (<= relative-depth 0)
+                                       (allout-descend-to-depth depth))
+                                   (if (allout-numbered-type-prefix)
+                                       allout-numbered-bullet))))
                       (point)))
          dbl-space
          doing-beginning)
@@ -2718,19 +2904,24 @@
                             (if (not (bobp))
                                 (allout-previous-heading)))
 	    (if (and before (bobp))
-		(allout-unprotected (open-line 1))))
+		(allout-unprotected (allout-open-line-not-read-only))))
 
           (if (<= relative-depth 0)
               ;; Not going inwards, don't snug up:
               (if doing-beginning
-		  (allout-unprotected (open-line (if dbl-space 2 1)))
+                  (allout-unprotected
+                   (if (not dbl-space)
+                       (allout-open-line-not-read-only)
+                     (allout-open-line-not-read-only)
+                     (allout-open-line-not-read-only)))
 		(if before
 		    (progn (end-of-line)
 			   (allout-pre-next-preface)
 			   (while (= ?\r (following-char))
                              (forward-char 1))
 			   (if (not (looking-at "^$"))
-			       (allout-unprotected (open-line 1))))
+			       (allout-unprotected
+                                (allout-open-line-not-read-only))))
 		  (allout-end-of-current-subtree)))
             ;; Going inwards - double-space if first offspring is,
             ;; otherwise snug up.
@@ -2748,38 +2939,47 @@
                       (progn (forward-line -1)
                              (looking-at "^\\s-*$"))))
                 (progn (forward-line 1)
-                       (allout-unprotected (open-line 1))))
+                       (allout-unprotected
+                        (allout-open-line-not-read-only))
+                       (forward-line 1)))
             (end-of-line))
           ;;(if doing-beginning (goto-char doing-beginning))
           (if (not (bobp))
+              ;; We insert a newline char rather than using open-line to
+              ;; avoid rear-stickiness inheritence of read-only property.
               (progn (if (and (not (> depth ref-depth))
                               (not before))
-                         (allout-unprotected (open-line 1))
+                         (allout-unprotected
+                          (allout-open-line-not-read-only))
 		       (if (> depth ref-depth)
-			   (allout-unprotected (newline 1))
+                         (allout-unprotected
+                          (allout-open-line-not-read-only))
 			 (if dbl-space
-			     (allout-unprotected (open-line 1))
+                             (allout-unprotected
+                              (allout-open-line-not-read-only))
 			   (if (not before)
 			       (allout-unprotected (newline 1))))))
                      (if dbl-space
-			 (allout-unprotected (newline  1)))
+			 (allout-unprotected (newline 1)))
                      (if (and (not (eobp))
                               (not (bolp)))
                          (forward-char 1))))
           ))
     (insert (concat (allout-make-topic-prefix opening-numbered
-					       t
-					       depth)
-		    " "))
+                                              t
+                                              depth)
+                           " "))
 
     ;;(if doing-beginning (save-excursion (newline (if dbl-space 2 1))))
 
 
-    (allout-rebullet-heading (and use-sib-bullet ref-bullet);;; solicit
+    (allout-rebullet-heading (and use_recent_bullet         ;;; solicit
+                                   ref-bullet)
                               depth			     ;;; depth
                               nil 			     ;;; number-control
                               nil			     ;;; index
-                              t)     (end-of-line)
+                              t)
+    (end-of-line)
     )
   )
 ;;;_    . open-topic contingencies
@@ -2795,6 +2995,13 @@
 ;;;_     ; buffer boundaries - special provisions for beginning and end ob
 ;;;_     ; level 1 topics have special provisions also - double space.
 ;;;_     ; location of new topic
+;;;_   > allout-open-line-not-read-only ()
+(defun allout-open-line-not-read-only ()
+  "Open line and remove inherited read-only text prop from new char, if any."
+  (open-line 1)
+  (if (plist-get (text-properties-at (point)) 'read-only)
+      (allout-unprotected
+       (remove-text-properties (point) (+ 1 (point)) '(read-only nil)))))
 ;;;_   > allout-open-subtopic (arg)
 (defun allout-open-subtopic (arg)
   "Open new topic header at deeper level than the current one.
@@ -2802,7 +3009,7 @@
 Negative universal arg means to open deeper, but place the new topic
 prior to the current one."
   (interactive "p")
-  (allout-open-topic 1 (> 0 arg)))
+  (allout-open-topic 1 (> 0 arg) (< 1 arg)))
 ;;;_   > allout-open-sibtopic (arg)
 (defun allout-open-sibtopic (arg)
   "Open new topic header at same level as the current one.
@@ -2812,7 +3019,7 @@
 Negative universal arg means to place the new topic prior to the current
 one."
   (interactive "p")
-  (allout-open-topic 0 (> 0 arg) (< 1 arg)))
+  (allout-open-topic 0 (> 0 arg) (not (= 1 arg))))
 ;;;_   > allout-open-supertopic (arg)
 (defun allout-open-supertopic (arg)
   "Open new topic header at shallower level than the current one.
@@ -2821,7 +3028,7 @@
 topic prior to the current one."
 
   (interactive "p")
-  (allout-open-topic -1 (> 0 arg)))
+  (allout-open-topic -1 (> 0 arg) (< 1 arg)))
 
 ;;;_  - Outline Alteration
 ;;;_   : Topic Modification
@@ -2877,15 +3084,15 @@
 		  (setq old-indent-begin (match-beginning 1)
 			old-indent-end (match-end 1))
 		  (not (looking-at allout-regexp)))
-	   (if (> 0 (setq excess (- (current-column)
-				     old-margin)))
+	   (if (> 0 (setq excess (- (- old-indent-end old-indent-begin)
+                                    old-margin)))
 	       ;; Text starts left of old margin - don't adjust:
 	       nil
 	     ;; Text was hanging at or right of old left margin -
 	     ;; reindent it, preserving its existing indentation
 	     ;; beyond the old margin:
 	     (delete-region old-indent-begin old-indent-end)
-	     (indent-to (+ new-margin excess)))))))))
+             (indent-to (+ new-margin excess (current-column))))))))))
 ;;;_    > allout-rebullet-current-heading (arg)
 (defun allout-rebullet-current-heading (arg)
   "Solicit new bullet for current visible heading."
@@ -2922,28 +3129,30 @@
 
   "Adjust bullet of current topic prefix.
 
+All args are optional.
+
 If SOLICIT is non-nil, then the choice of bullet is solicited from
 user.  If it's a character, then that character is offered as the
 default, otherwise the one suited to the context \(according to
 distinction or depth) is offered.  If non-nil, then the
 context-specific bullet is just used.
 
-Second arg NEW-DEPTH forces the topic prefix to that depth, regardless
+Second arg DEPTH forces the topic prefix to that depth, regardless
 of the topic's current depth.
 
 Third arg NUMBER-CONTROL can force the prefix to or away from
 numbered form.  It has effect only if `allout-numbered-bullet' is
 non-nil and soliciting was not explicitly invoked (via first arg).
 Its effect, numbering or denumbering, then depends on the setting
-of the fourth arg, INDEX.
+of the forth arg, INDEX.
 
-If NUMBER-CONTROL is non-nil and fourth arg INDEX is nil, then the
+If NUMBER-CONTROL is non-nil and forth arg INDEX is nil, then the
 prefix of the topic is forced to be non-numbered.  Null index and
 non-nil NUMBER-CONTROL forces denumbering.  Non-nil INDEX (and
 non-nil NUMBER-CONTROL) forces a numbered-prefix form.  If non-nil
 INDEX is a number, then that number is used for the numbered
 prefix.  Non-nil and non-number means that the index for the
-numbered prefix will be derived by `allout-make-topic-prefix'.
+numbered prefix will be derived by allout-make-topic-prefix.
 
 Fifth arg DO-SUCCESSORS t means re-resolve count on succeeding
 siblings.
@@ -2986,9 +3195,10 @@
 					; Put in new prefix:
       (allout-unprotected (insert new-prefix))
 
-      ;; Reindent the body if elected and margin changed:
+      ;; Reindent the body if elected, margin changed, and not encrypted body:
       (if (and allout-reindent-bodies
-	       (not (= new-depth current-depth)))
+	       (not (= new-depth current-depth))
+               (not (allout-encrypted-topic-p)))
 	  (allout-reindent-body current-depth new-depth))
 
       ;; Recursively rectify successive siblings of orig topic if
@@ -3010,7 +3220,7 @@
   ) ; defun
 ;;;_    > allout-rebullet-topic (arg)
 (defun allout-rebullet-topic (arg)
-  "Like `allout-rebullet-topic-grunt', but start from topic visible at point.
+  "Rebullet the visible topic containing point and all contained subtopics.
 
 Descends into invisible as well as visible topics, however.
 
@@ -3036,18 +3246,18 @@
                                                starting-point
                                                index
                                                do-successors)
+  "Like `allout-rebullet-topic', but on nearest containing topic
+\(visible or not).
 
-  "Rebullet the topic at point, visible or invisible, and all
-contained subtopics.  See `allout-rebullet-heading' for rebulleting
-behavior.
+See `allout-rebullet-heading' for rebulleting behavior.
 
-Arg RELATIVE-DEPTH means to shift the depth of the entire
-topic that amount.
+All arguments are optional.
 
-\(fn &optional RELATIVE-DEPTH)"
+First arg RELATIVE-DEPTH means to shift the depth of the entire
+topic that amount.
 
-  ;; All args except the first one are for internal recursive use by the
-  ;; function itself.
+The rest of the args are for internal recursive use by the function
+itself.  The are STARTING-DEPTH, STARTING-POINT, and INDEX."
 
   (let* ((relative-depth (or relative-depth 0))
          (new-depth (allout-depth))
@@ -3177,13 +3387,42 @@
         (setq more (allout-next-sibling depth nil))))))
 ;;;_    > allout-shift-in (arg)
 (defun allout-shift-in (arg)
-  "Increase depth of current heading and any topics collapsed within it."
+  "Increase depth of current heading and any topics collapsed within it.
+
+We disallow shifts that would result in the topic having a depth more than
+one level greater than the immediately previous topic, to avoid containment
+discontinuity.  The first topic in the file can be adjusted to any positive
+depth, however."
   (interactive "p")
+  (if (> arg 0)
+      (save-excursion
+        (allout-back-to-current-heading)
+        (if (not (bobp))
+            (let* ((current-depth (allout-recent-depth))
+                   (start-point (point))
+                   (predecessor-depth (progn
+                                        (forward-char -1)
+                                        (allout-goto-prefix)
+                                        (if (< (point) start-point)
+                                            (allout-recent-depth)
+                                          0))))
+              (if (and (> predecessor-depth 0)
+                       (> (+ current-depth arg)
+                          (1+ predecessor-depth)))
+                  (error (concat "May not shift deeper than offspring depth"
+                                 " of previous topic")))))))
   (allout-rebullet-topic arg))
 ;;;_    > allout-shift-out (arg)
 (defun allout-shift-out (arg)
-  "Decrease depth of current heading and any topics collapsed within it."
+  "Decrease depth of current heading and any topics collapsed within it.
+
+We disallow shifts that would result in the topic having a depth more than
+one level greater than the immediately previous topic, to avoid containment
+discontinuity.  The first topic in the file can be adjusted to any positive
+depth, however."
   (interactive "p")
+  (if (< arg 0)
+      (allout-shift-in (* arg -1)))
   (allout-rebullet-topic (* arg -1)))
 ;;;_   : Surgery (kill-ring) functions with special provisions for outlines:
 ;;;_    > allout-kill-line (&optional arg)
@@ -3191,24 +3430,58 @@
   "Kill line, adjusting subsequent lines suitably for outline mode."
 
   (interactive "*P")
-  (if (not (and (allout-mode-p)		; active outline mode,
-		allout-numbered-bullet		; numbers may need adjustment,
-		(bolp)				; may be clipping topic head,
-		(looking-at allout-regexp)))	; are clipping topic head.
-      ;; Above conditions do not obtain - just do a regular kill:
-      (kill-line arg)
-    ;; Ah, have to watch out for adjustments:
-    (let* ((depth (allout-depth)))
-                                        ; Do the kill:
-      (kill-line arg)
+
+  (let ((start-point (point))
+        (leading-kill-ring-entry (car kill-ring))
+        binding)
+
+    (condition-case err
+
+        (if (not (and (allout-mode-p)        ; active outline mode,
+                      allout-numbered-bullet ; numbers may need adjustment,
+                      (bolp)                  ; may be clipping topic head,
+                      (looking-at allout-regexp))) ; are clipping topic head.
+            ;; Above conditions do not obtain - just do a regular kill:
+            (kill-line arg)
+          ;; Ah, have to watch out for adjustments:
+          (let* ((depth (allout-depth))
+                 (start-point (point))
+                 binding)
+                                        ; Do the kill, presenting option
+                                        ; for read-only text:
+            (kill-line arg)
                                         ; Provide some feedback:
-      (sit-for 0)
-      (save-excursion
+          (sit-for 0)
+          (save-excursion
                                         ; Start with the topic
                                         ; following killed line:
-        (if (not (looking-at allout-regexp))
-            (allout-next-heading))
-        (allout-renumber-to-depth depth)))))
+            (if (not (looking-at allout-regexp))
+                (allout-next-heading))
+            (allout-renumber-to-depth depth))))
+      ;; condition case handler:
+      (text-read-only
+       (goto-char start-point)
+       (setq binding (where-is-internal 'allout-kill-topic nil t))
+       (cond ((not binding) (setq binding ""))
+             ((arrayp binding)
+              (setq binding (mapconcat 'key-description (list binding) ", ")))
+             (t (setq binding (format "%s" binding))))
+       ;; ensure prior kill-ring leader is properly restored:
+       (if (eq leading-kill-ring-entry (cadr kill-ring))
+           ;; Aborted kill got pushed on front - ditch it:
+           (let ((got (car kill-ring)))
+             (setq kill-ring (cdr kill-ring))
+             got)
+         ;; Aborted kill got appended to prior - resurrect prior:
+         (setcar kill-ring leading-kill-ring-entry))
+       ;; make last-command skip this failed command, so kill-appending
+       ;; conditions track:
+       (setq this-command last-command)
+       (error (concat "read-only text hit - use %s allout-kill-topic to"
+                      " discard collapsed stuff")
+              binding)))
+    )
+  )
 ;;;_    > allout-kill-topic ()
 (defun allout-kill-topic ()
   "Kill topic together with subtopics.
@@ -3236,14 +3509,14 @@
 		       (>= (allout-recent-depth) depth))))
 	    (forward-char 1)))
 
-    (kill-region beg (point))
+    (allout-unprotected (kill-region beg (point)))
     (sit-for 0)
     (save-excursion
       (allout-renumber-to-depth depth))))
 ;;;_    > allout-yank-processing ()
 (defun allout-yank-processing (&optional arg)
 
-  "Incidental outline specific business to be done just after text yanks.
+  "Incidental outline-specific business to be done just after text yanks.
 
 Does depth adjustment of yanked topics, when:
 
@@ -3259,7 +3532,7 @@
 
 The point is left in front of yanked, adjusted topics, rather than
 at the end (and vice-versa with the mark).  Non-adjusted yanks,
-however, are left exactly like normal, not outline specific yanks."
+however, are left exactly like normal, non-allout-specific yanks."
 
   (interactive "*P")
 					; Get to beginning, leaving
@@ -3463,6 +3736,60 @@
 ;;;_ #6 Exposure Control
 
 ;;;_  - Fundamental
+;;;_   > allout-flag-region (from to flag)
+(defun allout-flag-region (from to flag)
+  "Hide or show lines from FROM to TO, via Emacs selective-display FLAG char.
+Ie, text following flag C-m \(carriage-return) is hidden until the
+next C-j (newline) char.
+
+Returns the endpoint of the region."
+  ;; "OFR-" prefixes to avoid collisions with vars in code calling the macro.
+  ;; ie, elisp macro vars are not 'hygenic', so distinct names are necessary.
+  (let ((was-inhibit-r-o inhibit-read-only)
+        (was-undo-list buffer-undo-list)
+        (was-modified (buffer-modified-p))
+        trans)
+    (unwind-protect
+     (save-excursion
+       (setq inhibit-read-only t)
+       (setq buffer-undo-list t)
+       (if (> from to)
+           (setq trans from from to to trans))
+       (subst-char-in-region from to
+                             (if (= flag ?\n) ?\r ?\n)
+                             flag t)
+       ;; adjust character read-protection on all the affected lines.
+       ;; we handle the region line-by-line.
+       (goto-char to)
+       (end-of-line)
+       (setq to (min (+ 2 (point)) (point-max)))
+       (goto-char from)
+       (beginning-of-line)
+       (while (< (point) to)
+         ;; handle from start of exposed to beginning of hidden, or eol:
+         (remove-text-properties (point)
+                                 (progn (if (re-search-forward "[\r\n]"
+                                                               nil t)
+                                            (forward-char -1))
+                                        (point))
+                                 '(read-only nil))
+         ;; handle from start of hidden, if any, to eol:
+         (if (and (not (eobp)) (= (char-after (point)) ?\r))
+             (put-text-property (point) (progn (end-of-line) (point))
+                                'read-only t))
+         ;; Handle the end-of-line to beginning of next line:
+         (if (not (eobp))
+             (progn (forward-char 1)
+                    (remove-text-properties (1- (point)) (point)
+                                            '(read-only nil)))))
+       )
+     (if (not was-modified)
+         (set-buffer-modified-p nil))
+     (setq inhibit-read-only was-inhibit-r-o)
+     (setq buffer-undo-list was-undo-list)
+     )
+    )
+  )
 ;;;_   > allout-flag-current-subtree (flag)
 (defun allout-flag-current-subtree (flag)
   "Hide or show subtree of currently-visible topic.
@@ -3471,9 +3798,9 @@
 
   (save-excursion
     (allout-back-to-current-heading)
-    (allout-flag-region (point)
-			 (progn (allout-end-of-current-subtree) (1- (point)))
-			 flag)))
+    (let ((from (point))
+          (to (progn (allout-end-of-current-subtree) (1- (point)))))
+      (allout-flag-region from to flag))))
 
 ;;;_  - Topic-specific
 ;;;_   > allout-show-entry ()
@@ -3482,7 +3809,7 @@
 
 This is a way to give restricted peek at a concealed locality without the
 expense of exposing its context, but can leave the outline with aberrant
-exposure.  `allout-hide-current-entry-completely' or `allout-show-to-offshoot'
+exposure.  `allout-hide-current-entry-completely' or `allout-show-offshoot'
 should be used after the peek to rectify the exposure."
 
   (interactive)
@@ -3602,7 +3929,7 @@
   (allout-back-to-current-heading)
   (save-excursion
    (allout-flag-region (point)
-                        (progn (allout-end-of-current-entry) (point))
+                        (progn (allout-end-of-entry) (point))
                         ?\r)))
 ;;;_   > allout-show-current-entry (&optional arg)
 (defun allout-show-current-entry (&optional arg)
@@ -3614,8 +3941,9 @@
       (allout-hide-current-entry)
     (save-excursion
       (allout-flag-region (point)
-			   (progn (allout-end-of-current-entry) (point))
-			   ?\n))))
+			   (progn (allout-end-of-entry) (point))
+			   ?\n)
+      )))
 ;;;_   > allout-hide-current-entry-completely ()
 ; ... allout-hide-current-entry-completely also for isearch dynamic exposure:
 (defun allout-hide-current-entry-completely ()
@@ -3846,7 +4174,11 @@
       max-pos)))
 ;;;_   > allout-old-expose-topic (spec &rest followers)
 (defun allout-old-expose-topic (spec &rest followers)
-  "Dictate wholesale exposure scheme for current topic, according to SPEC.
+
+  "Deprecated.  Use `allout-expose-topic' \(with different schema
+format) instead.
+
+Dictate wholesale exposure scheme for current topic, according to SPEC.
 
 SPEC is either a number or a list.  Optional successive args
 dictate exposure for subsequent siblings of current topic.
@@ -3918,9 +4250,6 @@
       (allout-old-expose-topic (car followers))
       (setq followers (cdr followers)))
     max-pos))
-(make-obsolete 'allout-old-expose-topic
-               "use `allout-expose-topic' (with different schema format) instead."
-               "19.23")
 ;;;_   > allout-new-exposure '()
 (defmacro allout-new-exposure (&rest spec)
   "Literal frontend for `allout-expose-topic', doesn't evaluate arguments.
@@ -3929,6 +4258,8 @@
 
 Cursor is left at start position.
 
+Use this instead of obsolete `allout-exposure'.
+
 Examples:
 \(allout-new-exposure (-1 () () () 1) 0)
 	Close current topic at current level so only the immediate
@@ -4151,13 +4482,20 @@
 				 (cdr format)))))))
       ;; Put the list with first at front, to last at back:
       (nreverse result))))
+;;;_   > my-region-active-p ()
+(defmacro my-region-active-p ()
+  (if (fboundp 'region-active-p)
+      '(region-active-p)
+    'mark-active))
 ;;;_   > allout-process-exposed (&optional func from to frombuf
 ;;;					    tobuf format)
 (defun allout-process-exposed (&optional func from to frombuf tobuf
-					  format start-num)
+					  format &optional start-num)
   "Map function on exposed parts of current topic; results to another buffer.
 
-Apply FUNC to exposed portions FROM position TO position in buffer
+All args are options; default values itemized below.
+
+Apply FUNCTION to exposed portions FROM position TO position in buffer
 FROMBUF to buffer TOBUF.  Sixth optional arg, FORMAT, designates an
 alternate presentation form:
 
@@ -4170,7 +4508,7 @@
 		       except for distinctive bullets.
 
 Defaults:
-  FUNC:		`allout-insert-listified'
+  FUNCTION:	`allout-insert-listified'
   FROM:		region start, if region active, else start of buffer
   TO:		region end, if region active, else end of buffer
   FROMBUF:	current buffer
@@ -4219,9 +4557,7 @@
 
  \`(depth prefix text)'
 
-or
-
- \`(depth prefix text bullet-plus)'
+or \`(depth prefix text bullet-plus)'
 
 If `bullet-plus' is specified, it is inserted just after the entire prefix."
   (setq listified (cdr listified))
@@ -4237,7 +4573,7 @@
     (while text
       (insert (car text))
       (if (setq text (cdr text))
-	  (insert "\n")))
+	  (insert-string "\n")))
     (insert "\n")))
 ;;;_   > allout-copy-exposed-to-buffer (&optional arg tobuf format)
 (defun allout-copy-exposed-to-buffer (&optional arg tobuf format)
@@ -4440,14 +4776,14 @@
 	 body-content bop)
 					; Do the head line:
     (insert (concat "\\OneHeadLine{\\verb\1 "
-		    (allout-latex-verb-quote bullet)
-		    "\1}{"
-		    depth
-		    "}{\\verb\1 "
-		    (if head-line
-			(allout-latex-verb-quote head-line)
-		      "")
-		    "\1}\n"))
+                    (allout-latex-verb-quote bullet)
+                    "\1}{"
+                    depth
+                    "}{\\verb\1 "
+                    (if head-line
+                        (allout-latex-verb-quote head-line)
+                      "")
+                    "\1}\n"))
     (if (not body-lines)
 	nil
       ;;(insert "\\beginlines\n")
@@ -4509,7 +4845,668 @@
     (pop-to-buffer buf)
     (goto-char start-pt)))
 
-;;;_ #8 miscellaneous
+;;;_ #8 Encryption
+;;;_  > allout-toggle-current-subtree-encryption (&optional fetch-pass)
+(defun allout-toggle-current-subtree-encryption (&optional fetch-pass)
+  "Encrypt clear text or decrypt encoded topic contents \(body and subtopics.)
+
+Optional FETCH-PASS universal argument provokes key-pair encryption with
+single universal argument.  With doubled universal argument \(value = 16),
+it forces prompting for the passphrase regardless of availability from the
+passphrase cache.  With no universal argument, the appropriate passphrase
+for the is obtained from the cache, if available, else from the user.
+
+Currently only GnuPG encryption is supported.
+
+\**NOTE WELL** that the encrypted text must be ascii-armored.  For gnupg
+encryption, include the option ``armor'' in your ~/.gnupg/gpg.conf file.
+
+Both symmetric-key and key-pair encryption is implemented.  Symmetric is
+the default, use a single \(x4) universal argument for keypair mode.
+
+Encrypted topic's bullet is set to a `~' to signal that the contents of the
+topic \(body and subtopics, but not heading) is pending encryption or
+encrypted.  `*' asterisk immediately after the bullet signals that the body
+is encrypted, its' absence means the topic is meant to be encrypted but is
+not.  When a file with topics pending encryption is saved, topics pending
+encryption are encrypted.  See allout-encrypt-unencrypted-on-saves for
+auto-encryption specifics.
+
+\**NOTE WELL** that automatic encryption that happens during saves will
+default to symmetric encryption - you must manually \(re)encrypt key-pair
+encrypted topics if you want them to continue to use the key-pair cipher.
+
+Level-1 topics, with prefix consisting solely of an `*' asterisk, cannot be
+encrypted.  If you want to encrypt the contents of a top-level topic, use
+\\[allout-shift-in] to increase its depth.
+
+  Passphrase Caching
+
+The encryption passphrase is solicited if not currently available in the
+passphrase cache from a recent encryption action.
+
+The solicited passphrase is retained for reuse in a buffer-specific cache
+for some set period of time \(default, 60 seconds), after which the string
+is nulled.  The passphrase cache timeout is customized by setting
+`pgg-passphrase-cache-expiry'.
+
+  Symmetric Passphrase Hinting and Verification
+
+If the file previously had no associated passphrase, or had a different
+passphrase than specified, the user is prompted to repeat the new one for
+corroboration.  A random string encrypted by the new passphrase is set on
+the buffer-specific variable `allout-passphrase-verifier-string', for
+confirmation of the passphrase when next obtained, before encrypting or
+decrypting anything with it.  This helps avoid mistakenly shifting between
+keys.
+
+If allout customization var `allout-passphrase-verifier-handling' is
+non-nil, an entry for `allout-passphrase-verifier-string' and its value is
+added to an Emacs 'local variables' section at the end of the file, which
+is created if necessary.  That setting is for retention of the passphrase
+verifier across emacs sessions.
+
+Similarly, `allout-passphrase-hint-string' stores a user-provided reminder
+about their passphrase, and `allout-passphrase-hint-handling' specifies
+when the hint is presented, or if passphrase hints are disabled.  If
+enabled \(see the `allout-passphrase-hint-handling' docstring for details),
+the hint string is stored in the local-variables section of the file, and
+solicited whenever the passphrase is changed."
+
+  (interactive "P")
+  (save-excursion
+    (allout-end-of-prefix t)
+
+    (if (= (allout-recent-depth) 1)
+        (error (concat "Cannot encrypt or decrypt level 1 topics -"
+                       " shift it in to make it encryptable")))
+
+    (let* ((allout-buffer (current-buffer))
+           ;; Asses location:
+           (after-bullet-pos (point))
+           (was-encrypted
+            (progn (if (= (point-max) after-bullet-pos)
+                       (error "no body to encrypt"))
+                   (allout-encrypted-topic-p)))
+           (was-collapsed (if (not (re-search-forward "[\n\r]" nil t))
+                              nil
+                            (backward-char 1)
+                            (looking-at "\r")))
+           (subtree-beg (1+ (point)))
+           (subtree-end (allout-end-of-subtree))
+           (subject-text (buffer-substring-no-properties subtree-beg
+                                                         subtree-end))
+           (subtree-end-char (char-after (1- subtree-end)))
+           (subtree-trailling-char (char-after subtree-end))
+           (place-holder (if (or (string= "" subject-text)
+                                 (string= "\n" subject-text))
+                             (error "No topic contents to %scrypt"
+                                    (if was-encrypted "de" "en"))))
+           ;; Assess key parameters:
+           (key-info (or
+                      ;; detect the type by which it is already encrypted
+                      (and was-encrypted
+                           (allout-encrypted-key-info subject-text))
+                      (and (member fetch-pass '(4 (4)))
+                           '(keypair nil))
+                      '(symmetric nil)))
+           (for-key-type (car key-info))
+           (for-key-identity (cadr key-info))
+           (fetch-pass (and fetch-pass (member fetch-pass '(16 (16)))))
+           result-text)
+
+      (setq result-text
+            (allout-encrypt-string subject-text was-encrypted
+                                    (current-buffer)
+                                    for-key-type for-key-identity fetch-pass))
+
+       ;; Replace the subtree with the processed product.
+      (allout-unprotected
+       (progn
+         (set-buffer allout-buffer)
+         (delete-region subtree-beg subtree-end)
+         (insert result-text)
+         (if was-collapsed
+             (allout-flag-region subtree-beg (1- (point)) ?\r))
+         ;; adjust trailling-blank-lines to preserve topic spacing:
+         (if (not was-encrypted)
+             (if (and (member subtree-end-char '(?\r ?\n))
+                      (member subtree-trailling-char '(?\r ?\n)))
+                 (insert subtree-trailling-char)))
+         ;; Ensure that the item has an encrypted-entry bullet:
+         (if (not (string= (buffer-substring-no-properties
+                            (1- after-bullet-pos) after-bullet-pos)
+                           allout-topic-encryption-bullet))
+             (progn (goto-char (1- after-bullet-pos))
+                    (delete-char 1)
+                    (insert allout-topic-encryption-bullet)))
+         (if was-encrypted
+             ;; Remove the is-encrypted bullet qualifier:
+             (progn (goto-char after-bullet-pos)
+                    (delete-char 1))
+           ;; Add the is-encrypted bullet qualifier:
+           (goto-char after-bullet-pos)
+           (insert "*"))
+         )
+       )
+      )
+    )
+  )
+;;;_  > allout-encrypt-string (text decrypt allout-buffer key-type for-key
+;;;                                  fetch-pass &optional retried verifying
+;;;                                  passphrase)
+(defun allout-encrypt-string (text decrypt allout-buffer key-type for-key
+                                       fetch-pass &optional retried verifying
+                                       passphrase)
+  "Encrypt or decrypt message TEXT.
+
+If DECRYPT is true (default false), then decrypt instead of encrypt.
+
+FETCH-PASS (default false) forces fresh prompting for the passphrase.
+
+KEY-TYPE indicates whether to use a 'symmetric or 'keypair cipher.
+
+FOR-KEY is human readable identification of the first of the user's
+eligible secret keys a keypair decryption targets, or else nil.
+
+Optional RETRIED is for internal use - conveys the number of failed keys
+that have been solicited in sequence leading to this current call.
+
+Optional PASSPHRASE enables explicit delivery of the decryption passphrase,
+for verification purposes.
+
+Returns the resulting string, or nil if the transformation fails."
+
+  (require 'pgg)
+
+  (let* ((scheme (upcase
+                  (format "%s" (or pgg-scheme pgg-default-scheme "GPG"))))
+         (for-key (and (equal key-type 'keypair)
+                       (or for-key
+                           (split-string (read-string
+                                          (format "%s message recipients: "
+                                                  scheme))
+                                         "[ \t,]+"))))
+         (target-prompt-id (if (equal key-type 'keypair)
+                               (if (= (length for-key) 1)
+                                   (car for-key) for-key)
+                             (buffer-name allout-buffer)))
+         (target-cache-id (format "%s-%s"
+                                  key-type
+                                  (if (equal key-type 'keypair)
+                                      target-prompt-id
+                                    (or (buffer-file-name allout-buffer)
+                                        target-prompt-id))))
+         (comment "Processed by allout driving pgg")
+         work-buffer result result-text status)
+
+    (if (and fetch-pass (not passphrase))
+        ;; Force later fetch by evicting passphrase from the cache.
+        (pgg-remove-passphrase-from-cache target-cache-id t))
+
+    (catch 'encryption-failed
+
+        ;; Obtain the passphrase if we don't already have one and we're not
+        ;; doing a keypair encryption:
+        (if (not (or passphrase
+                     (and (equal key-type 'keypair)
+                          (not decrypt))))
+
+            (setq passphrase (allout-obtain-passphrase for-key
+                                                       target-cache-id
+                                                       target-prompt-id
+                                                       key-type
+                                                       allout-buffer
+                                                       retried fetch-pass)))
+        (with-temp-buffer
+
+          (insert (subst-char-in-string ?\r ?\n text))
+
+          (cond
+
+           ;; symmetric:
+           ((equal key-type 'symmetric)
+            (setq status
+                  (if decrypt
+
+                      (pgg-decrypt (point-min) (point-max) passphrase)
+
+                    (pgg-encrypt-symmetric (point-min) (point-max)
+                                           passphrase)))
+
+            (if status
+                (pgg-situate-output (point-min) (point-max))
+              ;; failed - handle passphrase caching
+              (if verifying
+                  (throw 'encryption-failed nil)
+                (pgg-remove-passphrase-from-cache target-cache-id t)
+                (error "Symmetric-cipher encryption failed - %s"
+                       "try again with different passphrase."))))
+
+           ;; encrypt 'keypair:
+           ((not decrypt)
+
+            (setq status
+
+                  (pgg-encrypt for-key
+                               nil (point-min) (point-max) passphrase))
+
+            (if status
+                (pgg-situate-output (point-min) (point-max))
+              (error (pgg-remove-passphrase-from-cache target-cache-id t)
+                     (error "encryption failed"))))
+
+           ;; decrypt 'keypair:
+           (t
+
+            (setq status
+                  (pgg-decrypt (point-min) (point-max) passphrase))
+
+            (if status
+                (pgg-situate-output (point-min) (point-max))
+              (error (pgg-remove-passphrase-from-cache target-cache-id t)
+                     (error "decryption failed"))))
+           )
+
+          (setq result-text
+                (buffer-substring 1 (- (point-max) (if decrypt 0 1))))
+
+          ;; validate result - non-empty
+          (cond ((not result-text)
+                 (if verifying
+                     nil
+                   ;; transform was fruitless, retry w/new passphrase.
+                   (pgg-remove-passphrase-from-cache target-cache-id t)
+                   (allout-encrypt-string text allout-buffer decrypt nil
+                                          (if retried (1+ retried) 1)
+                                          passphrase)))
+
+                ;; Barf if encryption yields extraordinary control chars:
+                ((and (not decrypt)
+                      (string-match "[\C-a\C-k\C-o-\C-z\C-@]"
+                                    result-text))
+                 (error (concat "encryption produced unusable"
+                                " non-armored text - reconfigure!")))
+
+                ;; valid result and just verifying or non-symmetric:
+                ((or verifying (not (equal key-type 'symmetric)))
+                 (if (or verifying decrypt)
+                     (pgg-add-passphrase-to-cache target-cache-id
+                                                  passphrase t))
+                 result-text)
+
+                ;; valid result and regular symmetric - "register"
+                ;; passphrase with mnemonic aids/cache.
+                (t
+                 (set-buffer allout-buffer)
+                 (if passphrase
+                     (pgg-add-passphrase-to-cache target-cache-id
+                                                  passphrase t))
+                 (allout-update-passphrase-mnemonic-aids for-key passphrase
+                                                         allout-buffer)
+                 result-text)
+                )
+          )
+        )
+    )
+  )
+;;;_  > allout-obtain-passphrase (for-key cache-id prompt-id key-type
+;;;                                       allout-buffer retried fetch-pass)
+(defun allout-obtain-passphrase (for-key cache-id prompt-id key-type 
+                                         allout-buffer retried fetch-pass)
+  "Obtain passphrase for a key from the cache or else from the user.
+
+When obtaining from the user, symmetric-cipher passphrases are verified
+against either, if available and enabled, a random string that was
+encrypted against the passphrase, or else against repeated entry by the
+user for corroboration.
+
+FOR-KEY is the key for which the passphrase is being obtained.
+
+CACHE-ID is the cache id of the key for the passphrase.
+
+PROMPT-ID is the id for use when prompting the user.
+
+KEY-TYPE is either 'symmetric or 'keypair.
+
+ALLOUT-BUFFER is the buffer containing the entry being en/decrypted.
+
+RETRIED is the number of this attempt to obtain this passphrase.
+
+FETCH-PASS causes the passphrase to be solicited from the user, regardless
+of the availability of a cached copy."
+
+  (if (not (equal key-type 'symmetric))
+      ;; do regular passphrase read on non-symmetric passphrase:
+      (pgg-read-passphrase (format "%s passphrase%s: "
+                                   (upcase (format "%s" (or pgg-scheme
+                                                            pgg-default-scheme
+                                                            "GPG")))
+                                     (if prompt-id
+                                         (format " for %s" prompt-id)
+                                       ""))
+                           cache-id t)
+
+    ;; Symmetric hereon:
+
+    (save-excursion
+      (set-buffer allout-buffer)
+      (let* ((hint (if (and (not (string= allout-passphrase-hint-string ""))
+                            (or (equal allout-passphrase-hint-handling 'always)
+                                (and (equal allout-passphrase-hint-handling
+                                            'needed)
+                                     retried)))
+                       (format " [%s]" allout-passphrase-hint-string)
+                     ""))
+             (retry-message (if retried (format " (%s retry)" retried) ""))
+             (prompt-sans-hint (format "'%s' symmetric passphrase%s: "
+                                       prompt-id retry-message))
+             (full-prompt (format "'%s' symmetric passphrase%s%s: "
+                                  prompt-id hint retry-message))
+             (prompt full-prompt)
+             (verifier-string (allout-get-encryption-passphrase-verifier))
+
+             (cached (and (not fetch-pass)
+                          (pgg-read-passphrase-from-cache cache-id t)))
+             (got-pass (or cached
+                           (pgg-read-passphrase full-prompt cache-id t)))
+
+             confirmation)
+
+        (if (not got-pass)
+            nil
+
+          ;; Duplicate our handle on the passphrase so it's not clobbered by
+          ;; deactivate-passwd memory clearing:
+          (setq got-pass (format "%s" got-pass))
+
+          (cond (verifier-string
+                 (save-window-excursion
+                   (if (allout-encrypt-string verifier-string 'decrypt
+                                              allout-buffer 'symmetric
+                                              for-key nil 0 'verifying
+                                              got-pass)
+                       (setq confirmation (format "%s" got-pass))))
+
+                 (if (and (not confirmation)
+                          (if (yes-or-no-p
+                               (concat "Passphrase differs from established"
+                                       " - use new one instead? "))
+                              ;; deactivate password for subsequent
+                              ;; confirmation:
+                              (progn
+                                (pgg-remove-passphrase-from-cache cache-id t)
+                                (setq prompt prompt-sans-hint)
+                                nil)
+                            t))
+                     (progn (pgg-remove-passphrase-from-cache cache-id t)
+                            (error "Wrong passphrase."))))
+                ;; No verifier string - force confirmation by repetition of
+                ;; (new) passphrase:
+                ((or fetch-pass (not cached))
+                 (pgg-remove-passphrase-from-cache cache-id t))))
+        ;; confirmation vs new input - doing pgg-read-passphrase will do the
+        ;; right thing, in either case:
+        (if (not confirmation)
+            (setq confirmation
+                  (pgg-read-passphrase (concat prompt
+                                               " ... confirm spelling: ")
+                                       cache-id t)))
+        (prog1
+            (if (equal got-pass confirmation)
+                confirmation
+              (if (yes-or-no-p (concat "spelling of original and"
+                                       " confirmation differ - retry? "))
+                  (progn (setq retried (if retried (1+ retried) 1))
+                         (pgg-remove-passphrase-from-cache cache-id t)
+                         ;; recurse to this routine:
+                         (pgg-read-passphrase prompt-sans-hint cache-id t))
+                (pgg-remove-passphrase-from-cache cache-id t)
+                (error "Confirmation failed.")))
+          ;; reduce opportunity for memory cherry-picking by zeroing duplicate:
+          (dotimes (i (length got-pass))
+            (aset got-pass i 0))
+          )
+        )
+      )
+    )
+  )
+;;;_  > allout-encrypted-topic-p ()
+(defun allout-encrypted-topic-p ()
+  "True if the current topic is encryptable and encrypted."
+  (save-excursion
+    (allout-end-of-prefix t)
+    (and (string= (buffer-substring-no-properties (1- (point)) (point))
+                  allout-topic-encryption-bullet)
+         (looking-at "\\*"))
+    )
+  )
+;;;_  > allout-encrypted-key-info (text)
+;; XXX gpg-specific, alas
+(defun allout-encrypted-key-info (text)
+  "Return a pair of the key type and identity of a recipient's secret key.
+
+The key type is one of 'symmetric or 'keypair.
+
+if 'keypair, and some of the user's secret keys are among those for which
+the message was encoded, return the identity of the first.  otherwise,
+return nil for the second item of the pair.
+
+An error is raised if the text is not encrypted."
+  (require 'pgg-parse)
+  (save-excursion
+    (with-temp-buffer
+      (insert (subst-char-in-string ?\r ?\n text))
+      (let* ((parsed-armor (pgg-parse-armor-region (point-min) (point-max)))
+             (type (if (pgg-gpg-symmetric-key-p parsed-armor)
+                       'symmetric
+                     'keypair))
+             secret-keys first-secret-key for-key-owner)
+        (if (equal type 'keypair)
+            (setq secret-keys (pgg-gpg-lookup-all-secret-keys)
+                  first-secret-key (pgg-gpg-select-matching-key parsed-armor
+                                                                secret-keys)
+                  for-key-owner (and first-secret-key
+                                     (pgg-gpg-lookup-key-owner
+                                      first-secret-key))))
+        (list type (pgg-gpg-key-id-from-key-owner for-key-owner))
+        )
+      )
+    )
+  )
+;;;_  > allout-create-encryption-passphrase-verifier (passphrase)
+(defun allout-create-encryption-passphrase-verifier (passphrase)
+  "Encrypt random message for later validation of symmetric key's passphrase."
+  ;; use 20 random ascii characters, across the entire ascii range.
+  (random t)
+  (let ((spew (make-string 20 ?\0)))
+    (dotimes (i (length spew))
+      (aset spew i (1+ (random 254))))
+    (allout-encrypt-string spew nil (current-buffer) 'symmetric
+                           nil nil 0 passphrase))
+  )
+;;;_  > allout-update-passphrase-mnemonic-aids (for-key passphrase
+;;;                                                     outline-buffer) 
+(defun allout-update-passphrase-mnemonic-aids (for-key passphrase
+                                                       outline-buffer)
+  "Update passphrase verifier and hint strings if necessary.
+
+See `allout-passphrase-verifier-string' and `allout-passphrase-hint-string'
+settings.
+
+PASSPHRASE is the passphrase being mnemonicized
+
+OUTLINE-BUFFER is the buffer of the outline being adjusted.
+
+These are used to help the user keep track of the passphrase they use for
+symmetric encryption in the file.
+
+Behavior is governed by `allout-passphrase-verifier-handling',
+`allout-passphrase-hint-handling', and also, controlling whether the values
+are preserved on Emacs local file variables,
+`allout-enable-file-variable-adjustment'."
+
+  ;; If passphrase doesn't agree with current verifier:
+  ;;   - adjust the verifier
+  ;;   - if passphrase hint handling is enabled, adjust the passphrase hint
+  ;;   - if file var settings are enabled, adjust the file vars
+
+  (let* ((new-verifier-needed (not (allout-verify-passphrase
+                                    for-key passphrase outline-buffer)))
+         (new-verifier-string
+          (if new-verifier-needed
+              ;; Collapse to a single line and enclose in string quotes:
+              (subst-char-in-string
+               ?\n ?\C-a (allout-create-encryption-passphrase-verifier
+                          passphrase))))
+         new-hint)
+    (when new-verifier-string
+      ;; do the passphrase hint first, since it's interactive
+      (when (and allout-passphrase-hint-handling
+                 (not (equal allout-passphrase-hint-handling 'disabled)))
+        (setq new-hint
+              (read-from-minibuffer "Passphrase hint to jog your memory: "
+                                    allout-passphrase-hint-string))
+        (when (not (string= new-hint allout-passphrase-hint-string))
+          (setq allout-passphrase-hint-string new-hint)
+          (allout-adjust-file-variable "allout-passphrase-hint-string"
+                                       allout-passphrase-hint-string)))
+      (when allout-passphrase-verifier-handling
+        (setq allout-passphrase-verifier-string new-verifier-string)
+        (allout-adjust-file-variable "allout-passphrase-verifier-string"
+                                     allout-passphrase-verifier-string))
+      )
+    )
+  )
+;;;_  > allout-get-encryption-passphrase-verifier ()
+(defun allout-get-encryption-passphrase-verifier ()
+  "Return text of the encrypt passphrase verifier, unmassaged, or nil if none.
+
+Derived from value of `allout-file-passphrase-verifier-string'."
+
+  (let ((verifier-string (and (boundp 'allout-passphrase-verifier-string)
+                              allout-passphrase-verifier-string)))
+    (if verifier-string
+        ;; Return it uncollapsed
+        (subst-char-in-string ?\C-a ?\n verifier-string))
+   )
+  )
+;;;_  > allout-verify-passphrase (key passphrase allout-buffer)
+(defun allout-verify-passphrase (key passphrase allout-buffer)
+  "True if passphrase successfully decrypts verifier, nil otherwise.
+
+\"Otherwise\" includes absence of passphrase verifier."
+  (save-excursion
+    (set-buffer allout-buffer)
+    (and (boundp 'allout-passphrase-verifier-string)
+         allout-passphrase-verifier-string
+         (allout-encrypt-string (allout-get-encryption-passphrase-verifier)
+                                 'decrypt allout-buffer 'symmetric
+                                 key nil 0 'verifying passphrase)
+         t)))
+;;;_  > allout-next-topic-pending-encryption (&optional except-mark)
+(defun allout-next-topic-pending-encryption (&optional except-mark)
+  "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."
+  (let (done got content-beg)
+    (while (not done)
+
+      (if (not (re-search-forward
+                (format "\\(\\`\\|[\n\r]\\)%s *%s[^*]"
+                        (regexp-quote allout-header-prefix)
+                        (regexp-quote allout-topic-encryption-bullet))
+                nil t))
+          (setq got nil
+                done t)
+        (goto-char (setq got (match-beginning 0)))
+        (if (looking-at "[\n\r]")
+            (forward-char 1))
+        (setq got (point)))
+
+      (cond ((not got)
+             (setq done t))
+
+            ((not (re-search-forward "[\n\r]"))
+             (setq got nil
+                   done t))
+
+            ((eobp)
+             (setq got nil
+                   done t))
+
+            (t
+             (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)))
+                 ;; Continue looking
+                 (setq got nil)
+               ;; Got it!
+               (setq done t)))
+            )
+      )
+    (if got
+        (goto-char got))
+    )
+  )
+;;;_  > allout-encrypt-decrypted (&optional except-mark)
+(defun allout-encrypt-decrypted (&optional except-mark)
+  "Encrypt topics pending encryption except those containing exemption point.
+
+EXCEPT-MARK identifies a point whose containing topics should be excluded
+from encryption.  This supports '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
+and exactly resituate the cursor if this is being done as part of a file
+save.  See `allout-encrypt-unencrypted-on-saves' for more info."
+
+  (interactive "p")
+  (save-excursion
+    (let ((current-mark (point-marker))
+          was-modified
+          bo-subtree
+          editing-topic editing-point)
+      (goto-char (point-min))
+      (while (allout-next-topic-pending-encryption except-mark)
+        (setq was-modified (buffer-modified-p))
+        (if (save-excursion
+              (and (boundp 'allout-encrypt-unencrypted-on-saves)
+                   allout-encrypt-unencrypted-on-saves
+                   (setq bo-subtree (re-search-forward "[\n\r]"))
+                   ;; Not collapsed:
+                   (string= (match-string 0) "\n")
+                   (>= current-mark (point))
+                   (allout-end-of-current-subtree)
+                   (<= current-mark (point))))
+            (setq editing-topic (point)
+                  ;; we had to wait for this 'til now so prior topics are
+                  ;; encrypted, any relevant text shifts are in place:
+                  editing-point (marker-position current-mark)))
+        (allout-toggle-current-subtree-encryption)
+        (if (not was-modified)
+            (set-buffer-modified-p nil))
+        )
+      (if (not was-modified)
+         (set-buffer-modified-p nil))
+      (if editing-topic (list editing-topic editing-point))
+      )
+    )
+  )
+
+;;;_ #9 miscellaneous
 ;;;_  > allout-mark-topic ()
 (defun allout-mark-topic ()
   "Put the region around topic currently containing point."
@@ -4521,7 +5518,9 @@
   (exchange-point-and-mark))
 ;;;_  > outlineify-sticky ()
 ;; outlinify-sticky is correct spelling; provide this alias for sticklers:
+;;;###autoload
 (defalias 'outlinify-sticky 'outlineify-sticky)
+;;;###autoload
 (defun outlineify-sticky (&optional arg)
   "Activate outline mode and establish file var so it is started subsequently.
 
@@ -4538,22 +5537,100 @@
 	t
       (allout-open-topic 2)
       (insert (concat "Dummy outline topic header - see"
-		      "`allout-mode' docstring: `^Hm'."))
-      (forward-line 1)
+                      "`allout-mode' docstring: `^Hm'."))
+      (allout-adjust-file-variable
+       "allout-layout" (format "%s" (or allout-layout '(-1 : 0)))))))
+;;;_  > allout-file-vars-section-data ()
+(defun allout-file-vars-section-data ()
+  "Return data identifying the file-vars section, or nil if none.
+
+Returns list `(beginning-point prefix-string suffix-string)'."
+  ;; minimally gleaned from emacs 21.4 files.el hack-local-variables function.
+  (let (beg prefix suffix)
+    (save-excursion
       (goto-char (point-max))
-      (open-line 1)
-      (allout-open-topic 0)
-      (insert "Local emacs vars.\n")
-      (allout-open-topic 1)
-      (insert "(`allout-layout' is for allout.el allout-mode)\n")
-      (allout-open-topic 0)
-      (insert "Local variables:\n")
-      (allout-open-topic 0)
-      (insert (format "allout-layout: %s\n"
-			     (or allout-layout
-				 '(-1 : 0))))
-      (allout-open-topic 0)
-      (insert "End:\n"))))
+      (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
+      (if (let ((case-fold-search t))
+	    (not (search-forward "Local Variables:" nil t)))
+          nil
+        (setq beg (- (point) 16))
+        (setq suffix (buffer-substring-no-properties
+                      (point)
+                      (progn (if (re-search-forward "[\n\r]" nil t)
+                                 (forward-char -1))
+                             (point))))
+        (setq prefix (buffer-substring-no-properties
+                      (progn (if (re-search-backward "[\n\r]" nil t)
+                                 (forward-char 1))
+                             (point))
+                      beg))
+        (list beg prefix suffix))
+      )
+    )
+  )
+;;;_  > allout-adjust-file-variable (varname value)
+(defun allout-adjust-file-variable (varname value)
+  "Adjust the setting of an emacs file variable named VARNAME to VALUE.
+
+This activity is inhibited if either `enable-local-variables'
+`allout-enable-file-variable-adjustment' are nil.
+
+When enabled, an entry for the variable is created if not already present,
+or changed if established with a different value.  The section for the file
+variables, itself, is created if not already present.  When created, the
+section lines \(including the section line) exist as second-level topics in
+a top-level topic at the end of the file.
+
+enable-local-variables must be true for any of this to happen."
+  (if (not (and enable-local-variables
+                allout-enable-file-variable-adjustment))
+      nil
+    (save-excursion
+      (let ((section-data (allout-file-vars-section-data))
+            beg prefix suffix)
+        (if section-data
+            (setq beg (car section-data)
+                  prefix (cadr section-data)
+                  suffix (car (cddr section-data)))
+          ;; create the section
+          (goto-char (point-max))
+          (open-line 1)
+          (allout-open-topic 0)
+          (end-of-line)
+          (insert "Local emacs vars.\n")
+          (allout-open-topic 1)
+          (setq beg (point)
+                suffix ""
+                prefix (buffer-substring-no-properties (progn
+                                                         (beginning-of-line)
+                                                         (point))
+                                                       beg))
+          (goto-char beg)
+          (insert "Local variables:\n")
+          (allout-open-topic 0)
+          (insert "End:\n")
+          )
+        ;; look for existing entry or create one, leaving point for insertion
+        ;; of new value:
+        (goto-char beg)
+        (allout-show-to-offshoot)
+        (if (search-forward (concat "\n" prefix varname ":") nil t)
+            (let* ((value-beg (point))
+                   (line-end (progn (if (re-search-forward "[\n\r]" nil t)
+                                        (forward-char -1))
+                                    (point)))
+                   (value-end (- line-end (length suffix))))
+              (if (> value-end value-beg)
+                  (delete-region value-beg value-end)))
+          (end-of-line)
+          (open-line 1)
+          (forward-line 1)
+          (insert (concat prefix varname ":")))
+        (insert (format " %S%s" value suffix))
+        )
+      )
+    )
+  )
 ;;;_  > solicit-char-in-string (prompt string &optional do-defaulting)
 (defun solicit-char-in-string (prompt string &optional do-defaulting)
   "Solicit (with first arg PROMPT) choice of a character from string STRING.
@@ -4594,8 +5671,7 @@
 Representations of actual backslashes - '\\\\\\\\' - are left as a
 single backslash.
 
-\(fn REGEXP)"
-;; Optional arg SUCCESSIVE-BACKSLASHES is used internally for recursion.
+Optional arg SUCCESSIVE-BACKSLASHES is used internally for recursion."
 
   (if (string= regexp "")
       ""
@@ -4611,11 +5687,6 @@
 		(regexp-sans-escapes (substring regexp 1)))
       ;; Exclude first char, but maintain count:
       (regexp-sans-escapes (substring regexp 1) successive-backslashes))))
-;;;_  > my-region-active-p ()
-(defmacro my-region-active-p ()
-  (if (fboundp 'region-active-p)
-      '(region-active-p)
-    'mark-active))
 ;;;_  - add-hook definition for divergent emacsen
 ;;;_   > add-hook (hook function &optional append)
 (if (not (fboundp 'add-hook))
@@ -4636,17 +5707,29 @@
 	       (if append
 		   (nconc (symbol-value hook) (list function))
 		 (cons function (symbol-value hook)))))))
+;;;_  > subst-char-in-string if necessary
+(if (not (fboundp 'subst-char-in-string))
+    (defun subst-char-in-string (fromchar tochar string &optional inplace)
+      "Replace FROMCHAR with TOCHAR in STRING each time it occurs.
+Unless optional argument INPLACE is non-nil, return a new string."
+      (let ((i (length string))
+            (newstr (if inplace string (copy-sequence string))))
+        (while (> i 0)
+          (setq i (1- i))
+          (if (eq (aref newstr i) fromchar)
+              (aset newstr i tochar)))
+        newstr)))
 ;;;_  : my-mark-marker to accommodate divergent emacsen:
 (defun my-mark-marker (&optional force buffer)
   "Accommodate the different signature for `mark-marker' across Emacsen.
 
-XEmacs takes two optional args, while GNU Emacs does not,
+XEmacs takes two optional args, while mainline GNU Emacs does not,
 so pass them along when appropriate."
   (if (featurep 'xemacs)
-      (mark-marker force buffer)
+      (apply 'mark-marker force buffer)
     (mark-marker)))
 
-;;;_ #9 Under development
+;;;_ #10 Under development
 ;;;_  > allout-bullet-isearch (&optional bullet)
 (defun allout-bullet-isearch (&optional bullet)
   "Isearch \(regexp) for topic with bullet BULLET."







[-- Attachment #5: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-12 23:47                                       ` Ken Manheimer
@ 2005-10-20 14:08                                         ` Ken Manheimer
  2005-10-20 14:12                                           ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-20 14:08 UTC (permalink / raw)


i just posted a new version of my allout patches which depend on the
pgg revisions of sascha and mine, so i thought i'd post a query in
this thread on the status of these patches - the new allout encryption
features won't work without these pgg refinements in place.  i also
should mention rms' initiative to relocate pgg to the lisp/ directory,
since pgg constitutes a facility in its own regard - i'm all for that.

i'm not attaching the pgg changes to this message, but can easily do
so if needed.

ken
ken.manheimer@gmail.com

On 10/12/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> as threatened, here is a complete patch against the current gnu.org
> lisp/gnus repository.  i've migrated all the allout encryption
> functionality to pgg and exercised this stuff pretty substantially,
> and am very comfortable with the way it works.
>
> there are a bunch of fixes, as well as extensions so the passphrases
> can be managed by the calling functions, as well as refinement of the
> passphrase caching mechanism (so multiple timeouts don't pileup for a
> single passphrase - the last one replaces the prior ones).   lotsa
> goodies.  the patch includes sascha wilde's symmetric-encryption
> additions - basically, the whole deal.
>
> what it does not include is revision of the pgg-pgp.el and pgg-pgp5.el
> modules, to track changes to the pgg api.  i started in on that, only
> to discover that they were already broken by the addition of a 'sign'
> parameter to some of the encryption functions.  there's no way to
> repair that short of implementing the feature for the other packages,
> and i'm not in a position to do that.  (plus, i'm not sure i am
> comfortable with the way it was done for pgg-gpg.)
>
> so it looks like pgg-pgp.el and pgg-pgp5.el are disfunctional already,
> without my changes.  i'm hoping that's not going to prevent the
> introduction of my changes.
>
> i'm going to be heading offline for five days, starting tomorrow, so
> it'll be a bit before i can respond to questions.  i hope the patch
> i'm sending (which  includes detaild ChangeLog entries) will be
> helpful to anyone that wishes to navigate them.
>
> and once again, i'm not sure the attachment will be delivered this
> time.  (it wasn't on a recent try, but then was on a subsequent
> message.  this is the first awkward gmail bug i've hit...)
>
> ken
> ken.manheimer@gmail.com
>
> On 10/10/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> > for those of you following the developments at home (:-), here's an
> > incremental patch on top of what i sent out a few days ago.  i fixed a
> > small stack of bugs in pgg-gpg.el that settles my complaint about
> > prompting with the secret key identity, and also filled in a small
> > oversight in the changes i sent out a few days ago.
> >
> > while this could be the last pgg patch, i'm still developing, hence
> > the incremental.  i plan to send out a full patch when i've finished
> > transitioning allout to pgg, at which point i expect my mucking with
> > pgg to be settled.  so, repository maintainers may want to wait for
> > that, while i'm hoping those actively involved (eg, sascha) will
> > scrutinize and, ideally, exercise these patches.
> >
> > we'll see if the attached patch makes it through this time.  (i
> > haven't re-attached it, which i think was the problem last time.)  if
> > not, look forward to a followup...

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-20 14:08                                         ` Ken Manheimer
@ 2005-10-20 14:12                                           ` Simon Josefsson
  2005-10-20 14:30                                             ` Ken Manheimer
                                                               ` (4 more replies)
  0 siblings, 5 replies; 156+ messages in thread
From: Simon Josefsson @ 2005-10-20 14:12 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel

Hi.  Thanks for reminding me.  I thought we were waiting for copyright
assignment papers?  Have the FSF received papers for all authors?  The
best way to proceed is to wait for them to arrive, and then send me a
complete patch against the then-current CVS that I can install.  I can
take care of installing it into Gnus CVS as well.

I'm all for relocating pgg.  However, I suggest lisp/pgg/ instead.
The lisp/ directory is pretty large as it is.

Ken Manheimer <ken.manheimer@gmail.com> writes:

> i just posted a new version of my allout patches which depend on the
> pgg revisions of sascha and mine, so i thought i'd post a query in
> this thread on the status of these patches - the new allout encryption
> features won't work without these pgg refinements in place.  i also
> should mention rms' initiative to relocate pgg to the lisp/ directory,
> since pgg constitutes a facility in its own regard - i'm all for that.
>
> i'm not attaching the pgg changes to this message, but can easily do
> so if needed.
>
> ken
> ken.manheimer@gmail.com
>
> On 10/12/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
>> as threatened, here is a complete patch against the current gnu.org
>> lisp/gnus repository.  i've migrated all the allout encryption
>> functionality to pgg and exercised this stuff pretty substantially,
>> and am very comfortable with the way it works.
>>
>> there are a bunch of fixes, as well as extensions so the passphrases
>> can be managed by the calling functions, as well as refinement of the
>> passphrase caching mechanism (so multiple timeouts don't pileup for a
>> single passphrase - the last one replaces the prior ones).   lotsa
>> goodies.  the patch includes sascha wilde's symmetric-encryption
>> additions - basically, the whole deal.
>>
>> what it does not include is revision of the pgg-pgp.el and pgg-pgp5.el
>> modules, to track changes to the pgg api.  i started in on that, only
>> to discover that they were already broken by the addition of a 'sign'
>> parameter to some of the encryption functions.  there's no way to
>> repair that short of implementing the feature for the other packages,
>> and i'm not in a position to do that.  (plus, i'm not sure i am
>> comfortable with the way it was done for pgg-gpg.)
>>
>> so it looks like pgg-pgp.el and pgg-pgp5.el are disfunctional already,
>> without my changes.  i'm hoping that's not going to prevent the
>> introduction of my changes.
>>
>> i'm going to be heading offline for five days, starting tomorrow, so
>> it'll be a bit before i can respond to questions.  i hope the patch
>> i'm sending (which  includes detaild ChangeLog entries) will be
>> helpful to anyone that wishes to navigate them.
>>
>> and once again, i'm not sure the attachment will be delivered this
>> time.  (it wasn't on a recent try, but then was on a subsequent
>> message.  this is the first awkward gmail bug i've hit...)
>>
>> ken
>> ken.manheimer@gmail.com
>>
>> On 10/10/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
>> > for those of you following the developments at home (:-), here's an
>> > incremental patch on top of what i sent out a few days ago.  i fixed a
>> > small stack of bugs in pgg-gpg.el that settles my complaint about
>> > prompting with the secret key identity, and also filled in a small
>> > oversight in the changes i sent out a few days ago.
>> >
>> > while this could be the last pgg patch, i'm still developing, hence
>> > the incremental.  i plan to send out a full patch when i've finished
>> > transitioning allout to pgg, at which point i expect my mucking with
>> > pgg to be settled.  so, repository maintainers may want to wait for
>> > that, while i'm hoping those actively involved (eg, sascha) will
>> > scrutinize and, ideally, exercise these patches.
>> >
>> > we'll see if the attached patch makes it through this time.  (i
>> > haven't re-attached it, which i think was the problem last time.)  if
>> > not, look forward to a followup...

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-20 14:12                                           ` Simon Josefsson
@ 2005-10-20 14:30                                             ` Ken Manheimer
  2005-10-20 14:42                                             ` Sascha Wilde
                                                               ` (3 subsequent siblings)
  4 siblings, 0 replies; 156+ messages in thread
From: Ken Manheimer @ 2005-10-20 14:30 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel

On 10/20/05, Simon Josefsson <jas@extundo.com> wrote:

> Hi.  Thanks for reminding me.  I thought we were waiting for copyright
> assignment papers?  Have the FSF received papers for all authors?  The

i'll send my pgg copyright assignment papers right now.  (they came
while i was away for a week.)  my allout assignment has been on file
for a while, happily.  dunno about status of sascha's assignment.

> best way to proceed is to wait for them to arrive, and then send me a
> complete patch against the then-current CVS that I can install.  I can
> take care of installing it into Gnus CVS as well.
>
> I'm all for relocating pgg.  However, I suggest lisp/pgg/ instead.
> The lisp/ directory is pretty large as it is.

lisp/pgg/ sounds like a good idea to me, too.

ken
ken.manheimer@gmail.com

> Ken Manheimer <ken.manheimer@gmail.com> writes:
>
> > i just posted a new version of my allout patches which depend on the
> > pgg revisions of sascha and mine, so i thought i'd post a query in
> > this thread on the status of these patches - the new allout encryption
> > features won't work without these pgg refinements in place.  i also
> > should mention rms' initiative to relocate pgg to the lisp/ directory,
> > since pgg constitutes a facility in its own regard - i'm all for that.
> >
> > i'm not attaching the pgg changes to this message, but can easily do
> > so if needed.
> >
> > ken
> > ken.manheimer@gmail.com
> >
> > On 10/12/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> >> as threatened, here is a complete patch against the current gnu.org
> >> lisp/gnus repository.  i've migrated all the allout encryption
> >> functionality to pgg and exercised this stuff pretty substantially,
> >> and am very comfortable with the way it works.
> >>
> >> there are a bunch of fixes, as well as extensions so the passphrases
> >> can be managed by the calling functions, as well as refinement of the
> >> passphrase caching mechanism (so multiple timeouts don't pileup for a
> >> single passphrase - the last one replaces the prior ones).   lotsa
> >> goodies.  the patch includes sascha wilde's symmetric-encryption
> >> additions - basically, the whole deal.
> >>
> >> what it does not include is revision of the pgg-pgp.el and pgg-pgp5.el
> >> modules, to track changes to the pgg api.  i started in on that, only
> >> to discover that they were already broken by the addition of a 'sign'
> >> parameter to some of the encryption functions.  there's no way to
> >> repair that short of implementing the feature for the other packages,
> >> and i'm not in a position to do that.  (plus, i'm not sure i am
> >> comfortable with the way it was done for pgg-gpg.)
> >>
> >> so it looks like pgg-pgp.el and pgg-pgp5.el are disfunctional already,
> >> without my changes.  i'm hoping that's not going to prevent the
> >> introduction of my changes.
> >>
> >> i'm going to be heading offline for five days, starting tomorrow, so
> >> it'll be a bit before i can respond to questions.  i hope the patch
> >> i'm sending (which  includes detaild ChangeLog entries) will be
> >> helpful to anyone that wishes to navigate them.
> >>
> >> and once again, i'm not sure the attachment will be delivered this
> >> time.  (it wasn't on a recent try, but then was on a subsequent
> >> message.  this is the first awkward gmail bug i've hit...)
> >>
> >> ken
> >> ken.manheimer@gmail.com
> >>
> >> On 10/10/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> >> > for those of you following the developments at home (:-), here's an
> >> > incremental patch on top of what i sent out a few days ago.  i fixed a
> >> > small stack of bugs in pgg-gpg.el that settles my complaint about
> >> > prompting with the secret key identity, and also filled in a small
> >> > oversight in the changes i sent out a few days ago.
> >> >
> >> > while this could be the last pgg patch, i'm still developing, hence
> >> > the incremental.  i plan to send out a full patch when i've finished
> >> > transitioning allout to pgg, at which point i expect my mucking with
> >> > pgg to be settled.  so, repository maintainers may want to wait for
> >> > that, while i'm hoping those actively involved (eg, sascha) will
> >> > scrutinize and, ideally, exercise these patches.
> >> >
> >> > we'll see if the attached patch makes it through this time.  (i
> >> > haven't re-attached it, which i think was the problem last time.)  if
> >> > not, look forward to a followup...
>

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-20 14:12                                           ` Simon Josefsson
  2005-10-20 14:30                                             ` Ken Manheimer
@ 2005-10-20 14:42                                             ` Sascha Wilde
  2005-10-25  7:23                                               ` Sascha Wilde
  2005-10-20 18:07                                             ` Relocating pgg*.el (was: pgg symmetric encryption patch) Reiner Steib
                                                               ` (2 subsequent siblings)
  4 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-20 14:42 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches), Ken Manheimer,
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 567 bytes --]

On Thu, Oct 20, 2005 at 04:12:58PM +0200, Simon Josefsson wrote:
> Hi.  Thanks for reminding me.  I thought we were waiting for copyright
> assignment papers?  Have the FSF received papers for all authors?

I signed papers and send them off by mail (from Germany) Saturday.  I
haven't got an answer by the fsf yet, but they should receive them at
least quite soon.

cheers
sascha
-- 
Sascha Wilde
    "Computers are good at following instructions,
     but not at reading your mind."
    D. E. Knuth, The TeXbook, Addison-Wesley 1984, 1986, 1996, p. 9

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Relocating pgg*.el (was: pgg symmetric encryption patch)
  2005-10-20 14:12                                           ` Simon Josefsson
  2005-10-20 14:30                                             ` Ken Manheimer
  2005-10-20 14:42                                             ` Sascha Wilde
@ 2005-10-20 18:07                                             ` Reiner Steib
  2005-10-20 22:22                                               ` Kim F. Storm
  2005-10-20 23:38                                             ` pgg symmetric encryption patch Richard M. Stallman
  2006-03-18 21:17                                             ` Small patch to enable use of gpg-agent with pgg Sascha Wilde
  4 siblings, 1 reply; 156+ messages in thread
From: Reiner Steib @ 2005-10-20 18:07 UTC (permalink / raw)


On Thu, Oct 20 2005, Simon Josefsson wrote:

> I'm all for relocating pgg.

I wasn't sure about the "best practice" in order to keep CVS history
when moving files around.

> However, I suggest lisp/pgg/ instead.  The lisp/ directory is pretty
> large as it is.

Shouldn't pgg*.el be put into a separate directory along with other
security or cryptography related libraries (maybe lisp/security or
lisp/crypto)?

PGG files:

gnus/pgg.el
gnus/pgg-pgp5.el
gnus/pgg-pgp.el
gnus/pgg-parse.el
gnus/pgg-gpg.el
gnus/pgg-def.el

Other files (used by Gnus):

gnus/sha1.el
gnus/starttls.el
net/tls.el

... and maybe others like password.el and encrypt.el (only in Gnus CVS
upto now).  It has been discussed previously[1] that it would be
useful to add password.el and encrypt.el to Emacs, but it wasn't done
because of the feature freeze.  I'd suggest to add those libraries.
Unless we start to modify existing Emacs 22 packages to use them, it
wouldn't destabilize anything.

Bye, Reiner.

[1] http://thread.gmane.org/gmane.emacs.gnus.general/58915

,----
| From: "Ted Zlatanov" <tzz@lifelogs.com>
| Subject: encrypt.el (was: pop3.el itegration with netrc.el)
| To: ding@gnus.org
| Cc: "emacs-devel" <emacs-devel@gnu.org>
| Date: Fri, 15 Oct 2004 21:14:59 +0200
| Message-ID: <4nfz4f94jw.fsf_-_@lifelogs.com>
`----
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Relocating pgg*.el (was: pgg symmetric encryption patch)
  2005-10-20 18:07                                             ` Relocating pgg*.el (was: pgg symmetric encryption patch) Reiner Steib
@ 2005-10-20 22:22                                               ` Kim F. Storm
  2005-10-21  4:49                                                 ` Richard M. Stallman
  0 siblings, 1 reply; 156+ messages in thread
From: Kim F. Storm @ 2005-10-20 22:22 UTC (permalink / raw)


Reiner Steib <reinersteib+gmane@imap.cc> writes:

> Shouldn't pgg*.el be put into a separate directory along with other
> security or cryptography related libraries (maybe lisp/security or
> lisp/crypto)?

I was thinking about using lisp/net, but a separate lisp/crypto
is a much better idea.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-20 14:12                                           ` Simon Josefsson
                                                               ` (2 preceding siblings ...)
  2005-10-20 18:07                                             ` Relocating pgg*.el (was: pgg symmetric encryption patch) Reiner Steib
@ 2005-10-20 23:38                                             ` Richard M. Stallman
  2005-10-21  7:07                                               ` Simon Josefsson
  2006-03-18 21:17                                             ` Small patch to enable use of gpg-agent with pgg Sascha Wilde
  4 siblings, 1 reply; 156+ messages in thread
From: Richard M. Stallman @ 2005-10-20 23:38 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, ueno, emacs-devel

    I'm all for relocating pgg.  However, I suggest lisp/pgg/ instead.

Please remember our policy not to have lots of small subdirectories.
We do not create directories of `lisp' for less than around 20 source
files.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Relocating pgg*.el (was: pgg symmetric encryption patch)
  2005-10-20 22:22                                               ` Kim F. Storm
@ 2005-10-21  4:49                                                 ` Richard M. Stallman
  0 siblings, 0 replies; 156+ messages in thread
From: Richard M. Stallman @ 2005-10-21  4:49 UTC (permalink / raw)
  Cc: emacs-devel

    I was thinking about using lisp/net, but a separate lisp/crypto
    is a much better idea.

It could be a good idea, if there are enough files that could be moved
from the top level Lisp directory so as to justify having another
subdirectory.  So I suggest people look at which other files in `lisp'
might belong there.

It would be ok to move files from other subdirs if they fit better in
the new subdir, but that isn't really making progress.

    gnus/pgg.el
    gnus/pgg-pgp5.el
    gnus/pgg-pgp.el
    gnus/pgg-parse.el
    gnus/pgg-gpg.el
    gnus/pgg-def.el

    gnus/sha1.el
    gnus/starttls.el
    net/tls.el

That isn't enough files to justify a subdirectory.
Also, the other three are not ones we plan to put in
the top level directory, so they won't be reducing its size.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-20 23:38                                             ` pgg symmetric encryption patch Richard M. Stallman
@ 2005-10-21  7:07                                               ` Simon Josefsson
  0 siblings, 0 replies; 156+ messages in thread
From: Simon Josefsson @ 2005-10-21  7:07 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, ueno, emacs-devel

"Richard M. Stallman" <rms@gnu.org> writes:

>     I'm all for relocating pgg.  However, I suggest lisp/pgg/ instead.
>
> Please remember our policy not to have lots of small subdirectories.
> We do not create directories of `lisp' for less than around 20 source
> files.

Ok.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-20 14:42                                             ` Sascha Wilde
@ 2005-10-25  7:23                                               ` Sascha Wilde
  2005-10-25 20:26                                                 ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-25  7:23 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches), Ken Manheimer,
	Daiki Ueno (pgg author), Richard M. Stallman, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 759 bytes --]

Sascha Wilde <wilde@sha-bang.de> wrote:

> On Thu, Oct 20, 2005 at 04:12:58PM +0200, Simon Josefsson wrote:
>> Hi.  Thanks for reminding me.  I thought we were waiting for copyright
>> assignment papers?  Have the FSF received papers for all authors?
>
> I signed papers and send them off by mail (from Germany) Saturday.

Ok, papers are ready now, and the assignment process is complete.  So
feel free to commit the patches, including my pgg symmetric encryption
stuff.

cheers
sascha
-- 
Sascha Wilde  :  "The PROPER way to handle HTML postings is to cancel
the article, then hire a hitman to kill the poster, his wife and kids,
and fuck his dog and smash his computer into little bits. Anything
more is just extremism."  -- Paul Tomblin

[-- Attachment #1.2: Type: application/pgp-signature, Size: 188 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-25  7:23                                               ` Sascha Wilde
@ 2005-10-25 20:26                                                 ` Ken Manheimer
  2005-10-25 21:18                                                   ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-25 20:26 UTC (permalink / raw)
  Cc: sascha schwab, Daiki Ueno (pgg author), emacs-devel,
	Richard M. Stallman, Simon Josefsson

On 10/25/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> Sascha Wilde <wilde@sha-bang.de> wrote:
>
> > On Thu, Oct 20, 2005 at 04:12:58PM +0200, Simon Josefsson wrote:
> >> Hi.  Thanks for reminding me.  I thought we were waiting for copyright
> >> assignment papers?  Have the FSF received papers for all authors?
> >
> > I signed papers and send them off by mail (from Germany) Saturday.
>
> Ok, papers are ready now, and the assignment process is complete.  So
> feel free to commit the patches, including my pgg symmetric encryption
> stuff.

my papers are in, too.

i'm attaching a cumulative patch, including sascha wilde's and my
changes (which are built on top of sascha's) against the current CVS
repository.  it include the ChangeLog and changes of pgg.el and
pgg-gpg.el.  this patch has some slight changes from the previous
"omnibus" patch i submitted on october 12, including a small fix and a
change which mitigates a byte-compiler warning.

caveats:

  - there is one remaining compiler warning which was already in pgg.el -
    i don't know the right way to mitigate it, so i'm leaving it as is.

  - these patches do not bring the pgp or pgp5 suppport in line
    ie, neither sascha's nor my patches provide for that, i don't
    have access to any pgp implementation in order to correct it.
    as far as i can tell, however, the pgp support was already
    broken before either of us touched the pgg stuff.

ken
ken.manheimer@gmail.com

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-25 20:26                                                 ` Ken Manheimer
@ 2005-10-25 21:18                                                   ` Sascha Wilde
  2005-10-25 21:28                                                     ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-25 21:18 UTC (permalink / raw)
  Cc: Simon Josefsson, sascha schwab, Daiki Ueno (pgg author),
	Richard M. Stallman, emacs-devel

Ken Manheimer <ken.manheimer@gmail.com> wrote:

> On 10/25/05, Sascha Wilde <wilde@sha-bang.de> wrote:

> i'm attaching a cumulative patch,

no, you didn't...  

guess we have some kind of tradition here.  ;-)

cheers
sascha
-- 
"Anyone who slaps a 'this page is best viewed with Browser X' label on a Web 
page appears to be yearning for the bad old days, before the Web, when you had 
very little chance of reading a document written on another computer, another 
word processor, or another network." -- Tim Berners-Lee, July 1996

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-25 21:18                                                   ` Sascha Wilde
@ 2005-10-25 21:28                                                     ` Ken Manheimer
  2005-10-26  9:57                                                       ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-25 21:28 UTC (permalink / raw)
  Cc: Simon Josefsson, sascha schwab, Daiki Ueno (pgg author),
	Richard M. Stallman, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 713 bytes --]

aargh - i'm attaching it now.  (i simply forgot to do so, in my previous post.)

On 10/25/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> Ken Manheimer <ken.manheimer@gmail.com> wrote:
>
> > On 10/25/05, Sascha Wilde <wilde@sha-bang.de> wrote:
>
> > i'm attaching a cumulative patch,
>
> no, you didn't...
>
> guess we have some kind of tradition here.  ;-)
>
> cheers
> sascha
> --
> "Anyone who slaps a 'this page is best viewed with Browser X' label on a Web
> page appears to be yearning for the bad old days, before the Web, when you had
> very little chance of reading a document written on another computer, another
> word processor, or another network." -- Tim Berners-Lee, July 1996
>

[-- Attachment #2: pgg-symmetric-06.patch --]
[-- Type: application/octet-stream, Size: 25376 bytes --]

Index: ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/ChangeLog,v
retrieving revision 1.8455
diff -u -r1.8455 ChangeLog
--- ChangeLog	25 Oct 2005 19:25:23 -0000	1.8455
+++ ChangeLog	25 Oct 2005 20:16:01 -0000
@@ -1,4 +1,79 @@
-2005-10-25  Romain Francoise  <romain@orebokech.com>
+2005-10-12  Ken Manheimer  <ken.manheimer@gmail.com>
+
+	* pgg-gpg.el
+	(pgg-gpg-select-matching-key): fixed: look at the right part of the
+	decoded armor to find the key-identifier
+	(pgg-gpg-lookup-key-owner): new function to return the
+	human-readable identifier of a key owner.
+	(pgg-gpg-lookup-id-from-key-owner): make it easy to identify the
+	key itself.
+	(pgg-gpg-decrypt-region): prompt with the key owner (rather
+	than the key value) if we have a key and can match it against a
+	secret key.  also, added an XXX note pointing out fact that the
+	prompt only indicates the first matching key.
+	(pgg-add-passphrase-to-cache): <= pgg-add-passphrase-cache
+	(pgg-remove-passphrase-from-cache) <= pgg-remove-passphrase-cache
+
+	* pgg.el (pgg-decrypt): passing along 'passphrase' in call to
+	pgg-decrypt-region; i overlooked this one in my previous patch.
+	(pgg-pending-timers): a new hash for tracking the passphrase cache
+	timers, so that new ones supercede old ones.
+	(pgg-add-passphrase-to-cache): renamed from
+	`pgg-add-passphrase-cache' to reduce confusion.  and modified to
+	cancel old timers when new ones are added.
+	(pgg-remove-passphrase-from-cache): renamed from
+	`pgg-remove-passphrase-cache' to reduce confusion.  and modified
+	to cancel old timers when their keys are removed from the cache.
+	(pgg-cancel-timer): in mainline gnu emacs, an alias for
+	cancel-timer; in xemacs, an indirection to delete-itimer.
+	(pgg-read-passphrase-from-cache, pgg-read-passphrase): extracted 
+	pgg-read-passphrase-from-cache from pgg-read-passphrase so users
+	can only check cache without risk of prompting.  corrected bug in
+	notruncate  behavior.
+	(pgg-read-passphrase-from-cache, pgg-read-passphrase,
+	pgg-add-passphrase-cache, pgg-remove-passphrase-cache): added
+	informative docstrings.
+	(pgg-decrypt): convey provided passphrase in subordinate call to
+	pgg-decrypt-region (missed that in a prior patch)
+
+2005-10-08  Ken Manheimer <ken.manheimer+emacs@gmail.com>
+
+	* pgg.el (pgg-encrypt-region, pgg-encrypt-symmetric-region,
+	pgg-encrypt-symmetric, pgg-encrypt, pgg-decrypt-region,
+	pgg-decrypt, pgg-sign-region, pgg-sign):
+	add optional 'passphrase' argument to all these routines, so the
+	passphrase can be managed externally and then passed in to the
+	system.
+
+	* pgg.el (pgg-read-passphrase, pgg-add-passphrase-cache,
+	pgg-remove-passphrase-cache): add optional 'notruncate' argument,
+	so the passphrase cache can be used reliably with identifiers
+	besides a pgp packet's key id.
+
+	* pgg-gpg.el (pgg-pgp-encrypt-region,
+	pgg-pgp-encrypt-symmetric-region, pgg-pgp-encrypt-symmetric,
+	pgg-pgp-encrypt, pgg-pgp-decrypt-region, pgg-pgp-decrypt,
+	pgg-pgp-sign-region, pgg-pgp-sign): add optional 'passphrase'
+	argument to all these routines, so the passphrase can be managed
+	externally and passed in to the system.
+
+	* pgg-gpg.el (pgg-gpg-possibly-cache-passphrase): add optional
+	'notruncate' argument, so the passphrase cache can be used
+	reliably with identifiers besides a pgp packet's key id.
+
+2005-10-06  Sascha Wilde  <swilde@sha-bang.de>
+
+	* pgg-gpg.el (pgg-gpg-encrypt-symmetric-region): New function for
+	symmetric encryption.
+	(pgg-gpg-symmetric-key-p): New function to check for an symmetric
+	encrypted session key.
+	(pgg-gpg-decrypt-region): When decrypting a symmetric encrypted
+	message ask for the passphrase in a proper way.
+
+	* pgg.el (pgg-encrypt-symmetric,pgg-encrypt-symmetric-region):
+	New user commands for symmetric encryption.
+
+005-10-25  Romain Francoise  <romain@orebokech.com>
 
 	* emacs-lisp/find-func.el (find-library-name): Also strip
 	extension if library name ends in .el, to take advantage of
Index: pgg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/pgg.el,v
retrieving revision 1.1
diff -u -r1.1 pgg.el
--- pgg.el	24 Oct 2005 09:46:27 -0000	1.1
+++ pgg.el	25 Oct 2005 20:16:01 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP
 
@@ -67,26 +68,110 @@
     (set-window-buffer window buffer)
     (shrink-window-if-larger-than-buffer window)))
 
+;; XXX `pgg-display-output-buffer' is a horrible name for this function.
+;;     It should be something like `pgg-situate-output-or-display-error'.
 (defun pgg-display-output-buffer (start end status)
+  "Situate en/decryption results or pop up an error buffer.
+
+Text from START to END is replaced by contents of output buffer if STATUS
+is true, or else the output buffer is displayed."
   (if status
-      (progn
-	(delete-region start end)
-	(insert-buffer-substring pgg-output-buffer)
-	(decode-coding-region start (point) buffer-file-coding-system))
-    (let ((temp-buffer-show-function
-	   (function pgg-temp-buffer-show-function)))
-      (with-output-to-temp-buffer pgg-echo-buffer
-	(set-buffer standard-output)
-	(insert-buffer-substring pgg-errors-buffer)))))
+      (pgg-situate-output start end)
+    (pgg-display-error-buffer)))
+
+(defun pgg-situate-output (start end)
+  "Place en/decryption result in place of current text from START to END."
+  (delete-region start end)
+  (insert-buffer-substring pgg-output-buffer)
+  (decode-coding-region start (point) buffer-file-coding-system))
+
+(defun pgg-display-error-buffer ()
+  "Pop up an error buffer indicating the reason for an en/decryption failure."
+  (let ((temp-buffer-show-function
+         (function pgg-temp-buffer-show-function)))
+    (with-output-to-temp-buffer pgg-echo-buffer
+      (set-buffer standard-output)
+      (insert-buffer-substring pgg-errors-buffer))))
 
 (defvar pgg-passphrase-cache (make-vector 7 0))
 
-(defun pgg-read-passphrase (prompt &optional key)
-  (or (and pgg-cache-passphrase
-	   key (setq key (pgg-truncate-key-identifier key))
-	   (symbol-value (intern-soft key pgg-passphrase-cache)))
+(defvar pgg-pending-timers (make-vector 7 0)
+  "Hash table for managing scheduled pgg cache management timers.
+
+We associate key and timer, so the timer can be cancelled if a new
+timeout for the key is set while an old one is still pending.")
+
+(defun pgg-read-passphrase (prompt &optional key notruncate)
+  "Using PROMPT, obtain passphrase for KEY from cache or user.
+
+Truncate the key to 8 trailing characters unless NOTRUNCATE is true
+\(default false).
+
+Custom variables `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry'
+regulate cache behavior."
+  (or (pgg-read-passphrase-from-cache key notruncate)
       (read-passwd prompt)))
 
+(defun pgg-read-passphrase-from-cache (key &optional notruncate)
+  "Obtain passphrase for KEY from time-limited passphrase cache.
+
+Truncate the key to 8 trailing characters unless NOTRUNCATE is true
+\(default false).
+
+Custom variables `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry'
+regulate cache behavior."
+  (and pgg-cache-passphrase
+       key (or notruncate
+                (setq key (pgg-truncate-key-identifier key)))
+       (symbol-value (intern-soft key pgg-passphrase-cache))))
+
+(defun pgg-add-passphrase-to-cache (key passphrase &optional notruncate)
+  "Associate KEY with PASSPHRASE in time-limited passphrase cache.
+
+Truncate the key to 8 trailing characters unless NOTRUNCATE is true
+\(default false).
+
+Custom variables `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry'
+regulate cache behavior."
+
+  (let* ((key (if notruncate key (pgg-truncate-key-identifier key)))
+         (interned-timer-key (intern-soft key pgg-pending-timers))
+         (old-timer (symbol-value interned-timer-key))
+         new-timer)
+    (when old-timer
+        (cancel-timer old-timer)
+        (unintern interned-timer-key pgg-pending-timers))
+    (set (intern key pgg-passphrase-cache)
+         passphrase)
+    (set (intern key pgg-pending-timers)
+         (pgg-run-at-time pgg-passphrase-cache-expiry nil
+                           #'pgg-remove-passphrase-from-cache
+                           key notruncate))))
+
+(defun pgg-remove-passphrase-from-cache (key &optional notruncate)
+  "Omit passphrase associated with KEY in time-limited passphrase cache.
+
+Truncate the key to 8 trailing characters unless NOTRUNCATE is true
+\(default false).
+
+This is a no-op if there is not entry for KEY (eg, it's already expired.
+
+The memory for the passphrase is filled with underscores to clear any
+references to it.
+
+Custom variables `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry'
+regulate cache behavior."
+  (let* ((passphrase (pgg-read-passphrase-from-cache key notruncate))
+         (key (if notruncate key (pgg-truncate-key-identifier key)))
+         (interned-timer-key (intern-soft key pgg-pending-timers))
+         (old-timer (symbol-value interned-timer-key)))
+    (when passphrase
+      (fillarray passphrase ?_)
+      (unintern key pgg-passphrase-cache))
+    (when old-timer
+      (pgg-cancel-timer old-timer)
+      (unintern interned-timer-key pgg-pending-timers))))
+
 (eval-when-compile
   (defmacro pgg-run-at-time-1 (time repeat function args)
     (when (featurep 'xemacs)
@@ -151,27 +236,20 @@
 
 (eval-and-compile
   (if (featurep 'xemacs)
-      (defun pgg-run-at-time (time repeat function &rest args)
-	"Emulating function run as `run-at-time'.
+      (progn
+        (defun pgg-run-at-time (time repeat function &rest args)
+          "Emulating function run as `run-at-time'.
 TIME should be nil meaning now, or a number of seconds from now.
 Return an itimer object which can be used in either `delete-itimer'
 or `cancel-timer'."
-	(pgg-run-at-time-1 time repeat function args))
-    (defalias 'pgg-run-at-time 'run-at-time)))
-
-(defun pgg-add-passphrase-cache (key passphrase)
-  (setq key (pgg-truncate-key-identifier key))
-  (set (intern key pgg-passphrase-cache)
-       passphrase)
-  (pgg-run-at-time pgg-passphrase-cache-expiry nil
-		   #'pgg-remove-passphrase-cache
-		   key))
-
-(defun pgg-remove-passphrase-cache (key)
-  (let ((passphrase (symbol-value (intern-soft key pgg-passphrase-cache))))
-    (when passphrase
-      (fillarray passphrase ?_)
-      (unintern key pgg-passphrase-cache))))
+          (pgg-run-at-time-1 time repeat function args))
+        (defun pgg-cancel-timer (timer)
+          "Emulate cancel-timer for xemacs."
+          (let ((delete-itimer 'delete-itimer))
+            (funcall delete-itimer timer)))
+        )
+    (defalias 'pgg-run-at-time 'run-at-time)
+    (defalias 'pgg-cancel-timer 'cancel-timer)))
 
 (defmacro pgg-convert-lbt-region (start end lbt)
   `(let ((pgg-conversion-end (set-marker (make-marker) ,end)))
@@ -222,93 +300,156 @@
 ;;;
 
 ;;;###autoload
-(defun pgg-encrypt-region (start end rcpts &optional sign)
+(defun pgg-encrypt-region (start end rcpts &optional sign passphrase)
   "Encrypt the current region between START and END for RCPTS.
-If optional argument SIGN is non-nil, do a combined sign and encrypt."
+
+If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive
    (list (region-beginning)(region-end)
 	 (split-string (read-string "Recipients: ") "[ \t,]+")))
   (let ((status
 	 (pgg-save-coding-system start end
 	   (pgg-invoke "encrypt-region" (or pgg-scheme pgg-default-scheme)
-		       (point-min) (point-max) rcpts sign))))
+		       (point-min) (point-max) rcpts sign passphrase))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-encrypt (rcpts &optional sign start end)
+(defun pgg-encrypt-symmetric-region (start end &optional passphrase)
+  "Encrypt the current region between START and END symmetric with passphrase.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+cache or user."
+  (interactive "r")
+  (let ((status
+	 (pgg-save-coding-system start end
+	   (pgg-invoke "encrypt-symmetric-region" 
+		       (or pgg-scheme pgg-default-scheme)
+		       (point-min) (point-max) passphrase))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt-symmetric (&optional start end passphrase)
+  "Encrypt the current buffer using a symmetric, rather than key-pair, cipher.
+
+If optional arguments START and END are specified, only encrypt within
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
+  (interactive)
+  (let* ((start (or start (point-min)))
+	 (end (or end (point-max)))
+	 (status (pgg-encrypt-symmetric-region start end passphrase)))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-encrypt (rcpts &optional sign start end passphrase)
   "Encrypt the current buffer for RCPTS.
+
 If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
 If optional arguments START and END are specified, only encrypt within
-the region."
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive (list (split-string (read-string "Recipients: ") "[ \t,]+")))
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
-	 (status (pgg-encrypt-region start end rcpts sign)))
+	 (status (pgg-encrypt-region start end rcpts sign passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-decrypt-region (start end)
-  "Decrypt the current region between START and END."
+(defun pgg-decrypt-region (start end &optional passphrase)
+  "Decrypt the current region between START and END.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "r")
   (let* ((buf (current-buffer))
 	 (status
 	  (pgg-save-coding-system start end
 	    (pgg-invoke "decrypt-region" (or pgg-scheme pgg-default-scheme)
-			(point-min) (point-max)))))
+			(point-min) (point-max) passphrase))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-decrypt (&optional start end)
+(defun pgg-decrypt (&optional start end passphrase)
   "Decrypt the current buffer.
+
 If optional arguments START and END are specified, only decrypt within
-the region."
+the region.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "")
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
-	 (status (pgg-decrypt-region start end)))
+	 (status (pgg-decrypt-region start end passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-sign-region (start end &optional cleartext)
+(defun pgg-sign-region (start end &optional cleartext passphrase)
   "Make the signature from text between START and END.
+
 If the optional 3rd argument CLEARTEXT is non-nil, it does not create
 a detached signature.
+
 If this function is called interactively, CLEARTEXT is enabled
-and the the output is displayed."
+and the the output is displayed.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "r")
   (let ((status (pgg-save-coding-system start end
 		  (pgg-invoke "sign-region" (or pgg-scheme pgg-default-scheme)
 			      (point-min) (point-max)
-			      (or (interactive-p) cleartext)))))
+			      (or (interactive-p) cleartext)
+                              passphrase))))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
 
 ;;;###autoload
-(defun pgg-sign (&optional cleartext start end)
+(defun pgg-sign (&optional cleartext start end passphrase)
   "Sign the current buffer.
+
 If the optional argument CLEARTEXT is non-nil, it does not create a
 detached signature.
+
 If optional arguments START and END are specified, only sign data
 within the region.
+
 If this function is called interactively, CLEARTEXT is enabled
-and the the output is displayed."
+and the the output is displayed.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (interactive "")
   (let* ((start (or start (point-min)))
 	 (end (or end (point-max)))
-	 (status (pgg-sign-region start end (or (interactive-p) cleartext))))
+	 (status (pgg-sign-region start end
+                                  (or (interactive-p) cleartext)
+                                  passphrase)))
     (when (interactive-p)
       (pgg-display-output-buffer start end status))
     status))
-  
+
 ;;;###autoload
 (defun pgg-verify-region (start end &optional signature fetch)
   "Verify the current region between START and END.
Index: pgg-gpg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/pgg-gpg.el,v
retrieving revision 1.1
diff -u -r1.1 pgg-gpg.el
--- pgg-gpg.el	24 Oct 2005 09:46:27 -0000	1.1
+++ pgg-gpg.el	25 Oct 2005 20:16:01 -0000
@@ -4,6 +4,7 @@
 ;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -96,19 +97,20 @@
 	  (delete-file output-file-name))
       (set-default-file-modes orig-mode))))
 
-(defun pgg-gpg-possibly-cache-passphrase (passphrase &optional key)
+(defun pgg-gpg-possibly-cache-passphrase (passphrase &optional key notruncate)
   (if (and pgg-cache-passphrase
 	   (progn
 	     (goto-char (point-min))
 	     (re-search-forward "^\\[GNUPG:] \\(GOOD_PASSPHRASE\\>\\)\\|\\(SIG_CREATED\\)" nil t)))
-      (pgg-add-passphrase-cache
+      (pgg-add-passphrase-to-cache
        (or key
 	   (progn
 	     (goto-char (point-min))
 	     (if (re-search-forward
 		  "^\\[GNUPG:] NEED_PASSPHRASE\\(_PIN\\)? \\w+ ?\\w*" nil t)
 		 (substring (match-string 0) -8))))
-       passphrase)))
+       passphrase
+       notruncate)))
 
 (defvar pgg-gpg-all-secret-keys 'unknown)
 
@@ -139,18 +141,53 @@
 			     nil t)
 	  (substring (match-string 2) 8)))))
 
-(defun pgg-gpg-encrypt-region (start end recipients &optional sign)
+(defun pgg-gpg-lookup-key-owner (string &optional all)
+  "Search keys associated with STRING and return owner of identified key.
+
+The value may be just the bare key id, or it may be a combination of the
+user name associated with the key and the key id, with the key id enclosed
+in \"<...>\" angle brackets.
+
+Optional ALL non-nil means search all keys, including secret keys."
+  (let ((args (list "--with-colons" "--no-greeting" "--batch"
+		    (if all "--list-secret-keys" "--list-keys")
+		    string))
+        (key-regexp (concat "^\\(sec\\|pub\\)"
+                            ":[^:]*:[^:]*:[^:]*:\\([^:]*\\):[^:]*"
+                            ":[^:]*:[^:]*:[^:]*:\\([^:]*\\):"))
+        )
+    (with-temp-buffer
+      (apply #'call-process pgg-gpg-program nil t nil args)
+      (goto-char (point-min))
+      (if (re-search-forward key-regexp
+                             nil t)
+          (match-string 3)))))
+
+(defun pgg-gpg-key-id-from-key-owner (key-owner)
+  (cond ((not key-owner) nil)
+        ;; Extract bare key id from outermost paired angle brackets, if any:
+        ((string-match "[^<]*<\\(.+\\)>[^>]*" key-owner)
+         (substring key-owner (match-beginning 1)(match-end 1)))
+        (key-owner))
+  )
+
+(defun pgg-gpg-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END.
-If optional argument SIGN is non-nil, do a combined sign and encrypt."
+
+If optional argument SIGN is non-nil, do a combined sign and encrypt.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
-	 (passphrase
-	  (when sign
-	    (pgg-read-passphrase
-	     (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	     pgg-gpg-user-id)))
+	 (passphrase (or passphrase
+                         (when sign
+                           (pgg-read-passphrase
+                            (format "GnuPG passphrase for %s: "
+                                    pgg-gpg-user-id)
+                            pgg-gpg-user-id))))
 	 (args
 	  (append
-	   (list "--batch" "--armor" "--always-trust" "--encrypt")
+	   (list "--batch" "--textmode" "--armor" "--always-trust" "--encrypt")
 	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
 	   (if recipients
 	       (apply #'nconc
@@ -169,19 +206,46 @@
 	(pgg-gpg-possibly-cache-passphrase passphrase)))
     (pgg-process-when-success)))
 
-(defun pgg-gpg-decrypt-region (start end)
-  "Decrypt the current region between START and END."
+(defun pgg-gpg-encrypt-symmetric-region (start end &optional passphrase)
+  "Encrypt the current region between START and END with symmetric cipher.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
+  (let* ((passphrase (or passphrase
+                         (pgg-read-passphrase
+                          "GnuPG passphrase for symmetric encryption: ")))
+	 (args
+	  (append (list "--batch" "--textmode" "--armor" "--symmetric" ))))
+    (pgg-as-lbt start end 'CRLF
+      (pgg-gpg-process-region start end passphrase pgg-gpg-program args))
+    (pgg-process-when-success)))
+
+(defun pgg-gpg-decrypt-region (start end &optional passphrase)
+  "Decrypt the current region between START and END.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((current-buffer (current-buffer))
 	 (message-keys (with-temp-buffer
 			 (insert-buffer-substring current-buffer)
 			 (pgg-decode-armor-region (point-min) (point-max))))
 	 (secret-keys (pgg-gpg-lookup-all-secret-keys))
+         ;; XXX the user is stuck if they need to use the passphrase for
+         ;;     any but the first secret key for which the message is
+         ;;     encrypted.  ideally, we would incrementally give them a
+         ;;     chance with subsequent keys each time they fail with one.
 	 (key (pgg-gpg-select-matching-key message-keys secret-keys))
-	 (pgg-gpg-user-id (or key pgg-gpg-user-id pgg-default-user-id))
-	 (passphrase
-	  (pgg-read-passphrase
-	   (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	   pgg-gpg-user-id))
+         (key-owner (and key (pgg-gpg-lookup-key-owner key t)))
+	 (key-id (pgg-gpg-key-id-from-key-owner key-owner))
+	 (pgg-gpg-user-id (or key-id key
+	                      pgg-gpg-user-id pgg-default-user-id))
+	 (passphrase (or passphrase
+                         (pgg-read-passphrase
+                          (format (if (pgg-gpg-symmetric-key-p message-keys)
+                                      "Passphrase for symmetric decryption: "
+                                    "GnuPG passphrase for %s: ")
+                                  (or key-owner "??"))
+                          pgg-gpg-user-id)))
 	 (args '("--batch" "--decrypt")))
     (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
     (with-current-buffer pgg-errors-buffer
@@ -189,21 +253,31 @@
       (goto-char (point-min))
       (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
 
+;;;###autoload
+(defun pgg-gpg-symmetric-key-p (message-keys)
+  "True if decoded armor MESSAGE-KEYS has symmetric encryption indicator."
+  (let (result)
+    (dolist (key message-keys result)
+      (when (and (eq (car key) 3)
+		 (member '(symmetric-key-algorithm) key))
+	(setq result key)))))
+
 (defun pgg-gpg-select-matching-key (message-keys secret-keys)
   "Choose a key from MESSAGE-KEYS that matches one of the keys in SECRET-KEYS."
   (loop for message-key in message-keys
 	for message-key-id = (and (equal (car message-key) 1)
-				  (cdr (assq 'key-identifier message-key)))
+				  (cdr (assq 'key-identifier
+                                             (cdr message-key))))
 	for key = (and message-key-id (pgg-lookup-key message-key-id 'encrypt))
 	when (and key (member key secret-keys)) return key))
 
-(defun pgg-gpg-sign-region (start end &optional cleartext)
+(defun pgg-gpg-sign-region (start end &optional cleartext passphrase)
   "Make detached signature from text between START and END."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
-	 (passphrase
-	  (pgg-read-passphrase
-	   (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-	   pgg-gpg-user-id))
+	 (passphrase (or passphrase
+                         (pgg-read-passphrase
+                          (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
+                          pgg-gpg-user-id)))
 	 (args
 	  (list (if cleartext "--clearsign" "--detach-sign")
 		"--armor" "--batch" "--verbose"

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-25 21:28                                                     ` Ken Manheimer
@ 2005-10-26  9:57                                                       ` Sascha Wilde
  2005-10-26 15:45                                                         ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-26  9:57 UTC (permalink / raw)
  Cc: sascha schwab, Daiki Ueno (pgg author), emacs-devel,
	Richard M. Stallman, Simon Josefsson

Thanks for the patch, but I'm missing the additions to the pgg
documentation I made.

cheers
sascha
-- 
Sascha Wilde
Life's too short to read boring signatures

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-26  9:57                                                       ` Sascha Wilde
@ 2005-10-26 15:45                                                         ` Ken Manheimer
  2005-10-27  7:37                                                           ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-26 15:45 UTC (permalink / raw)
  Cc: sascha schwab, Daiki Ueno (pgg author), emacs-devel,
	Richard M. Stallman, Simon Josefsson

On 10/26/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> Thanks for the patch, but I'm missing the additions to the pgg
> documentation I made.

here is the texi part of your patch, exactly as it was in
emacs-pgg-symmetric.patch-5 as you sent it.  (i included your
ChangeLog entry in the part of my patch for the ChangeLog, and
similarly for the pgg.el and pgg-gpg.el source files, so i think it's
now complete.)

ken
ken.manheimer@gmail.com

Index: man/pgg.texi
===================================================================
RCS file: /cvsroot/emacs/emacs/man/pgg.texi,v
retrieving revision 1.5
diff -u -r1.5 pgg.texi
--- man/pgg.texi	16 Sep 2005 22:11:00 -0000	1.5
+++ man/pgg.texi	8 Oct 2005 10:31:09 -0000
@@ -98,6 +98,8 @@
 @lisp
 (autoload 'pgg-encrypt-region "pgg"
   "Encrypt the current region." t)
+(autoload 'pgg-encrypt-symmetric-region "pgg"
+  "Encrypt the current region with symmetric algorithm." t)
 (autoload 'pgg-decrypt-region "pgg"
   "Decrypt the current region." t)
 (autoload 'pgg-sign-region "pgg"
@@ -140,6 +142,13 @@
 with GnuPG.
 @end deffn

+@deffn Command pgg-encrypt-symmetric-region start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher.  After invocation you are asked for a passphrase.
+
+This is currently only implemented for GnuPG.
+@end deffn
+
 @deffn Command pgg-decrypt-region start end
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it replaces the current region contents (in
@@ -305,6 +314,13 @@
 @var{recipients}.  If @var{sign} is non-@code{nil}, do a combined sign
 and encrypt.  If encryption is successful, it returns @code{t},
 otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-encrypt-symmetric-region scheme start end
+Encrypt the current region between @var{start} and @var{end} using a
+symmetric cipher and a passphrases.  If encryption is successful, it
+returns @code{t}, otherwise @code{nil}.  This function is currently only
+implemented for GnuPG.
 @end deffn

 @deffn Method pgg-scheme-decrypt-region scheme start end

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-26 15:45                                                         ` Ken Manheimer
@ 2005-10-27  7:37                                                           ` Sascha Wilde
  2005-10-29 11:42                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-10-27  7:37 UTC (permalink / raw)
  Cc: Simon Josefsson, sascha schwab, Daiki Ueno (pgg author),
	Richard M. Stallman, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 698 bytes --]

Ken Manheimer <ken.manheimer@gmail.com> wrote:

> On 10/26/05, Sascha Wilde <wilde@sha-bang.de> wrote:
>> Thanks for the patch, but I'm missing the additions to the pgg
>> documentation I made.
>
> here is the texi part of your patch, exactly as it was in
> emacs-pgg-symmetric.patch-5 as you sent it.  (i included your
> ChangeLog entry in the part of my patch for the ChangeLog, and
> similarly for the pgg.el and pgg-gpg.el source files, so i think it's
> now complete.)

Yes, thank you!

Could someone with write access please commit these two patches?

cheers
sascha
-- 
Sascha Wilde : The sum of intelligence on earth is a constant; 
             : population is growing

[-- Attachment #1.2: Type: application/pgp-signature, Size: 188 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-27  7:37                                                           ` Sascha Wilde
@ 2005-10-29 11:42                                                             ` Eli Zaretskii
  2005-10-29 19:50                                                               ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Eli Zaretskii @ 2005-10-29 11:42 UTC (permalink / raw)
  Cc: rms, schwab, ueno, emacs-devel, ken.manheimer, jas

> From: Sascha Wilde <wilde@sha-bang.de>
> Date: Thu, 27 Oct 2005 09:37:58 +0200
> Cc: Simon Josefsson <jas@extundo.com>, sascha schwab <schwab@suse.de>,
> 	"Daiki Ueno \(pgg author\)" <ueno@unixuser.org>,
> 	"Richard M. Stallman" <rms@gnu.org>, emacs-devel@gnu.org
> 
> Ken Manheimer <ken.manheimer@gmail.com> wrote:
> 
> > On 10/26/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> >> Thanks for the patch, but I'm missing the additions to the pgg
> >> documentation I made.
> >
> > here is the texi part of your patch, exactly as it was in
> > emacs-pgg-symmetric.patch-5 as you sent it.  (i included your
> > ChangeLog entry in the part of my patch for the ChangeLog, and
> > similarly for the pgg.el and pgg-gpg.el source files, so i think it's
> > now complete.)
> 
> Yes, thank you!
> 
> Could someone with write access please commit these two patches?

Done, thanks.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-29 11:42                                                             ` Eli Zaretskii
@ 2005-10-29 19:50                                                               ` Ken Manheimer
  2005-10-31 17:30                                                                 ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-29 19:50 UTC (permalink / raw)
  Cc: rms, Sascha Wilde, schwab, ueno, emacs-devel, jas

[-- Attachment #1: Type: text/plain, Size: 1834 bytes --]

thanks for applying the patches.  it looks all in place.  i have a
supplemental patch which reenables pgp and pgp5 operation, as well as
rectifying the pgg.texi documentation with the changes (plus suitable
entries for lisp/ChangeLog and man/ChangeLog).

this patch is somewhat speculative because i am unable to test it, not
having pgp or pgp5.  most of the additional functionality is not
specific to the encryption software implementation, and where it is
(providing the right arguments for signing) i used a man page found on
the web to try to do the right thing.  one thing i know is that
pgg-pgp5 and pgg-pgp would *not* work without this patch, because
there would be calling mismatches from the pgg generic functions.  i
am fairly confident that the patched code will work well.

ken
ken.manheimer@gmail.com


On 10/29/05, Eli Zaretskii <eliz@gnu.org> wrote:
> > From: Sascha Wilde <wilde@sha-bang.de>
> > Date: Thu, 27 Oct 2005 09:37:58 +0200
> > Cc: Simon Josefsson <jas@extundo.com>, sascha schwab <schwab@suse.de>,
> >       "Daiki Ueno \(pgg author\)" <ueno@unixuser.org>,
> >       "Richard M. Stallman" <rms@gnu.org>, emacs-devel@gnu.org
> >
> > Ken Manheimer <ken.manheimer@gmail.com> wrote:
> >
> > > On 10/26/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> > >> Thanks for the patch, but I'm missing the additions to the pgg
> > >> documentation I made.
> > >
> > > here is the texi part of your patch, exactly as it was in
> > > emacs-pgg-symmetric.patch-5 as you sent it.  (i included your
> > > ChangeLog entry in the part of my patch for the ChangeLog, and
> > > similarly for the pgg.el and pgg-gpg.el source files, so i think it's
> > > now complete.)
> >
> > Yes, thank you!
> >
> > Could someone with write access please commit these two patches?
>
> Done, thanks.
>

[-- Attachment #2: pgg-pgp-compat.patch --]
[-- Type: application/octet-stream, Size: 14673 bytes --]

Index: lisp/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/ChangeLog,v
retrieving revision 1.8476
diff -u -r1.8476 ChangeLog
--- lisp/ChangeLog	29 Oct 2005 16:02:05 -0000	1.8476
+++ lisp/ChangeLog	29 Oct 2005 19:32:47 -0000
@@ -1,3 +1,23 @@
+2005-10-29 Ken Manheimer  <ken.manheimer@gmail.com>
+
+	* pgg-pgp.el (pgg-pgp-encrypt-region, pgg-pgp-decrypt-region)
+	(pgg-pgp-encrypt-symmetric-region, pgg-pgp-encrypt-symmetric)
+	(pgg-pgp-encrypt, pgg-pgp-decrypt-region, pgg-pgp-decrypt)
+	(pgg-pgp-sign-region, pgg-pgp-sign): Add optional 'passphrase'
+	argument to all these routines, so the passphrase can be managed
+	externally and passed in to the system.
+	(pgg-pgp-decrypt-region, pgg-pgp-sign-region): Use new name for
+	pgg-add-passphrase-to-cache function.
+
+	* pgg-pgp5.el (pgg-pgp5-encrypt-region, pgg-pgp5-decrypt-region)
+	(pgg-pgp5-encrypt-symmetric-region, pgg-pgp5-encrypt-symmetric)
+	(pgg-pgp5-encrypt, pgg-pgp5-decrypt-region, pgg-pgp5-decrypt)
+	(pgg-pgp5-sign-region, pgg-pgp5-sign): Add optional 'passphrase'
+	argument to all these routines, so the passphrase can be managed
+	externally and passed in to the system.
+	(pgg-pgp5-sign-region): Use new name of
+	pgg-add-passphrase-to-cache function.
+
 2005-10-29  Roland Winkler  <roland.winkler@physik.uni-erlangen.de>
 
 	* textmodes/conf-mode.el (conf-assignment-sign)
@@ -63,10 +83,10 @@
 	so the passphrase cache can be used reliably with identifiers
 	besides a pgp packet's key id.
 
-	* pgg-gpg.el (pgg-pgp-encrypt-region)
-	(pgg-pgp-encrypt-symmetric-region, pgg-pgp-encrypt-symmetric)
-	(pgg-pgp-encrypt, pgg-pgp-decrypt-region, pgg-pgp-decrypt)
-	(pgg-pgp-sign-region, pgg-pgp-sign): Add optional 'passphrase'
+	* pgg-gpg.el (pgg-gpg-encrypt-region)
+	(pgg-gpg-encrypt-symmetric-region, pgg-gpg-encrypt-symmetric)
+	(pgg-gpg-encrypt, pgg-gpg-decrypt-region, pgg-gpg-decrypt)
+	(pgg-gpg-sign-region, pgg-gpg-sign): Add optional 'passphrase'
 	argument to all these routines, so the passphrase can be managed
 	externally and passed in to the system.
 
Index: lisp/pgg-pgp.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/pgg-pgp.el,v
retrieving revision 1.1
diff -u -r1.1 pgg-pgp.el
--- lisp/pgg-pgp.el	24 Oct 2005 09:46:27 -0000	1.1
+++ lisp/pgg-pgp.el	29 Oct 2005 19:32:48 -0000
@@ -132,41 +132,57 @@
 		 (buffer-substring (point)(progn (end-of-line) (point)))))
 	 2))))))
 
-(defun pgg-pgp-encrypt-region (start end recipients)
+(defun pgg-pgp-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END."
   (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
+	 (passphrase (or passphrase
+                         (when sign
+                           (pgg-read-passphrase
+                            (format "PGP passphrase for %s: "
+                                    pgg-pgp-user-id)
+                            pgg-gpg-user-id))))
 	 (args
-	  `("+encrypttoself=off +verbose=1" "+batchmode"
-	    "+language=us" "-fate"
-	    ,@(if recipients
-		  (mapcar (lambda (rcpt) (concat "\"" rcpt "\""))
-			  (append recipients
-				  (if pgg-encrypt-for-me
-				      (list pgg-pgp-user-id))))))))
+          (append
+           `("+encrypttoself=off +verbose=1" "+batchmode"
+             "+language=us" "-fate"
+             ,@(if recipients
+                   (mapcar (lambda (rcpt) (concat "\"" rcpt "\""))
+                           (append recipients
+                                   (if pgg-encrypt-for-me
+                                       (list pgg-pgp-user-id))))))
+           (if sign '("-s" "-u" pgg-pgp-user-id)))))
     (pgg-pgp-process-region start end nil pgg-pgp-program args)
     (pgg-process-when-success nil)))
 
-(defun pgg-pgp-decrypt-region (start end)
-  "Decrypt the current region between START and END."
+(defun pgg-pgp-decrypt-region (start end &optional passphrase)
+  "Decrypt the current region between START and END.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
 	 (key (pgg-pgp-lookup-key pgg-pgp-user-id 'encrypt))
 	 (passphrase
-	  (pgg-read-passphrase
-	   (format "PGP passphrase for %s: " pgg-pgp-user-id) key))
+          (or passphrase
+              (pgg-read-passphrase
+               (format "PGP passphrase for %s: " pgg-pgp-user-id) key)))
 	 (args
-	  '("+verbose=1" "+batchmode" "+language=us" "-f")))
+          '("+verbose=1" "+batchmode" "+language=us" "-f")))
     (pgg-pgp-process-region start end passphrase pgg-pgp-program args)
     (pgg-process-when-success
       (if pgg-cache-passphrase
-	  (pgg-add-passphrase-cache key passphrase)))))
+	  (pgg-add-passphrase-to-cache key passphrase)))))
+
+(defun pgg-pgp-sign-region (start end &optional clearsign passphrase)
+  "Make detached signature from text between START and END.
 
-(defun pgg-pgp-sign-region (start end &optional clearsign)
-  "Make detached signature from text between START and END."
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
 	 (passphrase
-	  (pgg-read-passphrase
-	   (format "PGP passphrase for %s: " pgg-pgp-user-id)
-	   (pgg-pgp-lookup-key pgg-pgp-user-id 'sign)))
+          (or passphrase
+              (pgg-read-passphrase
+               (format "PGP passphrase for %s: " pgg-pgp-user-id)
+               (pgg-pgp-lookup-key pgg-pgp-user-id 'sign))))
 	 (args
 	  (list (if clearsign "-fast" "-fbast")
 		"+verbose=1" "+language=us" "+batchmode"
@@ -181,7 +197,7 @@
 				    (point))
 			     (point-max))))))
 	  (if pgg-cache-passphrase
-	      (pgg-add-passphrase-cache
+	      (pgg-add-passphrase-to-cache
 	       (cdr (assq 'key-identifier packet))
 	       passphrase)))))))
 
Index: lisp/pgg-pgp5.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/pgg-pgp5.el,v
retrieving revision 1.1
diff -u -r1.1 pgg-pgp5.el
--- lisp/pgg-pgp5.el	24 Oct 2005 09:46:27 -0000	1.1
+++ lisp/pgg-pgp5.el	29 Oct 2005 19:32:48 -0000
@@ -143,41 +143,51 @@
 		 (buffer-substring (match-end 0)(progn (end-of-line)(point)))))
 	 2)))))
 
-(defun pgg-pgp5-encrypt-region (start end recipients &optional sign)
+(defun pgg-pgp5-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END."
   (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
+	 (passphrase (or passphrase
+                         (when sign
+                           (pgg-read-passphrase
+                            (format "PGP passphrase for %s: "
+                                    pgg-pgp5-user-id)
+                            pgg-pgp5-user-id))))
 	 (args
-	  `("+NoBatchInvalidKeys=off" "-fat" "+batchmode=1"
-	    ,@(if recipients
-		  (apply #'append
-			 (mapcar (lambda (rcpt)
-				   (list "-r"
-					 (concat "\"" rcpt "\"")))
-				 (append recipients
-					 (if pgg-encrypt-for-me
-					     (list pgg-pgp5-user-id)))))))))
+          (append
+           `("+NoBatchInvalidKeys=off" "-fat" "+batchmode=1"
+             ,@(if recipients
+                   (apply #'append
+                          (mapcar (lambda (rcpt)
+                                    (list "-r"
+                                          (concat "\"" rcpt "\"")))
+                                  (append recipients
+                                          (if pgg-encrypt-for-me
+                                              (list pgg-pgp5-user-id)))))))
+           (if sign '("-s" "-u" pgg-pgp5-user-id)))))
     (pgg-pgp5-process-region start end nil pgg-pgp5-pgpe-program args)
     (pgg-process-when-success nil)))
 
-(defun pgg-pgp5-decrypt-region (start end)
+(defun pgg-pgp5-decrypt-region (start end &optional passphrase)
   "Decrypt the current region between START and END."
   (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
 	 (passphrase
-	  (pgg-read-passphrase
-	   (format "PGP passphrase for %s: " pgg-pgp5-user-id)
-	   (pgg-pgp5-lookup-key pgg-pgp5-user-id 'encrypt)))
+          (or passphrase
+              (pgg-read-passphrase
+               (format "PGP passphrase for %s: " pgg-pgp5-user-id)
+               (pgg-pgp5-lookup-key pgg-pgp5-user-id 'encrypt))))
 	 (args
 	  '("+verbose=1" "+batchmode=1" "+language=us" "-f")))
     (pgg-pgp5-process-region start end passphrase pgg-pgp5-pgpv-program args)
     (pgg-process-when-success nil)))
 
-(defun pgg-pgp5-sign-region (start end &optional clearsign)
+(defun pgg-pgp5-sign-region (start end &optional clearsign passphrase)
   "Make detached signature from text between START and END."
   (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
 	 (passphrase
-	  (pgg-read-passphrase
-	   (format "PGP passphrase for %s: " pgg-pgp5-user-id)
-	   (pgg-pgp5-lookup-key pgg-pgp5-user-id 'sign)))
+          (or passphrase
+              (pgg-read-passphrase
+               (format "PGP passphrase for %s: " pgg-pgp5-user-id)
+               (pgg-pgp5-lookup-key pgg-pgp5-user-id 'sign))))
 	 (args
 	  (list (if clearsign "-fat" "-fbat")
 		"+verbose=1" "+language=us" "+batchmode=1"
@@ -191,7 +201,7 @@
 				    (point))
 			     (point-max))))))
 	  (if pgg-cache-passphrase
-	      (pgg-add-passphrase-cache
+	      (pgg-add-passphrase-to-cache
 	       (cdr (assq 'key-identifier packet))
 	       passphrase)))))))
 
Index: man/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/man/ChangeLog,v
retrieving revision 1.715
diff -u -r1.715 ChangeLog
--- man/ChangeLog	29 Oct 2005 11:40:18 -0000	1.715
+++ man/ChangeLog	29 Oct 2005 19:32:51 -0000
@@ -1,3 +1,9 @@
+2005-10-29 Ken Manheimer  <ken.manheimer@gmail.com>
+
+	* pgg.texi (User Commands): Document additional passphrase
+	argument for pgg-encrypt-*, pgg-decrypt-*, and pgg-sign-* functions.
+	(Backend methods): Likewise for corresponding pgg-scheme-* functions.
+
 2005-10-29  Sascha Wilde  <wilde@sha-bang.de>
 
 	* pgg.texi (How to use): Update the example to add autoload of
Index: man/pgg.texi
===================================================================
RCS file: /cvsroot/emacs/emacs/man/pgg.texi,v
retrieving revision 1.6
diff -u -r1.6 pgg.texi
--- man/pgg.texi	29 Oct 2005 11:39:49 -0000	1.6
+++ man/pgg.texi	29 Oct 2005 19:32:51 -0000
@@ -129,7 +129,7 @@
 fails immediately, but if the function had been called interactively, it
 would ask you to retrieve the signer's public key from the server.
 
-@deffn Command pgg-encrypt-region start end recipients &optional sign
+@deffn Command pgg-encrypt-region start end recipients &optional sign passphrase
 Encrypt the current region between @var{start} and @var{end} for
 @var{recipients}.  When the function were called interactively, you
 would be asked about the recipients.
@@ -138,29 +138,41 @@
 the accessible portion) with the resulting data.
 
 If optional argument @var{sign} is non-@code{nil}, the function is
-request to do a combined sign and encrypt.  This currently only work
-with GnuPG.
+request to do a combined sign and encrypt.  This currently is
+confirmed to work with GnuPG, but might not work with PGP or PGP5.
+
+If optional @var{passphrase} is @code{nil}, the passphrase will be
+obtained from the passphrase cache or user.
 @end deffn
 
-@deffn Command pgg-encrypt-symmetric-region start end
+@deffn Command pgg-encrypt-symmetric-region &optional start end passphrase
 Encrypt the current region between @var{start} and @var{end} using a
 symmetric cipher.  After invocation you are asked for a passphrase.
 
-This is currently only implemented for GnuPG.
+If optional @var{passphrase} is @code{nil}, the passphrase will be
+obtained from the passphrase cache or user.
+
+symmetric-cipher encryption is currently only implemented for GnuPG.
 @end deffn
 
-@deffn Command pgg-decrypt-region start end
+@deffn Command pgg-decrypt-region start end &optional passphrase
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it replaces the current region contents (in
 the accessible portion) with the resulting data.
+
+If optional @var{passphrase} is @code{nil}, the passphrase will be
+obtained from the passphrase cache or user.
 @end deffn
 
-@deffn Command pgg-sign-region start end &optional cleartext
+@deffn Command pgg-sign-region start end &optional cleartext passphrase
 Make the signature from text between @var{start} and @var{end}.  If the
 optional third argument @var{cleartext} is non-@code{nil}, or the
 function is called interactively, it does not create a detached
 signature.  In such a case, it replaces the current region contents (in
 the accessible portion) with the resulting data.
+
+If optional @var{passphrase} is @code{nil}, the passphrase will be
+obtained from the passphrase cache or user.
 @end deffn
 
 @deffn Command pgg-verify-region start end &optional signature fetch
@@ -309,26 +321,26 @@
 keyrings.
 @end deffn
 
-@deffn Method pgg-scheme-encrypt-region scheme start end recipients &optional sign
+@deffn Method pgg-scheme-encrypt-region scheme start end recipients &optional sign passphrase
 Encrypt the current region between @var{start} and @var{end} for
 @var{recipients}.  If @var{sign} is non-@code{nil}, do a combined sign
 and encrypt.  If encryption is successful, it returns @code{t},
 otherwise @code{nil}.
 @end deffn
 
-@deffn Method pgg-scheme-encrypt-symmetric-region scheme start end
+@deffn Method pgg-scheme-encrypt-symmetric-region scheme start end &optional passphrase
 Encrypt the current region between @var{start} and @var{end} using a
 symmetric cipher and a passphrases.  If encryption is successful, it
 returns @code{t}, otherwise @code{nil}.  This function is currently only
 implemented for GnuPG.
 @end deffn
 
-@deffn Method pgg-scheme-decrypt-region scheme start end
+@deffn Method pgg-scheme-decrypt-region scheme start end &optional passphrase
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it returns @code{t}, otherwise @code{nil}.
 @end deffn
 
-@deffn Method pgg-scheme-sign-region scheme start end &optional cleartext
+@deffn Method pgg-scheme-sign-region scheme start end &optional cleartext passphrase
 Make the signature from text between @var{start} and @var{end}.  If the
 optional third argument @var{cleartext} is non-@code{nil}, it does not
 create a detached signature.  If signing is successful, it returns




[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-29 19:50                                                               ` Ken Manheimer
@ 2005-10-31 17:30                                                                 ` Ken Manheimer
  2005-11-04 14:45                                                                   ` Eli Zaretskii
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2005-10-31 17:30 UTC (permalink / raw)
  Cc: rms, Sascha Wilde, schwab, ueno, emacs-devel, jas

[-- Attachment #1: Type: text/plain, Size: 2283 bytes --]

as things approach release-readyness, i'm hoping that there's room to
include this additional pgg patch i submitted.  it brings the pgg-pgp
and pgg-pgp5 support into line with the pgg scheme changes, and
revises the pgg manual to track those changes as well.

ken
ken.manheimer@gmail.com

On 10/29/05, Ken Manheimer <ken.manheimer@gmail.com> wrote:
> thanks for applying the patches.  it looks all in place.  i have a
> supplemental patch which reenables pgp and pgp5 operation, as well as
> rectifying the pgg.texi documentation with the changes (plus suitable
> entries for lisp/ChangeLog and man/ChangeLog).
>
> this patch is somewhat speculative because i am unable to test it, not
> having pgp or pgp5.  most of the additional functionality is not
> specific to the encryption software implementation, and where it is
> (providing the right arguments for signing) i used a man page found on
> the web to try to do the right thing.  one thing i know is that
> pgg-pgp5 and pgg-pgp would *not* work without this patch, because
> there would be calling mismatches from the pgg generic functions.  i
> am fairly confident that the patched code will work well.
>
> ken
> ken.manheimer@gmail.com
>
>
> On 10/29/05, Eli Zaretskii <eliz@gnu.org> wrote:
> > > From: Sascha Wilde <wilde@sha-bang.de>
> > > Date: Thu, 27 Oct 2005 09:37:58 +0200
> > > Cc: Simon Josefsson <jas@extundo.com>, sascha schwab <schwab@suse.de>,
> > >       "Daiki Ueno \(pgg author\)" <ueno@unixuser.org>,
> > >       "Richard M. Stallman" <rms@gnu.org>, emacs-devel@gnu.org
> > >
> > > Ken Manheimer <ken.manheimer@gmail.com> wrote:
> > >
> > > > On 10/26/05, Sascha Wilde <wilde@sha-bang.de> wrote:
> > > >> Thanks for the patch, but I'm missing the additions to the pgg
> > > >> documentation I made.
> > > >
> > > > here is the texi part of your patch, exactly as it was in
> > > > emacs-pgg-symmetric.patch-5 as you sent it.  (i included your
> > > > ChangeLog entry in the part of my patch for the ChangeLog, and
> > > > similarly for the pgg.el and pgg-gpg.el source files, so i think it's
> > > > now complete.)
> > >
> > > Yes, thank you!
> > >
> > > Could someone with write access please commit these two patches?
> >
> > Done, thanks.
> >
>
>
>

[-- Attachment #2: pgg-pgp-compat.patch --]
[-- Type: application/octet-stream, Size: 14677 bytes --]

Index: lisp/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/ChangeLog,v
retrieving revision 1.8476
diff -u -r1.8476 ChangeLog
--- lisp/ChangeLog	29 Oct 2005 16:02:05 -0000	1.8476
+++ lisp/ChangeLog	29 Oct 2005 19:32:47 -0000
@@ -1,3 +1,23 @@
+2005-10-29 Ken Manheimer  <ken.manheimer@gmail.com>
+
+	* pgg-pgp.el (pgg-pgp-encrypt-region, pgg-pgp-decrypt-region)
+	(pgg-pgp-encrypt-symmetric-region, pgg-pgp-encrypt-symmetric)
+	(pgg-pgp-encrypt, pgg-pgp-decrypt-region, pgg-pgp-decrypt)
+	(pgg-pgp-sign-region, pgg-pgp-sign): Add optional 'passphrase'
+	argument to all these routines, so the passphrase can be managed
+	externally and passed in to the system.
+	(pgg-pgp-decrypt-region, pgg-pgp-sign-region): Use new name for
+	pgg-add-passphrase-to-cache function.
+
+	* pgg-pgp5.el (pgg-pgp5-encrypt-region, pgg-pgp5-decrypt-region)
+	(pgg-pgp5-encrypt-symmetric-region, pgg-pgp5-encrypt-symmetric)
+	(pgg-pgp5-encrypt, pgg-pgp5-decrypt-region, pgg-pgp5-decrypt)
+	(pgg-pgp5-sign-region, pgg-pgp5-sign): Add optional 'passphrase'
+	argument to all these routines, so the passphrase can be managed
+	externally and passed in to the system.
+	(pgg-pgp5-sign-region): Use new name of
+	pgg-add-passphrase-to-cache function.
+
 2005-10-29  Roland Winkler  <roland.winkler@physik.uni-erlangen.de>
 
 	* textmodes/conf-mode.el (conf-assignment-sign)
@@ -63,10 +83,10 @@
 	so the passphrase cache can be used reliably with identifiers
 	besides a pgp packet's key id.
 
-	* pgg-gpg.el (pgg-pgp-encrypt-region)
-	(pgg-pgp-encrypt-symmetric-region, pgg-pgp-encrypt-symmetric)
-	(pgg-pgp-encrypt, pgg-pgp-decrypt-region, pgg-pgp-decrypt)
-	(pgg-pgp-sign-region, pgg-pgp-sign): Add optional 'passphrase'
+	* pgg-gpg.el (pgg-gpg-encrypt-region)
+	(pgg-gpg-encrypt-symmetric-region, pgg-gpg-encrypt-symmetric)
+	(pgg-gpg-encrypt, pgg-gpg-decrypt-region, pgg-gpg-decrypt)
+	(pgg-gpg-sign-region, pgg-gpg-sign): Add optional 'passphrase'
 	argument to all these routines, so the passphrase can be managed
 	externally and passed in to the system.
 
Index: lisp/pgg-pgp.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/pgg-pgp.el,v
retrieving revision 1.1
diff -u -r1.1 pgg-pgp.el
--- lisp/pgg-pgp.el	24 Oct 2005 09:46:27 -0000	1.1
+++ lisp/pgg-pgp.el	29 Oct 2005 19:32:48 -0000
@@ -132,41 +132,57 @@
 		 (buffer-substring (point)(progn (end-of-line) (point)))))
 	 2))))))
 
-(defun pgg-pgp-encrypt-region (start end recipients)
+(defun pgg-pgp-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END."
   (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
+	 (passphrase (or passphrase
+                         (when sign
+                           (pgg-read-passphrase
+                            (format "PGP passphrase for %s: "
+                                    pgg-pgp-user-id)
+                            pgg-gpg-user-id))))
 	 (args
-	  `("+encrypttoself=off +verbose=1" "+batchmode"
-	    "+language=us" "-fate"
-	    ,@(if recipients
-		  (mapcar (lambda (rcpt) (concat "\"" rcpt "\""))
-			  (append recipients
-				  (if pgg-encrypt-for-me
-				      (list pgg-pgp-user-id))))))))
+          (append
+           `("+encrypttoself=off +verbose=1" "+batchmode"
+             "+language=us" "-fate"
+             ,@(if recipients
+                   (mapcar (lambda (rcpt) (concat "\"" rcpt "\""))
+                           (append recipients
+                                   (if pgg-encrypt-for-me
+                                       (list pgg-pgp-user-id))))))
+           (if sign '("-s" "-u" pgg-pgp-user-id)))))
     (pgg-pgp-process-region start end nil pgg-pgp-program args)
     (pgg-process-when-success nil)))
 
-(defun pgg-pgp-decrypt-region (start end)
-  "Decrypt the current region between START and END."
+(defun pgg-pgp-decrypt-region (start end &optional passphrase)
+  "Decrypt the current region between START and END.
+
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
 	 (key (pgg-pgp-lookup-key pgg-pgp-user-id 'encrypt))
 	 (passphrase
-	  (pgg-read-passphrase
-	   (format "PGP passphrase for %s: " pgg-pgp-user-id) key))
+          (or passphrase
+              (pgg-read-passphrase
+               (format "PGP passphrase for %s: " pgg-pgp-user-id) key)))
 	 (args
-	  '("+verbose=1" "+batchmode" "+language=us" "-f")))
+          '("+verbose=1" "+batchmode" "+language=us" "-f")))
     (pgg-pgp-process-region start end passphrase pgg-pgp-program args)
     (pgg-process-when-success
       (if pgg-cache-passphrase
-	  (pgg-add-passphrase-cache key passphrase)))))
+	  (pgg-add-passphrase-to-cache key passphrase)))))
+
+(defun pgg-pgp-sign-region (start end &optional clearsign passphrase)
+  "Make detached signature from text between START and END.
 
-(defun pgg-pgp-sign-region (start end &optional clearsign)
-  "Make detached signature from text between START and END."
+If optional PASSPHRASE is not specified, it will be obtained from the
+passphrase cache or user."
   (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
 	 (passphrase
-	  (pgg-read-passphrase
-	   (format "PGP passphrase for %s: " pgg-pgp-user-id)
-	   (pgg-pgp-lookup-key pgg-pgp-user-id 'sign)))
+          (or passphrase
+              (pgg-read-passphrase
+               (format "PGP passphrase for %s: " pgg-pgp-user-id)
+               (pgg-pgp-lookup-key pgg-pgp-user-id 'sign))))
 	 (args
 	  (list (if clearsign "-fast" "-fbast")
 		"+verbose=1" "+language=us" "+batchmode"
@@ -181,7 +197,7 @@
 				    (point))
 			     (point-max))))))
 	  (if pgg-cache-passphrase
-	      (pgg-add-passphrase-cache
+	      (pgg-add-passphrase-to-cache
 	       (cdr (assq 'key-identifier packet))
 	       passphrase)))))))
 
Index: lisp/pgg-pgp5.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/pgg-pgp5.el,v
retrieving revision 1.1
diff -u -r1.1 pgg-pgp5.el
--- lisp/pgg-pgp5.el	24 Oct 2005 09:46:27 -0000	1.1
+++ lisp/pgg-pgp5.el	29 Oct 2005 19:32:48 -0000
@@ -143,41 +143,51 @@
 		 (buffer-substring (match-end 0)(progn (end-of-line)(point)))))
 	 2)))))
 
-(defun pgg-pgp5-encrypt-region (start end recipients &optional sign)
+(defun pgg-pgp5-encrypt-region (start end recipients &optional sign passphrase)
   "Encrypt the current region between START and END."
   (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
+	 (passphrase (or passphrase
+                         (when sign
+                           (pgg-read-passphrase
+                            (format "PGP passphrase for %s: "
+                                    pgg-pgp5-user-id)
+                            pgg-pgp5-user-id))))
 	 (args
-	  `("+NoBatchInvalidKeys=off" "-fat" "+batchmode=1"
-	    ,@(if recipients
-		  (apply #'append
-			 (mapcar (lambda (rcpt)
-				   (list "-r"
-					 (concat "\"" rcpt "\"")))
-				 (append recipients
-					 (if pgg-encrypt-for-me
-					     (list pgg-pgp5-user-id)))))))))
+          (append
+           `("+NoBatchInvalidKeys=off" "-fat" "+batchmode=1"
+             ,@(if recipients
+                   (apply #'append
+                          (mapcar (lambda (rcpt)
+                                    (list "-r"
+                                          (concat "\"" rcpt "\"")))
+                                  (append recipients
+                                          (if pgg-encrypt-for-me
+                                              (list pgg-pgp5-user-id)))))))
+           (if sign '("-s" "-u" pgg-pgp5-user-id)))))
     (pgg-pgp5-process-region start end nil pgg-pgp5-pgpe-program args)
     (pgg-process-when-success nil)))
 
-(defun pgg-pgp5-decrypt-region (start end)
+(defun pgg-pgp5-decrypt-region (start end &optional passphrase)
   "Decrypt the current region between START and END."
   (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
 	 (passphrase
-	  (pgg-read-passphrase
-	   (format "PGP passphrase for %s: " pgg-pgp5-user-id)
-	   (pgg-pgp5-lookup-key pgg-pgp5-user-id 'encrypt)))
+          (or passphrase
+              (pgg-read-passphrase
+               (format "PGP passphrase for %s: " pgg-pgp5-user-id)
+               (pgg-pgp5-lookup-key pgg-pgp5-user-id 'encrypt))))
 	 (args
 	  '("+verbose=1" "+batchmode=1" "+language=us" "-f")))
     (pgg-pgp5-process-region start end passphrase pgg-pgp5-pgpv-program args)
     (pgg-process-when-success nil)))
 
-(defun pgg-pgp5-sign-region (start end &optional clearsign)
+(defun pgg-pgp5-sign-region (start end &optional clearsign passphrase)
   "Make detached signature from text between START and END."
   (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
 	 (passphrase
-	  (pgg-read-passphrase
-	   (format "PGP passphrase for %s: " pgg-pgp5-user-id)
-	   (pgg-pgp5-lookup-key pgg-pgp5-user-id 'sign)))
+          (or passphrase
+              (pgg-read-passphrase
+               (format "PGP passphrase for %s: " pgg-pgp5-user-id)
+               (pgg-pgp5-lookup-key pgg-pgp5-user-id 'sign))))
 	 (args
 	  (list (if clearsign "-fat" "-fbat")
 		"+verbose=1" "+language=us" "+batchmode=1"
@@ -191,7 +201,7 @@
 				    (point))
 			     (point-max))))))
 	  (if pgg-cache-passphrase
-	      (pgg-add-passphrase-cache
+	      (pgg-add-passphrase-to-cache
 	       (cdr (assq 'key-identifier packet))
 	       passphrase)))))))
 
Index: man/ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/man/ChangeLog,v
retrieving revision 1.715
diff -u -r1.715 ChangeLog
--- man/ChangeLog	29 Oct 2005 11:40:18 -0000	1.715
+++ man/ChangeLog	29 Oct 2005 19:32:51 -0000
@@ -1,3 +1,9 @@
+2005-10-29 Ken Manheimer  <ken.manheimer@gmail.com>
+
+	* pgg.texi (User Commands): Document additional passphrase
+	argument for pgg-encrypt-*, pgg-decrypt-*, and pgg-sign-* functions.
+	(Backend methods): Likewise for corresponding pgg-scheme-* functions.
+
 2005-10-29  Sascha Wilde  <wilde@sha-bang.de>
 
 	* pgg.texi (How to use): Update the example to add autoload of
Index: man/pgg.texi
===================================================================
RCS file: /cvsroot/emacs/emacs/man/pgg.texi,v
retrieving revision 1.6
diff -u -r1.6 pgg.texi
--- man/pgg.texi	29 Oct 2005 11:39:49 -0000	1.6
+++ man/pgg.texi	29 Oct 2005 19:32:51 -0000
@@ -129,7 +129,7 @@
 fails immediately, but if the function had been called interactively, it
 would ask you to retrieve the signer's public key from the server.
 
-@deffn Command pgg-encrypt-region start end recipients &optional sign
+@deffn Command pgg-encrypt-region start end recipients &optional sign passphrase
 Encrypt the current region between @var{start} and @var{end} for
 @var{recipients}.  When the function were called interactively, you
 would be asked about the recipients.
@@ -138,29 +138,41 @@
 the accessible portion) with the resulting data.
 
 If optional argument @var{sign} is non-@code{nil}, the function is
-request to do a combined sign and encrypt.  This currently only work
-with GnuPG.
+request to do a combined sign and encrypt.  This currently is
+confirmed to work with GnuPG, but might not work with PGP or PGP5.
+
+If optional @var{passphrase} is @code{nil}, the passphrase will be
+obtained from the passphrase cache or user.
 @end deffn
 
-@deffn Command pgg-encrypt-symmetric-region start end
+@deffn Command pgg-encrypt-symmetric-region &optional start end passphrase
 Encrypt the current region between @var{start} and @var{end} using a
 symmetric cipher.  After invocation you are asked for a passphrase.
 
-This is currently only implemented for GnuPG.
+If optional @var{passphrase} is @code{nil}, the passphrase will be
+obtained from the passphrase cache or user.
+
+symmetric-cipher encryption is currently only implemented for GnuPG.
 @end deffn
 
-@deffn Command pgg-decrypt-region start end
+@deffn Command pgg-decrypt-region start end &optional passphrase
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it replaces the current region contents (in
 the accessible portion) with the resulting data.
+
+If optional @var{passphrase} is @code{nil}, the passphrase will be
+obtained from the passphrase cache or user.
 @end deffn
 
-@deffn Command pgg-sign-region start end &optional cleartext
+@deffn Command pgg-sign-region start end &optional cleartext passphrase
 Make the signature from text between @var{start} and @var{end}.  If the
 optional third argument @var{cleartext} is non-@code{nil}, or the
 function is called interactively, it does not create a detached
 signature.  In such a case, it replaces the current region contents (in
 the accessible portion) with the resulting data.
+
+If optional @var{passphrase} is @code{nil}, the passphrase will be
+obtained from the passphrase cache or user.
 @end deffn
 
 @deffn Command pgg-verify-region start end &optional signature fetch
@@ -309,26 +321,26 @@
 keyrings.
 @end deffn
 
-@deffn Method pgg-scheme-encrypt-region scheme start end recipients &optional sign
+@deffn Method pgg-scheme-encrypt-region scheme start end recipients &optional sign passphrase
 Encrypt the current region between @var{start} and @var{end} for
 @var{recipients}.  If @var{sign} is non-@code{nil}, do a combined sign
 and encrypt.  If encryption is successful, it returns @code{t},
 otherwise @code{nil}.
 @end deffn
 
-@deffn Method pgg-scheme-encrypt-symmetric-region scheme start end
+@deffn Method pgg-scheme-encrypt-symmetric-region scheme start end &optional passphrase
 Encrypt the current region between @var{start} and @var{end} using a
 symmetric cipher and a passphrases.  If encryption is successful, it
 returns @code{t}, otherwise @code{nil}.  This function is currently only
 implemented for GnuPG.
 @end deffn
 
-@deffn Method pgg-scheme-decrypt-region scheme start end
+@deffn Method pgg-scheme-decrypt-region scheme start end &optional passphrase
 Decrypt the current region between @var{start} and @var{end}.  If
 decryption is successful, it returns @code{t}, otherwise @code{nil}.
 @end deffn
 
-@deffn Method pgg-scheme-sign-region scheme start end &optional cleartext
+@deffn Method pgg-scheme-sign-region scheme start end &optional cleartext passphrase
 Make the signature from text between @var{start} and @var{end}.  If the
 optional third argument @var{cleartext} is non-@code{nil}, it does not
 create a detached signature.  If signing is successful, it returns








[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-31 17:30                                                                 ` Ken Manheimer
@ 2005-11-04 14:45                                                                   ` Eli Zaretskii
  0 siblings, 0 replies; 156+ messages in thread
From: Eli Zaretskii @ 2005-11-04 14:45 UTC (permalink / raw)
  Cc: wilde, schwab, ueno, emacs-devel, jas

> Date: Mon, 31 Oct 2005 13:30:40 -0400
> From: Ken Manheimer <ken.manheimer@gmail.com>
> Cc: Sascha Wilde <wilde@sha-bang.de>, jas@extundo.com, schwab@suse.de, 
> 	ueno@unixuser.org, rms@gnu.org, emacs-devel@gnu.org
> 
> as things approach release-readyness, i'm hoping that there's room to
> include this additional pgg patch i submitted.  it brings the pgg-pgp
> and pgg-pgp5 support into line with the pgg scheme changes, and
> revises the pgg manual to track those changes as well.

Thanks, I installed them.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-10-06 22:41                       ` Ken Manheimer
  2005-10-07 10:00                         ` Sascha Wilde
@ 2005-12-09 15:43                         ` Simon Josefsson
  2005-12-09 20:30                           ` Stefan Monnier
                                             ` (2 more replies)
  1 sibling, 3 replies; 156+ messages in thread
From: Simon Josefsson @ 2005-12-09 15:43 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), emacs-devel

Hi.  I'm belatedly looking into your PGG patches.  The reason is that
the we want to synchronize them with Gnus CVS, because that is the
origin of the files.  If Gnus CVS is later synched with Emacs CVS,
your patches would conflict, and it will be time consuming to sort out
the mess.  So I want the files to be in sync.

Ken Manheimer <ken.manheimer@gmail.com> writes:

> all of my experiments involve the current pgg code found in the
> gnu.org lisp/gnus CVS.

You may also check with the files in Gnus CVS.  The Gnus 5.10.x branch
is automatically synched to Emacs HEAD CVS, so it now has your
patches, but Gnus CVS HEAD is developed concurrently, and fixes to PGG
are installed there first.  I try to keep Gnus CVS HEAD and Emacs CVS
HEAD in sync.  If you are contributing more patches, this may be
useful to know.

> 2. i also have some fundamental problems with the way unaltered pgg's
>    passphrase caching system is wired.  i am not sure about my analysis,
>    and would love to be corrected, and filled in about how it actually does
>    work.  (the passphrase cache routines could really use some informative
>    docstrings.)

Right.  Gnus CVS HEAD is using password.el for this purpose.  I
proposed earlier to make Emacs CVS HEAD also use it, but it was then
considered too late before the Emacs release to make any feature
additions, so I didn't install it.  However, your changes are much
larger than mine, and I believe if PGG used password, it would be much
cleaner.

So I'm proposing to add password.el to Emacs CVS HEAD now.  This would
clean up PGG and enable the general password infrastructure that Gnus
CVS HEAD uses.

I will now compare Emacs CVS HEAD pgg with Gnus CVS HEAD pgg to see
which patches have been applied, and which should be synchronized in
either direction.

Thanks.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-12-09 15:43                         ` pgg symmetric encryption patch Simon Josefsson
@ 2005-12-09 20:30                           ` Stefan Monnier
  2005-12-09 20:31                           ` Stefan Monnier
  2005-12-10  4:13                           ` Richard M. Stallman
  2 siblings, 0 replies; 156+ messages in thread
From: Stefan Monnier @ 2005-12-09 20:30 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), emacs-devel

> You may also check with the files in Gnus CVS.  The Gnus 5.10.x branch
> is automatically synched to Emacs HEAD CVS, so it now has your
> patches, but Gnus CVS HEAD is developed concurrently, and fixes to PGG

Nitpick: you probably meant "CVS trunk" since every branch has a HEAD.


        Stefan

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-12-09 15:43                         ` pgg symmetric encryption patch Simon Josefsson
  2005-12-09 20:30                           ` Stefan Monnier
@ 2005-12-09 20:31                           ` Stefan Monnier
  2005-12-10  4:13                           ` Richard M. Stallman
  2 siblings, 0 replies; 156+ messages in thread
From: Stefan Monnier @ 2005-12-09 20:31 UTC (permalink / raw)
  Cc: sascha schwab (symmetric encryption patches),
	Daiki Ueno (pgg author), emacs-devel

> So I'm proposing to add password.el to Emacs CVS HEAD now.  This would
> clean up PGG and enable the general password infrastructure that Gnus
> CVS HEAD uses.

Sounds like a good idea to me,


        Stefan

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-12-09 15:43                         ` pgg symmetric encryption patch Simon Josefsson
  2005-12-09 20:30                           ` Stefan Monnier
  2005-12-09 20:31                           ` Stefan Monnier
@ 2005-12-10  4:13                           ` Richard M. Stallman
  2005-12-10 10:50                             ` Simon Josefsson
  2 siblings, 1 reply; 156+ messages in thread
From: Richard M. Stallman @ 2005-12-10  4:13 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, ueno, emacs-devel

    So I'm proposing to add password.el to Emacs CVS HEAD now.  This would
    clean up PGG and enable the general password infrastructure that Gnus
    CVS HEAD uses.

It is worrisome to make these large changes now, but in this case I
think we are stuck with doing it, so as to make the other code work.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-12-10  4:13                           ` Richard M. Stallman
@ 2005-12-10 10:50                             ` Simon Josefsson
  2005-12-11 13:32                               ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2005-12-10 10:50 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, ueno, emacs-devel

"Richard M. Stallman" <rms@gnu.org> writes:

>     So I'm proposing to add password.el to Emacs CVS HEAD now.  This would
>     clean up PGG and enable the general password infrastructure that Gnus
>     CVS HEAD uses.
>
> It is worrisome to make these large changes now, but in this case I
> think we are stuck with doing it, so as to make the other code work.

I will only do this if Ken and/or Sascha can test the resulting code
for their application.  Ken/Sascha, are you listening?  Do you have
time to test my patches now?  I haven't written them yet, but will
soon.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-12-10 10:50                             ` Simon Josefsson
@ 2005-12-11 13:32                               ` Sascha Wilde
  2005-12-11 13:42                                 ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2005-12-11 13:32 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, ueno, rms, emacs-devel

Simon Josefsson <jas@extundo.com> wrote:

> "Richard M. Stallman" <rms@gnu.org> writes:
>
>>     So I'm proposing to add password.el to Emacs CVS HEAD now.  This would
>>     clean up PGG and enable the general password infrastructure that Gnus
>>     CVS HEAD uses.
>>
>> It is worrisome to make these large changes now, but in this case I
>> think we are stuck with doing it, so as to make the other code work.
>
> I will only do this if Ken and/or Sascha can test the resulting code
> for their application.  Ken/Sascha, are you listening?  Do you have
> time to test my patches now?  I haven't written them yet, but will
> soon.

Yes, I'm listening and willing to test your patches.  The main work
and application however was done by ken, so he will have to test, if
his latest allout-mode features still work with your patches...

cheers
sascha
-- 
Sascha Wilde : "Der Nicht-Denkende glaubt, dass niemand denkt,
             : der Denkende weiss es!"
             : (Gabriel Laub)

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg symmetric encryption patch
  2005-12-11 13:32                               ` Sascha Wilde
@ 2005-12-11 13:42                                 ` Simon Josefsson
  0 siblings, 0 replies; 156+ messages in thread
From: Simon Josefsson @ 2005-12-11 13:42 UTC (permalink / raw)
  Cc: schwab, ken.manheimer, ueno, rms, emacs-devel

Sascha Wilde <wilde@sha-bang.de> writes:

> Simon Josefsson <jas@extundo.com> wrote:
>
>> "Richard M. Stallman" <rms@gnu.org> writes:
>>
>>>     So I'm proposing to add password.el to Emacs CVS HEAD now.  This would
>>>     clean up PGG and enable the general password infrastructure that Gnus
>>>     CVS HEAD uses.
>>>
>>> It is worrisome to make these large changes now, but in this case I
>>> think we are stuck with doing it, so as to make the other code work.
>>
>> I will only do this if Ken and/or Sascha can test the resulting code
>> for their application.  Ken/Sascha, are you listening?  Do you have
>> time to test my patches now?  I haven't written them yet, but will
>> soon.
>
> Yes, I'm listening and willing to test your patches.  The main work
> and application however was done by ken, so he will have to test, if
> his latest allout-mode features still work with your patches...

I've been talking with Ken offline.  I will try to propose a complete
set of patches soon, the extensions he needed in password.el are
implemented.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Small patch to enable use of gpg-agent with pgg
  2005-10-20 14:12                                           ` Simon Josefsson
                                                               ` (3 preceding siblings ...)
  2005-10-20 23:38                                             ` pgg symmetric encryption patch Richard M. Stallman
@ 2006-03-18 21:17                                             ` Sascha Wilde
  2006-03-18 23:30                                               ` Daniel Pittman
  2006-03-21 14:32                                               ` Simon Josefsson
  4 siblings, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-03-18 21:17 UTC (permalink / raw)
  Cc: Daiki Ueno (pgg author), ding, Simon Josefsson


[-- Attachment #1.1.1: Type: text/plain, Size: 387 bytes --]

Hi,

I wrote a small patch, which makes it possible to use the GnuPG agent
(which is part of gpg 1.9 and considered ready to use by Werner) with
the GnuPG backend of pgg.

I have done very little testing yet, but it seems to work fine.[0]

To test it: 
set up your gpg-agent as usual and set pgg-gpg-use-agent to t.

cheers
sascha

[0] I signed this Mail using it...  ;-)

[-- Attachment #1.1.2: pgg-gpg-agent.patch --]
[-- Type: text/x-patch, Size: 4943 bytes --]

*** pgg-gpg.el	11 Feb 2006 17:01:56 +0100	1.4
--- pgg-gpg.el	18 Mär 2006 21:57:00 +0100	
***************
*** 51,56 ****
--- 51,61 ----
    :type '(choice (const :tag "New `--recipient' option" "--recipient")
  		 (const :tag "Old `--remote-user' option" "--remote-user")))
  
+ (defcustom pgg-gpg-use-agent nil
+   "Whether to use gnupg agent for key caching."
+   :group 'pgg-gpg
+   :type 'boolean)
+ 
  (defvar pgg-gpg-user-id nil
    "GnuPG ID of your default identity.")
  
***************
*** 58,64 ****
    (let* ((output-file-name (pgg-make-temp-file "pgg-output"))
  	 (args
  	  `("--status-fd" "2"
! 	    ,@(if passphrase '("--passphrase-fd" "0"))
  	    "--yes" ; overwrite
  	    "--output" ,output-file-name
  	    ,@pgg-gpg-extra-args ,@args))
--- 63,71 ----
    (let* ((output-file-name (pgg-make-temp-file "pgg-output"))
  	 (args
  	  `("--status-fd" "2"
! 	    ,@(if (and passphrase (not pgg-gpg-use-agent)) 
! 		  '("--passphrase-fd" "0"))
! 	    ,(if pgg-gpg-use-agent "--use-agent")
  	    "--yes" ; overwrite
  	    "--output" ,output-file-name
  	    ,@pgg-gpg-extra-args ,@args))
***************
*** 77,83 ****
  		(input (buffer-substring-no-properties start end))
  		(default-enable-multibyte-characters nil))
  	    (with-temp-buffer
! 	      (when passphrase
  		(insert passphrase "\n"))
  	      (insert input)
  	      (setq exit-status
--- 84,90 ----
  		(input (buffer-substring-no-properties start end))
  		(default-enable-multibyte-characters nil))
  	    (with-temp-buffer
! 	      (when (and passphrase (not pgg-gpg-use-agent))
  		(insert passphrase "\n"))
  	      (insert input)
  	      (setq exit-status
***************
*** 181,187 ****
  If optional PASSPHRASE is not specified, it will be obtained from the
  passphrase cache or user."
    (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or passphrase
                           (when sign
                             (pgg-read-passphrase
                              (format "GnuPG passphrase for %s: "
--- 188,195 ----
  If optional PASSPHRASE is not specified, it will be obtained from the
  passphrase cache or user."
    (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or pgg-gpg-use-agent
! 			 passphrase
                           (when sign
                             (pgg-read-passphrase
                              (format "GnuPG passphrase for %s: "
***************
*** 213,219 ****
  
  If optional PASSPHRASE is not specified, it will be obtained from the
  passphrase cache or user."
!   (let* ((passphrase (or passphrase
                           (pgg-read-passphrase
                            "GnuPG passphrase for symmetric encryption: ")))
  	 (args
--- 221,228 ----
  
  If optional PASSPHRASE is not specified, it will be obtained from the
  passphrase cache or user."
!   (let* ((passphrase (or pgg-gpg-use-agent
! 			 passphrase
                           (pgg-read-passphrase
                            "GnuPG passphrase for symmetric encryption: ")))
  	 (args
***************
*** 241,247 ****
  	 (key-id (pgg-gpg-key-id-from-key-owner key-owner))
  	 (pgg-gpg-user-id (or key-id key
  	                      pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or passphrase
                           (pgg-read-passphrase
                            (format (if (pgg-gpg-symmetric-key-p message-keys)
                                        "Passphrase for symmetric decryption: "
--- 250,257 ----
  	 (key-id (pgg-gpg-key-id-from-key-owner key-owner))
  	 (pgg-gpg-user-id (or key-id key
  	                      pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or pgg-gpg-use-agent
! 			 passphrase
                           (pgg-read-passphrase
                            (format (if (pgg-gpg-symmetric-key-p message-keys)
                                        "Passphrase for symmetric decryption: "
***************
*** 276,282 ****
  (defun pgg-gpg-sign-region (start end &optional cleartext passphrase)
    "Make detached signature from text between START and END."
    (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or passphrase
                           (pgg-read-passphrase
                            (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
                            pgg-gpg-user-id)))
--- 286,293 ----
  (defun pgg-gpg-sign-region (start end &optional cleartext passphrase)
    "Make detached signature from text between START and END."
    (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or pgg-gpg-use-agent
! 			 passphrase
                           (pgg-read-passphrase
                            (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
                            pgg-gpg-user-id)))

[-- Attachment #1.1.3: Type: text/plain, Size: 101 bytes --]

-- 
Sascha Wilde 
Hi! I'm a .signature *virus*! Copy me into your ~/.signature to help me spread!

[-- Attachment #1.2: Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-18 21:17                                             ` Small patch to enable use of gpg-agent with pgg Sascha Wilde
@ 2006-03-18 23:30                                               ` Daniel Pittman
  2006-03-19  0:46                                                 ` Miles Bader
  2006-03-19  9:49                                                 ` Sascha Wilde
  2006-03-21 14:32                                               ` Simon Josefsson
  1 sibling, 2 replies; 156+ messages in thread
From: Daniel Pittman @ 2006-03-18 23:30 UTC (permalink / raw)
  Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1063 bytes --]

Sascha Wilde <wilde@sha-bang.de> writes:

> I wrote a small patch, which makes it possible to use the GnuPG agent
> (which is part of gpg 1.9 and considered ready to use by Werner) with
> the GnuPG backend of pgg.
>
> I have done very little testing yet, but it seems to work fine.[0]
>
> To test it: 
> set up your gpg-agent as usual and set pgg-gpg-use-agent to t.

I am not convinced that this is the best idea -- so far as I can see, if
I were to set `pgg-gpg-use-agent' to `t' then I *must* use the agent.

Is it not possible to enable gpg to try the agent first, then to prompt
for a passphrase?

Also, is it possible to automatically detect support for using the agent
so that it isn't necessary to manually enable this -- once a new enough
version is available, support is enabled?

Obviously, automatically enabling this is only useful if the first issue
is resolved. :)

   Daniel
-- 
Digital Infrastructure Solutions -- making IT simple, stable and secure
Phone: 0401 155 707	   email: contact@digital-infrastructure.com.au

[-- Attachment #2: Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-18 23:30                                               ` Daniel Pittman
@ 2006-03-19  0:46                                                 ` Miles Bader
  2006-03-19  3:45                                                   ` Daniel Pittman
  2006-03-19  9:49                                                 ` Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Miles Bader @ 2006-03-19  0:46 UTC (permalink / raw)
  Cc: emacs-devel

Daniel Pittman <daniel@rimspace.net> writes:
> Is it not possible to enable gpg to try the agent first, then to prompt
> for a passphrase?

In my experience (trying to do the same thing outside of gnus), gpg is
generally kind of stupid in this respect ... if you find a way to do it,
let me know!

-miles
-- 
"I distrust a research person who is always obviously busy on a task."
   --Robert Frosch, VP, GM Research




^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-19  0:46                                                 ` Miles Bader
@ 2006-03-19  3:45                                                   ` Daniel Pittman
  2006-03-19 18:28                                                     ` Miles Bader
  0 siblings, 1 reply; 156+ messages in thread
From: Daniel Pittman @ 2006-03-19  3:45 UTC (permalink / raw)
  Cc: emacs-devel

Miles Bader <miles@gnu.org> writes:
> Daniel Pittman <daniel@rimspace.net> writes:
>> Is it not possible to enable gpg to try the agent first, then to prompt
>> for a passphrase?
>
> In my experience (trying to do the same thing outside of gnus), gpg is
> generally kind of stupid in this respect ... if you find a way to do
> it, let me know!

Hrm.  According to the documentation I have here, '--use-agent' will
first try to contact the agent, and will then ask for a passphrase if
that fails.

I don't have access to the agent to test, but it seems that it may be
possible to have this accept a passphrase from Gnus as well as trying
the agent.   Just a simple matter of programming -- which is, of course,
easy for me to volunteer the original poster. ;)

     Daniel
-- 
Digital Infrastructure Solutions -- making IT simple, stable and secure
Phone: 0401 155 707	   email: contact@digital-infrastructure.com.au




^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-18 23:30                                               ` Daniel Pittman
  2006-03-19  0:46                                                 ` Miles Bader
@ 2006-03-19  9:49                                                 ` Sascha Wilde
  2006-03-19 17:30                                                   ` Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-03-19  9:49 UTC (permalink / raw)
  Cc: ding, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 1364 bytes --]

Daniel Pittman <daniel@rimspace.net> wrote:

> Sascha Wilde <wilde@sha-bang.de> writes:
>
>> I wrote a small patch, which makes it possible to use the GnuPG agent
>> (which is part of gpg 1.9 and considered ready to use by Werner) with
>> the GnuPG backend of pgg.
[...]
> I am not convinced that this is the best idea -- so far as I can see, if
> I were to set `pgg-gpg-use-agent' to `t' then I *must* use the agent.
>
> Is it not possible to enable gpg to try the agent first, then to prompt
> for a passphrase?

Yes, that would be good.  I'll try to implement it.

> Also, is it possible to automatically detect support for using the agent
> so that it isn't necessary to manually enable this -- once a new enough
> version is available, support is enabled?

This would be very error prone.  Even if a running gpg-agent is
available there are certain conditions which could make using it
impossible.  For example: on an text console running the standard
pin-entry program (which uses curses) from within emacs won't work.

That's why I think that using an available agent should be enabled
explicitly. 

cheers
sascha
-- 
Sascha Wilde
Real programmers don't want "what you see is what you get", they want
"you asked for it, you got it".  They want editors that are terse,
powerful, cryptic, and unforgiving.  In a word, Teco.

[-- Attachment #1.2: Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-19  9:49                                                 ` Sascha Wilde
@ 2006-03-19 17:30                                                   ` Sascha Wilde
  0 siblings, 0 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-03-19 17:30 UTC (permalink / raw)
  Cc: ding, emacs-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 869 bytes --]

Sascha Wilde <wilde@sha-bang.de> wrote:
> Daniel Pittman <daniel@rimspace.net> wrote:
>>> Sascha Wilde <wilde@sha-bang.de> writes:
>>
>>> I wrote a small patch, which makes it possible to use the GnuPG agent
>>> (which is part of gpg 1.9 and considered ready to use by Werner) with
>>> the GnuPG backend of pgg.
> [...]
>> I am not convinced that this is the best idea -- so far as I can see, if
>> I were to set `pgg-gpg-use-agent' to `t' then I *must* use the agent.
>>
>> Is it not possible to enable gpg to try the agent first, then to prompt
>> for a passphrase?
>
> Yes, that would be good.  I'll try to implement it.

I attached a patch which performs a test if gpg-agent is really
available when pgg-gpg-use-agent is set to t.

Please note, this new patch also fixees a bug, which was introduced
by the original patch and broke non agent use...

cheers
sascha


[-- Attachment #1.1.2: pgg-gpg-agent.patch --]
[-- Type: text/x-patch, Size: 6832 bytes --]

*** pgg-gpg.el	11 Feb 2006 17:01:56 +0100	1.4
--- pgg-gpg.el	19 Mär 2006 17:05:38 +0100	
***************
*** 4,10 ****
  ;;   2005, 2006 Free Software Foundation, Inc.
  
  ;; Author: Daiki Ueno <ueno@unixuser.org>
! ;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
  ;; Created: 1999/10/28
  ;; Keywords: PGP, OpenPGP, GnuPG
  
--- 4,11 ----
  ;;   2005, 2006 Free Software Foundation, Inc.
  
  ;; Author: Daiki Ueno <ueno@unixuser.org>
! ;; Symmetric encryption and gpg-agent support added by: 
! ;;   Sascha Wilde <wilde@sha-bang.de>
  ;; Created: 1999/10/28
  ;; Keywords: PGP, OpenPGP, GnuPG
  
***************
*** 51,64 ****
    :type '(choice (const :tag "New `--recipient' option" "--recipient")
  		 (const :tag "Old `--remote-user' option" "--remote-user")))
  
  (defvar pgg-gpg-user-id nil
    "GnuPG ID of your default identity.")
  
  (defun pgg-gpg-process-region (start end passphrase program args)
!   (let* ((output-file-name (pgg-make-temp-file "pgg-output"))
  	 (args
  	  `("--status-fd" "2"
! 	    ,@(if passphrase '("--passphrase-fd" "0"))
  	    "--yes" ; overwrite
  	    "--output" ,output-file-name
  	    ,@pgg-gpg-extra-args ,@args))
--- 52,73 ----
    :type '(choice (const :tag "New `--recipient' option" "--recipient")
  		 (const :tag "Old `--remote-user' option" "--remote-user")))
  
+ (defcustom pgg-gpg-use-agent nil
+   "Whether to use gnupg agent for key caching."
+   :group 'pgg-gpg
+   :type 'boolean)
+ 
  (defvar pgg-gpg-user-id nil
    "GnuPG ID of your default identity.")
  
  (defun pgg-gpg-process-region (start end passphrase program args)
!   (let* ((use-agent (pgg-gpg-use-agent-p)) 
! 	 (output-file-name (pgg-make-temp-file "pgg-output"))
  	 (args
  	  `("--status-fd" "2"
! 	    ,@(if (and passphrase (not use-agent)) 
! 		  '("--passphrase-fd" "0"))
! 	    ,@(if use-agent '("--use-agent"))
  	    "--yes" ; overwrite
  	    "--output" ,output-file-name
  	    ,@pgg-gpg-extra-args ,@args))
***************
*** 77,83 ****
  		(input (buffer-substring-no-properties start end))
  		(default-enable-multibyte-characters nil))
  	    (with-temp-buffer
! 	      (when passphrase
  		(insert passphrase "\n"))
  	      (insert input)
  	      (setq exit-status
--- 86,92 ----
  		(input (buffer-substring-no-properties start end))
  		(default-enable-multibyte-characters nil))
  	    (with-temp-buffer
! 	      (when (and passphrase (not (pgg-gpg-use-agent-p)))
  		(insert passphrase "\n"))
  	      (insert input)
  	      (setq exit-status
***************
*** 181,187 ****
  If optional PASSPHRASE is not specified, it will be obtained from the
  passphrase cache or user."
    (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or passphrase
                           (when sign
                             (pgg-read-passphrase
                              (format "GnuPG passphrase for %s: "
--- 190,197 ----
  If optional PASSPHRASE is not specified, it will be obtained from the
  passphrase cache or user."
    (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or (pgg-gpg-use-agent-p)
! 			 passphrase
                           (when sign
                             (pgg-read-passphrase
                              (format "GnuPG passphrase for %s: "
***************
*** 213,219 ****
  
  If optional PASSPHRASE is not specified, it will be obtained from the
  passphrase cache or user."
!   (let* ((passphrase (or passphrase
                           (pgg-read-passphrase
                            "GnuPG passphrase for symmetric encryption: ")))
  	 (args
--- 223,230 ----
  
  If optional PASSPHRASE is not specified, it will be obtained from the
  passphrase cache or user."
!   (let* ((passphrase (or (pgg-gpg-use-agent-p)
! 			 passphrase
                           (pgg-read-passphrase
                            "GnuPG passphrase for symmetric encryption: ")))
  	 (args
***************
*** 241,247 ****
  	 (key-id (pgg-gpg-key-id-from-key-owner key-owner))
  	 (pgg-gpg-user-id (or key-id key
  	                      pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or passphrase
                           (pgg-read-passphrase
                            (format (if (pgg-gpg-symmetric-key-p message-keys)
                                        "Passphrase for symmetric decryption: "
--- 252,259 ----
  	 (key-id (pgg-gpg-key-id-from-key-owner key-owner))
  	 (pgg-gpg-user-id (or key-id key
  	                      pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or (pgg-gpg-use-agent-p)
! 			 passphrase
                           (pgg-read-passphrase
                            (format (if (pgg-gpg-symmetric-key-p message-keys)
                                        "Passphrase for symmetric decryption: "
***************
*** 276,282 ****
  (defun pgg-gpg-sign-region (start end &optional cleartext passphrase)
    "Make detached signature from text between START and END."
    (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or passphrase
                           (pgg-read-passphrase
                            (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
                            pgg-gpg-user-id)))
--- 288,295 ----
  (defun pgg-gpg-sign-region (start end &optional cleartext passphrase)
    "Make detached signature from text between START and END."
    (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
! 	 (passphrase (or (pgg-gpg-use-agent-p)
! 			 passphrase
                           (pgg-read-passphrase
                            (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
                            pgg-gpg-user-id)))
***************
*** 345,350 ****
--- 358,382 ----
      (append-to-buffer pgg-output-buffer (point-min)(point-max))
      (pgg-process-when-success)))
  
+ (defun pgg-gpg-update-agent ()
+   "Try to connet to gpg-agent and send UPDATESTARTUPTTY."
+   (let* ((agent-info (getenv "GPG_AGENT_INFO")) 
+ 	 (socket (and agent-info
+ 		      (string-match "^\\([^:]*\\)" agent-info)
+ 		      (match-string 1 agent-info)))
+ 	 (conn (and socket
+ 		    (make-network-process :name "gpg-agent-process"
+ 					  :host 'local :family 'local
+ 					  :service socket))))
+     (when (and conn (eq (process-status conn) 'open))
+       (process-send-string conn "UPDATESTARTUPTTY\n")
+       (delete-process conn)
+       t)))
+ 
+ (defun pgg-gpg-use-agent-p ()
+   "Return t if `pgg-gpg-use-agent' is t and gpg-agent is available."
+   (and pgg-gpg-use-agent (pgg-gpg-update-agent)))
+ 
  (provide 'pgg-gpg)
  
  ;;; arch-tag: 2aa5d5d8-93a0-4865-9312-33e29830e000

[-- Attachment #1.1.3: Type: text/plain, Size: 174 bytes --]


-- 
Sascha Wilde : VI is to EMACS as masturbation is to making love:
             : effective and always available but probably not your
             : first choice...

[-- Attachment #1.2: Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-19  3:45                                                   ` Daniel Pittman
@ 2006-03-19 18:28                                                     ` Miles Bader
  0 siblings, 0 replies; 156+ messages in thread
From: Miles Bader @ 2006-03-19 18:28 UTC (permalink / raw)
  Cc: emacs-devel

Daniel Pittman <daniel@rimspace.net> writes:
> Hrm.  According to the documentation I have here, '--use-agent' will
> first try to contact the agent, and will then ask for a passphrase if
> that fails.

It does, but it doesn't really work very well -- it must use some
different mechanism than the ordinary (no agent specified at all) case
because it only prompts once (doesn't re-prompt if you give a wrong
password) and seems generally seems more flaky (fails in more cases,
e.g., given other options that ordinarily don't preclude password entry).

-Miles
-- 
Love is a snowmobile racing across the tundra.  Suddenly it flips over,
pinning you underneath.  At night the ice weasels come.  --Nietzsche




^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-18 21:17                                             ` Small patch to enable use of gpg-agent with pgg Sascha Wilde
  2006-03-18 23:30                                               ` Daniel Pittman
@ 2006-03-21 14:32                                               ` Simon Josefsson
  2006-03-21 21:29                                                 ` Reiner Steib
  2006-03-22  8:36                                                 ` Sascha Wilde
  1 sibling, 2 replies; 156+ messages in thread
From: Simon Josefsson @ 2006-03-21 14:32 UTC (permalink / raw)
  Cc: Daiki Ueno (pgg author), ding, emacs-devel

Sascha Wilde <wilde@sha-bang.de> writes:

> Hi,
>
> I wrote a small patch, which makes it possible to use the GnuPG agent
> (which is part of gpg 1.9 and considered ready to use by Werner) with
> the GnuPG backend of pgg.
>
> I have done very little testing yet, but it seems to work fine.[0]
>
> To test it: 
> set up your gpg-agent as usual and set pgg-gpg-use-agent to t.

Your patch didn't work well for me:

1) Non-agent mode didn't work at all (the args list contained 'nil' so
   invoking gpg failed with a lisp error).

2) After fixing the above, the patch made the passphrase be 't', which
   broke the passphrase cache, causing a lisp error.

How about this patch instead?  It works for me.  I've also improved
the pgg-use-agent default value.  I've installed this on Emacs CVS
trunk, Gnus v5-10 and Gnus CVS.

Thanks for working on this, it is quite useful.

--- pgg-gpg.el	21 Mar 2006 14:53:00 +0100	1.4
+++ pgg-gpg.el	21 Mar 2006 15:22:38 +0100	
@@ -51,6 +51,13 @@
   :type '(choice (const :tag "New `--recipient' option" "--recipient")
 		 (const :tag "Old `--remote-user' option" "--remote-user")))
 
+(defcustom pgg-gpg-use-agent (if (getenv "GPG_AGENT_INFO") t nil)
+  "Whether to use gnupg agent for key caching.
+By default, it will be enabled iff the environment variable
+\"GPG_AGENT_INFO\" is set."
+  :group 'pgg-gpg
+  :type 'boolean)
+
 (defvar pgg-gpg-user-id nil
   "GnuPG ID of your default identity.")
 
@@ -58,7 +65,8 @@
   (let* ((output-file-name (pgg-make-temp-file "pgg-output"))
 	 (args
 	  `("--status-fd" "2"
-	    ,@(if passphrase '("--passphrase-fd" "0"))
+	    ,@(if pgg-gpg-use-agent '("--use-agent")
+		(if passphrase '("--passphrase-fd" "0")))
 	    "--yes" ; overwrite
 	    "--output" ,output-file-name
 	    ,@pgg-gpg-extra-args ,@args))
@@ -100,7 +108,8 @@
       (set-default-file-modes orig-mode))))
 
 (defun pgg-gpg-possibly-cache-passphrase (passphrase &optional key notruncate)
-  (if (and pgg-cache-passphrase
+  (if (and passphrase
+	   pgg-cache-passphrase
 	   (progn
 	     (goto-char (point-min))
 	     (re-search-forward "^\\[GNUPG:] \\(GOOD_PASSPHRASE\\>\\)\\|\\(SIG_CREATED\\)" nil t)))
@@ -182,7 +191,7 @@
 passphrase cache or user."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase (or passphrase
-                         (when sign
+			 (when (and sign (not pgg-gpg-use-agent))
                            (pgg-read-passphrase
                             (format "GnuPG passphrase for %s: "
                                     pgg-gpg-user-id)
@@ -214,8 +223,9 @@
 If optional PASSPHRASE is not specified, it will be obtained from the
 passphrase cache or user."
   (let* ((passphrase (or passphrase
+			 (when (not pgg-gpg-use-agent)
                          (pgg-read-passphrase
-                          "GnuPG passphrase for symmetric encryption: ")))
+			    "GnuPG passphrase for symmetric encryption: "))))
 	 (args
 	  (append (list "--batch" "--armor" "--symmetric" )
 		  (if pgg-text-mode (list "--textmode")))))
@@ -242,12 +252,13 @@
 	 (pgg-gpg-user-id (or key-id key
 	                      pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase (or passphrase
+			 (when (not pgg-gpg-use-agent)
                          (pgg-read-passphrase
                           (format (if (pgg-gpg-symmetric-key-p message-keys)
                                       "Passphrase for symmetric decryption: "
                                     "GnuPG passphrase for %s: ")
                                   (or key-owner "??"))
-                          pgg-gpg-user-id)))
+			    pgg-gpg-user-id))))
 	 (args '("--batch" "--decrypt")))
     (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
     (with-current-buffer pgg-errors-buffer
@@ -277,9 +288,11 @@
   "Make detached signature from text between START and END."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase (or passphrase
+			 (when (not pgg-gpg-use-agent)
                          (pgg-read-passphrase
-                          (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
-                          pgg-gpg-user-id)))
+			    (format "GnuPG passphrase for %s: "
+				    pgg-gpg-user-id)
+			    pgg-gpg-user-id))))
 	 (args
 	  (append (list (if cleartext "--clearsign" "--detach-sign")
 			"--armor" "--batch" "--verbose"

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-21 14:32                                               ` Simon Josefsson
@ 2006-03-21 21:29                                                 ` Reiner Steib
  2006-03-22  9:49                                                   ` Simon Josefsson
  2006-03-22  8:36                                                 ` Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Reiner Steib @ 2006-03-21 21:29 UTC (permalink / raw)
  Cc: Miles Bader

On Tue, Mar 21 2006, Simon Josefsson wrote:

> I've installed this on Emacs CVS trunk, Gnus v5-10 and Gnus CVS.

The versions differed in whitespace.  I've synced them now.

I also removed the bogus pgg-gpg.el entry in lisp/gnus/ChangeLog
(added by Miles' sync script).  pgg-gpg.el is in lisp, where Simon
already added a ChangeLog entry.

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-21 14:32                                               ` Simon Josefsson
  2006-03-21 21:29                                                 ` Reiner Steib
@ 2006-03-22  8:36                                                 ` Sascha Wilde
  2006-03-22  9:16                                                   ` Daiki Ueno
                                                                     ` (2 more replies)
  1 sibling, 3 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-03-22  8:36 UTC (permalink / raw)
  Cc: Daiki Ueno (pgg author), ding, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1519 bytes --]

Simon Josefsson <jas@extundo.com> wrote:

Hi Simon,

first of all, fore some reasons you got lost from the list of CC's so
you missed some important messages in this thread, including a more
elaborated version of my patch...

> 1) Non-agent mode didn't work at all (the args list contained 'nil' so
>    invoking gpg failed with a lisp error).

Yes.  This was fixed in my second patch.  (and in the attached, of cause)

> 2) After fixing the above, the patch made the passphrase be 't', which
>    broke the passphrase cache, causing a lisp error.

Thanks, I used your strategy to fix this issue in my new patch (which
I attached).

> How about this patch instead?  It works for me.  I've also improved
> the pgg-use-agent default value.

This is very error prone.  As I wrote before on emacs-devel: there are
certain situations in which using the agent will fail -- even if it is
available: for example: on an text console running the standard
pin-entry program (which uses curses) from within emacs won't work.
That's why I think this option should be explicitly enabled by the user.

Another problem is, that checking for $GPG_AGENT_INFO is not
sufficient, the environment variable will stay set, even is the agent
was killed.

Could you please consider committing the attached patch, which
reverses the default of pgg-gpg-use-agent to nil, and adds an check if
the agent is _really_ available, when pgg-gpg-use-agent is set to t?

(The patch is against the latest CVS, including your patch that is)

cheers
sascha


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: pgg-gpg-agent.patch --]
[-- Type: text/x-patch, Size: 3869 bytes --]

Index: pgg-gpg.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/pgg-gpg.el,v
retrieving revision 1.6
diff -c -r1.6 pgg-gpg.el
--- pgg-gpg.el	21 Mar 2006 21:24:27 -0000	1.6
+++ pgg-gpg.el	22 Mar 2006 08:14:59 -0000
@@ -4,7 +4,8 @@
 ;;   2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
-;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
+;; Symmetric encryption and gpg-agent support added by: 
+;;   Sascha Wilde <wilde@sha-bang.de>
 ;; Created: 1999/10/28
 ;; Keywords: PGP, OpenPGP, GnuPG
 
@@ -51,10 +52,8 @@
   :type '(choice (const :tag "New `--recipient' option" "--recipient")
 		 (const :tag "Old `--remote-user' option" "--remote-user")))
 
-(defcustom pgg-gpg-use-agent (if (getenv "GPG_AGENT_INFO") t nil)
-  "Whether to use gnupg agent for key caching.
-By default, it will be enabled iff the environment variable
-\"GPG_AGENT_INFO\" is set."
+(defcustom pgg-gpg-use-agent nil
+  "Whether to use gnupg agent for key caching."
   :group 'pgg-gpg
   :type 'boolean)
 
@@ -62,10 +61,11 @@
   "GnuPG ID of your default identity.")
 
 (defun pgg-gpg-process-region (start end passphrase program args)
-  (let* ((output-file-name (pgg-make-temp-file "pgg-output"))
+  (let* ((use-agent (pgg-gpg-use-agent-p)) 
+	 (output-file-name (pgg-make-temp-file "pgg-output"))
 	 (args
 	  `("--status-fd" "2"
-	    ,@(if pgg-gpg-use-agent '("--use-agent")
+	    ,@(if use-agent '("--use-agent")
 		(if passphrase '("--passphrase-fd" "0")))
 	    "--yes" ; overwrite
 	    "--output" ,output-file-name
@@ -189,7 +189,7 @@
 passphrase cache or user."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase (or passphrase
-			 (when (and sign (not pgg-gpg-use-agent))
+			 (when (and sign (not (pgg-gpg-use-agent-p)))
 			   (pgg-read-passphrase
 			    (format "GnuPG passphrase for %s: "
 				    pgg-gpg-user-id)
@@ -221,7 +221,7 @@
 If optional PASSPHRASE is not specified, it will be obtained from the
 passphrase cache or user."
   (let* ((passphrase (or passphrase
-			 (when (not pgg-gpg-use-agent)
+			 (when (not (pgg-gpg-use-agent-p))
 			   (pgg-read-passphrase
 			    "GnuPG passphrase for symmetric encryption: "))))
 	 (args
@@ -250,7 +250,7 @@
 	 (pgg-gpg-user-id (or key-id key
 			      pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase (or passphrase
-			 (when (not pgg-gpg-use-agent)
+			 (when (not (pgg-gpg-use-agent-p))
 			   (pgg-read-passphrase
 			    (format (if (pgg-gpg-symmetric-key-p message-keys)
 					"Passphrase for symmetric decryption: "
@@ -286,7 +286,7 @@
   "Make detached signature from text between START and END."
   (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
 	 (passphrase (or passphrase
-			 (when (not pgg-gpg-use-agent)
+			 (when (not (pgg-gpg-use-agent-p))
 			   (pgg-read-passphrase
 			    (format "GnuPG passphrase for %s: "
 				    pgg-gpg-user-id)
@@ -356,6 +356,25 @@
     (append-to-buffer pgg-output-buffer (point-min)(point-max))
     (pgg-process-when-success)))
 
+(defun pgg-gpg-update-agent ()
+  "Try to connet to gpg-agent and send UPDATESTARTUPTTY."
+  (let* ((agent-info (getenv "GPG_AGENT_INFO")) 
+	 (socket (and agent-info
+		      (string-match "^\\([^:]*\\)" agent-info)
+		      (match-string 1 agent-info)))
+	 (conn (and socket
+		    (make-network-process :name "gpg-agent-process"
+					  :host 'local :family 'local
+					  :service socket))))
+    (when (and conn (eq (process-status conn) 'open))
+      (process-send-string conn "UPDATESTARTUPTTY\n")
+      (delete-process conn)
+      t)))
+
+(defun pgg-gpg-use-agent-p ()
+  "Return t if `pgg-gpg-use-agent' is t and gpg-agent is available."
+  (and pgg-gpg-use-agent (pgg-gpg-update-agent)))
+
 (provide 'pgg-gpg)
 
 ;;; arch-tag: 2aa5d5d8-93a0-4865-9312-33e29830e000

[-- Attachment #3: Type: text/plain, Size: 149 bytes --]


-- 
Sascha Wilde

"Unix was the first OS where you could carry the media and system
documentation around in a briefcase. This was fixed in BSD4.2."

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22  8:36                                                 ` Sascha Wilde
@ 2006-03-22  9:16                                                   ` Daiki Ueno
  2006-03-22  9:48                                                     ` Simon Josefsson
  2006-03-22 11:03                                                     ` Sascha Wilde
  2006-03-22  9:46                                                   ` Small patch to enable use of gpg-agent with pgg Simon Josefsson
  2006-03-22 16:13                                                   ` Simon Josefsson
  2 siblings, 2 replies; 156+ messages in thread
From: Daiki Ueno @ 2006-03-22  9:16 UTC (permalink / raw)
  Cc: emacs-devel, ding, Simon Josefsson

Hello,

>>>>> In <m2slpadgf0.fsf@kenny.sha-bang.de> 
>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> This is very error prone.  As I wrote before on emacs-devel: there are
> certain situations in which using the agent will fail -- even if it is
> available: for example: on an text console running the standard
> pin-entry program (which uses curses) from within emacs won't work.
> That's why I think this option should be explicitly enabled by the user.

> Another problem is, that checking for $GPG_AGENT_INFO is not
> sufficient, the environment variable will stay set, even is the agent
> was killed.

That looks a bit complicated for me.  Is there a choice of utilizing
--status-fd output?  That is, query a user for his passphrase only when
gpg requested (i.e. we see NEED_PASSPHRASE)

Though I know that this solution involves some coding to make use of
asynchronous process, I expect that it is not so hard to implement.

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22  8:36                                                 ` Sascha Wilde
  2006-03-22  9:16                                                   ` Daiki Ueno
@ 2006-03-22  9:46                                                   ` Simon Josefsson
  2006-03-22 16:13                                                   ` Simon Josefsson
  2 siblings, 0 replies; 156+ messages in thread
From: Simon Josefsson @ 2006-03-22  9:46 UTC (permalink / raw)
  Cc: Daiki Ueno (pgg author), ding, emacs-devel

Sascha Wilde <wilde@sha-bang.de> writes:

> Simon Josefsson <jas@extundo.com> wrote:
>
> Hi Simon,
>
> first of all, fore some reasons you got lost from the list of CC's so
> you missed some important messages in this thread, including a more
> elaborated version of my patch...

Hi Sascha.  Oops!

>> 1) Non-agent mode didn't work at all (the args list contained 'nil' so
>>    invoking gpg failed with a lisp error).
>
> Yes.  This was fixed in my second patch.  (and in the attached, of cause)
>
>> 2) After fixing the above, the patch made the passphrase be 't', which
>>    broke the passphrase cache, causing a lisp error.
>
> Thanks, I used your strategy to fix this issue in my new patch (which
> I attached).

Your patch look good, although Daiki's idea of querying for the
passphrase only when it is needed seem better.  I don't have time to
implement that though.  If you or Daiki have time, I'd prefer that
solution, but if there isn't a patch to commit within a few days, I'll
install your patch so we don't get stuck.  What do you think?

>> How about this patch instead?  It works for me.  I've also improved
>> the pgg-use-agent default value.
>
> This is very error prone.  As I wrote before on emacs-devel: there are
> certain situations in which using the agent will fail -- even if it is
> available: for example: on an text console running the standard
> pin-entry program (which uses curses) from within emacs won't work.
> That's why I think this option should be explicitly enabled by the user.
>
> Another problem is, that checking for $GPG_AGENT_INFO is not
> sufficient, the environment variable will stay set, even is the agent
> was killed.

Ah, I see.

> Could you please consider committing the attached patch, which
> reverses the default of pgg-gpg-use-agent to nil, and adds an check if
> the agent is _really_ available, when pgg-gpg-use-agent is set to t?
>
> (The patch is against the latest CVS, including your patch that is)

Seems fine, although I'll wait a day or so until I see if we can get
Daiki's idea implemented.

Thanks!

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22  9:16                                                   ` Daiki Ueno
@ 2006-03-22  9:48                                                     ` Simon Josefsson
  2006-03-22 11:03                                                     ` Sascha Wilde
  1 sibling, 0 replies; 156+ messages in thread
From: Simon Josefsson @ 2006-03-22  9:48 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

Daiki Ueno <ueno@unixuser.org> writes:

> Hello,
>
>>>>>> In <m2slpadgf0.fsf@kenny.sha-bang.de> 
>>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
>> This is very error prone.  As I wrote before on emacs-devel: there are
>> certain situations in which using the agent will fail -- even if it is
>> available: for example: on an text console running the standard
>> pin-entry program (which uses curses) from within emacs won't work.
>> That's why I think this option should be explicitly enabled by the user.
>
>> Another problem is, that checking for $GPG_AGENT_INFO is not
>> sufficient, the environment variable will stay set, even is the agent
>> was killed.
>
> That looks a bit complicated for me.  Is there a choice of utilizing
> --status-fd output?  That is, query a user for his passphrase only when
> gpg requested (i.e. we see NEED_PASSPHRASE)
>
> Though I know that this solution involves some coding to make use of
> asynchronous process, I expect that it is not so hard to implement.

Hi Daiki!  I like this.  Would you like to implement it?



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-21 21:29                                                 ` Reiner Steib
@ 2006-03-22  9:49                                                   ` Simon Josefsson
  0 siblings, 0 replies; 156+ messages in thread
From: Simon Josefsson @ 2006-03-22  9:49 UTC (permalink / raw)
  Cc: emacs-devel

Reiner Steib <reinersteib+gmane@imap.cc> writes:

> On Tue, Mar 21 2006, Simon Josefsson wrote:
>
>> I've installed this on Emacs CVS trunk, Gnus v5-10 and Gnus CVS.
>
> The versions differed in whitespace.  I've synced them now.
>
> I also removed the bogus pgg-gpg.el entry in lisp/gnus/ChangeLog
> (added by Miles' sync script).  pgg-gpg.el is in lisp, where Simon
> already added a ChangeLog entry.

Thanks!



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22  9:16                                                   ` Daiki Ueno
  2006-03-22  9:48                                                     ` Simon Josefsson
@ 2006-03-22 11:03                                                     ` Sascha Wilde
  2006-03-22 11:13                                                       ` Simon Josefsson
  1 sibling, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-03-22 11:03 UTC (permalink / raw)
  Cc: emacs-devel, ding, Simon Josefsson

Hello Daiki,

I'm afraid I don't understand your suggestion...

Daiki Ueno <ueno@unixuser.org> wrote:
>>>>>> In <m2slpadgf0.fsf@kenny.sha-bang.de> 
>>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
>> This is very error prone.  As I wrote before on emacs-devel: there are
>> certain situations in which using the agent will fail -- even if it is
>> available: for example: on an text console running the standard
>> pin-entry program (which uses curses) from within emacs won't work.
>> That's why I think this option should be explicitly enabled by the user.
>
>> Another problem is, that checking for $GPG_AGENT_INFO is not
>> sufficient, the environment variable will stay set, even is the agent
>> was killed.
>
> That looks a bit complicated for me.

What exactly looks complicated to you?

> Is there a choice of utilizing --status-fd output?  That is, query a
> user for his passphrase only when gpg requested (i.e. we see
> NEED_PASSPHRASE)

I don't understand this point -- with the proposed patch the user
already only gets queried for the passphrase when gpg needs it -- or
am I missing something?

While I can imagine that a solution utilizing --status-fd might be
more elegant, I don't see how this could improve usability (and I
would expect it to be rather more than less complicated).

Can you please explain what behavior you would expect from pgg, maybe
with an example?

Thanks
sascha
-- 
Sascha Wilde
Nota bene: wenn Word für Längeres geeignet wäre, würde es schließlich
nicht Word, sondern Sentence, Page oder Article heißen
 	-- Matthias Mühlich in dctt

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22 11:03                                                     ` Sascha Wilde
@ 2006-03-22 11:13                                                       ` Simon Josefsson
  2006-03-22 12:25                                                         ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-22 11:13 UTC (permalink / raw)
  Cc: Daiki Ueno, ding, emacs-devel

Sascha Wilde <wilde@sha-bang.de> writes:

>> Is there a choice of utilizing --status-fd output?  That is, query a
>> user for his passphrase only when gpg requested (i.e. we see
>> NEED_PASSPHRASE)
>
> I don't understand this point -- with the proposed patch the user
> already only gets queried for the passphrase when gpg needs it -- or
> am I missing something?

Right now, pgg assume that gpg will need a passphrase so it asks the
user for one.  It may be better if pgg postpone the passphrase query
until gpg tell pgg that it needs a passphrase.  Then it is only
queried for when it is needed.  This should be more reliable, but
slightly more complicated to implement (asynchronous code).

Gpg doesn't need a passphrase if the agent is used, or (I guess) if
the key isn't protected with a password.  If a smartcard is used, gpg
need a pin code and not a passphrase, I'm not sure pgg can handle this
at all now.  (This last point is separate, and wouldn't be solved if
we implement Daiki's idea.)

I may have misunderstood Daiki though...



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22 11:13                                                       ` Simon Josefsson
@ 2006-03-22 12:25                                                         ` Daiki Ueno
  2006-03-23 10:40                                                           ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-03-22 12:25 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

>>>>> In <877j6mg2af.fsf@latte.josefsson.org> 
>>>>>	Simon Josefsson <jas@extundo.com> wrote:
> Sascha Wilde <wilde@sha-bang.de> writes:

> >> Is there a choice of utilizing --status-fd output?  That is, query a
> >> user for his passphrase only when gpg requested (i.e. we see
> >> NEED_PASSPHRASE)
> >
> > I don't understand this point -- with the proposed patch the user
> > already only gets queried for the passphrase when gpg needs it -- or
> > am I missing something?

> Right now, pgg assume that gpg will need a passphrase so it asks the
> user for one.  It may be better if pgg postpone the passphrase query
> until gpg tell pgg that it needs a passphrase.  Then it is only
> queried for when it is needed.  This should be more reliable, but
> slightly more complicated to implement (asynchronous code).

Thanks for your explanation.  This is what I wanted to say.
We may need some experiments to see gpg use status fd as expected,
though.

Anyway, I'll try to implement this.

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22  8:36                                                 ` Sascha Wilde
  2006-03-22  9:16                                                   ` Daiki Ueno
  2006-03-22  9:46                                                   ` Small patch to enable use of gpg-agent with pgg Simon Josefsson
@ 2006-03-22 16:13                                                   ` Simon Josefsson
  2006-03-22 23:01                                                     ` Katsumi Yamaoka
  2 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-22 16:13 UTC (permalink / raw)
  Cc: emacs-devel, Daiki Ueno (pgg author), ding

Sascha Wilde <wilde@sha-bang.de> writes:

> Could you please consider committing the attached patch, which
> reverses the default of pgg-gpg-use-agent to nil, and adds an check if
> the agent is _really_ available, when pgg-gpg-use-agent is set to t?
>
> (The patch is against the latest CVS, including your patch that is)

Given the pending 5.10.x release, I installed it.  Installing Daiki's
work would come later, and would slightly improve the user experience
here (i.e., not having to set pgg-gpg-use-agent manually).



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22 16:13                                                   ` Simon Josefsson
@ 2006-03-22 23:01                                                     ` Katsumi Yamaoka
  2006-03-22 23:45                                                       ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Katsumi Yamaoka @ 2006-03-22 23:01 UTC (permalink / raw)
  Cc: Sascha Wilde, Daiki Ueno (pgg author), ding, emacs-devel

>>>>> In <87zmjicv9d.fsf@latte.josefsson.org> Simon Josefsson wrote:

> Given the pending 5.10.x release, I installed it.

Emacs 20, 21 and XEmacs complain to use of make-network-process
which isn't available.  To solve the problem, we may want to
introduce it as dns.el does.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22 23:01                                                     ` Katsumi Yamaoka
@ 2006-03-22 23:45                                                       ` Simon Josefsson
  2006-03-23  0:58                                                         ` Katsumi Yamaoka
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-22 23:45 UTC (permalink / raw)
  Cc: Sascha Wilde, Daiki Ueno (pgg author), ding, emacs-devel

Katsumi Yamaoka <yamaoka@jpl.org> writes:

>>>>>> In <87zmjicv9d.fsf@latte.josefsson.org> Simon Josefsson wrote:
>
>> Given the pending 5.10.x release, I installed it.
>
> Emacs 20, 21 and XEmacs complain to use of make-network-process
> which isn't available.  To solve the problem, we may want to
> introduce it as dns.el does.

Do those emacsen support socket processes?  If not, maybe we should
remove pgg-gpg-update-agent.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22 23:45                                                       ` Simon Josefsson
@ 2006-03-23  0:58                                                         ` Katsumi Yamaoka
  2006-03-23  9:12                                                           ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Katsumi Yamaoka @ 2006-03-23  0:58 UTC (permalink / raw)
  Cc: Sascha Wilde, emacs-devel, Daiki Ueno (pgg author), ding

>>>>> In <87irq6yrfo.fsf@latte.josefsson.org> Simon Josefsson wrote:

> Katsumi Yamaoka <yamaoka@jpl.org> writes:

>> Emacs 20, 21 and XEmacs complain to use of make-network-process
>> which isn't available.  To solve the problem, we may want to
>> introduce it as dns.el does.

> Do those emacsen support socket processes?  If not, maybe we should
> remove pgg-gpg-update-agent.

Oops.  ISHIKAWA Mutsumi wrote (in Japanese) in

http://lists.debian.or.jp/debian-devel/200502/msg00007.html

that Emacs 21 doesn't support the communication passing the UNIX
domain socket.  If we need to use it at all costs, we will have
to use an external program which communicates with the agent
process by way of the socket.



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23  0:58                                                         ` Katsumi Yamaoka
@ 2006-03-23  9:12                                                           ` Simon Josefsson
  2006-03-23 10:26                                                             ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-23  9:12 UTC (permalink / raw)
  Cc: Sascha Wilde, Daiki Ueno (pgg author), ding, emacs-devel

Katsumi Yamaoka <yamaoka@jpl.org> writes:

>>>>>> In <87irq6yrfo.fsf@latte.josefsson.org> Simon Josefsson wrote:
>
>> Katsumi Yamaoka <yamaoka@jpl.org> writes:
>
>>> Emacs 20, 21 and XEmacs complain to use of make-network-process
>>> which isn't available.  To solve the problem, we may want to
>>> introduce it as dns.el does.
>
>> Do those emacsen support socket processes?  If not, maybe we should
>> remove pgg-gpg-update-agent.
>
> Oops.  ISHIKAWA Mutsumi wrote (in Japanese) in
>
> http://lists.debian.or.jp/debian-devel/200502/msg00007.html
>
> that Emacs 21 doesn't support the communication passing the UNIX
> domain socket.  If we need to use it at all costs, we will have
> to use an external program which communicates with the agent
> process by way of the socket.

I think it is too complicated.  It is simpler to remove the function.
Sascha, what do you think?  People who enable pgg-gpg-use-agent
manually might be expected to make sure the agent really is running.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23  9:12                                                           ` Simon Josefsson
@ 2006-03-23 10:26                                                             ` Sascha Wilde
  2006-03-23 10:54                                                               ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-03-23 10:26 UTC (permalink / raw)
  Cc: Katsumi Yamaoka, emacs-devel, Daiki Ueno (pgg author), ding

Simon Josefsson <jas@extundo.com> wrote:

> Katsumi Yamaoka <yamaoka@jpl.org> writes:
>
>>>>>>> In <87irq6yrfo.fsf@latte.josefsson.org> Simon Josefsson wrote:
>>
>>> Katsumi Yamaoka <yamaoka@jpl.org> writes:
>>
>>>> Emacs 20, 21 and XEmacs complain to use of make-network-process
>>>> which isn't available.  To solve the problem, we may want to
>>>> introduce it as dns.el does.
>>
>>> Do those emacsen support socket processes?  If not, maybe we should
>>> remove pgg-gpg-update-agent.
>>
>> Oops.  ISHIKAWA Mutsumi wrote (in Japanese) in
>>
>> http://lists.debian.or.jp/debian-devel/200502/msg00007.html
>>
>> that Emacs 21 doesn't support the communication passing the UNIX
>> domain socket.  If we need to use it at all costs, we will have
>> to use an external program which communicates with the agent
>> process by way of the socket.
>
> I think it is too complicated.  It is simpler to remove the function.
> Sascha, what do you think?  People who enable pgg-gpg-use-agent
> manually might be expected to make sure the agent really is running.

I would like to see pgg do the right think when ever it can -- could
we keep it for emacs 22 and just not use it if its not available?  

How about testing for the emacs version, or availability of
make-network-process?

I'll purpose a more compatible patch later -- but I don't have the
time right now, sorry.

cheers
sascha
-- 
Sascha Wilde

A conclusion is simply the place where someone got tired of thinking.



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-22 12:25                                                         ` Daiki Ueno
@ 2006-03-23 10:40                                                           ` Daiki Ueno
  2006-03-23 11:00                                                             ` Simon Josefsson
  2006-03-23 12:52                                                             ` Sascha Wilde
  0 siblings, 2 replies; 156+ messages in thread
From: Daiki Ueno @ 2006-03-23 10:40 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 632 bytes --]

Hello,

>>>>> In <e8632056-d7b7-4ed6-91d6-7d9089c82f94@well-done.deisui.org> 
>>>>>	Daiki Ueno <ueno@unixuser.org> wrote:
> > Right now, pgg assume that gpg will need a passphrase so it asks the
> > user for one.  It may be better if pgg postpone the passphrase query
> > until gpg tell pgg that it needs a passphrase.  Then it is only
> > queried for when it is needed.  This should be more reliable, but
> > slightly more complicated to implement (asynchronous code).

> Anyway, I'll try to implement this.

Could you please try the attached pgg-gpg.el?

Please note, this patch is only for review, not meant to be committed now.

[-- Attachment #2: pgg-gpg.el --]
[-- Type: application/octet-stream, Size: 12450 bytes --]

;;; pgg-gpg.el --- GnuPG support for PGG.

;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
;;   2005, 2006 Free Software Foundation, Inc.

;; Author: Daiki Ueno <ueno@unixuser.org>
;; Symmetric encryption and gpg-agent support added by: 
;;   Sascha Wilde <wilde@sha-bang.de>
;; Created: 1999/10/28
;; Keywords: PGP, OpenPGP, GnuPG

;; This file is part of GNU Emacs.

;; GNU Emacs 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 2, or (at your option)
;; any later version.

;; GNU Emacs 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 GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Code:

(eval-when-compile
  (require 'pgg))

(defgroup pgg-gpg ()
  "GnuPG interface."
  :group 'pgg)

(defcustom pgg-gpg-program "gpg"
  "The GnuPG executable."
  :group 'pgg-gpg
  :type 'string)

(defcustom pgg-gpg-extra-args nil
  "Extra arguments for every GnuPG invocation."
  :group 'pgg-gpg
  :type '(repeat (string :tag "Argument")))

(defcustom pgg-gpg-recipient-argument "--recipient"
  "GnuPG option to specify recipient."
  :group 'pgg-gpg
  :type '(choice (const :tag "New `--recipient' option" "--recipient")
		 (const :tag "Old `--remote-user' option" "--remote-user")))

(defcustom pgg-gpg-use-agent nil
  "Whether to use gnupg agent for key caching."
  :group 'pgg-gpg
  :type 'boolean)

(defcustom pgg-gpg-timeout 60
  "Timeout of GnuPG command execution."
  :group 'pgg-gpg
  :type 'integer)

(defvar pgg-gpg-user-id nil
  "GnuPG ID of your default identity.")

(defvar pgg-gpg-user-id-alist nil
  "An alist mapping from key ID to user ID.")

(defvar pgg-gpg-read-point nil)
(defvar pgg-gpg-output-file-name nil)
(defvar pgg-gpg-pending-status-list nil)
(defvar pgg-gpg-key-id nil)
(defvar pgg-gpg-debug-buffer " *pgg-gpg-debug*")

(defun pgg-gpg-start-process (args)
  (let* ((output-file-name (pgg-make-temp-file "pgg-output"))
	 (args
	  (append (list "--no-tty"
			"--status-fd" "1"
			"--command-fd" "0"
			"--yes" ; overwrite
			"--output" output-file-name)
		  (if pgg-gpg-use-agent '("--use-agent"))
		  pgg-gpg-extra-args
		  args))
	 (coding-system-for-write 'binary)
	 (process-connection-type nil)
	 (orig-mode (default-file-modes))
	 default-enable-multibyte-characters
	 (buffer (if pgg-gpg-debug-buffer
		     pgg-gpg-debug-buffer
		   (generate-new-buffer " *pgg-gpg*")))
	 process)
    (if pgg-gpg-debug-buffer
	(save-excursion
	  (set-buffer (get-buffer-create pgg-gpg-debug-buffer))
	  (erase-buffer)))
    (with-current-buffer buffer
      (make-local-variable 'pgg-gpg-read-point)
      (setq pgg-gpg-read-point (point-min))
      (make-local-variable 'pgg-gpg-output-file-name)
      (setq pgg-gpg-output-file-name output-file-name)
      (make-local-variable 'pgg-gpg-pending-status-list)
      (setq pgg-gpg-pending-status-list nil)
      (make-local-variable 'pgg-gpg-key-id)
      (setq pgg-gpg-key-id nil))
    (unwind-protect
	(progn
	  (set-default-file-modes 448)
	  (setq process
		(apply #'start-process "pgg-gpg" buffer pgg-gpg-program args))
	  (set-process-filter process #'pgg-gpg-process-filter)
	  (set-process-sentinel process #'pgg-gpg-process-sentinel))
      (set-default-file-modes orig-mode))
    process))

(defun pgg-gpg-process-filter (process input)
  (save-excursion
    (set-buffer (process-buffer process))
    (goto-char (point-max))
    (insert input)
    (goto-char pgg-gpg-read-point)
    (beginning-of-line)
    (while (looking-at ".*\n")		;the input line is finished
      (save-excursion
	(if (looking-at "\\[GNUPG:] \\([A-Z_]+\\)\\>.*")
	    (let* ((status (match-string 1))
		   (symbol (intern-soft (concat "pgg-gpg-handle-" status)))
		   (entry (member status pgg-gpg-pending-status-list)))
	      (if entry
		  (setq pgg-gpg-pending-status-list
			(delq (car entry)
			      pgg-gpg-pending-status-list)))
	      (if (and symbol
		       (fboundp symbol))
		  (funcall symbol process (buffer-substring (match-beginning 1)
							    (match-end 0)))))))
      (forward-line))
    (setq pgg-gpg-read-point (point))))

(defun pgg-gpg-process-sentinel (process status)
  (save-excursion
    ;; Copy the contents of process-buffer to pgg-errors-buffer.
    (set-buffer (get-buffer-create pgg-errors-buffer))
    (buffer-disable-undo)
    (erase-buffer)
    (when (buffer-live-p (process-buffer process))
      (insert-buffer-substring (process-buffer process))
      (goto-char (point-min))
      (delete-matching-lines "^\\[GNUPG:] ")
      (goto-char (point-min))
      (while (re-search-forward "^gpg: " nil t)
	(replace-match "")))
    ;; Read the contents of the output file to pgg-output-buffer.
    (set-buffer (get-buffer-create pgg-output-buffer))
    (buffer-disable-undo)
    (erase-buffer)
    (if (and (equal status "finished\n")
	     (buffer-live-p (process-buffer process)))
	(let ((output-file-name (with-current-buffer (process-buffer process)
				  pgg-gpg-output-file-name)))
	  (when (file-exists-p output-file-name)
	    (let ((coding-system-for-read (if pgg-text-mode
					      'raw-text
					    'binary)))
	      (insert-file-contents output-file-name))
	    (delete-file output-file-name))))
    (if (buffer-live-p (process-buffer process))
	(kill-buffer (process-buffer process)))))

(defun pgg-gpg-wait-for-status (process status-list)
  (with-current-buffer (process-buffer process)
    (setq pgg-gpg-pending-status-list status-list)
    (while (and (eq (process-status process) 'run)
		pgg-gpg-pending-status-list)
      (accept-process-output process 1))))

(defun pgg-gpg-wait-for-process (process)
  (while (eq (process-status process) 'run)
    (accept-process-output process 1))
  (sit-for 1))

(defun pgg-gpg-handle-USERID_HINT (process line)
  (if (string-match "^USERID_HINT \\([^ ]+\\) \\(.*\\)" line)
      (let* ((key-id (match-string 1 line))
	     (user-id (match-string 2 line))
	     (entry (assoc key-id pgg-gpg-user-id-alist)))
	(if entry
	    (setcdr entry user-id)
	  (setq pgg-gpg-user-id-alist (cons (cons key-id user-id)
					    pgg-gpg-user-id-alist))))))
						  
(defun pgg-gpg-handle-NEED_PASSPHRASE (process line)
  (if (string-match "^NEED_PASSPHRASE \\([^ ]+\\)" line)
      (setq pgg-gpg-key-id (match-string 1 line))))

(defun pgg-gpg-handle-NEED_PASSPHRASE_SYM (process line)
  (setq pgg-gpg-key-id 'symmetric))

(defun pgg-gpg-handle-GET_HIDDEN (process line)
  (let* ((entry (assoc pgg-gpg-key-id pgg-gpg-user-id-alist))
	 (passphrase (pgg-read-passphrase
		      (if (eq pgg-gpg-key-id 'symmetric)
			  "GnuPG passphrase for symmetric encryption: "
			(format "GnuPG passphrase for %s: " (if entry
								(cdr entry)
							      pgg-gpg-key-id)))
		      pgg-gpg-key-id)))
    (if passphrase
	(process-send-string process (concat passphrase "\n")))))

(defun pgg-gpg-lookup-key (string &optional type)
  "Search keys associated with STRING."
  (let ((args (list "--with-colons" "--no-greeting" "--batch"
		    (if type "--list-secret-keys" "--list-keys")
		    string)))
    (with-temp-buffer
      (apply #'call-process pgg-gpg-program nil t nil args)
      (goto-char (point-min))
      (if (re-search-forward "^\\(sec\\|pub\\):[^:]*:[^:]*:[^:]*:\\([^:]*\\)"
			     nil t)
	  (substring (match-string 2) 8)))))

(defun pgg-gpg-encrypt-region (start end recipients &optional sign passphrase)
  "Encrypt the current region between START and END.

If optional argument SIGN is non-nil, do a combined sign and encrypt."
  (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
	 (args
	  (append
	   '("--armor" "--always-trust" "--encrypt")
	   (if pgg-text-mode '("--textmode"))
	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
	   (if recipients
	       (apply #'nconc
		      (mapcar (lambda (rcpt)
				(list pgg-gpg-recipient-argument rcpt))
			      (append recipients
				      (if pgg-encrypt-for-me
					  (list pgg-gpg-user-id))))))))
	 (process (pgg-gpg-start-process args)))
    (if sign
	(pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE")))
    (process-send-region process start end)
    (process-send-eof process)
    (pgg-gpg-wait-for-process process)
    (pgg-process-when-success)))

(defun pgg-gpg-encrypt-symmetric-region (start end &optional passphrase)
  "Encrypt the current region between START and END with symmetric cipher."
  (let* ((args
	  (append '("--armor" "--symmetric")
		  (if pgg-text-mode '("--textmode"))))
	 (process (pgg-gpg-start-process args)))
    (pgg-gpg-wait-for-status process '("GOT_IT"))
    (process-send-region process start end)
    (process-send-eof process)
    (pgg-gpg-wait-for-process process)
    (pgg-process-when-success)))

(defun pgg-gpg-decrypt-region (start end &optional passphrase)
  "Decrypt the current region between START and END."
  (let* ((args '("--decrypt"))
	 (process (pgg-gpg-start-process args)))
    (process-send-region process start end)
    (pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE"))
    (process-send-eof process)
    (pgg-gpg-wait-for-process process)
    (save-excursion
      (set-buffer pgg-errors-buffer)
      (goto-char (point-min))
      (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))

(defun pgg-gpg-sign-region (start end &optional cleartext passphrase)
  "Make detached signature from text between START and END."
  (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
	 (args
	  (append (list (if cleartext "--clearsign" "--detach-sign")
			"--armor" "--verbose"
			"--local-user" pgg-gpg-user-id)
		  (if pgg-text-mode '("--textmode"))))
	 (process (pgg-gpg-start-process args)))
    (pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE"))
    (process-send-region process start end)
    (process-send-eof process)
    (pgg-gpg-wait-for-process process)
    (pgg-process-when-success)))

(defun pgg-gpg-verify-region (start end &optional signature)
  "Verify region between START and END as the detached signature SIGNATURE."
  (let ((args '("--verify"))
	process)
    (when (stringp signature)
      (setq args (append args (list signature))))
    (setq process (pgg-gpg-start-process (append args '("-"))))
    (process-send-region process start end)
    (pgg-gpg-wait-for-process process)
    (with-current-buffer pgg-errors-buffer
      (goto-char (point-min))
      (while (re-search-forward "^gpg: \\(.*\\)\n" nil t)
	(with-current-buffer pgg-output-buffer
	  (insert-buffer-substring pgg-errors-buffer
				   (match-beginning 1) (match-end 0)))
	(delete-region (match-beginning 0) (match-end 0)))
      (goto-char (point-min))
      (re-search-forward "^\\[GNUPG:] GOODSIG\\>" nil t))))

(defun pgg-gpg-insert-key ()
  "Insert public key at point."
  (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
	 (args (list "--export" "--armor"
		     pgg-gpg-user-id))
	 (process (pgg-gpg-start-process args)))
    (pgg-gpg-wait-for-process process)
    (insert-buffer-substring pgg-output-buffer)))

(defun pgg-gpg-snarf-keys-region (start end)
  "Add all public keys in region between START and END to the keyring."
  (let* ((args '("--import" "-"))
	 (process (pgg-gpg-start-process args))
	 status)
    (process-send-region process start end)
    (process-send-eof process)
    (pgg-gpg-wait-for-process process)
    (set-buffer pgg-errors-buffer)
    (goto-char (point-min))
    (when (re-search-forward "^\\[GNUPG:] IMPORT_RES\\>" nil t)
      (setq status (buffer-substring (match-end 0)
				     (progn (end-of-line)(point)))
	    status (vconcat (mapcar #'string-to-number (split-string status))))
      (erase-buffer)
      (insert (format "Imported %d key(s).
\tArmor contains %d key(s) [%d bad, %d old].\n"
		      (+ (aref status 2)
			 (aref status 10))
		      (aref status 0)
		      (aref status 1)
		      (+ (aref status 4)
			 (aref status 11)))
	      (if (zerop (aref status 9))
		  ""
		"\tSecret keys are imported.\n")))
    (append-to-buffer pgg-output-buffer (point-min)(point-max))
    (pgg-process-when-success)))

(provide 'pgg-gpg)

;;; arch-tag: 2aa5d5d8-93a0-4865-9312-33e29830e000
;;; pgg-gpg.el ends here

[-- Attachment #3: Type: text/plain, Size: 25 bytes --]


Regards,
-- 
Daiki Ueno

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 10:26                                                             ` Sascha Wilde
@ 2006-03-23 10:54                                                               ` Simon Josefsson
  2006-03-23 11:12                                                                 ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-23 10:54 UTC (permalink / raw)
  Cc: Katsumi Yamaoka, Daiki Ueno (pgg author), ding, emacs-devel

Sascha Wilde <wilde@sha-bang.de> writes:

> Simon Josefsson <jas@extundo.com> wrote:
>
>> Katsumi Yamaoka <yamaoka@jpl.org> writes:
>>
>>>>>>>> In <87irq6yrfo.fsf@latte.josefsson.org> Simon Josefsson wrote:
>>>
>>>> Katsumi Yamaoka <yamaoka@jpl.org> writes:
>>>
>>>>> Emacs 20, 21 and XEmacs complain to use of make-network-process
>>>>> which isn't available.  To solve the problem, we may want to
>>>>> introduce it as dns.el does.
>>>
>>>> Do those emacsen support socket processes?  If not, maybe we should
>>>> remove pgg-gpg-update-agent.
>>>
>>> Oops.  ISHIKAWA Mutsumi wrote (in Japanese) in
>>>
>>> http://lists.debian.or.jp/debian-devel/200502/msg00007.html
>>>
>>> that Emacs 21 doesn't support the communication passing the UNIX
>>> domain socket.  If we need to use it at all costs, we will have
>>> to use an external program which communicates with the agent
>>> process by way of the socket.
>>
>> I think it is too complicated.  It is simpler to remove the function.
>> Sascha, what do you think?  People who enable pgg-gpg-use-agent
>> manually might be expected to make sure the agent really is running.
>
> I would like to see pgg do the right think when ever it can -- could
> we keep it for emacs 22 and just not use it if its not available?  
>
> How about testing for the emacs version, or availability of
> make-network-process?
>
> I'll purpose a more compatible patch later -- but I don't have the
> time right now, sorry.

Given that this function probably won't be used at all if Daiki's idea
is implemented, I think we should remove the function for now.
Daiki's approach (if I understand it correctly) of not second-guessing
what parameters gpg will need is more reliable than this approach,
even if this approach would work fine on all emacsen.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 10:40                                                           ` Daiki Ueno
@ 2006-03-23 11:00                                                             ` Simon Josefsson
  2006-03-23 12:18                                                               ` Daiki Ueno
  2006-03-23 12:52                                                             ` Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-23 11:00 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

Daiki Ueno <ueno@unixuser.org> writes:
Date: Thu, 23 Mar 2006 12:00:22 +0100
In-Reply-To: <c1918aef-cbd3-4019-ba21-92940132533b@well-done.deisui.org>
	(Daiki Ueno's message of "Thu, 23 Mar 2006 19:40:08 +0900")
Message-ID: <87mzfhwhmh.fsf@latte.josefsson.org>
User-Agent: Gnus/5.110004 (No Gnus v0.4) Emacs/22.0.50 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable

> Hello,
>
>>>>>> In <e8632056-d7b7-4ed6-91d6-7d9089c82f94@well-done.deisui.org>=20
>>>>>>	Daiki Ueno <ueno@unixuser.org> wrote:
>> > Right now, pgg assume that gpg will need a passphrase so it asks the
>> > user for one.  It may be better if pgg postpone the passphrase query
>> > until gpg tell pgg that it needs a passphrase.  Then it is only
>> > queried for when it is needed.  This should be more reliable, but
>> > slightly more complicated to implement (asynchronous code).
>
>> Anyway, I'll try to implement this.
>
> Could you please try the attached pgg-gpg.el?
>
> Please note, this patch is only for review, not meant to be committed now.

It just hangs, it seems gpg is waiting for input from stdin or
similar.  I don't have time to debug further, sorry.

Debugger entered--Lisp error: (quit)
  accept-process-output(#<process pgg-gpg> 1)
  (while (and (eq ... ...) pgg-gpg-pending-status-list) (accept-process-out=
put process 1))
  (save-current-buffer (set-buffer (process-buffer process)) (setq pgg-gpg-=
pending-status-list status-list) (while (and ... pgg-gpg-pending-status-lis=
t) (accept-process-output process 1)))
  (with-current-buffer (process-buffer process) (setq pgg-gpg-pending-statu=
s-list status-list) (while (and ... pgg-gpg-pending-status-list) (accept-pr=
ocess-output process 1)))
  pgg-gpg-wait-for-status(#<process pgg-gpg> ("GOOD_PASSPHRASE"))
  (let* ((pgg-gpg-user-id ...) (args ...) (process ...)) (pgg-gpg-wait-for-=
status process (quote ...)) (process-send-region process start end) (proces=
s-send-eof process) (pgg-gpg-wait-for-process process) (pgg-process-when-su=
ccess))
  pgg-gpg-sign-region(1 1790 nil nil)
  funcall(pgg-gpg-sign-region 1 1790 nil nil)
  apply(funcall pgg-gpg-sign-region (1 1790 nil nil))
  pgg-invoke("sign-region" gpg 1 1790 nil nil)
  pgg-sign-region(1 1790)
  mml2015-pgg-sign((part (sign . "pgpmime") (tag-location . 1743) (contents=
 . "Daiki Ueno <ueno@unixuser.org> writes:\n\n> Hello,\n>\n>>>>>> In <e8632=
056-d7b7-4ed6-91d6-7d9089c82f94@well-done.deisui.org> \n>>>>>>	Daiki Ueno <=
ueno@unixuser.org> wrote:\n>> > Right now, pgg assume that gpg will need a =
passphrase so it asks the\n>> > user for one.  It may be better if pgg post=
pone the passphrase query\n>> > until gpg tell pgg that it needs a passphra=
se.  Then it is only\n>> > queried for when it is needed.  This should be m=
ore reliable, but\n>> > slightly more complicated to implement (asynchronou=
s code).\n>\n>> Anyway, I'll try to implement this.\n>\n> Could you please =
try the attached pgg-gpg.el?\n>\n> Please note, this patch is only for revi=
ew, not meant to be committed now.\n\nIt just\n\ngpg: NOTE: signature key 5=
C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 10184339=
46\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\ngpg: NOTE: signa=
ture key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRE=
D 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\ngpg: N=
OTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:]=
 KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-inste=
ad\ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST=
\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexp=
ired-instead\ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06=
 2002 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-=
use-keyexpired-instead\ngpg: NOTE: signature key 5C980097 expired Wed Apr 1=
0 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED d=
eprecated-use-keyexpired-instead\ngpg: using subkey AABB1F7B instead of pri=
mary key B565716F\ngpg: writing to `/tmp/pgg-output6523Lpl'\n")))
  mml2015-sign((part (sign . "pgpmime") (tag-location . 1743) (contents . "=
Daiki Ueno <ueno@unixuser.org> writes:\n\n> Hello,\n>\n>>>>>> In <e8632056-=
d7b7-4ed6-91d6-7d9089c82f94@well-done.deisui.org> \n>>>>>>	Daiki Ueno <ueno=
@unixuser.org> wrote:\n>> > Right now, pgg assume that gpg will need a pass=
phrase so it asks the\n>> > user for one.  It may be better if pgg postpone=
 the passphrase query\n>> > until gpg tell pgg that it needs a passphrase. =
 Then it is only\n>> > queried for when it is needed.  This should be more =
reliable, but\n>> > slightly more complicated to implement (asynchronous co=
de).\n>\n>> Anyway, I'll try to implement this.\n>\n> Could you please try =
the attached pgg-gpg.el?\n>\n> Please note, this patch is only for review, =
not meant to be committed now.\n\nIt just\n\ngpg: NOTE: signature key 5C980=
097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n=
[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\ngpg: NOTE: signature=
 key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 10=
18433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\ngpg: NOTE:=
 signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEY=
EXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\n=
gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[G=
NUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired=
-instead\ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 200=
2 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-=
keyexpired-instead\ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 12=
:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED depre=
cated-use-keyexpired-instead\ngpg: using subkey AABB1F7B instead of primary=
 key B565716F\ngpg: writing to `/tmp/pgg-output6523Lpl'\n")))
  mml-pgpmime-sign-buffer((part (sign . "pgpmime") (tag-location . 1743) (c=
ontents . "Daiki Ueno <ueno@unixuser.org> writes:\n\n> Hello,\n>\n>>>>>> In=
 <e8632056-d7b7-4ed6-91d6-7d9089c82f94@well-done.deisui.org> \n>>>>>>	Daiki=
 Ueno <ueno@unixuser.org> wrote:\n>> > Right now, pgg assume that gpg will =
need a passphrase so it asks the\n>> > user for one.  It may be better if p=
gg postpone the passphrase query\n>> > until gpg tell pgg that it needs a p=
assphrase.  Then it is only\n>> > queried for when it is needed.  This shou=
ld be more reliable, but\n>> > slightly more complicated to implement (asyn=
chronous code).\n>\n>> Anyway, I'll try to implement this.\n>\n> Could you =
please try the attached pgg-gpg.el?\n>\n> Please note, this patch is only f=
or review, not meant to be committed now.\n\nIt just\n\ngpg: NOTE: signatur=
e key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 1=
018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\ngpg: NOTE=
: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KE=
YEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\=
ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[=
GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpire=
d-instead\ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 20=
02 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use=
-keyexpired-instead\ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 1=
2:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED depr=
ecated-use-keyexpired-instead\ngpg: NOTE: signature key 5C980097 expired We=
d Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEX=
PIRED deprecated-use-keyexpired-instead\ngpg: using subkey AABB1F7B instead=
 of primary key B565716F\ngpg: writing to `/tmp/pgg-output6523Lpl'\n")))
  mml-generate-mime-1((part (sign . "pgpmime") (tag-location . 1743) (conte=
nts . "Daiki Ueno <ueno@unixuser.org> writes:\n\n> Hello,\n>\n>>>>>> In <e8=
632056-d7b7-4ed6-91d6-7d9089c82f94@well-done.deisui.org> \n>>>>>>	Daiki Uen=
o <ueno@unixuser.org> wrote:\n>> > Right now, pgg assume that gpg will need=
 a passphrase so it asks the\n>> > user for one.  It may be better if pgg p=
ostpone the passphrase query\n>> > until gpg tell pgg that it needs a passp=
hrase.  Then it is only\n>> > queried for when it is needed.  This should b=
e more reliable, but\n>> > slightly more complicated to implement (asynchro=
nous code).\n>\n>> Anyway, I'll try to implement this.\n>\n> Could you plea=
se try the attached pgg-gpg.el?\n>\n> Please note, this patch is only for r=
eview, not meant to be committed now.\n\nIt just\n\ngpg: NOTE: signature ke=
y 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 10184=
33946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\ngpg: NOTE: si=
gnature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXP=
IRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead\ngpg=
: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST\n[GNUP=
G:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-in=
stead\ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 C=
EST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecated-use-key=
expired-instead\ngpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19=
:06 2002 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRED deprecat=
ed-use-keyexpired-instead\ngpg: NOTE: signature key 5C980097 expired Wed Ap=
r 10 12:19:06 2002 CEST\n[GNUPG:] KEYEXPIRED 1018433946\n[GNUPG:] SIGEXPIRE=
D deprecated-use-keyexpired-instead\ngpg: using subkey AABB1F7B instead of =
primary key B565716F\ngpg: writing to `/tmp/pgg-output6523Lpl'\n")))
  mml-generate-mime()
  message-encode-message-body()
  mml-to-mime()
  mml-preview((4))
  call-interactively(mml-preview)

The *pgg-gpg-debug* buffer contains:

gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST
[GNUPG:] KEYEXPIRED 1018433946
[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead
gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST
[GNUPG:] KEYEXPIRED 1018433946
[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead
gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST
[GNUPG:] KEYEXPIRED 1018433946
[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead
gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST
[GNUPG:] KEYEXPIRED 1018433946
[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead
gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST
[GNUPG:] KEYEXPIRED 1018433946
[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead
gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST
[GNUPG:] KEYEXPIRED 1018433946
[GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead
gpg: using subkey AABB1F7B instead of primary key B565716F
gpg: writing to `/tmp/pgg-output6523Lpl'

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 10:54                                                               ` Simon Josefsson
@ 2006-03-23 11:12                                                                 ` Simon Josefsson
  2006-03-23 11:16                                                                   ` Simon Josefsson
                                                                                     ` (2 more replies)
  0 siblings, 3 replies; 156+ messages in thread
From: Simon Josefsson @ 2006-03-23 11:12 UTC (permalink / raw)
  Cc: Sascha Wilde, Katsumi Yamaoka, Daiki Ueno (pgg author), ding,
	emacs-devel

Reinar, I think pgg is ready for v5-10 now.  I am sorry for all these
rapid changes.

Simon Josefsson <jas@extundo.com> writes:

>>> I think it is too complicated.  It is simpler to remove the function.
>>> Sascha, what do you think?  People who enable pgg-gpg-use-agent
>>> manually might be expected to make sure the agent really is running.
>>
>> I would like to see pgg do the right think when ever it can -- could
>> we keep it for emacs 22 and just not use it if its not available?  
>>
>> How about testing for the emacs version, or availability of
>> make-network-process?
>>
>> I'll purpose a more compatible patch later -- but I don't have the
>> time right now, sorry.
>
> Given that this function probably won't be used at all if Daiki's idea
> is implemented, I think we should remove the function for now.
> Daiki's approach (if I understand it correctly) of not second-guessing
> what parameters gpg will need is more reliable than this approach,
> even if this approach would work fine on all emacsen.

I removed the function.  The end result is this:

1) People who don't use the agent don't have to do anything, this is
   as before.

2) People who use the agent must enable pgg-gpg-use-agent manually.
   This is better than before, because the agent didn't work at all
   with pgg then.

3) People who use the agent must make sure the agent is still running
   (or disable the variable temporarily, or re-start the agent and
   fixing the environment variable using M-x setenv).

If/when Daiki's idea (as I understand it) is implemented, the end
result will be:

*) Pgg will invoke gpg and then figure out whether a passphrase is
   needed and only at that point query for it.  This will work
   regardless of whether the agent is used, whether a passphrase is
   required or not, or whether a pin code is required.  The user
   doesn't have to fiddle with any variable.

/Simon

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 11:12                                                                 ` Simon Josefsson
@ 2006-03-23 11:16                                                                   ` Simon Josefsson
  2006-03-23 12:51                                                                     ` Reiner Steib
  2006-03-23 12:00                                                                   ` Sascha Wilde
       [not found]                                                                   ` <m2wtels74l.fsf@kenny.sha-bang .de>
  2 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-23 11:16 UTC (permalink / raw)
  Cc: Katsumi Yamaoka, Daiki Ueno (pgg author), Reiner Steib, ding,
	emacs-devel

Simon Josefsson <jas@extundo.com> writes:

> I removed the function.  The end result is this:

To clarify: I removed it in v5-10 only.  For Emacs CVS, Sascha's patch
work fine so it can stay (although perhaps should be removed there
too, to simplify syncing?).  For Gnus CVS trunk, I don't know whether
it works or not (does it work on the XEmacs version Gnus CVS
require?).

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 11:12                                                                 ` Simon Josefsson
  2006-03-23 11:16                                                                   ` Simon Josefsson
@ 2006-03-23 12:00                                                                   ` Sascha Wilde
  2006-03-23 13:00                                                                     ` Simon Josefsson
       [not found]                                                                   ` <m2wtels74l.fsf@kenny.sha-bang .de>
  2 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-03-23 12:00 UTC (permalink / raw)
  Cc: Katsumi Yamaoka, Daiki Ueno (pgg author), emacs-devel, ding,
	Reiner Steib

Simon Josefsson <jas@extundo.com> wrote:

[pgg-gpg-update-agent won't work on pre 22 emacsen]

>> Given that this function probably won't be used at all if Daiki's idea
>> is implemented, I think we should remove the function for now.
>> Daiki's approach (if I understand it correctly) of not second-guessing
>> what parameters gpg will need is more reliable than this approach,
>> even if this approach would work fine on all emacsen.
>
> I removed the function.  The end result is this:
>
> 1) People who don't use the agent don't have to do anything, this is
>    as before.
>
> 2) People who use the agent must enable pgg-gpg-use-agent manually.
>    This is better than before, because the agent didn't work at all
>    with pgg then.
>
> 3) People who use the agent must make sure the agent is still running
>    (or disable the variable temporarily, or re-start the agent and
>    fixing the environment variable using M-x setenv).

Could you please leave it in the GNU Emacs CVS, where it actually
works as intended?

> If/when Daiki's idea (as I understand it) is implemented, the end
> result will be:
>
> *) Pgg will invoke gpg and then figure out whether a passphrase is
>    needed and only at that point query for it.  This will work
>    regardless of whether the agent is used, whether a passphrase is
>    required or not, or whether a pin code is required.  The user
>    doesn't have to fiddle with any variable.

I don't think so.  While I'm sure, that Daiki's idea -- once it
works -- will handle certain situations better than mine, there will
still be the need for an variable enabling the user to turn of any use
of the agent.

Here is an example[0] from my own experience:

- A user logs in on machine 'A' and starts the gpg-agent.
- He leaves the machine, but stays logged in...
- Now he uses machine 'B' to log in on machine 'A':
  the environment is setup to use the already running gpg-agent
  (automatically, in an login script)
- He starts Emacs/Gnus and tries to sign, decrypt whatever...
- The agent runs and is working, everything seems fine, but the user
  isn't queried for the passphrase ... what happened?
- The User _is_ actually queried, but the pinentry program is started
  on the X11 Display or tty of machine 'A'.

I think this is a design problem of the gpg-agent.  And yes, there are
several ways to circumvent this problem, but I think it would be very
convenient, if I could tell pgg to just ignore any agent and ask for
the passphrase.

Even gpg itself doesn't use an available agent automatically, but only
when it's asked to (by setting --use-agent) and I think this is a good
decision.

cheers
sascha

[0] actually, the simple example of emacs running an a text console
    which I used before, was totally wrong -- it works just fine as I
    tested a few minutes ago...  :-)
-- 
Sascha Wilde
Wer HTML postet oder gepostetes HTML quotet oder sich gepostetes oder
gequotetes HTML beschafft, um es in Verkehr zu bringen, wird geplonkt.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 11:00                                                             ` Simon Josefsson
@ 2006-03-23 12:18                                                               ` Daiki Ueno
  2006-03-23 13:08                                                                 ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-03-23 12:18 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

>>>>> In <87lkv1whmh.fsf@latte.josefsson.org> 
>>>>>	Simon Josefsson <jas@extundo.com> wrote:
> > Could you please try the attached pgg-gpg.el?
> >
> > Please note, this patch is only for review, not meant to be committed now.

> It just hangs, it seems gpg is waiting for input from stdin or
> similar.  I don't have time to debug further, sorry.

Sorry.  Could you tell me what version of GnuPG you are using?
I'm testing against "gnupg" and "gnupg-agent" package in Debian sid,
i.e.

$ gpg --version
gpg (GnuPG) 1.4.2.2
$ gpg-agent --version
gpg-agent (GnuPG) 1.9.20

> The *pgg-gpg-debug* buffer contains:

> gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST
> [GNUPG:] KEYEXPIRED 1018433946
> [GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead

The *pgg-gpg-debug* buffer looks like this:

[GNUPG:] USERID_HINT A5B6B2D4B15813FE Daiki Ueno <ueno@unixuser.org>
[GNUPG:] NEED_PASSPHRASE A5B6B2D4B15813FE A5B6B2D4B15813FE 17 0
[GNUPG:] GET_HIDDEN passphrase.enter
[GNUPG:] GOT_IT
[GNUPG:] GOOD_PASSPHRASE
gpg: writing to `/tmp/pgg-output11169j3s'
gpg: DSA/SHA1 signature from: "B15813FE Daiki Ueno <ueno@unixuser.org>"
[GNUPG:] SIG_CREATED D 17 2 00 1143115847 80037CD00F1A940003CA50AAA5B6B2D4B15813FE

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 11:16                                                                   ` Simon Josefsson
@ 2006-03-23 12:51                                                                     ` Reiner Steib
  2006-03-23 13:07                                                                       ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Reiner Steib @ 2006-03-23 12:51 UTC (permalink / raw)
  Cc: Sascha Wilde, Daiki Ueno (pgg author), ding, emacs-devel,
	Katsumi Yamaoka, Miles Bader

On Thu, Mar 23 2006, Simon Josefsson wrote:

> To clarify: I removed it in v5-10 only.  For Emacs CVS, Sascha's patch
> work fine so it can stay (although perhaps should be removed there
> too, to simplify syncing?).

It would be very much preferable to have the same code at least in
Emacs CVS and Gnus v5-10 branch.  (-> Cc-ing Miles.)

> For Gnus CVS trunk, I don't know whether it works or not (does it
> work on the XEmacs version Gnus CVS require?).

Given that Emacs 21 and XEmacs also complain (see Katsumi's message
<news:b4m3bha6kon.fsf@jpl.org>), we also need a fix for the Gnus
trunk.

Couldn't we let `pgg-gpg-update-agent' simply return `t' if
`make-network-process' isn't available?  (Or check for
`make-network-process' directly in `pgg-gpg-use-agent-p'?)

(defun pgg-gpg-update-agent ()
  "Try to connet to gpg-agent and send UPDATESTARTUPTTY."
  (if (fboundp 'make-network-process)
      (let* ((agent-info (getenv "GPG_AGENT_INFO")) 
	     (socket (and agent-info
			  (string-match "^\\([^:]*\\)" agent-info)
			  (match-string 1 agent-info)))
	     (conn (and socket
			(make-network-process :name "gpg-agent-process"
					      :host 'local :family 'local
					      :service socket))))
	(when (and conn (eq (process-status conn) 'open))
	  (process-send-string conn "UPDATESTARTUPTTY\n")
	  (delete-process conn)
	  t))
    ;; We can't check, so assume gpg-agent is up.
    t))

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 10:40                                                           ` Daiki Ueno
  2006-03-23 11:00                                                             ` Simon Josefsson
@ 2006-03-23 12:52                                                             ` Sascha Wilde
  2006-03-23 20:07                                                               ` Daiki Ueno
  1 sibling, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-03-23 12:52 UTC (permalink / raw)
  Cc: Simon Josefsson, ding, emacs-devel

Daiki Ueno <ueno@unixuser.org> wrote:
>>>>>> In <e8632056-d7b7-4ed6-91d6-7d9089c82f94@well-done.deisui.org> 
>>>>>>	Daiki Ueno <ueno@unixuser.org> wrote:
>> > Right now, pgg assume that gpg will need a passphrase so it asks the
>> > user for one.  It may be better if pgg postpone the passphrase query
>> > until gpg tell pgg that it needs a passphrase.  Then it is only
>> > queried for when it is needed.  This should be more reliable, but
>> > slightly more complicated to implement (asynchronous code).
>
>> Anyway, I'll try to implement this.

Hello Daiki,

In a first, very quick test your code doesn't work for me (the agent
asks for the passphrase but decryption fails.

But after having a look at the status output from --status-fd with
--use-agent and --no-use-agent I'm starting to doubt that your idea
can work at all.  The status output is in both cases identical...  :-(

Hopefully I'm missing something.

I'm using 
gpg (GnuPG) 1.4.2.2
and
gpg-agent (GnuPG) 1.9.20

cheers 
sascha
-- 
Sascha Wilde : VI is to EMACS as masturbation is to making love:
             : effective and always available but probably not your
             : first choice...



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 12:00                                                                   ` Sascha Wilde
@ 2006-03-23 13:00                                                                     ` Simon Josefsson
  2006-03-26 18:11                                                                       ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-23 13:00 UTC (permalink / raw)
  Cc: Reiner Steib, Katsumi Yamaoka, Daiki Ueno (pgg author), ding,
	emacs-devel

Sascha Wilde <wilde@sha-bang.de> writes:

> Could you please leave it in the GNU Emacs CVS, where it actually
> works as intended?

Yep, done.  It complicate syncing a bit, though.

>> If/when Daiki's idea (as I understand it) is implemented, the end
>> result will be:
>>
>> *) Pgg will invoke gpg and then figure out whether a passphrase is
>>    needed and only at that point query for it.  This will work
>>    regardless of whether the agent is used, whether a passphrase is
>>    required or not, or whether a pin code is required.  The user
>>    doesn't have to fiddle with any variable.
>
> I don't think so.  While I'm sure, that Daiki's idea -- once it
> works -- will handle certain situations better than mine, there will
> still be the need for an variable enabling the user to turn of any use
> of the agent.
>
> Here is an example[0] from my own experience:
>
> - A user logs in on machine 'A' and starts the gpg-agent.
> - He leaves the machine, but stays logged in...
> - Now he uses machine 'B' to log in on machine 'A':
>   the environment is setup to use the already running gpg-agent
>   (automatically, in an login script)
> - He starts Emacs/Gnus and tries to sign, decrypt whatever...
> - The agent runs and is working, everything seems fine, but the user
>   isn't queried for the passphrase ... what happened?
> - The User _is_ actually queried, but the pinentry program is started
>   on the X11 Display or tty of machine 'A'.
>
> I think this is a design problem of the gpg-agent.  And yes, there are
> several ways to circumvent this problem, but I think it would be very
> convenient, if I could tell pgg to just ignore any agent and ask for
> the passphrase.

This example seems strange.  How would the user's second session get
the GPG_AGENT_INFO environment variable that points to the gpg-agent
running in the user's first session?  Without that, I don't think it
will work as you describe.  I think the user should start another
gpg-agent for his new session.

I'm not sure I see any disadvantage (except code complexity) with
Daiki's approach.  Maybe you can expand on the above, or think of more
problems, and we can see whether maybe we should use some other
approach.  Perhaps move that discussion to the ding list only.

Daiki's approach is also arguable more correct if you don't have a
passphrase at all.  The Gnus query for a passphrase would be quite
confusing in that case.

> Even gpg itself doesn't use an available agent automatically, but only
> when it's asked to (by setting --use-agent) and I think this is a good
> decision.

I have 'use-agent' in my gpg.conf.  If the agent isn't available, gpg
will fall back to querying to user interactively.  That seem to give
the best user experience for gpg, so I think we should support it.

Further, if you use a smartcard (like an OpenPGP card), it seems you
_must_ use the agent for things to work at all.  (I can't get gpg to
sign anything using my smartcard if I disable the agent.)



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 12:51                                                                     ` Reiner Steib
@ 2006-03-23 13:07                                                                       ` Sascha Wilde
  2006-03-23 13:10                                                                         ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-03-23 13:07 UTC (permalink / raw)
  Cc: Daiki Ueno (pgg author), ding, emacs-devel, Katsumi Yamaoka,
	Simon Josefsson, Miles Bader

Reiner Steib <reinersteib+gmane@imap.cc> wrote:

> Couldn't we let `pgg-gpg-update-agent' simply return `t' if
> `make-network-process' isn't available?  (Or check for
> `make-network-process' directly in `pgg-gpg-use-agent-p'?)

That's what I had in mind, so I like it...  ;-)

cheers
sascha
-- 
Sascha Wilde
To become a Jedi, use Emacs you have to.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 12:18                                                               ` Daiki Ueno
@ 2006-03-23 13:08                                                                 ` Simon Josefsson
  2006-03-24  5:51                                                                   ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-23 13:08 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

Daiki Ueno <ueno@unixuser.org> writes:

> $ gpg --version
> gpg (GnuPG) 1.4.2.2
> $ gpg-agent --version
> gpg-agent (GnuPG) 1.9.20

Same here, from Debian testing.

>> The *pgg-gpg-debug* buffer contains:
>
>> gpg: NOTE: signature key 5C980097 expired Wed Apr 10 12:19:06 2002 CEST
>> [GNUPG:] KEYEXPIRED 1018433946
>> [GNUPG:] SIGEXPIRED deprecated-use-keyexpired-instead
>
> The *pgg-gpg-debug* buffer looks like this:
>
> [GNUPG:] USERID_HINT A5B6B2D4B15813FE Daiki Ueno <ueno@unixuser.org>
> [GNUPG:] NEED_PASSPHRASE A5B6B2D4B15813FE A5B6B2D4B15813FE 17 0
> [GNUPG:] GET_HIDDEN passphrase.enter
> [GNUPG:] GOT_IT
> [GNUPG:] GOOD_PASSPHRASE
> gpg: writing to `/tmp/pgg-output11169j3s'
> gpg: DSA/SHA1 signature from: "B15813FE Daiki Ueno <ueno@unixuser.org>"
> [GNUPG:] SIG_CREATED D 17 2 00 1143115847 80037CD00F1A940003CA50AAA5B6B2D4B15813FE

Ok, I got your file to work for two cases:

1) gpg-agent with normal secret key

2) no gpg-agent with normal secret key

but not with

3) gpg-agent with secret on smart card

With the stuff in CVS, all three work, but I have to toggle
pgg-gpg-use-agent manually.

Your code has a better query too (since it know which key gpg actually
wants), and it may improve passphrase caching too.  Very nice!

Maybe you can finish this code, and I can debug why it doesn't work
for a smartcard separately.  It is probably not an important feature.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 13:07                                                                       ` Sascha Wilde
@ 2006-03-23 13:10                                                                         ` Simon Josefsson
  0 siblings, 0 replies; 156+ messages in thread
From: Simon Josefsson @ 2006-03-23 13:10 UTC (permalink / raw)
  Cc: Reiner Steib, Katsumi Yamaoka, Daiki Ueno (pgg author), ding,
	emacs-devel, Miles Bader

Sascha Wilde <wilde@sha-bang.de> writes:

> Reiner Steib <reinersteib+gmane@imap.cc> wrote:
>
>> Couldn't we let `pgg-gpg-update-agent' simply return `t' if
>> `make-network-process' isn't available?  (Or check for
>> `make-network-process' directly in `pgg-gpg-use-agent-p'?)
>
> That's what I had in mind, so I like it...  ;-)

Yes, this sounds like a good idea, and then we can have all code in
sync again (except the password.el stuff of course...).

I'll install this modification now.



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 12:52                                                             ` Sascha Wilde
@ 2006-03-23 20:07                                                               ` Daiki Ueno
  2006-03-23 22:16                                                                 ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-03-23 20:07 UTC (permalink / raw)
  Cc: emacs-devel, ding, Simon Josefsson

Hello,

>>>>> In <m2pskds4q7.fsf@kenny.sha-bang.de> 
>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> Daiki Ueno <ueno@unixuser.org> wrote:
> But after having a look at the status output from --status-fd with
> --use-agent and --no-use-agent I'm starting to doubt that your idea
> can work at all.  The status output is in both cases identical...  :-(

> Hopefully I'm missing something.

I guess that you missed to specify --command-fd 0.  If it is specified,
you will get "GET_HIDDEN passphrase.enter" in the latter case:

$ gpg --decrypt --armor --status-fd 1 --command-fd 0 --use-agent test.txt.asc
gpg: CAST5 encrypted data
[GNUPG:] NEED_PASSPHRASE_SYM 3 3 2
(gpg spawns pinentry)

$ gpg --decrypt --armor --status-fd 1 --command-fd 0 --no-use-agent test.txt.asc
gpg: CAST5 encrypted data
[GNUPG:] NEED_PASSPHRASE_SYM 3 3 2
[GNUPG:] GET_HIDDEN passphrase.enter

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 20:07                                                               ` Daiki Ueno
@ 2006-03-23 22:16                                                                 ` Sascha Wilde
  2006-04-05  9:13                                                                   ` pgg-gpg broken? Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-03-23 22:16 UTC (permalink / raw)
  Cc: emacs-devel, ding, Simon Josefsson

Daiki Ueno <ueno@unixuser.org> wrote:

> Hello,
>
>>>>>> In <m2pskds4q7.fsf@kenny.sha-bang.de> 
>>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
>> Daiki Ueno <ueno@unixuser.org> wrote:
>> But after having a look at the status output from --status-fd with
>> --use-agent and --no-use-agent I'm starting to doubt that your idea
>> can work at all.  The status output is in both cases identical...  :-(
>
>> Hopefully I'm missing something.
>
> I guess that you missed to specify --command-fd 0.  If it is specified,
> you will get "GET_HIDDEN passphrase.enter" in the latter case:

Ah, I see.  Thanks for the explaining.

sascha
-- 
Sascha Wilde
begin  LOVE-OUTLOOK-LETTER.txt.vbs
I am a beasty signature virus. Distribute me!
end

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
       [not found]                                                                   ` <m2wtels74l.fsf@kenny.sha-bang .de>
@ 2006-03-23 23:09                                                                     ` Miles Bader
  2006-04-02  0:30                                                                       ` Ken Manheimer
  0 siblings, 1 reply; 156+ messages in thread
From: Miles Bader @ 2006-03-23 23:09 UTC (permalink / raw)
  Cc: emacs-devel

Sascha Wilde <wilde@sha-bang.de> writes:
> Even gpg itself doesn't use an available agent automatically, but only
> when it's asked to (by setting --use-agent) and I think this is a good
> decision.

You can enable it globally with the "use-agent" option in the
~/.gnupg/gpg.conf file -- and I expect many people do this, as it's just
too huge a pain in the ass otherwise.

-miles
-- 
Any man who is a triangle, has thee right, when in Cartesian Space, to
have angles, which when summed, come to know more, nor no less, than
nine score degrees, should he so wish.  [TEMPLE OV THEE LEMUR]




^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 13:08                                                                 ` Simon Josefsson
@ 2006-03-24  5:51                                                                   ` Daiki Ueno
  2006-03-26  0:29                                                                     ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-03-24  5:51 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

>>>>> In <87d5gd2ts1.fsf@latte.josefsson.org> 
>>>>>	Simon Josefsson <jas@extundo.com> wrote:
> Ok, I got your file to work for two cases:

> 1) gpg-agent with normal secret key

> 2) no gpg-agent with normal secret key

> but not with

> 3) gpg-agent with secret on smart card

Thanks for testing.

> Maybe you can finish this code, and I can debug why it doesn't work
> for a smartcard separately.  It is probably not an important feature.

The new code mostly finished.  Could you send me some examples of status
fd output in case 3?

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-24  5:51                                                                   ` Daiki Ueno
@ 2006-03-26  0:29                                                                     ` Daiki Ueno
  2006-03-26  1:08                                                                       ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-03-26  0:29 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 642 bytes --]

>>>>> In <b4edf9b5-2663-4d5c-981e-ddabca619ad6@well-done.deisui.org> 
>>>>>	Daiki Ueno <ueno@unixuser.org> wrote:
> > Maybe you can finish this code, and I can debug why it doesn't work
> > for a smartcard separately.  It is probably not an important feature.

> The new code mostly finished.

Ok, the attached file is (hopefully) the final version of the new code.
Differences from the previous one are:

- Passphrase caching now works again.
- pgg-gpg-use-agent is abolished.  Add "use-agent" to ~/.gnupg/gpg.conf
  if you want to enable use of gpg-agent, as Miles said.
- Tested with typical cases.  I also attach some test cases I used.


[-- Attachment #2: pgg-gpg.el --]
[-- Type: application/octet-stream, Size: 11785 bytes --]

;;; pgg-gpg.el --- GnuPG support for PGG.

;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
;;   2005, 2006 Free Software Foundation, Inc.

;; Author: Daiki Ueno <ueno@unixuser.org>
;; Symmetric encryption and gpg-agent support added by: 
;;   Sascha Wilde <wilde@sha-bang.de>
;; Created: 1999/10/28
;; Keywords: PGP, OpenPGP, GnuPG

;; This file is part of GNU Emacs.

;; GNU Emacs 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 2, or (at your option)
;; any later version.

;; GNU Emacs 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 GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Code:

(eval-when-compile
  (require 'pgg))

(defgroup pgg-gpg ()
  "GnuPG interface."
  :group 'pgg)

(defcustom pgg-gpg-program "gpg"
  "The GnuPG executable."
  :group 'pgg-gpg
  :type 'string)

(defcustom pgg-gpg-extra-args nil
  "Extra arguments for every GnuPG invocation."
  :group 'pgg-gpg
  :type '(repeat (string :tag "Argument")))

(defcustom pgg-gpg-recipient-argument "--recipient"
  "GnuPG option to specify recipient."
  :group 'pgg-gpg
  :type '(choice (const :tag "New `--recipient' option" "--recipient")
		 (const :tag "Old `--remote-user' option" "--remote-user")))

(defvar pgg-gpg-user-id nil
  "GnuPG ID of your default identity.")

(defvar pgg-gpg-user-id-alist nil
  "An alist mapping from key ID to user ID.")

(defvar pgg-gpg-read-point nil)
(defvar pgg-gpg-output-file-name nil)
(defvar pgg-gpg-pending-status-list nil)
(defvar pgg-gpg-key-id nil)
(defvar pgg-gpg-passphrase nil)
(defvar pgg-gpg-debug nil)

(defun pgg-gpg-start-process (args)
  (let* ((output-file-name (pgg-make-temp-file "pgg-output"))
	 (args
	  (append (list "--no-tty"
			"--status-fd" "1"
			"--command-fd" "0"
			"--yes" ; overwrite
			"--output" output-file-name)
		  pgg-gpg-extra-args
		  args))
	 (coding-system-for-write 'binary)
	 (process-connection-type nil)
	 (orig-mode (default-file-modes))
	 default-enable-multibyte-characters
	 (buffer (generate-new-buffer " *pgg-gpg*"))
	 process)
    (with-current-buffer buffer
      (make-local-variable 'pgg-gpg-read-point)
      (setq pgg-gpg-read-point (point-min))
      (make-local-variable 'pgg-gpg-output-file-name)
      (setq pgg-gpg-output-file-name output-file-name)
      (make-local-variable 'pgg-gpg-pending-status-list)
      (setq pgg-gpg-pending-status-list nil)
      (make-local-variable 'pgg-gpg-key-id)
      (setq pgg-gpg-key-id nil)
      (make-local-variable 'pgg-gpg-passphrase)
      (setq pgg-gpg-passphrase nil))
    (unwind-protect
	(progn
	  (set-default-file-modes 448)
	  (setq process
		(apply #'start-process "pgg-gpg" buffer pgg-gpg-program args)))
      (set-default-file-modes orig-mode))
    (set-process-filter process #'pgg-gpg-process-filter)
    (set-process-sentinel process #'pgg-gpg-process-sentinel)
    process))

(defun pgg-gpg-process-filter (process input)
  (save-excursion
    (if pgg-gpg-debug
	(save-excursion
	  (set-buffer (get-buffer-create  " *pgg-gpg-debug*"))
	  (goto-char (point-max))
	  (insert input)))
    (set-buffer (process-buffer process))
    (goto-char (point-max))
    (insert input)
    (goto-char pgg-gpg-read-point)
    (beginning-of-line)
    (while (looking-at ".*\n")		;the input line is finished
      (save-excursion
	(if (looking-at "\\[GNUPG:] \\([A-Z_]+\\)\\>.*")
	    (let* ((status (match-string 1))
		   (symbol (intern-soft (concat "pgg-gpg-status-" status)))
		   (entry (member status pgg-gpg-pending-status-list)))
	      (if entry
		  (setq pgg-gpg-pending-status-list
			(delq (car entry)
			      pgg-gpg-pending-status-list)))
	      (if (and symbol
		       (fboundp symbol))
		  (funcall symbol process (buffer-substring (match-beginning 1)
							    (match-end 0)))))))
      (forward-line))
    (setq pgg-gpg-read-point (point))))

(defun pgg-gpg-process-sentinel (process status)
  (set-process-filter process nil)
  (save-excursion
    ;; Copy the contents of process-buffer to pgg-errors-buffer.
    (set-buffer (get-buffer-create pgg-errors-buffer))
    (buffer-disable-undo)
    (erase-buffer)
    (when (buffer-live-p (process-buffer process))
      (insert-buffer-substring (process-buffer process))
      (goto-char (point-min))
      (delete-matching-lines "^\\[GNUPG:] ")
      (goto-char (point-min))
      (while (re-search-forward "^gpg: " nil t)
	(replace-match "")))
    ;; Read the contents of the output file to pgg-output-buffer.
    (set-buffer (get-buffer-create pgg-output-buffer))
    (buffer-disable-undo)
    (erase-buffer)
    (if (and (equal status "finished\n")
	     (buffer-live-p (process-buffer process)))
	(let ((output-file-name (with-current-buffer (process-buffer process)
				  pgg-gpg-output-file-name)))
	  (when (file-exists-p output-file-name)
	    (let ((coding-system-for-read (if pgg-text-mode
					      'raw-text
					    'binary)))
	      (insert-file-contents output-file-name))
	    (delete-file output-file-name))))))

(defun pgg-gpg-wait-for-status (process status-list)
  (with-current-buffer (process-buffer process)
    (setq pgg-gpg-pending-status-list status-list)
    (while (and (eq (process-status process) 'run)
		pgg-gpg-pending-status-list)
      (accept-process-output process 1))))

(defun pgg-gpg-wait-for-completion (process &optional status-list)
  (process-send-eof process)
  (while (eq (process-status process) 'run)
    (sit-for 0.1))
  (save-excursion
    (set-buffer (process-buffer process))
    (setq status-list (copy-sequence status-list))
    (let ((pointer status-list))
      (while pointer
	(goto-char (point-min))
	(unless (re-search-forward
		 (concat "^\\[GNUPG:] " (car pointer) "\\>")
		 nil t)
	  (setq status-list (delq (car pointer) status-list)))
	(setq pointer (cdr pointer))))
    (kill-buffer (process-buffer process))
    status-list))

(defun pgg-gpg-status-USERID_HINT (process line)
  (if (string-match "\\`USERID_HINT \\([^ ]+\\) \\(.*\\)" line)
      (let* ((key-id (match-string 1 line))
	     (user-id (match-string 2 line))
	     (entry (assoc key-id pgg-gpg-user-id-alist)))
	(if entry
	    (setcdr entry user-id)
	  (setq pgg-gpg-user-id-alist (cons (cons key-id user-id)
					    pgg-gpg-user-id-alist))))))

(defun pgg-gpg-status-NEED_PASSPHRASE (process line)
  (if (string-match "\\`NEED_PASSPHRASE \\([^ ]+\\)" line)
      (setq pgg-gpg-key-id (match-string 1 line))))

(defun pgg-gpg-status-NEED_PASSPHRASE_SYM (process line)
  (setq pgg-gpg-key-id 'SYM))

(defun pgg-gpg-status-NEED_PASSPHRASE_PIN (process line)
  (setq pgg-gpg-key-id 'PIN))

(defun pgg-gpg-status-GET_HIDDEN (process line)
  (let ((entry (assoc pgg-gpg-key-id pgg-gpg-user-id-alist)))
    (if (setq pgg-gpg-passphrase
	      (if (eq pgg-gpg-key-id 'SYM)
		  (pgg-read-passphrase
		   "GnuPG passphrase for symmetric encryption: ")
		(pgg-read-passphrase
		 (format "GnuPG passphrase for %s: "
			 (if entry
			     (cdr entry)
			   pgg-gpg-key-id))
		 (if (eq pgg-gpg-key-id 'PIN)
		     "PIN"
		   pgg-gpg-key-id))))
	(process-send-string process (concat pgg-gpg-passphrase "\n")))))

(defun pgg-gpg-status-GOOD_PASSPHRASE (process line)
  (when (and pgg-gpg-passphrase
	     (stringp pgg-gpg-key-id))
    (pgg-add-passphrase-to-cache pgg-gpg-key-id pgg-gpg-passphrase)
    (setq pgg-gpg-passphrase nil)))

(defun pgg-gpg-status-BAD_PASSPHRASE (process line)
  (when pgg-gpg-passphrase
    (fillarray pgg-gpg-passphrase 0)
    (setq pgg-gpg-passphrase nil)))

(defun pgg-gpg-lookup-key (string &optional type)
  "Search keys associated with STRING."
  (let ((args (list "--with-colons" "--no-greeting" "--batch"
		    (if type "--list-secret-keys" "--list-keys")
		    string)))
    (with-temp-buffer
      (apply #'call-process pgg-gpg-program nil t nil args)
      (goto-char (point-min))
      (if (re-search-forward "^\\(sec\\|pub\\):[^:]*:[^:]*:[^:]*:\\([^:]*\\)"
			     nil t)
	  (substring (match-string 2) 8)))))

(defun pgg-gpg-encrypt-region (start end recipients &optional sign passphrase)
  "Encrypt the current region between START and END.

If optional argument SIGN is non-nil, do a combined sign and encrypt."
  (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
	 (args
	  (append
	   '("--armor" "--always-trust" "--encrypt")
	   (if pgg-text-mode '("--textmode"))
	   (if sign (list "--sign" "--local-user" pgg-gpg-user-id))
	   (if recipients
	       (apply #'nconc
		      (mapcar (lambda (rcpt)
				(list pgg-gpg-recipient-argument rcpt))
			      (append recipients
				      (if pgg-encrypt-for-me
					  (list pgg-gpg-user-id))))))))
	 (process (pgg-gpg-start-process args)))
    (if sign
	(pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE")))
    (process-send-region process start end)
    (pgg-gpg-wait-for-completion process '("SIG_CREATED" "END_ENCRYPTION"))))

(defun pgg-gpg-encrypt-symmetric-region (start end &optional passphrase)
  "Encrypt the current region between START and END with symmetric cipher."
  (let* ((args
	  (append '("--armor" "--symmetric")
		  (if pgg-text-mode '("--textmode"))))
	 (process (pgg-gpg-start-process args)))
    (pgg-gpg-wait-for-status process '("BEGIN_ENCRYPTION"))
    (process-send-region process start end)
    (pgg-gpg-wait-for-completion process '("END_ENCRYPTION"))))

(defun pgg-gpg-decrypt-region (start end &optional passphrase)
  "Decrypt the current region between START and END."
  (let* ((args '("--decrypt"))
	 (process (pgg-gpg-start-process args)))
    (process-send-region process start end)
    (pgg-gpg-wait-for-status process '("BEGIN_DECRYPTION"))
    (pgg-gpg-wait-for-completion process '("GOODSIG" "DECRYPTION_OKAY"))))

(defun pgg-gpg-sign-region (start end &optional cleartext passphrase)
  "Make detached signature from text between START and END."
  (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
	 (args
	  (append (list (if cleartext "--clearsign" "--detach-sign")
			"--armor" "--verbose"
			"--local-user" pgg-gpg-user-id)
		  (if pgg-text-mode '("--textmode"))))
	 (process (pgg-gpg-start-process args)))
    (pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE"))
    (process-send-region process start end)
    (pgg-gpg-wait-for-completion process '("SIG_CREATED"))))

(defun pgg-gpg-verify-region (start end &optional signature)
  "Verify region between START and END as the detached signature SIGNATURE."
  (let ((args '("--verify"))
	process)
    (when (stringp signature)
      (setq args (append args (list signature))))
    (setq process (pgg-gpg-start-process (append args '("-"))))
    (process-send-region process start end)
    (pgg-gpg-wait-for-completion process '("GOODSIG"))))

(defun pgg-gpg-insert-key ()
  "Insert public key at point."
  (let* ((pgg-gpg-user-id (or pgg-gpg-user-id pgg-default-user-id))
	 (args (list "--export" "--armor"
		     pgg-gpg-user-id))
	 (process (pgg-gpg-start-process args)))
    (pgg-gpg-wait-for-completion process)
    (insert-buffer-substring pgg-output-buffer)))

(defun pgg-gpg-snarf-keys-region (start end)
  "Add all public keys in region between START and END to the keyring."
  (let* ((args '("--import" "-"))
	 (process (pgg-gpg-start-process args))
	 status)
    (process-send-region process start end)
    (pgg-gpg-wait-for-completion process '("IMPORT_RES"))))

(provide 'pgg-gpg)

;;; arch-tag: 2aa5d5d8-93a0-4865-9312-33e29830e000
;;; pgg-gpg.el ends here

[-- Attachment #3: Type: text/plain, Size: 1 bytes --]



[-- Attachment #4: test-pgg-gpg.el --]
[-- Type: application/octet-stream, Size: 972 bytes --]

(require 'pgg)
(require 'pgg-gpg)

(with-temp-buffer
  (insert "00000")
  (pgg-gpg-sign-region (point-min) (point-max) t)
  (save-excursion
    (set-buffer pgg-output-buffer)
    (pgg-gpg-verify-region (point-min) (point-max))))
;; ("GOODSIG")

(with-temp-buffer
  (insert "00000")
  (pgg-gpg-encrypt-region (point-min) (point-max) '("ueno@unixuser.org"))
  (save-excursion
    (set-buffer pgg-output-buffer)
    (pgg-gpg-decrypt-region (point-min) (point-max))))
;; ("DECRYPTION_OKAY")

(with-temp-buffer
  (insert "00000")
  (pgg-gpg-encrypt-region (point-min) (point-max) '("ueno@unixuser.org") t)
  (save-excursion
    (set-buffer pgg-output-buffer)
    (pgg-gpg-decrypt-region (point-min) (point-max))))
;; ("GOODSIG" "DECRYPTION_OKAY")

(with-temp-buffer
  (insert "00000")
  (pgg-gpg-encrypt-symmetric-region (point-min) (point-max))
  (save-excursion
    (set-buffer pgg-output-buffer)
    (pgg-gpg-decrypt-region (point-min) (point-max))))
;; ("DECRYPTION_OKAY")

[-- Attachment #5: Type: text/plain, Size: 25 bytes --]


Regards,
-- 
Daiki Ueno

[-- Attachment #6: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-26  0:29                                                                     ` Daiki Ueno
@ 2006-03-26  1:08                                                                       ` Simon Josefsson
  2006-03-26  3:29                                                                         ` Miles Bader
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-26  1:08 UTC (permalink / raw)
  Cc: Sascha Wilde, ding, emacs-devel

Daiki Ueno <ueno@unixuser.org> writes:

>>>>>> In <b4edf9b5-2663-4d5c-981e-ddabca619ad6@well-done.deisui.org> 
>>>>>>	Daiki Ueno <ueno@unixuser.org> wrote:
>> > Maybe you can finish this code, and I can debug why it doesn't work
>> > for a smartcard separately.  It is probably not an important feature.
>
>> The new code mostly finished.
>
> Ok, the attached file is (hopefully) the final version of the new code.
> Differences from the previous one are:
>
> - Passphrase caching now works again.
> - pgg-gpg-use-agent is abolished.  Add "use-agent" to ~/.gnupg/gpg.conf
>   if you want to enable use of gpg-agent, as Miles said.
> - Tested with typical cases.  I also attach some test cases I used.

This works fine except for used with a smartcard.  The current version
works with a smartcard (when you enable pgg-gpg-use-agent), so I think
that should be fixed.

I debugged this, and it seems invoking gpg using the smartcard will
not print any useful [GNUPG:] statements:

/usr/bin/gpg --no-tty --status-fd 1 --command-fd 0 --yes --output /tmp/pgg-output29825FPB --detach-sign --armor --verbose --local-user jas --textmode
...
gpg: using subkey AABB1F7B instead of primary key B565716F
gpg: writing to `/tmp/pgg-output29825FPB'

Then it waits for input.  PGG infloop waiting for GOOD_PASSPHRASE
here.  I think it should wait for 'gpg: writing to' instead, it is the
last printed statement for both smartcard and non-smartcard cases, and
it seem to be printed when gpg is ready to accept input.

For references, here is the non-smartcard case:

jas@latte:~$ /usr/bin/gpg --no-tty --status-fd 1 --command-fd 0 --yes --output /tmp/pgg-output29825FPB --detach-sign --armor --verbose --local-user b565716f! --textmode
[GNUPG:] USERID_HINT EDA21E94B565716F Simon Josefsson <simon@josefsson.org>
[GNUPG:] NEED_PASSPHRASE EDA21E94B565716F EDA21E94B565716F 1 0
<<<hangs here until i type password to the agent>>>
[GNUPG:] GOOD_PASSPHRASE
gpg: writing to `/tmp/pgg-output29825FPB'

Then it hangs waiting for the input to sign.

What do you think?  It might be ugly to depend on the 'gpg: writing'
output instead of the [GNUPG:] stuff, but I see no option here.

I suspect password-less keys may have similar issues.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-26  1:08                                                                       ` Simon Josefsson
@ 2006-03-26  3:29                                                                         ` Miles Bader
  2006-03-26  5:06                                                                           ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Miles Bader @ 2006-03-26  3:29 UTC (permalink / raw)
  Cc: ding

Simon Josefsson <jas@extundo.com> writes:
> What do you think?  It might be ugly to depend on the 'gpg: writing'
> output instead of the [GNUPG:] stuff, but I see no option here.

Of course if such a kludge is used, an important thing is to report the
problem with the "official" interface as a bug...

-miles
-- 
Love is a snowmobile racing across the tundra.  Suddenly it flips over,
pinning you underneath.  At night the ice weasels come.  --Nietzsche

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-26  3:29                                                                         ` Miles Bader
@ 2006-03-26  5:06                                                                           ` Daiki Ueno
  2006-03-26 17:05                                                                             ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-03-26  5:06 UTC (permalink / raw)
  Cc: ding, emacs-devel

>>>>> In <87irq1evdk.fsf@catnip.gol.com> 
>>>>>	Miles Bader <miles@gnu.org> wrote:
> Simon Josefsson <jas@extundo.com> writes:
> > What do you think?  It might be ugly to depend on the 'gpg: writing'
> > output instead of the [GNUPG:] stuff, but I see no option here.

> Of course if such a kludge is used, an important thing is to report the
> problem with the "official" interface as a bug...

Yes.  I think the root of the problem is that gpg does not emit any
trigger of signature creation.  I'll propose a patch to GnuPG so as to
introduce BEGIN_SIGNING and END_SIGNING status.

For the meantime, how about using pgg-gpg-use-agent as a flag to
indicate that GnuPG will _not_ ask a passphrase in signing?  Smartcard
users should have to set pgg-gpg-use-agent explicitly though.

Here is the patch to the previous post:

--- pgg-gpg.el~	2006-03-26 13:48:29.000000000 +0900
+++ pgg-gpg.el	2006-03-26 13:50:43.000000000 +0900
@@ -51,6 +51,11 @@
   :type '(choice (const :tag "New `--recipient' option" "--recipient")
 		 (const :tag "Old `--remote-user' option" "--remote-user")))
 
+(defcustom pgg-gpg-use-agent nil
+  "Whether to use gnupg agent for key caching."
+  :group 'pgg-gpg
+  :type 'boolean)
+
 (defvar pgg-gpg-user-id nil
   "GnuPG ID of your default identity.")
 
@@ -72,6 +77,7 @@
 			"--command-fd" "0"
 			"--yes" ; overwrite
 			"--output" output-file-name)
+		  (if pgg-gpg-use-agent '("--use-agent"))
 		  pgg-gpg-extra-args
 		  args))
 	 (coding-system-for-write 'binary)
@@ -261,7 +267,7 @@
 				      (if pgg-encrypt-for-me
 					  (list pgg-gpg-user-id))))))))
 	 (process (pgg-gpg-start-process args)))
-    (if sign
+    (if (and sign (not pgg-gpg-use-agent))
 	(pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE")))
     (process-send-region process start end)
     (pgg-gpg-wait-for-completion process '("SIG_CREATED" "END_ENCRYPTION"))))
@@ -293,7 +299,8 @@
 			"--local-user" pgg-gpg-user-id)
 		  (if pgg-text-mode '("--textmode"))))
 	 (process (pgg-gpg-start-process args)))
-    (pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE"))
+    (unless pgg-gpg-use-agent
+      (pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE")))
     (process-send-region process start end)
     (pgg-gpg-wait-for-completion process '("SIG_CREATED"))))

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-26  5:06                                                                           ` Daiki Ueno
@ 2006-03-26 17:05                                                                             ` Simon Josefsson
  2006-03-26 18:24                                                                               ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-03-26 17:05 UTC (permalink / raw)
  Cc: Miles Bader, ding, emacs-devel

Daiki Ueno <ueno@unixuser.org> writes:

>>>>>> In <87irq1evdk.fsf@catnip.gol.com> 
>>>>>>	Miles Bader <miles@gnu.org> wrote:
>> Simon Josefsson <jas@extundo.com> writes:
>> > What do you think?  It might be ugly to depend on the 'gpg: writing'
>> > output instead of the [GNUPG:] stuff, but I see no option here.
>
>> Of course if such a kludge is used, an important thing is to report the
>> problem with the "official" interface as a bug...
>
> Yes.  I think the root of the problem is that gpg does not emit any
> trigger of signature creation.  I'll propose a patch to GnuPG so as to
> introduce BEGIN_SIGNING and END_SIGNING status.

That sounds like a good idea.

> For the meantime, how about using pgg-gpg-use-agent as a flag to
> indicate that GnuPG will _not_ ask a passphrase in signing?  Smartcard
> users should have to set pgg-gpg-use-agent explicitly though.

This patch now works fine for me, both smart card and non-smartcard.

Has anyone else tested it?  Should we install it?  I think so, so
unless there are objections within a few days, I'll install it on
v5-10 and Emacs CVS.  Ok, Reinar?  We could also wait until after the
new v5-10 release, this is a pretty large change.

There is another nit (I'll fix this once your code has been
installed), which was present earlier too: specifying a --local-user
parameter even when the Gnus user didn't customize pgg-gpg-user-id
seem wrong -- it will override a 'default-key' in the gpg.conf, and
thus the default behaviour of PGG is different from the default
behaviour of gpg.  In my case, I have a default-key of b565716f (local
secret key on disk) but PGG specify --local-user jas which make gpg
select my smart card key instead, and signing in Gnus doesn't work
unless I toggle pgg-gpg-use-agent.  The solution is to only specify
--local-user when the PGG user customized the user name to sign with.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 13:00                                                                     ` Simon Josefsson
@ 2006-03-26 18:11                                                                       ` Sascha Wilde
  0 siblings, 0 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-03-26 18:11 UTC (permalink / raw)
  Cc: Katsumi Yamaoka, Daiki Ueno (pgg author), Reiner Steib, ding,
	emacs-devel

Simon Josefsson <jas@extundo.com> wrote:
> Sascha Wilde <wilde@sha-bang.de> writes:
>> Here is an example[0] from my own experience:
>>
>> - A user logs in on machine 'A' and starts the gpg-agent.
>> - He leaves the machine, but stays logged in...
>> - Now he uses machine 'B' to log in on machine 'A':
>>   the environment is setup to use the already running gpg-agent
>>   (automatically, in an login script)
>> - He starts Emacs/Gnus and tries to sign, decrypt whatever...
>> - The agent runs and is working, everything seems fine, but the user
>>   isn't queried for the passphrase ... what happened?
>> - The User _is_ actually queried, but the pinentry program is started
>>   on the X11 Display or tty of machine 'A'.
>>
>> I think this is a design problem of the gpg-agent.  And yes, there are
>> several ways to circumvent this problem, but I think it would be very
>> convenient, if I could tell pgg to just ignore any agent and ask for
>> the passphrase.
>
> This example seems strange.  How would the user's second session get
> the GPG_AGENT_INFO environment variable that points to the gpg-agent
> running in the user's first session?  Without that, I don't think it
> will work as you describe.

You are right, but that is the way things work, when you follow the
official gpg-agent documentation:

| [...]  If you don't use an X server, you can also put this into your
| regular startup file `~/.profile' or `.bash_profile'.  It is best
| not to run multiple instance of the `gpg-agent', so you should make
| sure that only one is running: `gpg-agent' uses an environment
| variable to inform clients about the communication parameters. You
| can write the content of this environment variable to a file so that
| you can test for a running agent.  [...]

> I'm not sure I see any disadvantage (except code complexity) with
> Daiki's approach.

Having a second thought on the subject I agree.

The problem exists (even in simpler use cases: when you login on the
text console and start an X server from there, the pinentry will
always appear on the console) but it is only related to gpg-agent
design and the documented use pattern -- so the place where this
problems should be discussed and solved is gnupg development.

I'll write the gnupg developers on this subject.

cheers
sascha
-- 
Sascha Wilde 
- no sig today... sorry!

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-26 17:05                                                                             ` Simon Josefsson
@ 2006-03-26 18:24                                                                               ` Sascha Wilde
  2006-03-27  9:36                                                                                 ` Simon Josefsson
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-03-26 18:24 UTC (permalink / raw)
  Cc: Daiki Ueno, emacs-devel, ding, Miles Bader

Simon Josefsson <jas@extundo.com> wrote:

> This patch now works fine for me, both smart card and non-smartcard.
>
> Has anyone else tested it?

Yes, I just gave it a try -- works great.

> Should we install it? 

I would vote:  yes. 

@daiki: if you like, you could remove "and gpg-agent " from the
header: 
;; Symmetric encryption and gpg-agent support added by: 
;;   Sascha Wilde <wilde@sha-bang.de>
its no longer true.  :-)

sascha
-- 
Sascha Wilde : "GUIs normally make it simple to accomplish simple 
             : actions and impossible to accomplish complex actions."
             : (Doug Gwyn - 22/Jun/91 in comp.unix.wizards)

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-26 18:24                                                                               ` Sascha Wilde
@ 2006-03-27  9:36                                                                                 ` Simon Josefsson
  0 siblings, 0 replies; 156+ messages in thread
From: Simon Josefsson @ 2006-03-27  9:36 UTC (permalink / raw)
  Cc: Daiki Ueno, emacs-devel, ding, Miles Bader

Sascha Wilde <wilde@sha-bang.de> writes:

> Simon Josefsson <jas@extundo.com> wrote:
>
>> This patch now works fine for me, both smart card and non-smartcard.
>>
>> Has anyone else tested it?
>
> Yes, I just gave it a try -- works great.
>
>> Should we install it? 
>
> I would vote:  yes. 
>
> @daiki: if you like, you could remove "and gpg-agent " from the
> header: 
> ;; Symmetric encryption and gpg-agent support added by: 
> ;;   Sascha Wilde <wilde@sha-bang.de>
> its no longer true.  :-)

I've installed it, with this modification, on v5-10, trunk and in
emacs CVS.

Thanks to Daiki for implementing it and everyone who tested this!



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-03-23 23:09                                                                     ` Miles Bader
@ 2006-04-02  0:30                                                                       ` Ken Manheimer
  2006-04-02  8:28                                                                         ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Ken Manheimer @ 2006-04-02  0:30 UTC (permalink / raw)
  Cc: ding, emacs-devel

hi, all.  i'm just catching up on this development - partly spurred by
breakage of some of my code (allout's encryption stuff) which depends
on functions that have been removed from pgg-gpg,
pgg-gpg-symmetric-key-p and pgg-gpg-select-matching-key.

on looking at the pgg-gpg, i noticed that some other convenience
functions on which i depend have been removed, as well:
pgg-gpg-lookup-key-owner and pgg-gpg-key-id-from-key-owner, and i
suppose others.

unless replaced with something equivalent, i think that the  removal
of these functions means that application code can not anticipate the
kind of key to request from the user.  am i missing something here?

the ChangeLog says nothing about these changes...
--
ken manheimer
ken.manheimer@gmail.com
http://myriadicity.net

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: Small patch to enable use of gpg-agent with pgg
  2006-04-02  0:30                                                                       ` Ken Manheimer
@ 2006-04-02  8:28                                                                         ` Daiki Ueno
  0 siblings, 0 replies; 156+ messages in thread
From: Daiki Ueno @ 2006-04-02  8:28 UTC (permalink / raw)
  Cc: emacs-devel, ding, Miles Bader

Hello Ken,

>>>>> In <2cd46e7f0604011630r6388edackc4c7ef21b92ecaa7@mail.gmail.com> 
>>>>>	"Ken Manheimer" <ken.manheimer@gmail.com> wrote:
> hi, all.  i'm just catching up on this development - partly spurred by
> breakage of some of my code (allout's encryption stuff) which depends
> on functions that have been removed from pgg-gpg,
> pgg-gpg-symmetric-key-p and pgg-gpg-select-matching-key.

I'm sorry I missed that.

However, pgg-gpg is one of backend modules of pgg and it should not
provide its own API.  If we revive these functions, we should add them
to pgg.el instead of pgg-gpg.el.

I'll read allout's encryption stuff and try to prepare a fix.

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* pgg-gpg broken?
  2006-03-23 22:16                                                                 ` Sascha Wilde
@ 2006-04-05  9:13                                                                   ` Sascha Wilde
  2006-04-05  9:42                                                                     ` Daiki Ueno
  2006-04-05 16:14                                                                     ` pgg-gpg broken? Reiner Steib
  0 siblings, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-04-05  9:13 UTC (permalink / raw)
  Cc: Simon Josefsson, ding, emacs-devel

Hi *,

I just needed to decrypt an old Mail using Gnus/pgg (which i decrypted
successfully many times before), but it failed.

This is the backtrace I get:

Debugger entered--Lisp error: (error "Process pgg-gpg not running")
  process-send-string(#<process pgg-gpg> "DerDenkendeWeissEs\n")
  pgg-gpg-status-GET_HIDDEN(#<process pgg-gpg> "GET_HIDDEN
  passphrase.enter")
  pgg-gpg-process-filter(#<process pgg-gpg> "[GNUPG:] USERID_HINT
  31A16202F8F7E674 Sascha Wilde <Sascha.Wilde@intevation.de>\n[GNUPG:]
  NEED_PASSPHRASE 31A16202F8F7E674 BB2185144BB86568 16 0\n[GNUPG:]
  GET_HIDDEN passphrase.enter\n[GNUPG:] GOT_IT\n[GNUPG:]
  BAD_PASSPHRASE 31A16202F8F7E674\ngpg: Invalid passphrase; please try
  again ...\n[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde
  <Sascha.Wilde@intevation.de>\n[GNUPG:] NEED_PASSPHRASE
  31A16202F8F7E674 BB2185144BB86568 16 0\n[GNUPG:] GET_HIDDEN
  passphrase.enter\n[GNUPG:] GOT_IT\n[GNUPG:] BAD_PASSPHRASE
  31A16202F8F7E674\ngpg: Invalid passphrase; please try again
  ...\n[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde
  <Sascha.Wilde@intevation.de>\n[GNUPG:] NEED_PASSPHRASE
  31A16202F8F7E674 BB2185144BB86568 16 0\n[GNUPG:] GET_HIDDEN
  passphrase.enter\n[GNUPG:] GOT_IT\n[GNUPG:] BAD_PASSPHRASE
  31A16202F8F7E674\n[GNUPG:] ENC_TO xxxxxxxxxxxxxxxx 16 0\ngpg:
  encrypted with 1024-bit ELG-E key, ID xxxxxxxx, created 2003-06-24\n
  \"xxxxxx xxxxxxxx xxxx <xxxxxx@intevation.de>\"\n[GNUPG:] NO_SECKEY
  xxxxxxxxxxxxxxxx\ngpg: encrypted with 2048-bit ELG-E key, ID
  F8F7E674, created 2004-11-15\n      \"Sascha Wilde
  <Sascha.Wilde@intevation.de>\"\ngpg: public key decryption failed:
  bad passphrase\n[GNUPG:] BEGIN_DECRYPTION\n[GNUPG:]
  DECRYPTION_FAILED\ngpg: decryption failed: secret key not
  available\ngpg: CRC error; 3CB1DD - 15B95A\n[GNUPG:]
  END_DECRYPTION\n")

Signing mails works (including querying the passphrase).

Might this be related to the latest changes by Daiki?
Sorry I don't have time to investigate this any further right now...

cheers
sascha
-- 
Sascha Wilde : "Der Nicht-Denkende glaubt, dass niemand denkt,
             : der Denkende weiss es!"
             : (Gabriel Laub)

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-05  9:13                                                                   ` pgg-gpg broken? Sascha Wilde
@ 2006-04-05  9:42                                                                     ` Daiki Ueno
  2006-04-05 10:18                                                                       ` Sascha Wilde
  2006-04-05 16:14                                                                     ` pgg-gpg broken? Reiner Steib
  1 sibling, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-04-05  9:42 UTC (permalink / raw)
  Cc: Simon Josefsson, ding, emacs-devel

>>>>> In <m2k6a4z8or.fsf_-_@kenny.sha-bang.de> 
>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> I just needed to decrypt an old Mail using Gnus/pgg (which i decrypted
> successfully many times before), but it failed.

> This is the backtrace I get:

> Debugger entered--Lisp error: (error "Process pgg-gpg not running")
>   process-send-string(#<process pgg-gpg> "DerDenkendeWeissEs\n")
>   pgg-gpg-status-GET_HIDDEN(#<process pgg-gpg> "GET_HIDDEN
>   passphrase.enter")
>   pgg-gpg-process-filter(#<process pgg-gpg> "[GNUPG:] USERID_HINT
>   31A16202F8F7E674 Sascha Wilde <Sascha.Wilde@intevation.de>\n[GNUPG:]
>   NEED_PASSPHRASE 31A16202F8F7E674 BB2185144BB86568 16 0\n[GNUPG:]
>   GET_HIDDEN passphrase.enter\n[GNUPG:] GOT_IT\n[GNUPG:]
>   BAD_PASSPHRASE 31A16202F8F7E674\ngpg: Invalid passphrase; please try
>   again ...\n[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde

> Might this be related to the latest changes by Daiki?

The problem might be related to the default-enable-multibyte-characters
issue:
http://article.gmane.org/gmane.emacs.gnus.general/62428
if you are using non-ASCII characters in your passphrase.

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-05  9:42                                                                     ` Daiki Ueno
@ 2006-04-05 10:18                                                                       ` Sascha Wilde
  2006-04-05 21:33                                                                         ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-04-05 10:18 UTC (permalink / raw)
  Cc: Simon Josefsson, ding, emacs-devel

Daiki Ueno <ueno@unixuser.org> wrote:

>>>>>> In <m2k6a4z8or.fsf_-_@kenny.sha-bang.de> 
>>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
>> I just needed to decrypt an old Mail using Gnus/pgg (which i decrypted
>> successfully many times before), but it failed.
>
>> This is the backtrace I get:
>
>> Debugger entered--Lisp error: (error "Process pgg-gpg not running")
>>   process-send-string(#<process pgg-gpg> "DerDenkendeWeissEs\n")
>>   pgg-gpg-status-GET_HIDDEN(#<process pgg-gpg> "GET_HIDDEN
>>   passphrase.enter")
>>   pgg-gpg-process-filter(#<process pgg-gpg> "[GNUPG:] USERID_HINT
>>   31A16202F8F7E674 Sascha Wilde <Sascha.Wilde@intevation.de>\n[GNUPG:]
>>   NEED_PASSPHRASE 31A16202F8F7E674 BB2185144BB86568 16 0\n[GNUPG:]
>>   GET_HIDDEN passphrase.enter\n[GNUPG:] GOT_IT\n[GNUPG:]
>>   BAD_PASSPHRASE 31A16202F8F7E674\ngpg: Invalid passphrase; please try
>>   again ...\n[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde
>
>> Might this be related to the latest changes by Daiki?
>
> The problem might be related to the default-enable-multibyte-characters
> issue:
> http://article.gmane.org/gmane.emacs.gnus.general/62428
> if you are using non-ASCII characters in your passphrase.

No, only plain ASCII.

sascha
-- 
Sascha Wilde : "Ist es nicht schon schlimm genug, dass ICH hier rumtrolle?"
             : (Henning Leise in d.o.c.)

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-05  9:13                                                                   ` pgg-gpg broken? Sascha Wilde
  2006-04-05  9:42                                                                     ` Daiki Ueno
@ 2006-04-05 16:14                                                                     ` Reiner Steib
  2006-04-05 19:22                                                                       ` Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Reiner Steib @ 2006-04-05 16:14 UTC (permalink / raw)
  Cc: Daiki Ueno, emacs-devel, ding, Simon Josefsson

On Wed, Apr 05 2006, Sascha Wilde wrote:

> I just needed to decrypt an old Mail using Gnus/pgg (which i decrypted
> successfully many times before), but it failed.
[...]
> Signing mails works (including querying the passphrase).
>
> Might this be related to the latest changes by Daiki?

Could you test with `pgg-gpg.el' revision 1.4 from Emacs CVS or
revision 7.11 from Gnus CVS, please?

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-05 16:14                                                                     ` pgg-gpg broken? Reiner Steib
@ 2006-04-05 19:22                                                                       ` Sascha Wilde
  0 siblings, 0 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-04-05 19:22 UTC (permalink / raw)
  Cc: emacs-devel, ding, Simon Josefsson

Reiner Steib <reinersteib+gmane@imap.cc> wrote:

> On Wed, Apr 05 2006, Sascha Wilde wrote:
>
>> I just needed to decrypt an old Mail using Gnus/pgg (which i decrypted
>> successfully many times before), but it failed.
> [...]
>> Signing mails works (including querying the passphrase).
>>
>> Might this be related to the latest changes by Daiki?
>
> Could you test with `pgg-gpg.el' revision 1.4 from Emacs CVS or
> revision 7.11 from Gnus CVS, please?

I fetched 1.4 from Emacs CVS and it works perfectly well with the mail
in question.

Same holds true for 1.8 from Emacs CVS, which includes my original
version of gpg-agent support, but it stops working with 1.9 -- so it
seems the problem lies withing Daiki's new code...

Some more revelations regarding the problem:

It is somewhat more specific: while I can't decrypt the old mail with
the current pgg-gpg code, I actually can decrypt an fresh test Mail,
which I just send to myself for testing.  This matches my observations
about the different versions.  I have no idea whats so special about
this one mail (it's encrypted for more than one key, but this is no
problem in other cases...).

cheers
sascha
-- 
Sascha Wilde : xedit? Das sieht zwar wie vi aus als könne es nix, aber im
             : Gegensatz zu vi kann es wirklich nix und nix ist noch geschönt!
             : (Michael Core in dafc)

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-05 10:18                                                                       ` Sascha Wilde
@ 2006-04-05 21:33                                                                         ` Daiki Ueno
  2006-04-06  9:00                                                                           ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-04-05 21:33 UTC (permalink / raw)
  Cc: Simon Josefsson, ding, emacs-devel

>>>>> In <m2zmj0xr4x.fsf@kenny.sha-bang.de> 
>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> Daiki Ueno <ueno@unixuser.org> wrote:

> >>>>>> In <m2k6a4z8or.fsf_-_@kenny.sha-bang.de> 
> >>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> >> I just needed to decrypt an old Mail using Gnus/pgg (which i decrypted
> >> successfully many times before), but it failed.
> >
> >> This is the backtrace I get:
> >
> >> Debugger entered--Lisp error: (error "Process pgg-gpg not running")
> >>   process-send-string(#<process pgg-gpg> "DerDenkendeWeissEs\n")
> >>   pgg-gpg-status-GET_HIDDEN(#<process pgg-gpg> "GET_HIDDEN
> >>   passphrase.enter")
> >>   BAD_PASSPHRASE 31A16202F8F7E674\ngpg: Invalid passphrase; please try
> >>   again ...\n[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde
> >
> >> Might this be related to the latest changes by Daiki?
> >
> > The problem might be related to the default-enable-multibyte-characters
> > issue:
> > http://article.gmane.org/gmane.emacs.gnus.general/62428
> > if you are using non-ASCII characters in your passphrase.

> No, only plain ASCII.

Two more questions:

1. The passphrase you entered was correct?
2. How many times were you queried your passphrase?

A straightforward way to investigate this problem is decrypting the mail
from the command line as pgg-gpg does.  Could you try the following?

$ cat input.txt | gpg --no-tty --status-fd 1 --command-fd 0 --yes \
  --output output.txt --decrypt

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-05 21:33                                                                         ` Daiki Ueno
@ 2006-04-06  9:00                                                                           ` Sascha Wilde
  2006-04-06  9:21                                                                             ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-04-06  9:00 UTC (permalink / raw)
  Cc: emacs-devel, ding, Simon Josefsson

Daiki Ueno <ueno@unixuser.org> wrote:

>>>>>> In <m2zmj0xr4x.fsf@kenny.sha-bang.de> 
>>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
>> Daiki Ueno <ueno@unixuser.org> wrote:
>
>> >>>>>> In <m2k6a4z8or.fsf_-_@kenny.sha-bang.de> 
>> >>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
>> >> I just needed to decrypt an old Mail using Gnus/pgg (which i decrypted
>> >> successfully many times before), but it failed.
>> >
>> >> This is the backtrace I get:
>> >
>> >> Debugger entered--Lisp error: (error "Process pgg-gpg not running")
>> >>   process-send-string(#<process pgg-gpg> "DerDenkendeWeissEs\n")
>> >>   pgg-gpg-status-GET_HIDDEN(#<process pgg-gpg> "GET_HIDDEN
>> >>   passphrase.enter")
>> >>   BAD_PASSPHRASE 31A16202F8F7E674\ngpg: Invalid passphrase; please try
>> >>   again ...\n[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde
>> >
>> >> Might this be related to the latest changes by Daiki?
>> >
>> > The problem might be related to the default-enable-multibyte-characters
>> > issue:
>> > http://article.gmane.org/gmane.emacs.gnus.general/62428
>> > if you are using non-ASCII characters in your passphrase.
>
>> No, only plain ASCII.
>
> Two more questions:
>
> 1. The passphrase you entered was correct?

Yes.  I tried this _many_ times, and only this mail fails (and only
with your new code).

> 2. How many times were you queried your passphrase?

Once.  If the passphrase is already cached (I'm _not_ using the agent
on this system): none.  I also encountered the situation of getting
asked over and over again, but I can't reproduce that...

> A straightforward way to investigate this problem is decrypting the mail
> from the command line as pgg-gpg does.  Could you try the following?
>
> $ cat input.txt | gpg --no-tty --status-fd 1 --command-fd 0 --yes \
>   --output output.txt --decrypt

This doesn't work (it tries to read the passphrase from the pipe, too.
But this works:

gpg --no-tty --status-fd 1 --command-fd 0 --yes \ 
  --output output.txt --decrypt test.msg

Here is the Output:

[GNUPG:] ENC_TO 31A16202F8F7E674 16 0
[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde
<Sascha.Wilde@intevation.de>
[GNUPG:] NEED_PASSPHRASE 31A16202F8F7E674 BB2185144BB86568 16 0
[GNUPG:] GET_HIDDEN passphrase.enter
***********************
[GNUPG:] GOT_IT
[GNUPG:] GOOD_PASSPHRASE
[GNUPG:] ENC_TO **************** 16 0
gpg: encrypted with 1024-bit ELG-E key, ID C42134DD, created
2003-06-24
      "******** **** <*******@intevation.de>"
[GNUPG:] NO_SECKEY ****************
gpg: encrypted with 2048-bit ELG-E key, ID F8F7E674, created
2004-11-15
      "Sascha Wilde <Sascha.Wilde@intevation.de>"
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] PLAINTEXT 74 1143202578 mutt-eukrante-10004-12773-1220
gpg: Signature made Fre 24 Mr 2006 13:16:19 CET using DSA key ID
********
[GNUPG:] SIG_ID AfiFfg5+XNFF741BR7ts3MOF6ds 2006-03-24 1143202579
[GNUPG:] GOODSIG **************** ******** ****
<******@intevation.de>
gpg: Good signature from "******** **** <*******@intevation.de>"
gpg:                 aka "******** **** ***** <*******.********@intevation.de>"
[GNUPG:] VALIDSIG 53D27A45B9AD27915EE44EDE5BB3F5195816791A 2006-03-24
1143202579 0 3 0 17 2 01 53D27A45B9AD27915EE44EDE5BB3F5195816791A
[GNUPG:] TRUST_FULLY
[GNUPG:] DECRYPTION_OKAY
[GNUPG:] GOODMDC
[GNUPG:] END_DECRYPTION

As you can see: everything worked well...
BUT, doing more tests, things became more and more strange:

I tried 

gpg --no-tty --status-fd 1 --command-fd 0 --yes \ 
  --output output.txt --decrypt

And pasted in the message using copy and paste, then I got this error:

gpg: CRC error; 6E24DE - 15B95A
[GNUPG:] END_DECRYPTION

So I set pgg-gpg-debug to t and found the same error.

Even more strange, when using the gpg-agent

gpg --no-tty --status-fd 1 --command-fd 0 --yes \
  --output output.txt --decrypt <test.msg

works fine, while decryption using the agent + pgg-gpg just hangs...

cheers
sascha
-- 
Sascha Wilde : "Der Nicht-Denkende glaubt, dass niemand denkt,
             : der Denkende weiss es!"
             : (Gabriel Laub)

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-06  9:00                                                                           ` Sascha Wilde
@ 2006-04-06  9:21                                                                             ` Daiki Ueno
  2006-04-06  9:58                                                                               ` Sascha Wilde
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-04-06  9:21 UTC (permalink / raw)
  Cc: Simon Josefsson, ding, emacs-devel

>>>>> In <m21wwbcc46.fsf@kenny.sha-bang.de> 
>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> > A straightforward way to investigate this problem is decrypting the mail
> > from the command line as pgg-gpg does.  Could you try the following?
> >
> > $ cat input.txt | gpg --no-tty --status-fd 1 --command-fd 0 --yes \
> >   --output output.txt --decrypt

> This doesn't work (it tries to read the passphrase from the pipe, too.

As I said in the private mail, this is because the pipe is closed after
cat exits.  Could you try this one and see if gpg waits after "[GNUPG:]
GET_HIDDEN passphrase.enter"?

$ (cat test.msg; sleep 10) | gpg --no-tty --status-fd 1 --command-fd 0 --yes \
  --output output.txt --decrypt

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-06  9:21                                                                             ` Daiki Ueno
@ 2006-04-06  9:58                                                                               ` Sascha Wilde
  2006-04-06 10:13                                                                                 ` Daiki Ueno
  2006-04-07 10:32                                                                                 ` gpg-agent support removed?! (was: pgg-gpg broken?) Sascha Wilde
  0 siblings, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-04-06  9:58 UTC (permalink / raw)
  Cc: Simon Josefsson, ding, emacs-devel

Daiki Ueno <ueno@unixuser.org> wrote:

>>>>>> In <m21wwbcc46.fsf@kenny.sha-bang.de> 
>>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
>> > A straightforward way to investigate this problem is decrypting the mail
>> > from the command line as pgg-gpg does.  Could you try the following?
>> >
>> > $ cat input.txt | gpg --no-tty --status-fd 1 --command-fd 0 --yes \
>> >   --output output.txt --decrypt
>
>> This doesn't work (it tries to read the passphrase from the pipe, too.
>
> As I said in the private mail, this is because the pipe is closed after
> cat exits.  Could you try this one and see if gpg waits after "[GNUPG:]
> GET_HIDDEN passphrase.enter"?
>
> $ (cat test.msg; sleep 10) | gpg --no-tty --status-fd 1 --command-fd 0 --yes \
>   --output output.txt --decrypt

No, it doesn't -- here is what happens 
(thomas agreed with posting this information, so no more '*'s):

(cat test.msg; sleep 10) | gpg --no-tty --status-fd 1 --command-fd 0 --yes \
  --output output.txt --decrypt
[GNUPG:] ENC_TO 31A16202F8F7E674 16 0
[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde <Sascha.Wilde@intevation.de>
[GNUPG:] NEED_PASSPHRASE 31A16202F8F7E674 BB2185144BB86568 16 0
[GNUPG:] GET_HIDDEN passphrase.enter
[GNUPG:] GOT_IT
[GNUPG:] BAD_PASSPHRASE 31A16202F8F7E674
gpg: Invalid passphrase; please try again ...
[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde <Sascha.Wilde@intevation.de>
[GNUPG:] NEED_PASSPHRASE 31A16202F8F7E674 BB2185144BB86568 16 0
[GNUPG:] GET_HIDDEN passphrase.enter
[GNUPG:] GOT_IT
[GNUPG:] BAD_PASSPHRASE 31A16202F8F7E674
gpg: Invalid passphrase; please try again ...
[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde <Sascha.Wilde@intevation.de>
[GNUPG:] NEED_PASSPHRASE 31A16202F8F7E674 BB2185144BB86568 16 0
[GNUPG:] GET_HIDDEN passphrase.enter
[GNUPG:] GOT_IT
[GNUPG:] BAD_PASSPHRASE 31A16202F8F7E674
[GNUPG:] ENC_TO 8699BF5FC42134DD 16 0
gpg: encrypted with 1024-bit ELG-E key, ID C42134DD, created 2003-06-24
      "Thomas Arendsen Hein <thomas@intevation.de>"
[GNUPG:] NO_SECKEY 8699BF5FC42134DD
gpg: encrypted with 2048-bit ELG-E key, ID F8F7E674, created 2004-11-15
      "Sascha Wilde <Sascha.Wilde@intevation.de>"
gpg: public key decryption failed: bad passphrase
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] DECRYPTION_FAILED
gpg: decryption failed: secret key not available
gpg: CRC error; 474D93 - 15B95A
[GNUPG:] END_DECRYPTION

is seems that gpg detects the end early and uses the rest of the
message as passphrase, which of cause fails...

So either the PGP Message is malformed, or that there is a
bug in gpg.

In either case, I don't understand why 

gpg --no-tty --status-fd 1 --command-fd 0 --yes \ 
  --output output.txt --decrypt test.msg

works without any error:

[GNUPG:] ENC_TO 31A16202F8F7E674 16 0   
[GNUPG:] USERID_HINT 31A16202F8F7E674 Sascha Wilde <Sascha.Wilde@intevation.de>
[GNUPG:] NEED_PASSPHRASE 31A16202F8F7E674 BB2185144BB86568 16 0
[GNUPG:] GET_HIDDEN passphrase.enter
*************************
[GNUPG:] GOT_IT
[GNUPG:] GOOD_PASSPHRASE
[GNUPG:] ENC_TO 8699BF5FC42134DD 16 0
gpg: encrypted with 1024-bit ELG-E key, ID C42134DD, created 2003-06-24
      "Thomas Arendsen Hein <thomas@intevation.de>"
[GNUPG:] NO_SECKEY 8699BF5FC42134DD
gpg: encrypted with 2048-bit ELG-E key, ID F8F7E674, created 2004-11-15
      "Sascha Wilde <Sascha.Wilde@intevation.de>"
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] PLAINTEXT 74 1143202578 mutt-eukrante-10004-12773-1220
gpg: Signature made Fre 24 Mr 2006 13:16:19 CET using DSA key ID 5816791A
[GNUPG:] SIG_ID AfiFfg5+XNFF741BR7ts3MOF6ds 2006-03-24 1143202579
[GNUPG:] GOODSIG 5BB3F5195816791A Thomas Arendsen Hein <thomas@intevation.de>
gpg: Good signature from "Thomas Arendsen Hein <thomas@intevation.de>"
gpg:                 aka "Thomas Arendsen Hein (private) <thomas@jtah.de>"
gpg:                 aka "Thomas Arendsen Hein <Thomas.Arendsen.Hein@intevation.   de>"
[GNUPG:] VALIDSIG 53D27A45B9AD27915EE44EDE5BB3F5195816791A 2006-03-24 1143202579    0 3 0 17 2 01 53D27A45B9AD27915EE44EDE5BB3F5195816791A
[GNUPG:] TRUST_FULLY
[GNUPG:] DECRYPTION_OKAY
[GNUPG:] GOODMDC
[GNUPG:] END_DECRYPTION

cheers
-- 
Sascha Wilde

A conclusion is simply the place where someone got tired of thinking.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: pgg-gpg broken?
  2006-04-06  9:58                                                                               ` Sascha Wilde
@ 2006-04-06 10:13                                                                                 ` Daiki Ueno
  2006-04-07 10:32                                                                                 ` gpg-agent support removed?! (was: pgg-gpg broken?) Sascha Wilde
  1 sibling, 0 replies; 156+ messages in thread
From: Daiki Ueno @ 2006-04-06 10:13 UTC (permalink / raw)
  Cc: emacs-devel, ding, Simon Josefsson

>>>>> In <m2y7yjdo02.fsf@kenny.sha-bang.de> 
>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> Daiki Ueno <ueno@unixuser.org> wrote:

> > As I said in the private mail, this is because the pipe is closed after
> > cat exits.  Could you try this one and see if gpg waits after "[GNUPG:]
> > GET_HIDDEN passphrase.enter"?
> >
> > $ (cat test.msg; sleep 10) | gpg --no-tty --status-fd 1 --command-fd 0 --yes \
> >   --output output.txt --decrypt

> No, it doesn't -- here is what happens 

> is seems that gpg detects the end early and uses the rest of the
> message as passphrase, which of cause fails...

If you have pgpdump installed, you will see what packets are read from
the message.

Anyway, I'll try to change pgg-gpg-decrypt-region to read a PGP message
from a temporary file.  Thanks for testing!

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* gpg-agent support removed?! (was: pgg-gpg broken?)
  2006-04-06  9:58                                                                               ` Sascha Wilde
  2006-04-06 10:13                                                                                 ` Daiki Ueno
@ 2006-04-07 10:32                                                                                 ` Sascha Wilde
  2006-04-07 12:11                                                                                   ` Simon Josefsson
                                                                                                     ` (2 more replies)
  1 sibling, 3 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-04-07 10:32 UTC (permalink / raw)
  Cc: Daiki Ueno, emacs-devel, Reiner Steib, ding, Simon Josefsson

Hi *,

after noticing, that the broken mail con suddenly be decrypted again I
checked the changelog and found this entry:

  2006-04-06  Romain Francoise  <romain@orebokech.com>

         * pgg-gpg.el: Sync back with Gnus 5.10, reverting changes that add
         symmetric encryption features and a new asynchronous interface to
         GnuPG.  This new version is version 1.4, plus whitespace changes.

why was that done?!  And why was it done without any discussion or
even informing the people involved?!?

sascha
-- 
Sascha Wilde  :  "I heard that if you play the Windows CD backward, you
              :  get a satanic message. But that's nothing compared to
              :  when you play it forward: It installs Windows...." 
              :  -- G. R. Gaudreau

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?! (was: pgg-gpg broken?)
  2006-04-07 10:32                                                                                 ` gpg-agent support removed?! (was: pgg-gpg broken?) Sascha Wilde
@ 2006-04-07 12:11                                                                                   ` Simon Josefsson
  2006-04-07 12:14                                                                                   ` gpg-agent support removed?! Romain Francoise
  2006-04-07 12:35                                                                                   ` Reiner Steib
  2 siblings, 0 replies; 156+ messages in thread
From: Simon Josefsson @ 2006-04-07 12:11 UTC (permalink / raw)
  Cc: Daiki Ueno, romain, Reiner Steib, ding, emacs-devel

> Hi *,
>
> after noticing, that the broken mail con suddenly be decrypted again I
> checked the changelog and found this entry:
>
>   2006-04-06  Romain Francoise  <romain@orebokech.com>
>
>          * pgg-gpg.el: Sync back with Gnus 5.10, reverting changes that
> add
>          symmetric encryption features and a new asynchronous interface to
>          GnuPG.  This new version is version 1.4, plus whitespace changes.
>
> why was that done?!  And why was it done without any discussion or
> even informing the people involved?!?

I thought all discussions about this were kept on the mailing list?  Maybe
check the ding list, perhaps emacs-devel was removed at some point.

I think we decided to back out Daiki's asynchronous interface, because it
is too much new code and we need to have people use it for a while and
work out the problems (on the Gnus CVS trunk).  Perhaps Romain backed out
more than that?  I think we should revert to the pgg-gpg.el right before
adding Daiki's partial rewrite.  The symmetric stuff, and the more recent
addition of the pgg-gpg-use-agent variable should be fine.

I don't have a workable internet connection, and I'm going away on holiday
tomorrow, so I hope others can help work out the details, or wait 10 days.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 10:32                                                                                 ` gpg-agent support removed?! (was: pgg-gpg broken?) Sascha Wilde
  2006-04-07 12:11                                                                                   ` Simon Josefsson
@ 2006-04-07 12:14                                                                                   ` Romain Francoise
  2006-04-07 13:00                                                                                     ` Sascha Wilde
  2006-04-07 12:35                                                                                   ` Reiner Steib
  2 siblings, 1 reply; 156+ messages in thread
From: Romain Francoise @ 2006-04-07 12:14 UTC (permalink / raw)
  Cc: Daiki Ueno, emacs-devel, Reiner Steib, ding, Simon Josefsson

Sascha Wilde <wilde@sha-bang.de> writes:

> And why was it done without any discussion or even informing the
> people involved?!?

Since PGG is historically a Gnus package, it was discussed on the ding
mailing-list, which you obviously don't read...  :-)

The relevant sub-thread starts here:

  <URL: http://article.gmane.org/gmane.emacs.gnus.general/62545>

The reasons why this was done are:

1) The new code has bugs and is a major rewrite from previous versions;
   it isn't yet very stable, at least not enough for a stable Gnus
   release.

2) A new Gnus v5.10 release is due out this week-end, so there wasn't
   enough time to fix the bugs in the new code, hence the decision to
   revert it in Gnus 5.10.  Since Emacs 22 is supposed to have Gnus
   5.10, I reverted the changes in Emacs CVS in order to keep the
   upcoming Gnus release and Emacs in sync.

3) The changes broke allout.el's encryption features, and require a
   transition to ensure that allout and PGG can work correctly together
   without breakage.

4) We're trying to get Emacs to a releasable state, and introducing new
   features right now might not be the best idea, depending on how
   seriously you take the feature freeze.

At the moment, the plan is to let the new code mature in the Gnus trunk
(not the Emacs trunk), and then sync it back in Gnus' v5-10 branch and
the Emacs trunk once things have settled down.  I realize that part of
the problem is that PGG is maintained as a Gnus package in Gnus, and as
a general-purpose package in Emacs...

Hoping this clarifies the situation,

-- 
Romain Francoise <romain@orebokech.com> | The sea! the sea! the open
it's a miracle -- http://orebokech.com/ | sea! The blue, the fresh, the
                                        | ever free! --Bryan W. Procter

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 10:32                                                                                 ` gpg-agent support removed?! (was: pgg-gpg broken?) Sascha Wilde
  2006-04-07 12:11                                                                                   ` Simon Josefsson
  2006-04-07 12:14                                                                                   ` gpg-agent support removed?! Romain Francoise
@ 2006-04-07 12:35                                                                                   ` Reiner Steib
  2006-04-07 13:02                                                                                     ` Daiki Ueno
  2006-04-07 21:36                                                                                     ` Richard Stallman
  2 siblings, 2 replies; 156+ messages in thread
From: Reiner Steib @ 2006-04-07 12:35 UTC (permalink / raw)
  Cc: Simon Josefsson, Daiki Ueno, romain, ding, emacs-devel

On Fri, Apr 07 2006, Sascha Wilde wrote:

>   2006-04-06  Romain Francoise  <romain@orebokech.com>
>
>          * pgg-gpg.el: Sync back with Gnus 5.10, reverting changes that add
>          symmetric encryption features and a new asynchronous interface to
>          GnuPG.  This new version is version 1.4, plus whitespace changes.
>
> why was that done?!  And why was it done without any discussion or
> even informing the people involved?!?

Let me try to summarize (CMIIW):

There were several unresolved serious problems¹ (including your
report) with the new code.  So for the upcoming release of Gnus 5.10.8
we (Simon and me) agreed to revert `pgg-gpg.el' in the stable Gnus
branch (v5-10).

Simon's advised on keeping the new code in the Gnus trunk, so I
followed his suggestion.  I didn't have a strong option on what is
best for the version² in Emacs CVS, so I didn't touch it.  IIRC Simon
didn't express an opinion concerning this version neither.  Probably
Romain thought that the problems with the new code are too serious
also for Emacs CVS.

After the Gnus 5.10.8 release (which should be this week-end unless
Lars needs to shift it) we can put the new code plus Daiki's fixes
posted today back in all three branches.

Bye, Reiner.

¹ Unresolved serious problems with the new code in `pgg-gpg.el':
  http://article.gmane.org/gmane.emacs.pretest.bugs/11591
  http://article.gmane.org/gmane.emacs.devel/52450
  http://article.gmane.org/gmane.emacs.gnus.general/62567
  
  Maybe more?  I don't remember exactly.

² Normally the version in Emacs CVS and Gnus stable (v5-10) are and
  should be synched (semi-)automatically by Miles Bader.  Because of
  the upcoming stable Gnus release, I asked Miles suspend it until
  Gnus 5.10.8 is released.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 12:14                                                                                   ` gpg-agent support removed?! Romain Francoise
@ 2006-04-07 13:00                                                                                     ` Sascha Wilde
  2006-04-07 13:30                                                                                       ` Simon Josefsson
  2006-04-08  9:36                                                                                       ` Romain Francoise
  0 siblings, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-04-07 13:00 UTC (permalink / raw)
  Cc: Daiki Ueno, emacs-devel, Reiner Steib, ding, Simon Josefsson

Romain Francoise <romain@orebokech.com> wrote:

> Sascha Wilde <wilde@sha-bang.de> writes:
>
>> And why was it done without any discussion or even informing the
>> people involved?!?
>
> Since PGG is historically a Gnus package, it was discussed on the ding
> mailing-list, which you obviously don't read...  :-)

That's true, so please CC me at any response.
(at least if it doesn't go too emacs-devel, too).

Thanks to everybody for summarizing the discussion.

May I suggest to revert the code to version 1.8 from GNU Emacs CVS instead?

This version includes my original agent support code and Reiners small
compatibility fix.

I would prefer this version because it:  
- allow using the agent
- but only if enabled explicitly by the user, so the default behavior
  is completely unchanged compared to the old code
- introduces only very few code changes, with no known bugs
- has none of the problems of Daikis code regarding robustness 
  or api changes 

IIRC this version was already discussed and accepted for 5.10.

cheers
sascha
-- 
Sascha Wilde
Well, *my* brain likes to think it's vastly more powerful than any
finite Turing machine but it hasn't proven that to me...
  -- Christopher Koppler in comp.lang.lisp

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 12:35                                                                                   ` Reiner Steib
@ 2006-04-07 13:02                                                                                     ` Daiki Ueno
  2006-04-07 13:08                                                                                       ` Sascha Wilde
  2006-04-07 14:05                                                                                       ` Thomas Baumann
  2006-04-07 21:36                                                                                     ` Richard Stallman
  1 sibling, 2 replies; 156+ messages in thread
From: Daiki Ueno @ 2006-04-07 13:02 UTC (permalink / raw)
  Cc: Sascha Wilde, Simon Josefsson, romain, ding, emacs-devel

>>>>> In <v9lkuhd0mv.fsf@marauder.physik.uni-ulm.de> 
>>>>>	Reiner Steib <reinersteib+gmane@imap.cc> wrote:
> ¹ Unresolved serious problems with the new code in `pgg-gpg.el':
>   http://article.gmane.org/gmane.emacs.pretest.bugs/11591

Sorry, I didn't read emacs-pretest-bug.  Thomas, could you tell me what
happened more precisely?  i.e. (setq debug-on-error t) and (setq
pgg-gpg-debug t)

>   http://article.gmane.org/gmane.emacs.devel/52450

I think this is fixed by the patch I posted some time ago.
http://article.gmane.org/gmane.emacs.gnus.general/62571

>   http://article.gmane.org/gmane.emacs.gnus.general/62567

I hope that this should be fixed in the right way, not in the way such
as just reversion.  So to say, this is a bug of *allout.el* and not of
PGG, I think.

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 13:02                                                                                     ` Daiki Ueno
@ 2006-04-07 13:08                                                                                       ` Sascha Wilde
  2006-04-07 13:26                                                                                         ` Daiki Ueno
  2006-04-07 13:40                                                                                         ` Reiner Steib
  2006-04-07 14:05                                                                                       ` Thomas Baumann
  1 sibling, 2 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-04-07 13:08 UTC (permalink / raw)
  Cc: Reiner Steib, Thomas Baumann, romain, emacs-devel, ding,
	Simon Josefsson

Daiki Ueno <ueno@unixuser.org> wrote:

>>>>>> In <v9lkuhd0mv.fsf@marauder.physik.uni-ulm.de> 
>>>>>>	Reiner Steib <reinersteib+gmane@imap.cc> wrote:

>>   http://article.gmane.org/gmane.emacs.devel/52450
>
> I think this is fixed by the patch I posted some time ago.
> http://article.gmane.org/gmane.emacs.gnus.general/62571

This sounds interesting -- where can I get this version for testing?

-- 
Sascha Wilde
We're Germans and we use Unix. That's a combination of two 
demographic groups known to have no sense of humour whatsoever.
  -- Hanno Mueller in de.comp.os.unix.programming



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 13:08                                                                                       ` Sascha Wilde
@ 2006-04-07 13:26                                                                                         ` Daiki Ueno
  2006-04-09 16:04                                                                                           ` Sascha Wilde
  2006-04-07 13:40                                                                                         ` Reiner Steib
  1 sibling, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-04-07 13:26 UTC (permalink / raw)
  Cc: Reiner Steib, Thomas Baumann, romain, emacs-devel, ding,
	Simon Josefsson

>>>>> In <m2lkuhcz2y.fsf@kenny.sha-bang.de> 
>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
> >>   http://article.gmane.org/gmane.emacs.devel/52450
> >
> > I think this is fixed by the patch I posted some time ago.
> > http://article.gmane.org/gmane.emacs.gnus.general/62571

> This sounds interesting -- where can I get this version for testing?

I put the tarball which contains the current pgg*.el at

http://www.unixuser.org/~ueno/pgg-20060407.tar.gz

Regards,
-- 
Daiki Ueno



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 13:00                                                                                     ` Sascha Wilde
@ 2006-04-07 13:30                                                                                       ` Simon Josefsson
  2006-04-07 20:59                                                                                         ` Reiner Steib
  2006-04-08  9:36                                                                                       ` Romain Francoise
  1 sibling, 1 reply; 156+ messages in thread
From: Simon Josefsson @ 2006-04-07 13:30 UTC (permalink / raw)
  Cc: Daiki Ueno, Romain Francoise, Reiner Steib, ding, emacs-devel

> May I suggest to revert the code to version 1.8 from GNU Emacs CVS
> instead?
>
> This version includes my original agent support code and Reiners small
> compatibility fix.
>
> I would prefer this version because it:
> - allow using the agent
> - but only if enabled explicitly by the user, so the default behavior
>   is completely unchanged compared to the old code
> - introduces only very few code changes, with no known bugs
> - has none of the problems of Daikis code regarding robustness
>   or api changes
>
> IIRC this version was already discussed and accepted for 5.10.

I agree, we shouldn't revert more than Daiki's asynchronous stuff in
v5-10/Emacs CVS.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 13:08                                                                                       ` Sascha Wilde
  2006-04-07 13:26                                                                                         ` Daiki Ueno
@ 2006-04-07 13:40                                                                                         ` Reiner Steib
  1 sibling, 0 replies; 156+ messages in thread
From: Reiner Steib @ 2006-04-07 13:40 UTC (permalink / raw)
  Cc: Daiki Ueno, ding, emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 1115 bytes --]

[ Reducing Cc list ]

On Fri, Apr 07 2006, Sascha Wilde wrote:

> Daiki Ueno <ueno@unixuser.org> wrote:
>
>>>>>>> In <v9lkuhd0mv.fsf@marauder.physik.uni-ulm.de> 
>>>>>>>	Reiner Steib <reinersteib+gmane@imap.cc> wrote:
>
>>>   http://article.gmane.org/gmane.emacs.devel/52450
>>
>> I think this is fixed by the patch I posted some time ago.
>> http://article.gmane.org/gmane.emacs.gnus.general/62571

,----
| RCS file: /usr/local/cvsroot/gnus/lisp/pgg-gpg.el,v
| retrieving revision 7.22
| diff -u -r7.22 pgg-gpg.el
| --- lisp/pgg-gpg.el	5 Apr 2006 12:57:22 -0000	7.22
| +++ lisp/pgg-gpg.el	7 Apr 2006 08:07:26 -0000
`----

So this is a patch against the Gnus trunk (revision 7.22)

> This sounds interesting -- where can I get this version for testing?

$ cvs -d :pserver:gnus@cvs.gnus.org:/usr/local/cvsroot login
CVS password: gnus
$ cvs -d :pserver:gnus@cvs.gnus.org:/usr/local/cvsroot checkout gnus/lisp/pgg-gpg.el

(cf. http://www.gnus.org/distribution.html)

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

[-- Attachment #1.2: Type: application/pgp-signature, Size: 188 bytes --]

[-- Attachment #2: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 13:02                                                                                     ` Daiki Ueno
  2006-04-07 13:08                                                                                       ` Sascha Wilde
@ 2006-04-07 14:05                                                                                       ` Thomas Baumann
  2006-04-07 14:40                                                                                         ` Daiki Ueno
  1 sibling, 1 reply; 156+ messages in thread
From: Thomas Baumann @ 2006-04-07 14:05 UTC (permalink / raw)
  Cc: Reiner Steib, Sascha Wilde, romain, emacs-devel, ding,
	Simon Josefsson

GNU Emacs 22.0.50.1 (i686-suse-linux-gnu, X toolkit, Xaw3d scroll bars)
of 2006-04-05 on norvel

gpg (GnuPG) 1.4.2


Description:

I write an email to be signed.
From: Thomas Baumann <thomas.baumann@ch.tum.de>
To: tb
cc: 
Subject: sign
X-Mailer: MH-E 7.93+cvs; nmh 1.2; GNU Emacs 22.0.50.1
Reply-To: thomas.baumann@ch.tum.de
--------
<#secure method=pgpmime mode=sign sender=AE757F32>
Test

after C-cC-c emacs waits for something endlessly....

backtrace

Debugger entered--Lisp error: (quit)
  accept-process-output(#<process pgg-gpg<4>> 1)
  pgg-gpg-wait-for-status(#<process pgg-gpg<4>> ("BEGIN_SIGNING"))
  pgg-gpg-sign-region(1 7 nil nil)
  funcall(pgg-gpg-sign-region 1 7 nil nil)
  apply(funcall pgg-gpg-sign-region (1 7 nil nil))
  pgg-invoke("sign-region" gpg 1 7 nil nil)
  pgg-sign-region(1 7)
  mml2015-pgg-sign((part (sign . "pgpmime") (sender . "AE757F32") (tag-location . 173) (contents . "Test\n")))
  mml2015-sign((part (sign . "pgpmime") (sender . "AE757F32") (tag-location . 173) (contents . "Test\n")))
  mml-pgpmime-sign-buffer((part (sign . "pgpmime") (sender . "AE757F32") (tag-location . 173) (contents . "Test\n")))
  mml-generate-mime-1((part (sign . "pgpmime") (sender . "AE757F32") (tag-location . 173) (contents . "Test\n")))
  mml-generate-mime()
  message-encode-message-body()
  mml-to-mime()
  (condition-case err (mml-to-mime) (error (with-current-buffer buffer ... ... ...) (error ...)))
  (let ((saved-text ...) (buffer ...) (modified-flag ...)) (condition-case err (mml-to-mime) (error ... ...)))
  mh-mml-to-mime()
  mh-send-letter(nil)
  call-interactively(mh-send-letter)


Things are ok if I the following version of pgg-gpg.el

-rw-r--r--   1 tb users  13819 Feb 10 07:33 pgg-gpg.el


With todays cvs signing does work, but checking the signatures won't
work any more. 

open an email with signature
[mouse-1] on [[PGP Signed Part:Undecided]]

= everything between [[PGP Signed Part:Undecided]] and [[End of PGP
Signed Part]] disappears and there is no change to the buttons....

again this works with pgg-gpg from February...

Thomas



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 14:05                                                                                       ` Thomas Baumann
@ 2006-04-07 14:40                                                                                         ` Daiki Ueno
  2006-04-07 15:45                                                                                           ` Reiner Steib
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-04-07 14:40 UTC (permalink / raw)
  Cc: Reiner Steib, Sascha Wilde, romain, ding, emacs-devel,
	Simon Josefsson

>>>>> In <25746.1144418743@norvel.baumann-gauting.site> 
>>>>>	Thomas Baumann <thomas.baumann@ch.tum.de> wrote:

Thanks for testing again, Thomas.

> Debugger entered--Lisp error: (quit)
>   accept-process-output(#<process pgg-gpg<4>> 1)
>   pgg-gpg-wait-for-status(#<process pgg-gpg<4>> ("BEGIN_SIGNING"))

Looks odd.  I think that the code which waits only for "BEGIN_SIGNING"
has not ever been incorporated in Gnus CVS.

> Things are ok if I the following version of pgg-gpg.el

> -rw-r--r--   1 tb users  13819 Feb 10 07:33 pgg-gpg.el

Could you tell me what version did you test the above?

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 14:40                                                                                         ` Daiki Ueno
@ 2006-04-07 15:45                                                                                           ` Reiner Steib
  2006-04-07 20:55                                                                                             ` Daiki Ueno
  0 siblings, 1 reply; 156+ messages in thread
From: Reiner Steib @ 2006-04-07 15:45 UTC (permalink / raw)
  Cc: thomas.baumann, ding, emacs-devel

[ Reducing Cc list ]

On Fri, Apr 07 2006, Daiki Ueno wrote:

>>>>>> In <25746.1144418743@norvel.baumann-gauting.site> 
>>>>>>	Thomas Baumann <thomas.baumann@ch.tum.de> wrote:
>> Debugger entered--Lisp error: (quit)
>>   accept-process-output(#<process pgg-gpg<4>> 1)
>>   pgg-gpg-wait-for-status(#<process pgg-gpg<4>> ("BEGIN_SIGNING"))
>
> Looks odd.  I think that the code which waits only for "BEGIN_SIGNING"
> has not ever been incorporated in Gnus CVS.

| X-Mailer: MH-E 7.93+cvs; nmh 1.2; GNU Emacs 22.0.50.1

MH-E uses the MIME stuff from Gnus, but Thomas is using MH-E from
Emacs CVS.

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 15:45                                                                                           ` Reiner Steib
@ 2006-04-07 20:55                                                                                             ` Daiki Ueno
  2006-04-07 21:22                                                                                               ` Reiner Steib
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-04-07 20:55 UTC (permalink / raw)
  Cc: thomas.baumann, ding, emacs-devel

>>>>> In <v97j61crtc.fsf@marauder.physik.uni-ulm.de> 
>>>>>	Reiner Steib <reinersteib+gmane@imap.cc> wrote:
> >>>>>> In <25746.1144418743@norvel.baumann-gauting.site> 
> >>>>>>	Thomas Baumann <thomas.baumann@ch.tum.de> wrote:
> >> Debugger entered--Lisp error: (quit)
> >>   accept-process-output(#<process pgg-gpg<4>> 1)
> >>   pgg-gpg-wait-for-status(#<process pgg-gpg<4>> ("BEGIN_SIGNING"))
> >
> > Looks odd.  I think that the code which waits only for "BEGIN_SIGNING"
> > has not ever been incorporated in Gnus CVS.

> | X-Mailer: MH-E 7.93+cvs; nmh 1.2; GNU Emacs 22.0.50.1

> MH-E uses the MIME stuff from Gnus, but Thomas is using MH-E from
> Emacs CVS.

Did someone mistakenly installed the first BEGIN_SIGNING patch to Emacs
CVS, while it has not been commited in Gnus CVS?  Simon vetoed it
because it does _not_ work with the earlier GnuPG versions than 1.4.3.

http://article.gmane.org/gmane.emacs.gnus.general/62513
http://article.gmane.org/gmane.emacs.gnus.general/62514

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 13:30                                                                                       ` Simon Josefsson
@ 2006-04-07 20:59                                                                                         ` Reiner Steib
  0 siblings, 0 replies; 156+ messages in thread
From: Reiner Steib @ 2006-04-07 20:59 UTC (permalink / raw)
  Cc: Romain Francoise, Reiner Steib, Sascha Wilde, Daiki Ueno, ding,
	emacs-devel

On Fri, Apr 07 2006, Simon Josefsson wrote:

>> May I suggest to revert the code to version 1.8 from GNU Emacs CVS
>> instead?
>>
>> This version includes my original agent support code and Reiners small
>> compatibility fix.
>>
>> I would prefer this version because it:
>> - allow using the agent
>> - but only if enabled explicitly by the user, so the default behavior
>>   is completely unchanged compared to the old code
>> - introduces only very few code changes, with no known bugs
>> - has none of the problems of Daikis code regarding robustness
>>   or api changes
>>
>> IIRC this version was already discussed and accepted for 5.10.
>
> I agree, we shouldn't revert more than Daiki's asynchronous stuff in
> v5-10/Emacs CVS.

Okay, I'll do this (revision 7.15 in Gnus).

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 20:55                                                                                             ` Daiki Ueno
@ 2006-04-07 21:22                                                                                               ` Reiner Steib
  2006-04-08  7:03                                                                                                 ` Thomas Baumann
  2006-04-08 10:18                                                                                                 ` Daiki Ueno
  0 siblings, 2 replies; 156+ messages in thread
From: Reiner Steib @ 2006-04-07 21:22 UTC (permalink / raw)
  Cc: thomas.baumann, ding, emacs-devel

On Fri, Apr 07 2006, Daiki Ueno wrote:

>>>>>>	Reiner Steib <reinersteib+gmane@imap.cc> wrote:
>> > Looks odd.  I think that the code which waits only for "BEGIN_SIGNING"
>> > has not ever been incorporated in Gnus CVS.
>
>> | X-Mailer: MH-E 7.93+cvs; nmh 1.2; GNU Emacs 22.0.50.1
>
>> MH-E uses the MIME stuff from Gnus, but Thomas is using MH-E from
>> Emacs CVS.
>
> Did someone mistakenly installed the first BEGIN_SIGNING patch to Emacs
> CVS, while it has not been commited in Gnus CVS?  

----------------------------
revision 1.13
date: 2006-04-05 11:00:11 +0000;  author: jas;  state: Exp;  lines: +2 -2
2006-04-05  Daiki Ueno  <ueno@unixuser.org>

	* pgg-gpg.el (pgg-gpg-encrypt-region, pgg-gpg-sign-region): Wait
	for BEGIN_SIGNING too, new in GnuPG 1.4.3.
----------------------------

> Simon vetoed it because it does _not_ work with the earlier GnuPG
> versions than 1.4.3.

AFAICS, Simon installed a modified version:

--8<---------------cut here---------------start------------->8---
--- pgg-gpg.el	4 Apr 2006 23:30:02 -0000	1.12
+++ pgg-gpg.el	5 Apr 2006 11:00:11 -0000	1.13
@@ -256,7 +256,7 @@
 					  (list pgg-gpg-user-id))))))))
 	 (process (pgg-gpg-start-process args)))
     (if (and sign (not pgg-gpg-use-agent))
-	(pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE")))
+	(pgg-gpg-wait-for-status process '("BEGIN_SIGNING" "GOOD_PASSPHRASE")))
     (process-send-region process start end)
     (pgg-gpg-wait-for-completion process)
     (save-excursion
@@ -303,7 +303,7 @@
 		  (if pgg-text-mode '("--textmode"))))
 	 (process (pgg-gpg-start-process args)))
     (unless pgg-gpg-use-agent
-      (pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE")))
+      (pgg-gpg-wait-for-status process '("BEGIN_SIGNING" "GOOD_PASSPHRASE")))
     (process-send-region process start end)
     (pgg-gpg-wait-for-completion process)
     (save-excursion
--8<---------------cut here---------------end--------------->8---

Thomas should update from CVS (I have reverted to revision 1.8,
i.e. before your asynchronous gpg call, after adding gpg-agent support
from Sascha) and check again, I think.  Or test your version.

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 12:35                                                                                   ` Reiner Steib
  2006-04-07 13:02                                                                                     ` Daiki Ueno
@ 2006-04-07 21:36                                                                                     ` Richard Stallman
  2006-04-08  9:45                                                                                       ` Romain Francoise
  1 sibling, 1 reply; 156+ messages in thread
From: Richard Stallman @ 2006-04-07 21:36 UTC (permalink / raw)
  Cc: wilde, jas, ueno, Reiner Steib, emacs-devel

    Simon's advised on keeping the new code in the Gnus trunk, so I
    followed his suggestion.  I didn't have a strong option on what is
    best for the version² in Emacs CVS, so I didn't touch it.  IIRC Simon
    didn't express an opinion concerning this version neither.  Probably
    Romain thought that the problems with the new code are too serious
    also for Emacs CVS.

Romain, would you please explain to me why you removed the code in
Emacs CVS?  Why not install Daiki's fixes instead?

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 21:22                                                                                               ` Reiner Steib
@ 2006-04-08  7:03                                                                                                 ` Thomas Baumann
  2006-04-08 10:18                                                                                                 ` Daiki Ueno
  1 sibling, 0 replies; 156+ messages in thread
From: Thomas Baumann @ 2006-04-08  7:03 UTC (permalink / raw)


Reiner Steib <reinersteib+gmane@imap.cc> wrote:

> On Fri, Apr 07 2006, Daiki Ueno wrote:
> 
> >>>>>>	Reiner Steib <reinersteib+gmane@imap.cc> wrote:
> >> > Looks odd.  I think that the code which waits only for "BEGIN_SIGNING"
> >> > has not ever been incorporated in Gnus CVS.
> >
> >> | X-Mailer: MH-E 7.93+cvs; nmh 1.2; GNU Emacs 22.0.50.1
> >
> >> MH-E uses the MIME stuff from Gnus, but Thomas is using MH-E from
> >> Emacs CVS.
> >
> > Did someone mistakenly installed the first BEGIN_SIGNING patch to Emacs
> > CVS, while it has not been commited in Gnus CVS?  
> 
> ----------------------------
> revision 1.13
> date: 2006-04-05 11:00:11 +0000;  author: jas;  state: Exp;  lines: +2 -2
> 2006-04-05  Daiki Ueno  <ueno@unixuser.org>
> 
> 	* pgg-gpg.el (pgg-gpg-encrypt-region, pgg-gpg-sign-region): Wait
> 	for BEGIN_SIGNING too, new in GnuPG 1.4.3.
> ----------------------------
> 
> > Simon vetoed it because it does _not_ work with the earlier GnuPG
> > versions than 1.4.3.
> 
> AFAICS, Simon installed a modified version:
> 
> --8<---------------cut here---------------start------------->8---
> --- pgg-gpg.el	4 Apr 2006 23:30:02 -0000	1.12
> +++ pgg-gpg.el	5 Apr 2006 11:00:11 -0000	1.13
> @@ -256,7 +256,7 @@
>  					  (list pgg-gpg-user-id))))))))
>  	 (process (pgg-gpg-start-process args)))
>      (if (and sign (not pgg-gpg-use-agent))
> -	(pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE")))
> +	(pgg-gpg-wait-for-status process '("BEGIN_SIGNING" "GOOD_PASSPHRASE")))
>      (process-send-region process start end)
>      (pgg-gpg-wait-for-completion process)
>      (save-excursion
> @@ -303,7 +303,7 @@
>  		  (if pgg-text-mode '("--textmode"))))
>  	 (process (pgg-gpg-start-process args)))
>      (unless pgg-gpg-use-agent
> -      (pgg-gpg-wait-for-status process '("GOOD_PASSPHRASE")))
> +      (pgg-gpg-wait-for-status process '("BEGIN_SIGNING" "GOOD_PASSPHRASE")))
>      (process-send-region process start end)
>      (pgg-gpg-wait-for-completion process)
>      (save-excursion
> --8<---------------cut here---------------end--------------->8---
> 
> Thomas should update from CVS (I have reverted to revision 1.8,
> i.e. before your asynchronous gpg call, after adding gpg-agent support
> from Sascha) and check again, I think.  Or test your version.
> 
> Bye, Reiner.
> -- 
>        ,,,
>       (o o)
> ---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/
> 

Everything back to normal with this mornings CVS, at least for the
pgg-gpg.el, thanks

Thomas



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 13:00                                                                                     ` Sascha Wilde
  2006-04-07 13:30                                                                                       ` Simon Josefsson
@ 2006-04-08  9:36                                                                                       ` Romain Francoise
  2006-04-08 10:05                                                                                         ` Sascha Wilde
  1 sibling, 1 reply; 156+ messages in thread
From: Romain Francoise @ 2006-04-08  9:36 UTC (permalink / raw)
  Cc: Daiki Ueno, emacs-devel, Reiner Steib, ding, Simon Josefsson

Sascha Wilde <wilde@sha-bang.de> writes:

> May I suggest to revert the code to version 1.8 from GNU Emacs CVS
> instead?

Reiner has now done that, in Gnus and Emacs.

-- 
Romain Francoise <romain@orebokech.com> | The sea! the sea! the open
it's a miracle -- http://orebokech.com/ | sea! The blue, the fresh, the
                                        | ever free! --Bryan W. Procter

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 21:36                                                                                     ` Richard Stallman
@ 2006-04-08  9:45                                                                                       ` Romain Francoise
  2006-04-08 10:11                                                                                         ` Daiki Ueno
  2006-04-08 22:34                                                                                         ` Richard Stallman
  0 siblings, 2 replies; 156+ messages in thread
From: Romain Francoise @ 2006-04-08  9:45 UTC (permalink / raw)
  Cc: wilde, jas, ueno, Reiner Steib, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Romain, would you please explain to me why you removed the code in
> Emacs CVS?

To keep it level with the same code in Gnus, which we planned to include
in a new Gnus stable release this week-end.

> Why not install Daiki's fixes instead?

Because they weren't available at the time, and because we had agreed to
test this new code in the Gnus trunk.


Anyway, Reiner has now changed it again in Gnus and Emacs to a later
version that satisfies everyone, I think (revision 1.8 vs. 1.4).

-- 
Romain Francoise <romain@orebokech.com> | The sea! the sea! the open
it's a miracle -- http://orebokech.com/ | sea! The blue, the fresh, the
                                        | ever free! --Bryan W. Procter

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-08  9:36                                                                                       ` Romain Francoise
@ 2006-04-08 10:05                                                                                         ` Sascha Wilde
  0 siblings, 0 replies; 156+ messages in thread
From: Sascha Wilde @ 2006-04-08 10:05 UTC (permalink / raw)
  Cc: Daiki Ueno, emacs-devel, Reiner Steib, ding, Simon Josefsson

Romain Francoise <romain@orebokech.com> wrote:

> Sascha Wilde <wilde@sha-bang.de> writes:
>
>> May I suggest to revert the code to version 1.8 from GNU Emacs CVS
>> instead?
>
> Reiner has now done that, in Gnus and Emacs.

Thanks.
sascha
-- 
Sascha Wilde
Nothing is fool-proof to a sufficiently talented fool.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-08  9:45                                                                                       ` Romain Francoise
@ 2006-04-08 10:11                                                                                         ` Daiki Ueno
  2006-04-08 11:30                                                                                           ` Romain Francoise
  2006-04-10 22:40                                                                                           ` gpg-agent support removed?! Ken Manheimer
  2006-04-08 22:34                                                                                         ` Richard Stallman
  1 sibling, 2 replies; 156+ messages in thread
From: Daiki Ueno @ 2006-04-08 10:11 UTC (permalink / raw)
  Cc: wilde, jas, rms, Reiner Steib, emacs-devel

>>>>> In <873bgo4d0e.fsf@pacem.orebokech.com> 
>>>>>	Romain Francoise <romain@orebokech.com> wrote:
> Richard Stallman <rms@gnu.org> writes:

> > Romain, would you please explain to me why you removed the code in
> > Emacs CVS?

> To keep it level with the same code in Gnus, which we planned to include
> in a new Gnus stable release this week-end.

> > Why not install Daiki's fixes instead?

> Because they weren't available at the time,

As I said yesterday, the current version is at 
http://www.unixuser.org/~ueno/pgg-20060407.tar.gz
This code should be fairly stable.

> and because we had agreed to test this new code in the Gnus trunk.

I agreeded to revert the code from v5-10 branch of Gnus because the
release of Gnus v5.10.8 is so imminent.  However, I didn't think the
release of Emacs is as well.

> Anyway, Reiner has now changed it again in Gnus and Emacs to a later
> version that satisfies everyone, I think (revision 1.8 vs. 1.4).

No, I wasn't satisfied with your decision at all.  Though allout.el
appearantly has a bug, i.e. allout.el uses PGG in a bad way, it works as
expected by Ken (the author of allout.el), so it won't be fixed.  On the
other hand, I have many enhancement plans of PGG based on the new code
such as keysigning features, string-based interface, etc.  I think it
should be tested not only by the Gnus people but also by Emacs people.

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 21:22                                                                                               ` Reiner Steib
  2006-04-08  7:03                                                                                                 ` Thomas Baumann
@ 2006-04-08 10:18                                                                                                 ` Daiki Ueno
  1 sibling, 0 replies; 156+ messages in thread
From: Daiki Ueno @ 2006-04-08 10:18 UTC (permalink / raw)
  Cc: thomas.baumann, ding, emacs-devel

>>>>> In <v9acaxw05w.fsf@marauder.physik.uni-ulm.de> 
>>>>>	Reiner Steib <reinersteib+gmane@imap.cc> wrote:
> AFAICS, Simon installed a modified version:

> --- pgg-gpg.el	4 Apr 2006 23:30:02 -0000	1.12
> +++ pgg-gpg.el	5 Apr 2006 11:00:11 -0000	1.13

This patch had a bug, and I posted the fix just after.  However, I don't
see the reason, Simon didn't commit the fix to Emacs CVS.

http://article.gmane.org/gmane.emacs.gnus.general/62522

So, this bug is fixed in the current PGG code

http://www.unixuser.org/~ueno/pgg-20060407.tar.gz

Thomas, could you test this?

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-08 10:11                                                                                         ` Daiki Ueno
@ 2006-04-08 11:30                                                                                           ` Romain Francoise
  2006-04-08 11:58                                                                                             ` Daiki Ueno
  2006-04-10 22:40                                                                                           ` gpg-agent support removed?! Ken Manheimer
  1 sibling, 1 reply; 156+ messages in thread
From: Romain Francoise @ 2006-04-08 11:30 UTC (permalink / raw)
  Cc: rms, emacs-devel

Daiki Ueno <ueno@unixuser.org> writes:

> I agreeded to revert the code from v5-10 branch of Gnus because the
> release of Gnus v5.10.8 is so imminent.  However, I didn't think the
> release of Emacs is as well.

The release isn't imminent partly because people keep adding new
features which, inevitably, introduce new bugs.

> On the other hand, I have many enhancement plans of PGG based on the
> new code such as keysigning features, string-based interface, etc.

That sounds great, and I look forward to having these new features.
However, I think the Emacs trunk isn't the place to test them, at least
at the moment.

-- 
Romain Francoise <romain@orebokech.com> | The sea! the sea! the open
it's a miracle -- http://orebokech.com/ | sea! The blue, the fresh, the
                                        | ever free! --Bryan W. Procter

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-08 11:30                                                                                           ` Romain Francoise
@ 2006-04-08 11:58                                                                                             ` Daiki Ueno
  2006-04-10 18:04                                                                                               ` PGG maintainance (was: gpg-agent support removed?!) Reiner Steib
  0 siblings, 1 reply; 156+ messages in thread
From: Daiki Ueno @ 2006-04-08 11:58 UTC (permalink / raw)
  Cc: rms, emacs-devel

>>>>> In <87r7482tjt.fsf@pacem.orebokech.com> 
>>>>>	Romain Francoise <romain@orebokech.com> wrote:
> > On the other hand, I have many enhancement plans of PGG based on the
> > new code such as keysigning features, string-based interface, etc.

> However, I think the Emacs trunk isn't the place to test them, at least
> at the moment.

Yes, I know.  However, I'm beginning to think that Gnus CVS is also not
the right place to do this because PGG is now used by programs other
than Gnus and I have no CVS write access to Gnus CVS.  Even for a tiny
fix I have to explain the reason and wait for Simon to commit.

Regards,
-- 
Daiki Ueno

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-08  9:45                                                                                       ` Romain Francoise
  2006-04-08 10:11                                                                                         ` Daiki Ueno
@ 2006-04-08 22:34                                                                                         ` Richard Stallman
  1 sibling, 0 replies; 156+ messages in thread
From: Richard Stallman @ 2006-04-08 22:34 UTC (permalink / raw)
  Cc: wilde, jas, ueno, Reiner.Steib, emacs-devel

    Anyway, Reiner has now changed it again in Gnus and Emacs to a later
    version that satisfies everyone, I think (revision 1.8 vs. 1.4).

Ok, thanks.

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-07 13:26                                                                                         ` Daiki Ueno
@ 2006-04-09 16:04                                                                                           ` Sascha Wilde
  2006-04-10 18:04                                                                                             ` Reiner Steib
  0 siblings, 1 reply; 156+ messages in thread
From: Sascha Wilde @ 2006-04-09 16:04 UTC (permalink / raw)
  Cc: Reiner Steib, Thomas Baumann, romain, ding, emacs-devel,
	Simon Josefsson

Daiki Ueno <ueno@unixuser.org> wrote:

>>>>>> In <m2lkuhcz2y.fsf@kenny.sha-bang.de> 
>>>>>>	Sascha Wilde <wilde@sha-bang.de> wrote:
>> >>   http://article.gmane.org/gmane.emacs.devel/52450
>> >
>> > I think this is fixed by the patch I posted some time ago.
>> > http://article.gmane.org/gmane.emacs.gnus.general/62571
>
>> This sounds interesting -- where can I get this version for testing?
>
> I put the tarball which contains the current pgg*.el at
>
> http://www.unixuser.org/~ueno/pgg-20060407.tar.gz

Thanks.  I finally found the time to give it a try -- and it seems to
solve my problem.

cheers
sascha
-- 
Sascha Wilde  :  "I heard that if you play the Windows CD backward, you
              :  get a satanic message. But that's nothing compared to
              :  when you play it forward: It installs Windows...." 
              :  -- G. R. Gaudreau

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-09 16:04                                                                                           ` Sascha Wilde
@ 2006-04-10 18:04                                                                                             ` Reiner Steib
  0 siblings, 0 replies; 156+ messages in thread
From: Reiner Steib @ 2006-04-10 18:04 UTC (permalink / raw)
  Cc: romain, Thomas Baumann, Daiki Ueno, ding, emacs-devel,
	Simon Josefsson

On Sun, Apr 09 2006, Sascha Wilde wrote:

> Daiki Ueno <ueno@unixuser.org> wrote:
>> I put the tarball which contains the current pgg*.el at
>>
>> http://www.unixuser.org/~ueno/pgg-20060407.tar.gz
>
> Thanks.  I finally found the time to give it a try -- and it seems to
> solve my problem.

Daiki, should this version be installed in Gnus trunk?  Could you
provide ChangeLog entries (compared to the version in Gnus CVS trunk),
please?

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* PGG maintainance (was: gpg-agent support removed?!)
  2006-04-08 11:58                                                                                             ` Daiki Ueno
@ 2006-04-10 18:04                                                                                               ` Reiner Steib
  0 siblings, 0 replies; 156+ messages in thread
From: Reiner Steib @ 2006-04-10 18:04 UTC (permalink / raw)
  Cc: Simon Josefsson, ding, emacs-devel

On Sat, Apr 08 2006, Daiki Ueno wrote:

>>>>>> In <87r7482tjt.fsf@pacem.orebokech.com> 
>>>>>>	Romain Francoise <romain@orebokech.com> wrote:
>> However, I think the Emacs trunk isn't the place to test them, at least
>> at the moment.
>
> Yes, I know.  However, I'm beginning to think that Gnus CVS is also not
> the right place to do this because PGG is now used by programs other
> than Gnus and I have no CVS write access to Gnus CVS.  Even for a tiny
> fix I have to explain the reason and wait for Simon to commit.

If you'd like to maintain pgg*.el in Gnus' repository, you could ask
Lars for write access.

Bye, Reiner.
-- 
       ,,,
      (o o)
---ooO-(_)-Ooo---  |  PGP key available  |  http://rsteib.home.pages.de/

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: gpg-agent support removed?!
  2006-04-08 10:11                                                                                         ` Daiki Ueno
  2006-04-08 11:30                                                                                           ` Romain Francoise
@ 2006-04-10 22:40                                                                                           ` Ken Manheimer
  1 sibling, 0 replies; 156+ messages in thread
From: Ken Manheimer @ 2006-04-10 22:40 UTC (permalink / raw)
  Cc: rms, Reiner Steib, wilde, Romain Francoise, emacs-devel, jas

daiki, i still have some problems with your patch, and the changes
you're suggesting for allout, and i think you've oversimplified the
problems allout has having with your patches.  details interspersed
with the cited text.

On 4/8/06, Daiki Ueno <ueno@unixuser.org> wrote:
> >>>>> In <873bgo4d0e.fsf@pacem.orebokech.com>
> >>>>>   Romain Francoise <romain@orebokech.com> wrote:
> > Richard Stallman <rms@gnu.org> writes:
>
> > > Romain, would you please explain to me why you removed the code in
> > > Emacs CVS?
>
> > To keep it level with the same code in Gnus, which we planned to include
> > in a new Gnus stable release this week-end.
>
> > > Why not install Daiki's fixes instead?
>
> > Because they weren't available at the time,
>
> As I said yesterday, the current version is at
> http://www.unixuser.org/~ueno/pgg-20060407.tar.gz
> This code should be fairly stable.
>
> > and because we had agreed to test this new code in the Gnus trunk.
>
> I agreeded to revert the code from v5-10 branch of Gnus because the
> release of Gnus v5.10.8 is so imminent.  However, I didn't think the
> release of Emacs is as well.
>
> > Anyway, Reiner has now changed it again in Gnus and Emacs to a later
> > version that satisfies everyone, I think (revision 1.8 vs. 1.4).
>
> No, I wasn't satisfied with your decision at all.  Though allout.el
> appearantly has a bug, i.e. allout.el uses PGG in a bad way, it works as

you characterized it that way because allout uses some internal pgg
functions.  that was not complete, nor did your suggested remedy solve
that problem, though it would allow the removal of those functions
from pgg-gpg.

first, your initial patch crippled allout's passphrase provisions
because the pgg-gpg functions which took an optional passphrase
argument were not respecting it.  i mentioned that, and you seem to
have fixed it - that problem no longer exists with your more recent
patch.  that's very important to allout's encryption operations, and
i'm glad it's resolved - thanks!

second, you suggest fixing some of the cases where allout uses
internal functions by having allout implement its own version of those
functions, allowing you to eliminate the versions of those functions
in pgg-gpg.  that mostly works, but it amounts to allout's versions of
those functions depending on internal data structures in pgg-gpg,
leading to a yet more brittle situation than depending on internal
functions.  i think a better fix would be to provide the
functionality, or some equivalent, at the generic pgg level.  i did
not do so because i had limited time and no access to the other
backends, in order to establish that the functionality would be
available with them.

it also so happens that there is at least one other function from
pgg-gpg which allout depends on and which is missing from your revised
pgg-gpg: `pgg-gpg-lookup-all-secret-keys'.  this one calls out to pgg,
and so does not even remotely belong in allout.  perhaps it was
renamed or the functionality is available in another way, and i'm not
opposed to tracking that, but i cannot do so immediately, and would
need time and justification to do so.

> expected by Ken (the author of allout.el), so it won't be fixed.  On the

now i'm confused.  what gave you the idea that it won't be fixed?  i
never said i wouldn't consider what you suggested, and in fact have
been planning to do so but haven't had the time until now.  i think
the approach is flawed, for the reason i mentioned above, but you may
be able to convince me otherwise - i'm willing to talk about it.

> other hand, I have many enhancement plans of PGG based on the new code
> such as keysigning features, string-based interface, etc.  I think it
> should be tested not only by the Gnus people but also by Emacs people.

i think pgg could stand some attention, and am glad you're willing to
do so.  the thing is, taking it may require some consolidation before
extending it - it has grown a bit unordered, and probably needs some
attention to rationalizing it against existing consumer's
requirements, including those of allout.

for now, i have a branch version of allout that does as you suggested
and works partly against your pgg-20060407.tar.gz patch, except that
key-pair encryption fails for lack of pgg-gpg-lookup-all-secret-keys,
as mentioned above.  i am going to be going away for a week, starting
tomorrow evening, so i'm hoping that there will not be a migration to
your new version until this is resolved.  i ultimately would prefer
that the problems be resolved in a better way, along the lines
mentioned above, but am willing to go with a partial solution if some
provision for its stability can be made.  i do want to see pgg
continue to ripen.
--
ken manheimer
ken.manheimer@gmail.com
http://myriadicity.net

^ permalink raw reply	[flat|nested] 156+ messages in thread

end of thread, other threads:[~2006-04-10 22:40 UTC | newest]

Thread overview: 156+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-09-30 17:24 new version of allout.el - patch and ChangeLog Ken Manheimer
2005-09-30 21:06 ` Sascha Wilde
2005-09-30 21:52   ` Ken Manheimer
2005-10-01  8:20     ` Andreas Schwab
2005-10-01 12:41       ` Reiner Steib
2005-10-01 23:54         ` James Cloos
2005-10-01 16:28     ` Ken Manheimer
2005-10-02 10:48       ` Sascha Wilde
2005-10-02 14:23         ` Ken Manheimer
2005-10-02 20:31         ` Richard M. Stallman
2005-10-03 19:25           ` pgg symmetric encryption patch (was: new version of allout.el - patch and ChangeLog) Sascha Wilde
2005-10-03 19:50             ` Ken Manheimer
2005-10-04 10:53               ` Sascha Wilde
2005-10-04 12:46                 ` pgg symmetric encryption patch Stefan Monnier
2005-10-05 16:19                 ` Sascha Wilde
2005-10-05 19:16                   ` Ken Manheimer
2005-10-10  4:15                     ` Richard M. Stallman
2005-10-06  2:18                   ` Daiki Ueno
2005-10-06  9:01                     ` Sascha Wilde
2005-10-06 22:41                       ` Ken Manheimer
2005-10-07 10:00                         ` Sascha Wilde
2005-10-07 18:06                           ` Ken Manheimer
2005-10-07 21:49                             ` Sascha Wilde
2005-10-08  8:48                               ` Simon Josefsson
2005-10-08 10:36                                 ` Sascha Wilde
2005-10-08 11:14                                   ` Simon Josefsson
2005-10-08 12:56                                     ` Ken Manheimer
2005-10-08 22:56                                       ` Richard M. Stallman
2005-10-10 21:50                                         ` Ken Manheimer
2005-10-11 14:44                                           ` Richard M. Stallman
2005-10-08 13:43                                     ` Sascha Wilde
2005-10-08 18:31                                   ` Ken Manheimer
2005-10-08 19:16                                     ` Ken Manheimer
2005-10-10 21:15                                     ` Ken Manheimer
2005-10-10 21:16                                       ` Ken Manheimer
2005-10-12 23:47                                       ` Ken Manheimer
2005-10-20 14:08                                         ` Ken Manheimer
2005-10-20 14:12                                           ` Simon Josefsson
2005-10-20 14:30                                             ` Ken Manheimer
2005-10-20 14:42                                             ` Sascha Wilde
2005-10-25  7:23                                               ` Sascha Wilde
2005-10-25 20:26                                                 ` Ken Manheimer
2005-10-25 21:18                                                   ` Sascha Wilde
2005-10-25 21:28                                                     ` Ken Manheimer
2005-10-26  9:57                                                       ` Sascha Wilde
2005-10-26 15:45                                                         ` Ken Manheimer
2005-10-27  7:37                                                           ` Sascha Wilde
2005-10-29 11:42                                                             ` Eli Zaretskii
2005-10-29 19:50                                                               ` Ken Manheimer
2005-10-31 17:30                                                                 ` Ken Manheimer
2005-11-04 14:45                                                                   ` Eli Zaretskii
2005-10-20 18:07                                             ` Relocating pgg*.el (was: pgg symmetric encryption patch) Reiner Steib
2005-10-20 22:22                                               ` Kim F. Storm
2005-10-21  4:49                                                 ` Richard M. Stallman
2005-10-20 23:38                                             ` pgg symmetric encryption patch Richard M. Stallman
2005-10-21  7:07                                               ` Simon Josefsson
2006-03-18 21:17                                             ` Small patch to enable use of gpg-agent with pgg Sascha Wilde
2006-03-18 23:30                                               ` Daniel Pittman
2006-03-19  0:46                                                 ` Miles Bader
2006-03-19  3:45                                                   ` Daniel Pittman
2006-03-19 18:28                                                     ` Miles Bader
2006-03-19  9:49                                                 ` Sascha Wilde
2006-03-19 17:30                                                   ` Sascha Wilde
2006-03-21 14:32                                               ` Simon Josefsson
2006-03-21 21:29                                                 ` Reiner Steib
2006-03-22  9:49                                                   ` Simon Josefsson
2006-03-22  8:36                                                 ` Sascha Wilde
2006-03-22  9:16                                                   ` Daiki Ueno
2006-03-22  9:48                                                     ` Simon Josefsson
2006-03-22 11:03                                                     ` Sascha Wilde
2006-03-22 11:13                                                       ` Simon Josefsson
2006-03-22 12:25                                                         ` Daiki Ueno
2006-03-23 10:40                                                           ` Daiki Ueno
2006-03-23 11:00                                                             ` Simon Josefsson
2006-03-23 12:18                                                               ` Daiki Ueno
2006-03-23 13:08                                                                 ` Simon Josefsson
2006-03-24  5:51                                                                   ` Daiki Ueno
2006-03-26  0:29                                                                     ` Daiki Ueno
2006-03-26  1:08                                                                       ` Simon Josefsson
2006-03-26  3:29                                                                         ` Miles Bader
2006-03-26  5:06                                                                           ` Daiki Ueno
2006-03-26 17:05                                                                             ` Simon Josefsson
2006-03-26 18:24                                                                               ` Sascha Wilde
2006-03-27  9:36                                                                                 ` Simon Josefsson
2006-03-23 12:52                                                             ` Sascha Wilde
2006-03-23 20:07                                                               ` Daiki Ueno
2006-03-23 22:16                                                                 ` Sascha Wilde
2006-04-05  9:13                                                                   ` pgg-gpg broken? Sascha Wilde
2006-04-05  9:42                                                                     ` Daiki Ueno
2006-04-05 10:18                                                                       ` Sascha Wilde
2006-04-05 21:33                                                                         ` Daiki Ueno
2006-04-06  9:00                                                                           ` Sascha Wilde
2006-04-06  9:21                                                                             ` Daiki Ueno
2006-04-06  9:58                                                                               ` Sascha Wilde
2006-04-06 10:13                                                                                 ` Daiki Ueno
2006-04-07 10:32                                                                                 ` gpg-agent support removed?! (was: pgg-gpg broken?) Sascha Wilde
2006-04-07 12:11                                                                                   ` Simon Josefsson
2006-04-07 12:14                                                                                   ` gpg-agent support removed?! Romain Francoise
2006-04-07 13:00                                                                                     ` Sascha Wilde
2006-04-07 13:30                                                                                       ` Simon Josefsson
2006-04-07 20:59                                                                                         ` Reiner Steib
2006-04-08  9:36                                                                                       ` Romain Francoise
2006-04-08 10:05                                                                                         ` Sascha Wilde
2006-04-07 12:35                                                                                   ` Reiner Steib
2006-04-07 13:02                                                                                     ` Daiki Ueno
2006-04-07 13:08                                                                                       ` Sascha Wilde
2006-04-07 13:26                                                                                         ` Daiki Ueno
2006-04-09 16:04                                                                                           ` Sascha Wilde
2006-04-10 18:04                                                                                             ` Reiner Steib
2006-04-07 13:40                                                                                         ` Reiner Steib
2006-04-07 14:05                                                                                       ` Thomas Baumann
2006-04-07 14:40                                                                                         ` Daiki Ueno
2006-04-07 15:45                                                                                           ` Reiner Steib
2006-04-07 20:55                                                                                             ` Daiki Ueno
2006-04-07 21:22                                                                                               ` Reiner Steib
2006-04-08  7:03                                                                                                 ` Thomas Baumann
2006-04-08 10:18                                                                                                 ` Daiki Ueno
2006-04-07 21:36                                                                                     ` Richard Stallman
2006-04-08  9:45                                                                                       ` Romain Francoise
2006-04-08 10:11                                                                                         ` Daiki Ueno
2006-04-08 11:30                                                                                           ` Romain Francoise
2006-04-08 11:58                                                                                             ` Daiki Ueno
2006-04-10 18:04                                                                                               ` PGG maintainance (was: gpg-agent support removed?!) Reiner Steib
2006-04-10 22:40                                                                                           ` gpg-agent support removed?! Ken Manheimer
2006-04-08 22:34                                                                                         ` Richard Stallman
2006-04-05 16:14                                                                     ` pgg-gpg broken? Reiner Steib
2006-04-05 19:22                                                                       ` Sascha Wilde
2006-03-22  9:46                                                   ` Small patch to enable use of gpg-agent with pgg Simon Josefsson
2006-03-22 16:13                                                   ` Simon Josefsson
2006-03-22 23:01                                                     ` Katsumi Yamaoka
2006-03-22 23:45                                                       ` Simon Josefsson
2006-03-23  0:58                                                         ` Katsumi Yamaoka
2006-03-23  9:12                                                           ` Simon Josefsson
2006-03-23 10:26                                                             ` Sascha Wilde
2006-03-23 10:54                                                               ` Simon Josefsson
2006-03-23 11:12                                                                 ` Simon Josefsson
2006-03-23 11:16                                                                   ` Simon Josefsson
2006-03-23 12:51                                                                     ` Reiner Steib
2006-03-23 13:07                                                                       ` Sascha Wilde
2006-03-23 13:10                                                                         ` Simon Josefsson
2006-03-23 12:00                                                                   ` Sascha Wilde
2006-03-23 13:00                                                                     ` Simon Josefsson
2006-03-26 18:11                                                                       ` Sascha Wilde
     [not found]                                                                   ` <m2wtels74l.fsf@kenny.sha-bang .de>
2006-03-23 23:09                                                                     ` Miles Bader
2006-04-02  0:30                                                                       ` Ken Manheimer
2006-04-02  8:28                                                                         ` Daiki Ueno
2005-12-09 15:43                         ` pgg symmetric encryption patch Simon Josefsson
2005-12-09 20:30                           ` Stefan Monnier
2005-12-09 20:31                           ` Stefan Monnier
2005-12-10  4:13                           ` Richard M. Stallman
2005-12-10 10:50                             ` Simon Josefsson
2005-12-11 13:32                               ` Sascha Wilde
2005-12-11 13:42                                 ` Simon Josefsson
2005-10-02 17:08       ` new version of allout.el - patch and ChangeLog Richard M. Stallman
     [not found] ` <E1ELj0L-0000Pn-3T@fencepost.gnu.org>
2005-10-01 22:33   ` Ken Manheimer
2005-10-20 13:57     ` Ken Manheimer

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).