home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!ferkel.ucsb.edu!taco!gatech!paladin.american.edu!howland.reston.ans.net!zaphod.mps.ohio-state.edu!magnus.acs.ohio-state.edu!usenet.ins.cwru.edu!agate!agate.berkeley.edu!dodd
- From: dodd@mycenae.cchem.berkeley.edu (Lawrence R. Dodd)
- Newsgroups: gnu.emacs.sources
- Subject: crypt++.el -- enhanced version of crypt
- Date: 24 Jan 93 07:44:09
- Organization: Dept of Chemical Engineering, Polytechnic Univ, NY, USA
- Lines: 900
- Message-ID: <DODD.93Jan24074409@mycenae.cchem.berkeley.edu>
- NNTP-Posting-Host: mycenae.cchem.berkeley.edu
- Summary: code for handling all sorts of compressed and encrypted files
- Keywords: crypt++.el, table-driven
-
-
- Hello all,
-
- Here is an updated and enhanced version of `crypt.el' called `crypt++.el'.
- It main advantage over previous versions of crypt is that it is table-driven
- making the addition of alternate compression programs trivial. This version
- also allows the user to write out buffers in compressed or plain format
- independent of the origin of the buffer. It does this by monitoring the
- file-name extension passed to `write-file' (C-x C-w) to see if a change in
- format is possibly being requested. It then (optionally) confirms with the
- user before writing the buffer.
-
- Since the elisp-archive seems to be in a state of dormancy, this file is
- also available via anonymous ftp to roebling.poly.edu in /pub/. Please try
- to exercise customary ftp etiquette and use only on off-peak hours.
-
- Furthermore, since the package is named `crypt++.el' you should replace any
- occurrence of (require 'crypt) in your .emacs or (for instance) in
- `lispdir.el' with (require 'crypt++) otherwise this is a drop-in replacement
- for the previous versions of crypt (see INSTALLATION in header).
-
- Finally, if you have any questions, comments, bug-reports, or smart remarks
- concerning crypt++.el type M-x crypt-submit-report and a template for a bug
- report will be generated (this idea was taken from Barry A. Warsaw's
- c++-mode.el).
-
- share and enjoy,
-
- Larry Dodd <dodd@roebling.poly.edu>
- and
- Rod Whitby <rwhitby@research.canon.oz.au>
-
-
- <file: ~/lisp/crypt++.el>
- ........................... cut along dotted line ...........................
- ;;; crypt++.el -- code for handling all sorts of compressed and encrypted files
-
- (defconst crypt-version (substring "$Revision: 2.7 $" 11 -2)
- "The revision number of crypt++.el -- code for handling all sorts of
- compression and encryption files. To send a bug report type
- M-x crypt-submit-report. Complete RCS identity is
-
- $Id: crypt++.el,v 2.7 1993/01/24 15:22:48 dodd Exp $")
-
- ;;; Copyright (C) 1993 Rod Whitby and Lawrence R. Dodd
- ;;; Copyright (C) 1988, 1989, 1990 Kyle E. Jones
- ;;;
- ;;; This program 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 of the License, or
- ;;; (at your option) any later version.
- ;;;
- ;;; This program 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 this program; if not, write to the Free Software
- ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ;;; AVAILABLE:
- ;;;
- ;;; via anonymous ftp to roebling.poly.edu [128.238.5.31] in /pub/crypt++.el
- ;;; (ange-ftp TAG: /roebling.poly.edu:/pub/crypt++.el)
-
- ;;; Send bug reports to:
- ;;;
- ;;; Lawrence R. Dodd <dodd@roebling.poly.edu>
- ;;; Department of Chemical Engineering
- ;;; Polymer Research Institute
- ;;; Polytechnic University
- ;;; Brooklyn, New York, 11201 USA
- ;;;
- ;;; or
- ;;; _--_|\
- ;;; Rod Whitby <rwhitby@research.canon.oz.au> / \
- ;;; Canon Information Systems Research Australia \_.--._/
- ;;; 1 Thomas Holt Drive, North Ryde, N.S.W., 2113 v
- ;;;
- ;;; or type M-x crypt-submit-report to generate a bug report template
-
- ;;; $Id: crypt++.el,v 2.7 1993/01/24 15:22:48 dodd Exp $
- ;;; $Date: 1993/01/24 15:22:48 $
- ;;; $Revision: 2.7 $
- ;;;
- ;;; version log
- ;;; 1.1 - original version of crypt.el
- ;;; 1.2 -
- ;;; jwz: works with tar-mode.el
- ;;; jwz: applied patch from piet, merged with Lawrence Dodd's gzip version
- ;;; 1.3 -
- ;;; lrd: fixed compress-magic-regexp
- ;;; 1.4, 1.5, 1.6 -
- ;;; lrd: write-file compresses or gzips based on file extension
- ;;; 2.1 -
- ;;; lrd: merged with Rod Whitby's table-driven version (major upgrade)
- ;;; 2.2 -
- ;;; rjw: Changed file name to crypt++.el, so archie and lispdir can find it.
- ;;; 2.3 -
- ;;; rjw: Separated the hook additions and minor mode alist additions.
- ;;; 2.4 -
- ;;; rjw: Fixed the interactive form for crypt-buffer.
- ;;; 2.5 -
- ;;; lrd: doc mods, changed GNU free software notice (was out of date), added
- ;;; anonymous ftp information
- ;;; 2.6 -
- ;;; lrd: added back in definition of `buffer' in defun crypt-buffer caused
- ;;; an error when trying to read encrypted file; modified check for minor
- ;;; mode alist addition; added gzip magic number warning
- ;;; 2.7 -
- ;;; lrd: added `TO DO' and `KNOW BUGS' section to header
-
- ;; INSTALLATION:
- ;;
- ;; To use this package, simply put it in a file called "crypt++.el" in a Lisp
- ;; directory known to Emacs, byte-compile it, and put the line:
- ;;
- ;; (require 'crypt++)
- ;;
- ;; in your ~/.emacs file or in the file default.el in the ../lisp directory of
- ;; the Emacs distribution. Do not bother trying to autoload this file; this
- ;; package uses find-file and write-file hooks and thus should be loaded the
- ;; first time you visit any sort of file.
- ;;
- ;; Users also may wish to toggle the values of `crypt-auto-decode-buffer,'
- ;; `crypt-freeze-vs-fortran,' and `crypt-auto-write-buffer' from their
- ;; defaults and possibly change the method of encryption and decryption using
- ;; the values of `crypt-encryption-program' and `crypt-decryption-program.'
- ;;
- ;; Note that the magic number used by gzip (GNU zip) was changed by Jean-loup
- ;; Gailly in his Beta version 0.6. The magic regular expression used below in
- ;; `crypt-encoding-alist' reflects this change. If you are using a version of
- ;; gzip earlier than 0.6, then please upgrade.
-
- ;; DESCRIPTION
- ;;
- ;; The basic purpose of this package of Lisp functions is to recognize
- ;; automatically encrypted and encoded (i.e., compressed) files when they are
- ;; first visited or written. The BUFFER corresponding to the file is decoded
- ;; and/or decrypted before it is presented to the user. The file itself is
- ;; unchanged on the disk. When the buffer is subsequently saved to disk, a
- ;; hook function re-encodes the buffer before the actual disk write takes
- ;; place.
- ;;
- ;; This package recognizes all sorts of compressed files by a magic number at
- ;; the beginning of these files but uses a heuristic to detect encrypted
- ;; files. If you are asked for an encryption key for a file that is in fact
- ;; not encrypted, just hit RET and the file will be accepted as is, and the
- ;; crypt minor mode will not be entered.
- ;;
- ;; Other types of encoding programs may be added to crypt++ using the variable
- ;; `crypt-encoding-alist' which contains a table of encoding programs such as
- ;; compress, gzip (GNU zip), and compact.
- ;;
- ;; This new extended version of crypt now monitors the filename extensions of
- ;; buffers that are written out using write-file (C-x C-w). If the filename
- ;; extension matches one of the extensions listed in `crypt-encoding-alist,'
- ;; then crypt++ will write the file out using the corresponding encoding
- ;; (compression) method. This is done whether or not the buffer originated
- ;; from a previously encoded (compressed) file.
- ;;
- ;; Thus, if the user is editing a file that may or may not have been encoded
- ;; originally (e.g., foobar.Z or foobar) and decides to write it to a
- ;; different file (e.g., barfoo or barfoo.z or barfoo.C). Crypt++ will examine
- ;; the filename extension and write the buffer in plain format or an alternate
- ;; encoding (compression) format by searching through the entries in the table
- ;; of encoding methods `crypt-encoding-alist.' This change in encoding state
- ;; is done automatically if the variable `crypt-auto-write-buffer' is t
- ;; otherwise the user is asked.
-
- ;; TO DO/KNOWN BUGS:
- ;;
- ;; * currently crypt++ assumes that if a file is both encrypted and encoded
- ;; (i.e., compressed) that the order in which it was done was encryption
- ;; first _then_ compression. As has been pointed by many people compression
- ;; following encryption is useless since the encrypted file is basically
- ;; random. On the other hand, many agree that doing encryption _following_
- ;; compression is better since it makes it harder to crack the encryption.
- ;; We would like to make the ordering of these two user-configurable or if
- ;; nothing else change the order.
- ;;
- ;; * some have complained that the encryption key that crypt++.el requests is
- ;; visible via `ps' We would like to pass the key to the encryption and
- ;; decryption program(s) in a more secure manner.
-
-
- ;; user definable variables
-
- (defvar crypt-encryption-program "crypt"
- "*Command to be used for encryption.")
-
- (defvar crypt-decryption-program "crypt"
- "*Command to be used for decryption.")
-
- (defvar crypt-auto-decode-buffer t
- "*t value means that the buffers associated with encoded files will
- be decoded automatically, without requesting confirmation from the user.
- `nil' means to ask before doing the decoding.")
-
- (defvar crypt-auto-write-buffer nil
- "*t value means buffers to be written to files ending in extensions
- matching those in `crypt-encoding-alist' will be encoded automatically,
- without requesting confirmation from the user. `nil' means to ask before doing
- this encoding. Likewise, buffers originating from encoded files to be written
- to different files ending in extensions that do not match any of those in
- `crypt-encoding-alist' will be written in plain format automatically, without
- requesting confirmation from the user. `nil' means to ask before doing this
- decoding.")
-
- (defvar crypt-freeze-vs-fortran t
- "*t values means that the .F file extension denotes a frozen file
- rather than a Fortran file.")
-
- (defvar crypt-encoding-alist
- (list
- '(compact "\377\037" "\\(\\.C\\)$" "compact" "uncompact" "Compact")
- '(compress "\037\235" "\\(\\.Z\\)$" "compress" "uncompress" "Compress")
- (and
- crypt-freeze-vs-fortran
- '(freeze "\037\236\\|\037\237" "\\(\\.F\\)$" "freeze" "unfreeze" "Freeze"))
- '(gzip "\037\213" "\\(\\.z\\)$" "gzip" "gzip -d" "Zip")
- ;; Add new elements here ...
- )
- "*A list of elements describing the encoding methods available, each of
- which looks like
-
- \(ENCODING-TYPE MAGIC-REGEXP FILE-EXTENSION
- ENCODE-PROGRAM DECODE-PROGRAM
- MINOR-MODE
- \)
-
- ENCODING-TYPE is a symbol denoting the encoding type. Currently known
- encodings are (compress compact freeze gzip).
-
- MAGIC-REGEXP is a regexp that matches the magic number at the
- beginning of files encoded with ENCODING-TYPE.
-
- FILE-EXTENSION is a string denoting the file extension usually
- appended the filename of files encoded with ENCODING-TYPE.
-
- ENCODE-PROGRAM is a string denoting the name of the program used to
- encode files.
-
- DECODE-PROGRAM is a string denoting the name of the program used to
- decode files.
-
- MINOR-MODE is a string denoting the name for the encoded minor mode as
- it will appear in the mode line.
- ")
-
-
- ;; buffer locals
-
- (defvar buffer-save-encrypted nil
- "*Non-nil means that when this buffer is saved it will be written out
- encrypted, using the commands in variables `crypt-encryption-program' and
- `crypt-decryption-program.' Automatically local to all buffers.")
- (make-variable-buffer-local 'buffer-save-encrypted)
-
- (defvar buffer-encryption-key nil
- "*Key to use when encrypting the current buffer, prior to saving it.
- Automatically local to all buffers.")
- (make-variable-buffer-local 'buffer-encryption-key)
-
- (defvar buffer-save-encoded nil
- "*Non-nil means that when this buffer is saved it will be written out
- encoded with ENCODING-TYPE, as with the ENCODING-PROGRAM command.
- Automatically local to all buffers.")
- (make-variable-buffer-local 'buffer-save-encoded)
-
- (defvar buffer-encoding-type nil
- "*Non-nil means that this buffer is encoded with ENCODING-TYPE.
- Automatically local to all buffers.")
- (make-variable-buffer-local 'buffer-encoding-type)
-
-
- ;; defuns that work on the encoding-alist
-
- (defun encoding-magic-regexp (encoding-type)
- "Returns a regexp that matches the magic number at the beginning of files
- encoded with ENCODING-TYPE."
- (let ((elt (assoc encoding-type crypt-encoding-alist)))
- (and elt
- (nth 1 elt))))
-
- (defun encoding-file-extension (encoding-type)
- "Returns a regexp that matches the file-extension typically associated with
- files encoded with ENCODING-TYPE."
- (let ((elt (assoc encoding-type crypt-encoding-alist)))
- (and elt
- (nth 2 elt))))
-
- (defun encoding-encode-program (encoding-type)
- "Returns a string denoting the name of the program used to encode files
- encoded with ENCODING-TYPE."
- (let ((elt (assoc encoding-type crypt-encoding-alist)))
- (and elt
- (nth 3 elt))))
-
- (defun encoding-decode-program (encoding-type)
- "Returns a string denoting the name of the program used to decode files
- encoded with ENCODING-TYPE."
- (let ((elt (assoc encoding-type crypt-encoding-alist)))
- (and elt
- (nth 4 elt))))
-
- (defun crypt-buffer-save-name (encoding-type)
- "Returns a variable name. t means that when the buffer is saved it will be
- written out using its decoding program. Automatically local to all buffers."
- (intern (concat "buffer-save-" (symbol-name encoding-type))))
-
-
- ;; Create a buffer-local variable for each type of encoding.
- ;; These variables are used to trigger the minor mode names.
-
- (defvar crypt-minor-mode-encrypted
- '(buffer-save-encrypted " Crypt")
- "Minor mode alist entry for encrypted buffers.")
-
- (defvar crypt-minor-mode-alist
- (append
- (list crypt-minor-mode-encrypted)
- (mapcar
- (function
- (lambda (element)
- (let ((variable (crypt-buffer-save-name (car element))))
- (make-variable-buffer-local variable)
- (list variable (concat " " (nth 5 element))))))
- crypt-encoding-alist))
- "Alist derived from `crypt-encoding-alist' containing encoded minor modes.")
-
-
- ;; Encrypted files have no magic number, so we have to hack a way of
- ;; determining which new buffers start in crypt mode. The current setup is
- ;; that we use only buffers that have a non-ASCII character very close to
- ;; beginning of buffer and that do NOT match crypt-magic-regexp-inverse.
- ;; Currently crypt-magic-regexp-inverse will match Sun OS, 4.x BSD, and
- ;; Ultrix executable magic numbers, so binaries can still be edited (heh)
- ;; without headaches.
-
- (defconst crypt-magic-regexp-inverse
- "\\(..\\)?\\([\007\010\013]\001\\|\001[\007\010\013]\\)"
- "Regexp that must NOT match the beginning of an encrypted buffer.")
-
- (defmacro save-point (&rest body)
- "Save value of point, evaluate FORMS, and restore value of point.
- If the saved value of point is no longer valid go to (point-max).
- This macro exists because, save-excursion loses track of point during
- some types of deletions."
- (let ((var (make-symbol "saved-point")))
- (list 'let (list (list var '(point)))
- (list 'unwind-protect
- (cons 'progn body)
- (list 'goto-char var)))))
-
-
- (defun crypt-find-file-hook ()
- "Hook run for decoding and/or decrypting the contents of a buffer. Part of
- find-file-hooks"
- (let ((buffer-file-name buffer-file-name)
- (old-buffer-file-name buffer-file-name)
- (old-buffer-modified-p (buffer-modified-p))
- found
- elt regexp
- encrypted encoded
- case-fold-search buffer-read-only)
-
- (save-point
- (save-restriction
- (widen)
- (goto-char (point-min))
-
- ;; We can reasonably assume that either compaction or compression will
- ;; be used, or neither, but not both.
-
- ;; find the file type
-
- (let ((alist crypt-encoding-alist))
- (while (and alist (setq elt (car alist)) (not found))
- (if (looking-at (nth 1 elt))
- (progn (setq buffer-encoding-type (nth 0 elt))
- (setq found t))
- ;; decrement
- (setq alist (cdr alist)))))
-
- ;; do we have to decode? if not move on
- (if (and found
- (or crypt-auto-decode-buffer
- (y-or-n-p (format "Decode buffer %s? "
- (buffer-name)))))
- (progn
- (message "Decoding %s..." (buffer-name))
- (encode-buffer (current-buffer) t)
-
- ;; We can not actually go into encoding mode yet because the
- ;; major mode may change later on and blow away all local
- ;; variables (and thus the minor modes). So we make a note to go
- ;; into encoding mode later.
-
- (setq encoded buffer-encoding-type)
-
- ;; here we strip the encoded file's extension so that later we
- ;; can set the buffer's major mode based on this modified name
- ;; instead of the name with the extension.
-
- (if (string-match (encoding-file-extension buffer-encoding-type)
- buffer-file-name)
- (setq buffer-file-name
- (substring buffer-file-name 0 (match-beginning 1))))
-
- (if (not (input-pending-p))
- (message "Decoding %s... done" (buffer-name)))))
-
- ;; Now peek at the file and see if it still looks like a binary file.
- ;; If so, try the crypt-magic-regexp-inverse against it and if it FAILS
- ;; we assume that this is an encrypted buffer.
-
- (cond (
-
- (and (not (eobp))
- (re-search-forward "[\200-\377]" (min (point-max) 15) t)
- (goto-char (point-min))
- (not (looking-at crypt-magic-regexp-inverse)))
-
- (if (not buffer-encryption-key)
- (call-interactively 'set-encryption-key))
-
- ;; if user did not enter a key, turn off crypt mode. good for
- ;; binaries that crypt-magic-regexp-inverse doesn't recognize.
- ;; -- thanx to Paul Dworkin (paul@media-lab.media.mit.edu)
-
- (if (equal buffer-encryption-key "")
-
- (message "No key given, buffer %s assumed normal."
- (buffer-name))
-
- (message "Decrypting %s..." (buffer-name))
-
- (crypt-buffer buffer-encryption-key nil)
-
- ;; Tuck the key away for safe keeping since setting the major
- ;; mode may well blow it away.
-
- (setq encrypted buffer-encryption-key)
-
- (if (not (input-pending-p))
- (message "Decrypting %s... done" (buffer-name))))))
- ))
-
- ;; OK, if any changes have been made to the buffer we need to rerun the
- ;; code the does automatic selection of major mode.
-
- (cond (
-
- (or encoded encrypted)
- (set-auto-mode)
- (hack-local-variables)
-
- ;; Now set our own minor modes.
- (if encoded
- (progn
- (setq buffer-encoding-type encoded)
- (encoded-mode 1)))
-
- (if encrypted
- (progn (crypt-mode 1)
- (setq buffer-encryption-key encrypted)))
-
- ;; Restore buffer file name now, so that lock file entry is removed
- ;; properly.
-
- (setq buffer-file-name old-buffer-file-name)
-
- ;; Restore buffer modified flag to its previous value. This will
- ;; also remove the lock file entry for the buffer if the previous
- ;; value was nil; this is why buffer-file-name had to be manually
- ;; restored above.
-
- (set-buffer-modified-p old-buffer-modified-p)))))
-
-
- ;; This function should be called ONLY as a write-file hook.
- ;; Odd things will happen if it is called elsewhere.
-
- (defun crypt-write-file-hook ()
-
- "Writes out file, if need be, in a non-plain format. Note this terminates
- the calls in write-file-hooks so should probably be at the end of that list."
-
- ;; We flag a buffer to be written out in encoded form if the file ends in
- ;; one of the file-extensions in crypt-encoding-alist. Conversely, we write
- ;; out a buffer as a plain file if it does _not_ end in one of these
- ;; file-extensions even if buffer-save-encoded is non-`nil'.
-
- (let ((alist crypt-encoding-alist)
- case-fold-search found elt)
-
- ;; search through the file name extensions for a match
- (while (and alist (setq elt (car alist)) (not found))
- (if (string-match (nth 2 elt) buffer-file-name)
- (setq found t)
- ;; decrement
- (setq alist (cdr alist))))
-
- ;; did we find a match?
- (if found
-
- ;; file name ends in a very provocative extension
-
- ;; check to see if we should write as an encoded file
- (if buffer-save-encoded
-
- ;; already encoded - do the methods of encoding match? - if not
- ;; then change the method of encoding
- (if (and
- (not (eq (nth 0 elt) buffer-encoding-type))
- (or crypt-auto-write-buffer
- (y-or-n-p (concat "write file using " (nth 3 elt) "? "))))
-
- ;; case one
- ;; turn off original encoding and turn on new encoding
- (progn (encoded-mode -1)
- (setq buffer-encoding-type (nth 0 elt))
- (encoded-mode 1)))
-
- ;; was a plain file
- (if (or crypt-auto-write-buffer
- (y-or-n-p (concat "write file using " (nth 3 elt) "? ")))
-
- ;; case two
- ;; turn on encoding flags and _then_ the minor mode
- (progn (setq buffer-save-encoded t)
- (setq buffer-encoding-type (nth 0 elt))
- (encoded-mode 1))))
-
- ;; no match - a plain-jane file extension - but if the encoded flag is
- ;; non-`nil' then the user may really want it written out in plain
- ;; format so we must override this flag
- (if (and buffer-save-encoded
- (or crypt-auto-write-buffer
- (y-or-n-p "write as a plain file? ")))
-
- ;; case three
- ;; turn off the minor mode and _then_ the flags
- (progn (encoded-mode -1)
- (setq buffer-save-encoded nil)
- (setq buffer-encoding-type nil)))))
-
- ;; Now decide whether or not we need to continue with this defun. Does the
- ;; buffer need to be saved in a non-plain form? If not then writing is not
- ;; done here but later in the write-file-hooks (probably at the end).
-
- (if (or buffer-save-encoded buffer-save-encrypted)
-
- (save-excursion
- (save-restriction
- (let
-
- ;; BINDINGS
- ((copy-buffer (get-buffer-create " *crypt copy buffer*"))
- (selective-display selective-display)
- (buffer-read-only))
-
- ;; FORMS
- (copy-to-buffer copy-buffer 1 (1+ (buffer-size)))
- (narrow-to-region (point) (point))
-
- (unwind-protect
-
- (progn
- (insert-buffer-substring copy-buffer)
- (kill-buffer copy-buffer)
-
- ;; selective-display non-`nil' means we must convert
- ;; carriage returns to newlines now, and set
- ;; selective-display temporarily to nil.
-
- (cond (selective-display
- (goto-char (point-min))
- (subst-char-in-region (point-min) (point-max) ?\r ?\n)
- (setq selective-display nil)))
-
- (cond
- (buffer-save-encrypted
- (if (null buffer-encryption-key)
- (error "No encryption key set for buffer %s"
- (buffer-name)))
- (if (not (stringp buffer-encryption-key))
- (error "Encryption key is not a string"))
- (message "Encrypting %s..." (buffer-name))
- (crypt-buffer buffer-encryption-key t)))
-
- (cond
- (buffer-save-encoded
- (message "Encoding %s..." (buffer-name))
- (encode-buffer)))
-
- ;; write buffer/region to disk
- (write-region (point-min) (point-max) buffer-file-name nil t)
- (delete-region (point-min) (point-max))
- (set-buffer-modified-p nil)
-
- ;; return t so that basic-save-buffer will
- ;; know that the save has already been done.
-
- ;; NOTE: this TERMINATES write-file-hooks so any hooks
- ;; following crypt-write-file-hook will not be executed
-
- t )
- ;; unwind...sit back...take a load off...have a beer
- ;; If the crypted stuff has already been removed
- ;; then this is a no-op.
- (delete-region (point-min) (point-max))))))))
-
-
- ;;;; Defuns that do the actual decoding-encoding and decryption-encryption
-
- ;;; ENCRYPTING
-
- (defun crypt-region (start end encrypt key)
-
- "Encrypt/decrypt the text in the region. From a program, this function takes
- four args: START, END, ENCRYPT and KEY. When called interactively START and
- END default to point and mark \(START being the lesser of the two\), KEY is
- prompted for. If ENCRYPT is t encryption is done otherwise decrypt is done
- using contents of variables `crypt-encryption-program' and
- `crypt-decryption-program.'"
-
- (interactive
- (progn
- (barf-if-buffer-read-only)
- (list (region-beginning) (region-end)
- (y-or-n-p "Encrypt? ")
- (read-string-no-echo "Crypt region using key: "))))
-
- (save-point
- (let ((opoint-max (point-max)))
- (call-process-region
- start end shell-file-name t t nil "-c"
- (concat
- (if encrypt crypt-encryption-program crypt-decryption-program)
- " " key)))))
-
- (defun crypt-buffer (key encrypt &optional buffer)
-
- "Using KEY, if prefix arg (or ENCRYPT non-nil from a program), then encrypt
- BUFFER \(defaults to the current buffer\), otherwise decrypt."
-
- (interactive
- (progn
- (barf-if-buffer-read-only)
- (list (read-string-no-echo "Crypt buffer using key: ")
- current-prefix-arg
- (read-buffer "Crypt buffer: " (current-buffer)))))
-
- (or buffer (setq buffer (current-buffer)))
- (save-excursion (set-buffer buffer)
- (crypt-region (point-min) (point-max) encrypt key)))
-
-
- ;;; ENCODING
-
- (defun encode-region (start end &optional undo)
-
- "Encode the text in the region. From a program, this function takes three
- args: START, END and UNDO. When called interactively START and END default to
- point and mark \(START being the lesser of the two\). Prefix arg \(or
- optional second arg non-nil\) UNDO means decode."
-
- (interactive "*r\nP")
-
- (save-point
-
- (call-process-region
- start end shell-file-name t t nil "-c"
- (if undo (encoding-decode-program buffer-encoding-type)
- (encoding-encode-program buffer-encoding-type)))
-
- (cond ((not undo)
- (goto-char start)
- (let (case-fold-search)
- (if (not (looking-at (encoding-magic-regexp buffer-encoding-type)))
- (error "%s failed!" (if undo "Decoding" "Encoding"))))))))
-
- (defun encode-buffer (&optional buffer undo)
-
- "Encode BUFFER \(defaults to the current buffer\). Prefix arg \(or second
- arg non-nil from a program) UNDO means decode."
-
- (interactive (list (current-buffer) current-prefix-arg))
- (or buffer (setq buffer (current-buffer)))
- (save-excursion (set-buffer buffer)
- (encode-region (point-min) (point-max) undo)))
-
-
-
- ;;;; MODES
-
- (defun crypt-mode (&optional arg)
-
- "Toggle crypt mode. With arg, turn crypt mode on iff arg is positive,
- otherwise turn it off. In crypt mode, buffers are automatically encrypted
- before being written. If crypt mode is toggled and a key has been set for the
- current buffer, then the current buffer is marked modified, since it needs to
- be rewritten with \(or without\) encryption.
-
- Use \\[set-encryption-key] to set the encryption key for the current buffer.
-
- Entering crypt mode causes auto-saving to be turned off in the current buffer,
- as there is no way \(in Emacs Lisp\) to force auto save files to be
- encrypted."
-
- (interactive "P")
- (let ((oldval buffer-save-encrypted))
- (setq buffer-save-encrypted
- (if arg (> arg 0) (not buffer-save-encrypted)))
- (if buffer-save-encrypted
- (auto-save-mode 0)
- (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
- (if buffer-encryption-key
- (set-buffer-modified-p
- (not (eq oldval buffer-save-encrypted))))))
-
-
-
- (defun encoded-mode (&optional arg)
-
- "Toggle encoded mode. With arg, turn encoded mode on iff arg is positive,
- otherwise turn it off. In encoded mode, buffers are automatically encoded
- before being written. If encoded mode is toggled, the current buffer is
- marked modified, since it needs to be written with (or without) encoding.
-
- Entering encoded mode causes auto-saving to be turned off in the current
- buffer, as there is no way (in Emacs Lisp) to force auto save files to be
- encoded."
-
- (interactive "P")
- (let ((oldval buffer-save-encoded))
-
- (setq buffer-save-encoded
- (if arg (> arg 0) (not buffer-save-encoded)))
- (set-variable (crypt-buffer-save-name buffer-encoding-type)
- buffer-save-encoded)
-
- (if buffer-save-encoded
- (auto-save-mode 0)
- (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
-
- (set-buffer-modified-p (not (eq oldval buffer-save-encoded)))))
-
-
- ;;;; Additional crypt defuns
-
- (defun read-string-no-echo (prompt &optional confirm)
-
- "Read a string from the minibuffer, prompting with PROMPT. Optional second
- argument CONFIRM non-nil means that the user will be asked to type the string
- a second time for confirmation and if there is a mismatch, the process is
- repeated.
-
- Line editing keys are --
- C-h, DEL rubout
- C-u, C-x line kill
- C-q, C-v literal next"
-
- (catch 'return-value
- (save-excursion
- (let ((input-buffer (get-buffer-create " *password*"))
- (cursor-in-echo-area t)
- (echo-keystrokes 0)
- char string help-form done kill-ring)
- (set-buffer input-buffer)
- (unwind-protect
- (while t
- (erase-buffer)
- (message prompt)
- (while (not (memq (setq char (read-char)) '(?\C-m ?\C-j)))
- (if (setq form
- (cdr
- (assq char
- '((?\C-h . (delete-char -1))
- (?\C-? . (delete-char -1))
- (?\C-u . (delete-region 1 (point)))
- (?\C-x . (delete-region 1 (point)))
- (?\C-q . (quoted-insert 1))
- (?\C-v . (quoted-insert 1))))))
- (condition-case error-data
- (eval form)
- (error t))
- (insert char))
- (message prompt))
- (cond ((and confirm string)
- (cond ((not (string= string (buffer-string)))
- (message
- (concat prompt "[Mismatch... try again.]"))
- (ding)
- (sit-for 2)
- (setq string nil))
- (t (throw 'return-value string))))
- (confirm
- (setq string (buffer-string))
- (message (concat prompt "[Retype to confirm...]"))
- (sit-for 2))
- (t (throw 'return-value (buffer-string)))))
- (set-buffer-modified-p nil)
- (kill-buffer input-buffer))))))
-
- (defun set-encryption-key (key &optional buffer)
-
- "Set the encryption KEY for BUFFER. KEY should be a string. BUFFER should be
- a buffer or the name of one; it defaults to the current buffer. If BUFFER is
- in crypt mode, then it is also marked as modified, since it needs to be saved
- with the new key."
-
- (interactive
- (progn
- (barf-if-buffer-read-only)
- (list
- (read-string-no-echo
- (format "Set encryption key for buffer %s: " (buffer-name))))))
- (or buffer (setq buffer (current-buffer)))
- (save-excursion
- (set-buffer buffer)
- (if (equal key buffer-encryption-key)
- (message "Key is identical to original, no change.")
- (setq buffer-encryption-key key)
- ;; don't touch the modify flag unless we're in crypt-mode.
- (if buffer-save-encrypted
- (set-buffer-modified-p t)))))
-
-
- ;; Install the hooks, then add the mode indicators to the minor mode alist.
-
- ;; Check that the hooks are not already installed.
-
- (cond
- ((not (memq 'crypt-write-file-hook write-file-hooks))
- ;; make this hook last on purpose
- (setq write-file-hooks (append write-file-hooks
- (list 'crypt-write-file-hook))
- find-file-hooks (cons 'crypt-find-file-hook find-file-hooks)
- find-file-not-found-hooks (cons 'crypt-find-file-hook
- find-file-not-found-hooks))))
-
- ;; Check that the mode indicators are not already installed.
-
- (cond
- ((not (memq crypt-minor-mode-encrypted minor-mode-alist))
- ;; add the mode indicators
- (setq minor-mode-alist (append crypt-minor-mode-alist
- minor-mode-alist))))
-
-
- ;;;; BUG REPORTS
-
- ;;; this section is provided for reports.
- ;;; adopted from Barry A. Warsaw's c++-mode.el
-
- (defvar crypt-mailer 'mail
- "*Mail package to use to generate report mail buffer.")
-
- (defconst crypt-help-address
- "dodd@roebling.poly.edu, rwhitby@research.canon.oz.au"
- "Address(es) accepting submission of reports on crypt++.el.")
-
- (defconst crypt-maintainer "Larry and Rod"
- "First name(s) of people accepting submission of reports on crypt++.el.")
-
- (defconst crypt-file "crypt++.el"
- "Name of file containing emacs lisp code.")
-
- (defun crypt-submit-report ()
- "Submit via mail a report using the mailer in crypt-mailer, filename in
- crypt-file, to address in crypt-help-address."
- (interactive)
- (funcall crypt-mailer)
- (insert crypt-help-address)
- (if (re-search-forward "^subject:[ \t]+" (point-max) 'move)
- (insert "Report on " crypt-file " version " crypt-version))
- (if (not (re-search-forward mail-header-separator (point-max) 'move))
- (progn (goto-char (point-max))
- (insert "\n" mail-header-separator "\n")
- (goto-char (point-max)))
- (forward-line 1))
- (set-mark (point)) ;user should see mark change
- (insert "\n\n---------\n")
- (insert (emacs-version) "\n")
- (insert "code: " crypt-file ",v " crypt-version)
- (insert "\n\n")
- (insert "current value of crypt-encoding-alist:\n\n")
- (insert (prin1-to-string crypt-encoding-alist))
- (exchange-point-and-mark)
- (insert "\n" crypt-maintainer ",\n\n ")
- (message "%s, please write the message, use C-c C-c to send" (user-login-name)))
-
- ;; provide this package
- (provide 'crypt++)
- ........................... cut along dotted line ...........................
- <end file: ~/lisp/crypt++.el>
-