1
;;; crypt++.el -- handle all sorts of compressed and encrypted files
1
;;; crypt.el -- handle all sorts of compressed and encrypted files
2
2
;;; (may also be installed as crypt.el)
4
4
;; Authors: Lawrence R. Dodd <dodd@roebling.poly.edu>
5
5
;; Rod Whitby <rwhitby@research.canon.oz.au>
6
6
;; Kyle E. Jones <kyle@uunet.uu.net>
7
;; Maintainer: <karl@gnu.org>
8
;; Created: crypt.el in 1988, crypt++.el on 18 Jan 1993.
7
;; Maintainer: xemacs-beta@xemacs.org
8
;; Created: crypt.el in 1988, crypt++.el on 18 Jan 1993
10
;; Date: 1994/03/31 12:30:17
10
11
;; Keywords: extensions
11
;; $Id: crypt++.el,v 1.31 2003/01/17 18:52:17 karl Exp $
13
13
;;; Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
14
14
;;; Copyright (C) 1994 Lawrence R. Dodd
29
29
;;; along with this program; if not, write to the Free Software
30
30
;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32
;;; Synched up with: Not in FSF.
34
36
;;; Please see notes on INSTALLATION and USAGE on the pages below.
36
38
;;; LCD Archive Entry:
37
;;; crypt++|Rod Whitby and Lawrence R. Dodd|karl@gnu.org|
38
;;; Handle compressed and encrypted files.|
39
;;; 2003-01-17|2.92|~/misc/crypt++.el.Z|
42
;;; http://www.cs.umb.edu/~karl/crypt++/
43
;;; news:gnu.emacs.sources
39
;;; crypt++|Rod Whitby and Lawrence R. Dodd|xemacs-beta@xemacs.org|
40
;;; Code for handling all sorts of compressed and encrypted files.|
41
;;; 1994/03/31 12:30:17|2.94|~/misc/crypt++.el.Z|
46
45
;;; Type M-x crypt-submit-report to generate a bug report template or put your
47
46
;;; cursor at the end of this line and type C-x C-e: (crypt-submit-report)
58
57
;;; Polytechnic University
59
58
;;; Brooklyn, New York USA
63
;;; Ident: crypt++.el,v 2.82 1994/03/31 12:30:17 dodd Exp
64
;;; Date: 1994/03/31 12:30:17
64
;;; To use this package, simply put it in a file called "crypt++.el" in a Lisp
69
;;; To use this package, simply put it in a file called "crypt.el" in a Lisp
65
70
;;; directory known to Emacs (see `load-path'), byte-compile it (ignore
66
71
;;; warnings about undefined functions), and put the line:
68
;;; (require 'crypt++)
70
75
;;; in your ~/.emacs file or in the file default.el in the ../lisp directory
71
76
;;; of the Emacs distribution.
73
78
;;; For reliable operation with Emacs versions with coding system
74
79
;;; support, you also need:
76
81
;;; (modify-coding-system-alist 'file "\\.bz\\'" 'no-conversion)
77
82
;;; (modify-coding-system-alist 'file "\\.bz2\\'" 'no-conversion)
78
83
;;; (modify-coding-system-alist 'file "\\.gpg\\'" 'no-conversion)
79
84
;;; (modify-coding-system-alist 'file "\\.gz\\'" 'no-conversion)
80
85
;;; (modify-coding-system-alist 'file "\\.Z\\'" 'no-conversion)
82
87
;;; With XEmacs, you need 'no-conversion-unix instead of 'no-conversion.
83
88
;;; (Thanks to Jose M. Vidal <vidal@sc.edu>.)
90
;;; XEmacs note: not modifying file-coding-system-alist to include .gpg,
91
;;; because those files are ASCII-compatible, and non-ASCII-compatible
92
;;; support in XEmacs is and will remain (for the moment) patchy at best.
85
94
;;; Otherwise, Emacs tampers with the bytes before crypt++ gets them.
86
95
;;; The above won't help for files without those extensions. You just
87
96
;;; have to specify the no-conversion coding system manually when
88
97
;;; visiting those files, or set no-conversion for all files if that suits you.
90
99
;;; Do not bother trying to autoload this package; it uses find-file and
91
100
;;; write-file hooks and thus should be loaded the first time you visit
92
101
;;; any sort of file. Any package loaded after this one that appends
100
109
;;; with "ln -s crypt++.el crypt.el". This will make crypt++ act like a
101
110
;;; drop-in replacement for the original crypt since any package requiring
102
111
;;; crypt will find crypt++ instead.
104
112
;;; NOTE: encryption users should set `crypt-encryption-type' to one of the
105
113
;;; values in `crypt-encryption-alist' (see USAGE below).
115
;;; SEE ALSO: /roebling.poly.edu:/pub/crypt++-fnf.el for file-not-found
116
;;; support for GNU Emacs.
107
118
;;; SPECIAL NOTES:
109
;;; If crypt++ is dumped with the emacs executable, or if it has already been
120
;;; If crypt is dumped with the emacs executable, or if it has already been
110
121
;;; loaded in an emacs session, then modifying the variables used in building
111
122
;;; the encryption and encoding tables will have no effect until these tables
112
123
;;; are rebuilt. This may be done with `M-x crypt-rebuild-tables'. See USAGE
116
127
;;; via `M-x crypt-rebuild-tables'. Similarly, post-load changes to
117
128
;;; `crypt-bind-insert-file' are handled with `M-x crypt-bind-insert-file'.
119
;;; DUMPING CRYPT++ WITH GNU EMACS 18:
121
;;; If crypt++ has been dumped with emacs then calls to `crypt-rebuild-tables'
122
;;; and `crypt-bind-insert-file' will be needed in the user's ~/.emacs or
123
;;; ../lisp/default.el file in order to assure the changes take effect. For
126
;;; ;; Set my own preferences...
127
;;; (setq crypt-encryption-type 'des
128
;;; crypt-encryption-file-extension "\\(\\.e\\)$"
129
;;; crypt-bind-insert-file nil
130
;;; crypt-freeze-vs-fortran nil)
132
;;; ;; Has crypt++ been loaded already?
133
;;; (if (featurep 'crypt++)
135
;;; ;; Yes. Just rebuild the encryption and encoding tables
136
;;; ;; and key binding.
138
;;; (crypt-rebuild-tables)
139
;;; (crypt-bind-insert-file))
141
;;; ;; No. Load the whole thing.
142
;;; (require 'crypt++))
144
;;; This guarantees that the users preferences will be incorporated into
145
;;; crypt++ without having to reload all of crypt++.el to do it.
147
;;; In GNU Emacs 19 and Lucid Emacs 19.8 the execution of
148
;;; `crypt-rebuild-tables' and `crypt-bind-insert-file' is done automatically
149
;;; through `after-init-hook'. So, for the above example, all that is needed
152
;;; ;; Set my own preferences...
153
;;; (setq crypt-encryption-type 'des
154
;;; crypt-encryption-file-extension "\\(\\.e\\)$"
155
;;; crypt-bind-insert-file nil
156
;;; crypt-freeze-vs-fortran nil)
158
;;; (require 'crypt++)
160
;;; There is an `after-init-hook' in Lucid Emacs v 19.8 but in early versions
161
;;; of Lucid Emacs it will use `term-setup-hook' instead.
166
133
;;; By default, intended to be transparent. User-defined variables
168
;;; controlling ENCRYPTION are:
135
;;; controlling ENCRYPTION are
169
137
;;; crypt-encryption-type
170
138
;;; crypt-encryption-file-extension
171
139
;;; crypt-never-ever-decrypt
195
164
;;; the end of any of the variable names, and hit C-h v [RET].
197
166
;;; NOTE: encryption users should set `crypt-encryption-type' to one of the
198
;;; values in `crypt-encryption-alist'.
200
;;; Although rarely needed, the following may be called interactively:
167
;;; values in `crypt-encryption-alist'
169
;;; Although rarely needed, the following functions may be called interactively
201
171
;;; (crypt-encoded-mode)
202
172
;;; (crypt-encode-region)
203
173
;;; (crypt-encrypted-mode)
207
177
;;; (crypt-insert-file)
208
178
;;; (crypt-bind-insert-file)
209
179
;;; (crypt-submit-report)
210
;;; (crypt-pgp-pub-clear-recipients)
212
181
;;; To find out more about these functions, load this file, put your cursor
213
182
;;; inside any of the `()' of the above lines, and hit C-h f [RET].
215
;;; You may wish to use mailcrypt in conjunction with crypt++.
216
;;; http://mailcrypt.sourceforge.net/
219
185
;;; NOTES ON INTERFACES WITH OTHER PROGRAMS AND PACKAGES:
221
187
;;; GZIP: the environment variable GZIP of gzip can cause an error if it
222
188
;;; contains `--verbose' because standard output messages will be appended to
223
189
;;; gzip'ed files. This corrupts the files. The cleanest solution is to pass
224
;;; the `--quiet' switch in `crypt-encoding-alist' to override this. Use gzip
225
;;; version 1.0.4 or higher from ftp://ftp.gnu.org/pub/gnu/gzip-*.tar.gz.
190
;;; the `--quiet' switch in `crypt-encoding-alist' to override this. use gzip
191
;;; version 1.0.4 or higher from prep.ai.mit.edu:/pub/gnu
227
193
;;; TAR-MODE: works properly with version 1.28 (or higher) with v19 emacs.
229
;;; RMAIL and CHANGING MAJOR MODE (for v18 ONLY): in v18 emacs
230
;;; crypt++.el's buffer local variables are smashed whenever the major
231
;;; mode is changed of a buffer or whenever RMAIL is run on an encrypted
232
;;; and/or compressed file. This screws things up. No smashing occurs
233
;;; with v19 Emacs. for v18 emacs Joe Wells' "kill-fix.el" is needed to
234
;;; prevent this. Get a copy of kill-fix.el from
235
;;; archive.cis.ohio-state.edu, store it where emacs can find it, stick
236
;;; a "(require 'kill-fix)" anywhere in your ~/.emacs, and the problem
239
;;; LISPDIR: if you save this file as crypt++.el then the "(require 'crypt)"
240
;;; in lispdir.el needs to be replaced with "(require 'crypt++)"
241
;;; or the symbolic link suggested above can be used.
758
710
;;; (crypt-encoded-disable-auto-save, crypt-encrypted-disable-auto-save):
759
711
;;; New user-defined variables. (crypt-encoded-mode, crypt-encrypted-mode):
762
;;; kb: Changed occurrences of roebling. Do (set-visited-file-name).
763
;;; Incorporate patches from David Rosinger <dsrosing@ingr.com> for win32.
765
;;; kb: Applied XEmacs 2.83 patch by hniksic to add custom support.
766
;;; Support .tgz as .tar.gz.
767
;;; Add bzip support.
768
;;; Merge pgp support from John Heidemann <johnh@isi.edu>,
769
;;; http://www.isi.edu/~johnh/SOFTWARE/index.html.
770
;;; Requires either mailcrypt or "PEM - PGP Enhanced Messaging for
771
;;; GNU Emacs" from Roy Frederick Busdiecker, III (Rick).
772
;;; Merge Mac support from Daniel M. German <dmg@csg.uwaterloo.ca>.
774
;;; cro@nca.asu.edu: Add support in pgp-pub for encrypting files with
775
;;; multiple user's keys. New variables: crypt-pgp-pub-multirecipients,
776
;;; crypt-pgp-pub-recipients, crypt-pgp-pub-recipients-history.
777
;;; This support is on by default.
778
;;; nosuzuki@e-mail.ne.jp: defvar shell-command-switch.
779
;;; knabe@cs.virginia.edu: crypt-pgp variable names.
781
;;; nmg97r@ecs.soton.ac.uk: Discard stderr from subprocesses instead
782
;;; of inserting into the current buffer.
784
;;; add crypt-decode-{dos,mac}-p.
786
;;; kifer@cs.sunysb.edu: (coding-system-for-write 'no-conversion)
787
;;; ryk@coho.net: (buffer-file-coding-system 'no-conversion)
788
;;; johnh@isi.edu: mailcrypt & pgp/pgp5.0/gpg.
790
;;; joerg@plate.cx (Joerg Plate): bzip != bzip2.
791
;;; plord@hgmp.mrc.ac.uk (Phillip Lord) (crypt-file-write-hook):
792
;;; (let inhibit-read-only t) so we can save with read-only properties.
793
;;; cro@nca.asu.edu (Charles R. Oldham) (crypt-pgp-pub-encrypt-region):
794
;;; typo, pgp used in gpg block.
795
;;; hull@paracel.com (David Hull): gpg file support, also
796
;;; set coding-system-for-read to 'no-conversion, fixes decryption
797
;;; bug with files beginning with a blank line.
798
;;; kb (crypt-encode-region): set coding-system-for-*. This
799
;;; backwards incompatibility sure has been painful.
801
;;; kb: pattern for .elc files.
803
;;; forcer@debian.org (Jorgen Schaefer): mcrypt entry.
804
;;; doc fixes from dmagda@magda.ca (David Magda)
805
;;; and vidal@sc.edu (Jose Vidal).
807
;;; kb: no more ftp.cs.umb.edu.
808
;;; mernst@alum.mit.edu (Michael Ernst): rc4 encoding.
714
;;; hniksic: Added custom.
716
;;; Aidan Kehoe: imported Karl Berry's Crypt++. See ChangeLog for details
717
;;; of the changes made there.
813
722
;;;; User definable variables.
814
723
(defvar shell-command-switch "-c") ; in case it isn't defined yet.
816
(defvar crypt-encryption-type 'crypt
727
"Handling compressed and encrypted files."
731
(defcustom crypt-encryption-type 'crypt
817
732
"*Method of encryption. Must be an element of `crypt-encryption-alist.'
818
If you change this after crypt++ is loaded then do \\[crypt-rebuild-tables].")
733
If you change this after crypt++ is loaded then do \\[crypt-rebuild-tables]."
820
(defvar crypt-encryption-file-extension nil
737
(defcustom crypt-encryption-file-extension nil
821
738
"*Regexp for extension of files encrypted with `crypt-encryption-type.'
822
739
Should be of the form \"\\\\(\\\\.foo\\\\)$\". nil says use default values in
823
740
`crypt-encryption-alist.' If you change this after crypt++ is loaded then do
824
\\[crypt-rebuild-tables].")
826
(defvar crypt-never-ever-decrypt nil
827
"*t says never attempt to decrypt a buffer.")
829
(defvar crypt-auto-write-buffer-encrypted nil
741
\\[crypt-rebuild-tables]."
745
(defcustom crypt-never-ever-decrypt nil
746
"*t says never attempt to decrypt a buffer."
750
(defcustom crypt-auto-write-buffer-encrypted nil
830
751
"*t says files with `crypt-encryption-alist' file extension auto-encrypted.
831
nil says query. See `crypt-auto-write-buffer.'")
833
(defvar crypt-confirm-password nil
834
"*t says confirm new passwords and when writing a newly encrypted buffer.")
836
(defvar crypt-encoded-disable-auto-save t
752
nil says query. See `crypt-auto-write-buffer.'"
756
(defcustom crypt-confirm-password nil
757
"*t says confirm new passwords when writing a newly encrypted buffer."
761
(defcustom crypt-encoded-disable-auto-save t
837
762
"*If t, turn off auto-save-mode for buffers which are encoded.
838
763
If non-nil but not t, then no message is displayed.
846
771
It is probably best to set this variable to nil and use buffer-local
847
772
variables in files for which you don't actually care about autosaves.
848
Unencoded recovery data is better than none at all.")
773
Unencoded recovery data is better than none at all."
774
:type '(choice (const :tag "on" t)
775
(const :tag "off" nil)
776
(const :tag "no message" other))
850
(defvar crypt-encrypted-disable-auto-save t
779
(defcustom crypt-encrypted-disable-auto-save t
851
780
"*If t, turn off auto-save-mode for buffers which are encrypted.
852
781
If non-nil but not t, then no message is displayed.
1052
(defvar crypt-auto-decode-buffer t
999
(defcustom crypt-auto-decode-buffer t
1053
1000
"*t says buffers visiting encoded files will be decoded automatically.
1054
nil means to ask before doing the decoding.")
1001
nil means to ask before doing the decoding."
1056
(defvar crypt-auto-write-buffer nil
1005
(defcustom crypt-auto-write-buffer nil
1057
1006
"*t says save files with `crypt-encoding-alist' file extensions as encoded.
1058
1007
nil says to ask before doing this encoding. Similarly, buffers originating
1059
1008
from encoded files to be written to files not ending in `crypt-encoding-alist'
1060
1009
file extensions will be written in plain format automatically. nil says to
1061
ask before doing this decoding.")
1010
ask before doing this decoding."
1063
1014
;; This is an internal variable documented here and not in a DOCSTRING in
1064
1015
;; order to save memory. If this variable's value has been changed from its
1102
1055
NOTE: (1) this does not affect find-file (C-x C-f) since that works with a
1103
1056
magic regexp. (2) there is no way to distinguish between write-file and
1104
save-buffer so nil will mean that neither will query.")
1057
save-buffer so nil will mean that neither will query."
1106
(defvar crypt-freeze-vs-fortran t
1061
(defcustom crypt-freeze-vs-fortran t
1107
1062
"*t says `.F' file extension denotes a frozen file not a Fortran file.
1108
1063
If you change this variable after crypt++ has been loaded then do
1109
\\[crypt-rebuild-tables].")
1064
\\[crypt-rebuild-tables]."
1111
(defvar crypt-compact-vs-C++ nil
1068
(defcustom crypt-compact-vs-C++ nil
1112
1069
"*t says `.C' file extension denotes a compacted file not a C++ file.
1113
1070
If you change this variable after crypt++ has been loaded then do
1114
\\[crypt-rebuild-tables].")
1071
\\[crypt-rebuild-tables]."
1116
(defvar crypt-ignored-filenames nil
1075
(defcustom crypt-ignored-filenames nil
1117
1076
"*List of regexp filenames for which encoded to plain conversion is not done.
1118
1077
A filename with a plain extension, in encoded format, that is matched by one of
1119
1078
these elements will be saved in encoded format without a query for conversion to
1123
1082
for RMAIL and VM which look for files `RMAIL' and `INBOX,' respectively, to
1124
1083
store incoming mail. For example, the gzip extensions on `RMAIL.gz' and
1125
1084
`INBOX.gz' can be removed, this variable set to '\(\"INBOX$\" \"RMAIL$\"\) and
1126
no query about conversion to plain format will be made.")
1085
no query about conversion to plain format will be made."
1086
:type '(repeat regexp)
1128
(defvar crypt-default-encoding "gzip"
1089
(defcustom crypt-default-encoding "gzip"
1129
1090
"*Default encoding type as string used when `crypt-encoded-mode' is toggled.
1130
Must match one of the elements of `crypt-encoding-alist'.")
1091
Must match one of the elements of `crypt-encoding-alist'."
1132
(defvar crypt-dos-has-ctrl-z nil
1095
(defcustom crypt-dos-has-ctrl-z nil
1133
1096
"t if this buffer had a ctrl-z stripped from end, otherwise, nil.
1134
Buffer local and set by `crypt-dos-to-unix-region'")
1097
Buffer local and set by `crypt-dos-to-unix-region'"
1135
1100
(make-variable-buffer-local 'crypt-dos-has-ctrl-z)
1136
1101
(setq-default crypt-dos-has-ctrl-z nil)
1137
1102
(put 'crypt-dos-has-ctrl-z 'permanent-local t) ; for v19 Emacs
1474
1440
(if (and (not (null buffer-file-name))
1475
1441
(string-match "\\.Z$" buffer-file-name))
1476
1442
(set-visited-file-name
1477
(substring buffer-file-name 0 (match-beginning 0))))
1478
(if (and (not (null buffer-file-name))
1479
(string-match "\\.g?z$" buffer-file-name))
1480
(set-visited-file-name
1481
(substring buffer-file-name 0 (match-beginning 0))))
1482
(if (and (not (null buffer-file-name))
1483
(string-match "\\.bz2?$" buffer-file-name))
1484
(set-visited-file-name
1485
(substring buffer-file-name 0 (match-beginning 0))))
1486
(if (and (not (null buffer-file-name))
1487
(string-match "\\.tgz$" buffer-file-name))
1488
(set-visited-file-name (concat
1489
(substring buffer-file-name 0 (match-beginning 0)) ".tar")))
1490
(if (and (not (null buffer-file-name))
1491
(string-match "\\.tbz$" buffer-file-name))
1492
(set-visited-file-name (concat
1493
(substring buffer-file-name 0 (match-beginning 0)) ".tar")))
1443
(substring buffer-file-name 0 (match-beginning 0)))
1444
(if (and (not (null buffer-file-name))
1445
(string-match "\\.g?z$" buffer-file-name))
1446
(set-visited-file-name
1447
(substring buffer-file-name 0 (match-beginning 0))))
1448
(if (and (not (null buffer-file-name))
1449
(string-match "\\.tgz$" buffer-file-name))
1450
(set-visited-file-name
1451
(concat (substring buffer-file-name 0 (match-beginning 0)) ".tar")))
1452
(if (and (not (null buffer-file-name))
1453
(string-match "\\.tbz$" buffer-file-name))
1454
(set-visited-file-name
1455
(concat (substring buffer-file-name 0 (match-beginning 0)) ".tar")))
1456
(if (and (not (null buffer-file-name))
1457
(string-match "\\.bz2?$" buffer-file-name))
1458
(set-visited-file-name
1459
(substring buffer-file-name 0 (match-beginning 0)))))
1495
1460
(message "Decoding %s..." (buffer-name))
1496
1461
(crypt-encode-buffer t)
1589
1554
(goto-char (point-min))
1590
1555
(let ((alist crypt-encoding-alist) elt found)
1591
1556
(while (and alist (setq elt (car alist)) (not found))
1592
(if (looking-at (nth 1 elt))
1557
(if (and (looking-at (nth 1 elt))
1558
(not (memq (nth 0 elt) crypt-inhibit-formats)))
1593
1559
(setq crypt-buffer-encoding-type (nth 0 elt)
1596
1562
(setq alist (cdr alist))))
1565
(defun crypt-encryption-type-get (file)
1566
"Determine type of encryption from file extension."
1569
(dolist (elt crypt-encryption-alist)
1570
(setq regexp (nth 3 elt))
1571
(if (and (stringp regexp)
1572
(string-match regexp file))
1573
(return (nth 0 elt))))))
1575
(defun crypt-encryption-type-set ()
1576
"Set `crypt-encryption-type'"
1578
(if (setq type (crypt-encryption-type-get buffer-file-name))
1580
(setq crypt-encryption-type type)
1581
(crypt-rebuild-tables)))))
1599
1583
(defun crypt-encrypted-p (&optional buffer)
1600
1584
;; Returns t if current buffer, or optionally BUFFER, is encrypted.
1601
1585
;; Look for MAGIC-REGEXP and absence of MAGIC-REGEXP-INVERSE. If so, then
2229
2223
(not (eq args t))) ; just in case...
2230
2224
(setq prog (concat prog " " args))))
2232
;(message "start=%d end=%d prog+args=%s" start end prog)
2233
;(message "buffer before:\n%s\n--end" (buffer-string))
2234
2226
(call-process-region start end shell-file-name t '(t nil) nil
2235
shell-command-switch prog)
2236
;(message "buffer after:\n%s\n--end" (buffer-string))
2227
shell-command-switch prog))
2239
2229
;; Otherwise try and eval it.
2241
;(message "eval prog=%s args=%s" prog args)
2243
2232
(list prog start end args)
2244
2233
(list prog start end))))))
2320
2308
(if crypt-dos-has-ctrl-z (replace-match ""))))))))
2322
2310
(defun crypt-unix-to-dos-region (start end)
2323
"Converts region from START to END, from dos to unix format.
2311
"Converts region from START to END, from unix to dos format.
2324
2312
Replaces \"\\n\" with \"\\r\\n\" and adds a ^Z at end of file if
2325
2313
`crypt-dos-has-ctrl-z' is non-nil."
2326
2314
(save-excursion
2327
;(message "doing unix to dos")
2328
2315
(save-restriction
2329
2316
(let ((add-ctrl-z (and crypt-dos-has-ctrl-z
2330
2317
(equal end (point-max)))))
2417
2404
(set-buffer-modified-p t)))))
2407
;;; Forgetting encryption keys (by jwz)
2408
;;; This is really kind of bogus. Good behavior would be:
2409
;;; - If a crypted buffer has not been "accessed" (edited? selected?
2410
;;; viewed?) in N minutes, kill the buffer (since the plaintext is valuable.)
2411
;;; - If a crypted buffer is modified, but "idle", just forget the password
2412
;;; instead of killing the buffer (though the plaintext is valuable, it's
2413
;;; also unsaved...)
2414
;;; - The "idleness" of a modified buffer should be reset with every mod, so
2415
;;; that an unsaved buffer that you have been constantly typing at for an
2416
;;; hour doesn't lose its password.
2417
;;; - But, if a password for a buffer has been discarded, and then an attempt
2418
;;; is made to save that buffer, then we should confirm that the newly-
2419
;;; typed password is the same as the password used in the file on disk.
2420
;;; with PGP, we could check that by attempting to decrypt the file on
2421
;;; disk into a scratch buffer and seeing if it contains the PGP error
2423
;;; - BUG: if a password has been forgotten, and you save, and are prompted,
2424
;;; the old file has already been renamed to a backup!! so if you ^G, the
2425
;;; real file name no longer exists on disk - only as a ~ file.
2427
(defun crypt-forget-encryption-key ()
2428
(cond (crypt-buffer-encryption-key
2429
(let ((inhibit-quit t))
2430
(fillarray crypt-buffer-encryption-key 0)
2431
(setq crypt-buffer-encryption-key nil))
2435
(add-hook 'kill-buffer-hook 'crypt-forget-encryption-key)
2437
(defcustom crypt-forget-passwd-timeout (* 60 60)
2438
"*Do not retain passwords for encrypted buffers more than this many seconds.
2439
If nil, keep them indefinitely."
2440
:type '(choice integer (const :tag "indefinite" nil))
2443
(defun crypt-reset-passwd-timer ()
2444
(if (fboundp 'get-itimer) ; XEmacs, or anything with itimer.el loaded.
2445
(let ((name "crypt-forget-passwds"))
2446
(if (get-itimer name)
2447
(delete-itimer name))
2448
(if crypt-forget-passwd-timeout
2450
'crypt-reset-passwds-timeout
2451
crypt-forget-passwd-timeout)))))
2453
(defun crypt-reset-passwds-timeout ()
2454
;; run by the timer code to forget all passwords
2455
(let ((buffers (buffer-list))
2460
(set-buffer (car buffers))
2461
(cond ((and crypt-buffer-encryption-key
2462
(buffer-modified-p))
2463
;; don't forget the password in modified buffers, but
2464
;; do check again later (maybe it will be unmodified.)
2465
(setq keep-going t))
2466
(crypt-buffer-encryption-key
2467
;; forget the password in unmodified buffers.
2468
(crypt-forget-encryption-key)
2469
;; Mark the buffer read only so that it's not accidentally
2470
;; edited; the smart thing to do is revert it, type the
2471
;; encryption key (to make sure they same key is used)
2472
;; and then edit it.
2473
(setq buffer-read-only t)
2474
(message "Password discarded in buffer %s"
2475
(buffer-name (car buffers))))
2477
(setq buffers (cdr buffers)))
2479
(crypt-reset-passwd-timer))
2420
2483
;;; Originally `tek-symbol-alist-to-table' from tek-highlight.el.
2421
2484
(defun crypt-symbol-alist-to-table (list)
2422
2485
;; Converts an alist of symbols to a table suitable for `completing-read.'
2527
2590
(fboundp 'buffer-flush-undo)
2528
2591
(fset 'buffer-disable-undo 'buffer-flush-undo))
2530
(defun crypt-read-string-no-echo (prompt &optional confirm)
2532
;; Read a string from minibuffer, prompting with PROMPT, echoing periods.
2533
;; Optional second argument CONFIRM non-nil means that the user will be
2534
;; asked to type the string a second time for confirmation and if there is a
2535
;; mismatch, the whole process is repeated.
2537
;; Line editing keys are --
2539
;; C-u, C-x line kill
2540
;; C-q, C-v literal next
2542
(catch 'return-value
2545
(let ((input-buffer (get-buffer-create (make-temp-name " *password*")))
2546
char hold-password help-form kill-ring)
2548
(set-buffer input-buffer)
2549
;; Don't add to undo ring.
2550
(buffer-disable-undo input-buffer)
2552
(let ((cursor-in-echo-area t)
2553
(echo-keystrokes 0))
2558
;; Repeat until we get a `throw'.
2561
(message "%s" prompt) ; avoid errors if "%" in prompt
2564
(while (not (memq (setq char (read-char)) '(?\C-m ?\C-j)))
2568
'((?\C-h . (delete-char -1))
2569
(?\C-? . (delete-char -1))
2570
(?\C-u . (delete-region 1 (point)))
2571
(?\C-x . (delete-region 1 (point)))
2572
(?\C-q . (quoted-insert 1))
2573
(?\C-v . (quoted-insert 1))))))
2574
(condition-case error-data
2577
;; Just a plain character - insert into password buffer.
2580
;; I think crypt-read-string-no-echo should echo asterisks.
2581
;; -- Jamie. How about periods like in ange-ftp? -- lrd
2583
(message "%s%s" prompt (make-string (buffer-size) ?.)))
2585
;; Do we have to confirm password?
2588
;; No confirmation requested - terminate.
2590
(throw 'return-value (buffer-string)))
2592
;; Can we compare (confirm) password values yet?
2594
(if (string= hold-password (buffer-string))
2595
;; The two passwords match - terminate.
2596
(throw 'return-value hold-password)
2598
;; Mismatch - start over.
2600
(message (concat prompt "[Mismatch. Start over]"))
2603
(fillarray hold-password 0) ; destroy extra copy now
2604
(setq hold-password nil))))
2606
;; Store password and read again.
2608
(setq hold-password (buffer-string))
2609
(message (concat prompt "[Retype to confirm]"))
2614
(set-buffer input-buffer)
2615
(set-buffer-modified-p nil)
2616
(buffer-disable-undo input-buffer) ; redundant, but why not be safe.
2618
(goto-char (point-min))
2619
(while (not (eobp)) (delete-char 1) (insert "*")) ; destroy now
2620
(kill-buffer input-buffer)))))))
2593
(fset 'crypt-read-string-no-echo 'read-passwd)
2622
2595
(defun crypt-set-encryption-key (key &optional buffer)
2648
2621
(message "Key is identical to original, no change.")
2651
;; #### Smash contents of old crypt-buffer-encryption-key string here?
2652
;; That wouldn't be ok if some other buffer held a pointer to it.
2624
;; jwz: destroy old string
2625
(if (and crypt-buffer-encryption-key
2626
(not (eq crypt-buffer-encryption-key key)))
2627
(fillarray crypt-buffer-encryption-key 0))
2653
2628
(setq crypt-buffer-encryption-key key)
2655
2630
;; Don't touch the modify flag unless we're in `(crypt-encrypted-mode)'.
2656
2631
(if crypt-buffer-save-encrypted
2657
(set-buffer-modified-p t))))))
2632
(set-buffer-modified-p t))
2634
(crypt-reset-passwd-timer)
2660
2638
;;;; Install hooks and mode indicators.
2747
2725
;;; Code for conditionally decoding/decrypting an inserted file
2749
(defvar crypt-bind-insert-file t
2727
(defcustom crypt-bind-insert-file t
2750
2728
"*t value means bind `crypt-insert-file' over `insert-file'.
2751
2729
If you wish to change this variable after crypt++ has been loaded then do
2752
\\[crypt-bind-insert-file].")
2730
\\[crypt-bind-insert-file]."
2754
(defvar crypt-auto-decode-insert nil
2734
(defcustom crypt-auto-decode-insert nil
2755
2735
"*t says decode/decrypt files that are inserted with `crypt-insert-file'.
2756
nil says to ask before doing this.")
2736
nil says to ask before doing this."
2758
2740
;;; Bind `crypt-insert-file' over wherever `insert-file' is bound?
2759
2741
(defun crypt-bind-insert-file ()
2776
2758
(crypt-bind-insert-file)
2778
2760
;;; crypt++ replacement for `insert-file'
2779
(defun crypt-insert-file (filename)
2761
(defun crypt-insert-file (filename &optional codesys)
2780
2762
"Insert decoded/decrypted contents of file FILENAME into buffer after point.
2781
2763
Set mark after the inserted text.
2765
Under XEmacs/Mule, optional second argument specifies the
2766
coding system to use when decoding the file. Interactively,
2767
with a prefix argument, you will be prompted for the coding system.
2783
2769
This function is meant for the user to run interactively.
2784
2770
Don't call it from programs! Use `insert-file-contents' instead.
2785
2771
\(Its calling sequence is different; see its documentation\).
2787
2773
This version will attempt to decrypt and/or decode file before inserting.
2788
2774
see variable `crypt-auto-decode-insert'."
2789
(interactive "fInsert file: ")
2775
(interactive "*fInsert file: \nZCoding system: ")
2790
2776
(if (file-directory-p filename)
2791
2777
(signal 'file-error (list "Opening input file" "file is a directory"
2793
(let ((tem (crypt-insert-file-contents filename))) ; use crypt++ to insert
2779
(let* (format-alist ; format.el only confuses people in this context
2782
(let ((coding-system-for-read
2783
(get-coding-system codesys)))
2784
(crypt-insert-file-contents filename))
2785
(crypt-insert-file-contents filename))))
2794
2786
(push-mark (+ (point) (car (cdr tem))))))
2796
2788
;; Similar to `insert-file-contents' except decoding/decrypting of FILE
2797
2789
;; attempted. See `crypt-insert-file' and `crypt-auto-decode-insert'
2799
2791
(defun crypt-insert-file-contents (file)
2800
2792
(let (temp-buffer
2841
2833
;;; This section is provided for reports.
2842
2834
;;; Using Barry A. Warsaw's reporter.el
2844
(defconst crypt-version "2.92"
2836
(defconst crypt-version "2.94"
2845
2837
"Revision number of crypt++.el -- handles compressed and encrypted files.
2846
2838
Type \\[crypt-submit-report] to send a bug report. Available via anonymous
2847
ftp at ftp://ftp.cs.umb.edu/pub/misc/crypt++.el")
2839
+ftp at ftp://ftp.cs.umb.edu/pub/misc/crypt++.el")
2849
2841
(defconst crypt-help-address
2842
"xemacs-beta@xemacs.org"
2851
2843
"Address(es) accepting submission of reports on crypt++.el.")
2853
(defconst crypt-maintainer "Karl"
2845
(defconst crypt-maintainer "XEmacs Developers"
2854
2846
"First name(s) of people accepting submission of reports on crypt++.el.")
2856
(defconst crypt-file "crypt++.el"
2848
(defconst crypt-file "crypt.el"
2857
2849
"Name of file containing emacs lisp code.")
2859
2851
(defconst crypt-variable-list