home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / packages / crypt.el < prev    next >
Encoding:
Text File  |  1995-01-27  |  107.1 KB  |  2,568 lines

  1. ;;; crypt.el --- code for handling all sorts of compressed and encrypted files
  2.  
  3. ;; Author: Lawrence R. Dodd <dodd@roebling.poly.edu>
  4. ;;    Rod Whitby <rwhitby@research.canon.oz.au>
  5. ;;    Kyle E. Jones <kyle@uunet.uu.net>
  6. ;; Maintainer: Lawrence R. Dodd <dodd@roebling.poly.edu>
  7. ;; Created: crypt.el in 1988, crypt++.el on 18 Jan 1993
  8. ;; Version: 2.82
  9. ;; Date: 1994/03/31 12:30:17
  10. ;; Keywords: extensions
  11.  
  12. ;;; Copyright (C) 1994 Lawrence R. Dodd
  13. ;;; Copyright (C) 1993 Lawrence R. Dodd and Rod Whitby
  14. ;;; Copyright (C) 1988, 1989, 1990 Kyle E. Jones
  15. ;;;  
  16. ;;; This program is free software; you can redistribute it and/or modify
  17. ;;; it under the terms of the GNU General Public License as published by
  18. ;;; the Free Software Foundation; either version 2 of the License, or
  19. ;;; (at your option) any later version.
  20. ;;;
  21. ;;; This program is distributed in the hope that it will be useful,
  22. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. ;;; GNU General Public License for more details.
  25. ;;;
  26. ;;; You should have received a copy of the GNU General Public License
  27. ;;; along with this program; if not, write to the Free Software
  28. ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  
  30. ;;; Synched up with: Not in FSF.
  31.  
  32. ;;; Commentary:
  33.  
  34. ;;; Please see notes on INSTALLATION and USAGE on the pages below.
  35.  
  36. ;;; LCD Archive Entry:
  37. ;;; crypt++|Rod Whitby and Lawrence R. Dodd|dodd@roebling.poly.edu|
  38. ;;; Code for handling all sorts of compressed and encrypted files.|
  39. ;;; 1994/03/31 12:30:17|2.82|~/misc/crypt++.el.Z|
  40.  
  41. ;;; AVAILABLE: 
  42. ;;; 
  43. ;;; via anonymous ftp to roebling.poly.edu [128.238.5.31] in 
  44. ;;; /pub/lisp/crypt++.el.gz
  45. ;;; 
  46. ;;; via anonymous ftp to archive.cis.ohio-state.edu [128.146.8.52] in 
  47. ;;; /pub/gnu/emacs/elisp-archive/misc/crypt++.el.Z
  48.  
  49. ;;; BUG REPORTS
  50. ;;; 
  51. ;;; Type M-x crypt-submit-report to generate a bug report template or put your
  52. ;;; cursor at the end of this line and type C-x C-e: (crypt-submit-report)
  53. ;;; 
  54. ;;; Please note that this bug-report facility (crypt-submit-report) uses Barry
  55. ;;; Warsaw's reporter.el which is part of GNU Emacs v19 and bundled with many
  56. ;;; other packages.  If needed, you can obtain a copy of reporter.el at
  57. ;;; /roebling.poly.edu:/pub/reporter.el or the elisp-archive.  In fact,
  58. ;;; crypt-submit-report will attempt to ange-ftp a copy for you from roebling
  59. ;;; if you do not have one accessible.
  60.  
  61. ;;; Lawrence R. Dodd <dodd@roebling.poly.edu>
  62. ;;; Polytechnic University
  63. ;;; Brooklyn, New York USA
  64.  
  65. ;;; VERSION:
  66. ;;;  
  67. ;;; Version: 2.82
  68. ;;; Ident: crypt++.el,v 2.82 1994/03/31 12:30:17 dodd Exp
  69. ;;; Date: 1994/03/31 12:30:17
  70.  
  71.  
  72. ;;; INSTALLATION:
  73. ;;;
  74. ;;; To use this package, simply put it in a file called "crypt.el" in a Lisp
  75. ;;; directory known to Emacs (see `load-path'), byte-compile it (you may get a
  76. ;;; warning saying that the function reporter-submit-bug-report is not known
  77. ;;; to be defined -- ignore it), and put the line:
  78. ;;;
  79. ;;;                      (require 'crypt)
  80. ;;;
  81. ;;; in your ~/.emacs file or in the file default.el in the ../lisp directory
  82. ;;; of the Emacs distribution.  Do not bother trying to autoload this file;
  83. ;;; this package uses find-file and write-file hooks and thus should be loaded
  84. ;;; the first time you visit any sort of file.  Any package loaded after this
  85. ;;; one that appends something to `write-file-hooks' will not be executed
  86. ;;; because this package writes out the file.  Other packages that append to
  87. ;;; `write-file-hooks' should either be modified to prepend to that hook or be
  88. ;;; loaded before this one (preferably the former).
  89.  
  90. ;;; NOTE: encryption users should set `crypt-encryption-type' to one of the
  91. ;;; values in `crypt-encryption-alist' (see USAGE below).
  92.  
  93. ;;; SEE ALSO: /roebling.poly.edu:/pub/crypt++-fnf.el for file-not-found 
  94. ;;; support for GNU Emacs.
  95.  
  96. ;;; SPECIAL NOTES:
  97. ;;;  
  98. ;;; If crypt is dumped with the emacs executable, or if it has already been
  99. ;;; loaded in an emacs session, then modifying the variables used in building
  100. ;;; the encryption and encoding tables will have no effect until these tables
  101. ;;; are rebuilt.  This may be done with `M-x crypt-rebuild-tables'.  See USAGE
  102. ;;; below to determine variables for which this is needed.  For example,
  103. ;;; post-load changes to `crypt-encryption-file-extension' or
  104. ;;; `crypt-freeze-vs-fortran' can be incorporated into the encryption table
  105. ;;; via `M-x crypt-rebuild-tables'.  Similarly, post-load changes to
  106. ;;; `crypt-bind-insert-file' are handled with `M-x crypt-bind-insert-file'.
  107.  
  108.  
  109. ;;; USAGE:
  110. ;;; 
  111. ;;; By default, intended to be transparent.  User-defined variables 
  112. ;;; 
  113. ;;;     controlling ENCRYPTION are
  114. ;;;  
  115. ;;;        crypt-encryption-type
  116. ;;;        crypt-encryption-file-extension
  117. ;;;        crypt-never-ever-decrypt
  118. ;;;        crypt-auto-write-buffer-encrypted
  119. ;;;        crypt-confirm-password
  120. ;;;        crypt-encrypted-disable-auto-save
  121. ;;;        crypt-encryption-alist
  122. ;;;  
  123. ;;;     controlling ENCODING are
  124. ;;;  
  125. ;;;        crypt-auto-decode-buffer
  126. ;;;        crypt-auto-write-buffer
  127. ;;;        crypt-query-if-interactive
  128. ;;;        crypt-no-extension-implies-plain
  129. ;;;        crypt-freeze-vs-fortran
  130. ;;;        crypt-compact-vs-C++
  131. ;;;        crypt-ignored-filenames
  132. ;;;        crypt-default-encoding
  133. ;;;        crypt-encoded-disable-auto-save
  134. ;;;        crypt-encoding-alist
  135. ;;; 
  136. ;;;     controlling file insertion are
  137. ;;; 
  138. ;;;        crypt-bind-insert-file
  139. ;;;        crypt-auto-decode-insert
  140. ;;;      
  141. ;;; To find out more about these variables, load this file, put your cursor at 
  142. ;;; the end of any of the variable names, and hit C-h v [RET].
  143. ;;;  
  144. ;;; NOTE: encryption users should set `crypt-encryption-type' to one of the
  145. ;;; values in `crypt-encryption-alist'
  146. ;;;
  147. ;;; Although rarely needed, the following functions may be called interactively
  148. ;;;
  149. ;;;        (crypt-encoded-mode)
  150. ;;;        (crypt-encode-region)
  151. ;;;        (crypt-encrypted-mode)
  152. ;;;        (crypt-encrypt-region)
  153. ;;;        (crypt-set-encryption-key)
  154. ;;;        (crypt-rebuild-tables)
  155. ;;;        (crypt-insert-file)
  156. ;;;        (crypt-bind-insert-file)
  157. ;;;        (crypt-submit-report)
  158. ;;;
  159. ;;; To find out more about these functions, load this file, put your cursor
  160. ;;; inside any of the `()' of the above lines, and hit C-h f [RET].
  161.  
  162.  
  163. ;;; NOTES ON INTERFACES WITH OTHER PROGRAMS AND PACKAGES:
  164. ;;;
  165. ;;; GZIP: the environment variable GZIP of gzip can cause an error if it
  166. ;;; contains `--verbose' because standard output messages will be appended to
  167. ;;; gzip'ed files.  This corrupts the files.  The cleanest solution is to pass
  168. ;;; the `--quiet' switch in `crypt-encoding-alist' to override this.  use gzip
  169. ;;; version 1.0.4 or higher from prep.ai.mit.edu:/pub/gnu
  170. ;;; 
  171. ;;; TAR-MODE: works properly with version 1.28 (or higher) with v19 emacs.
  172.  
  173.  
  174. ;;; DESCRIPTION:
  175. ;;;
  176. ;;; The basic purpose of this package of Lisp functions is to recognize
  177. ;;; automatically encrypted and encoded (i.e., compressed) files when they are
  178. ;;; first visited or written.  The BUFFER corresponding to the file is decoded
  179. ;;; and/or decrypted before it is presented to the user.  The file itself is
  180. ;;; unchanged on the disk.  When the buffer is subsequently saved to disk, a
  181. ;;; hook function re-encodes the buffer before the actual disk write takes
  182. ;;; place.
  183. ;;;
  184. ;;; This package recognizes all sorts of compressed files by a magic number at
  185. ;;; the beginning of these files but uses a heuristic to detect encrypted
  186. ;;; files.  If you are asked for an encryption key for a file that is in fact
  187. ;;; not encrypted, just hit RET and the file will be accepted as is, and the
  188. ;;; crypt minor mode will not be entered.
  189. ;;;
  190. ;;; Other types of encoding programs may be added to this package by using the
  191. ;;; variable `crypt-encoding-alist' which contains a table of encoding
  192. ;;; programs such as compress, gzip (GNU zip), freeze, and compact.
  193. ;;;
  194. ;;; This new extended version of crypt now monitors the filename extensions of
  195. ;;; buffers that are written out using write-file (C-x C-w).  If the filename
  196. ;;; extension matches one of the extensions listed in `crypt-encoding-alist,'
  197. ;;; then this package will write the file out using the corresponding encoding
  198. ;;; (compression) method. This is done whether or not the buffer originated
  199. ;;; from a previously encoded (compressed) file.
  200. ;;;
  201. ;;; Thus, if the user is editing a file that may or may not have been encoded
  202. ;;; originally (e.g., foobar.Z or foobar) and decides to write it to a
  203. ;;; different file (e.g., barfoo or barfoo.z or barfoo.C).  This package will
  204. ;;; examine the filename extension and write the buffer in plain format or an
  205. ;;; alternate encoding (compression) format by searching through the entries
  206. ;;; in the table of encoding methods `crypt-encoding-alist.'  This change in
  207. ;;; encoding state is done automatically if the variable
  208. ;;; `crypt-auto-write-buffer' is t otherwise the user is asked.
  209.  
  210.  
  211. ;;; TO DO/KNOWN BUGS/HELP WANTED/APPLY WITHIN: 
  212. ;;; 
  213. ;;; All Users/hackers out there are strongly encouraged to pursue any of these
  214. ;;; matters further (especially those that concern encryption and decryption!).
  215. ;;; It is important to future programmers and modifiers of crypt++.el to know
  216. ;;; about its perceived limitations.  Since necessity drives invention, users
  217. ;;; who find any of the following features of crypt++.el annoying are asked to
  218. ;;; make suggestions and send patches (again, especially those that concern
  219. ;;; encryption and decryption!).
  220. ;;; 
  221. ;;; * currently crypt++ assumes that if a file is both encrypted and encoded
  222. ;;;   (i.e., compressed) that the order in which it was done was encryption
  223. ;;;   first _then_ compression.  As has been pointed by many people compression
  224. ;;;   following encryption is useless since the encrypted file is basically
  225. ;;;   random.  On the other hand, many agree that doing encryption _following_
  226. ;;;   compression is better since it makes it harder to crack the encryption.
  227. ;;;   We would like to make the ordering of these two user-configurable or if
  228. ;;;   nothing else change the order.
  229. ;;; 
  230. ;;;   Having read the above however, Francois Pinard <pinard@iro.umontreal.ca> 
  231. ;;;   writes that encryption following compression may not be harder to crack 
  232. ;;;   since "the fact that the first few uncrypted bytes are expected (the 
  233. ;;;   compress signature) facilitates a serious attempt at uncrypting." 
  234. ;;;   jwz agrees with Francois.
  235. ;;; 
  236. ;;; * get write-region and append-to-file to handle encoded and encrypted
  237. ;;;   files.  There is an interesting low-level encoding package by Jay Adams
  238. ;;;   <jka@ece.cmu.edu> called jka-compr.el that might address some of these
  239. ;;;   issues.  We encourage hackers out there to come up with crypt++ versions
  240. ;;;   of write-region and append-to-file.  The difficulty is creating versions
  241. ;;;   that mimic the originals as closely as possible.
  242. ;;;
  243. ;;; * instead of using call-process-region (which can fail badly if the region 
  244. ;;;   is large and there's not much room in /tmp), write the region to a temp 
  245. ;;;   file (with a customisable location) and use call-process directly.
  246. ;;;
  247. ;;; * users have mentioned trouble using crypt++ and hilit simultaneously since 
  248. ;;;   the functions in write-file-hook for both write the file to disk and
  249. ;;;   return t.  A possible solution is to have one of them write to a
  250. ;;;   scratch buffer instead of to disk and return nil and then allow the
  251. ;;;   other to do its work on the scratch buffer and write it to disk.  Thanks
  252. ;;;   to Wayne Folta <folta@cs.UMD.EDU> and Amir J Katz <amir@matis.ingr.com>.
  253. ;;;   It would be nice to have another way in emacs to have an
  254. ;;;   after-write-file-hook and a before-write-file-hook of some sort.
  255. ;;;   Lucid Emacs has an after-write-file-hook.  Recent versions of hilit19.el 
  256. ;;;   do not automatically attach to `write-file-hooks' and return t. 
  257. ;;;   However, the general problem of multiple packages returning t still 
  258. ;;;   remains.  dos-mode.el and crypt.el also conflict.
  259. ;;;  
  260. ;;; * another possible source of trouble is with encryption (and encoding) 
  261. ;;;   programs sticking verbose output into buffers prior to being written to
  262. ;;;   disk.  This was definitely occurring with gzip because of --verbose in
  263. ;;;   the GZIP environment variable and is solved/hidden with the --quiet
  264. ;;;   switch.  However, I suspect that some encryption problems out there are
  265. ;;;   capable of similar things so the user should be careful.
  266. ;;; 
  267. ;;; * integrating crypt++ with a backgrounding package such as Olin Shivers' 
  268. ;;;   `background.el' might be useful too.  thanks to Mark Borges 
  269. ;;;   <mdb@noaacrd.Colorado.EDU> for suggesting this.
  270. ;;; 
  271. ;;; * Performing M-x crypt-encode-buffer or M-x crypt-encrypt-buffer and then
  272. ;;;   saving the file would possibly cause errors.  It is better to toggle
  273. ;;;   `crypt-encoded-mode' (or `crypt-encrypted-mode') and simply save the
  274. ;;;   file.  It is for this reason that `crypt-encode-buffer' and
  275. ;;;   `crypt-encrypt-buffer' are not interactive.
  276. ;;; 
  277. ;;; * use plists instead of alists replacing calls to `nth' with `get' 
  278. ;;; 
  279. ;;; * merge encryption code completely into encoding code making encryption
  280. ;;;   just a special case of encoding.
  281.  
  282.  
  283. ;;; Change log:
  284. ;;;  
  285. ;;; 1.1 - original version of crypt.el
  286. ;;; 1.2 -
  287. ;;;   jwz: works with tar-mode.el
  288. ;;;   jwz: applied patch from piet, merged with Lawrence Dodd's gzip version
  289. ;;; 1.3 -
  290. ;;;   lrd: fixed compress-magic-regexp 
  291. ;;; 1.4, 1.5, 1.6 -
  292. ;;;   lrd: write-file compresses or gzips based on file extension
  293. ;;; 2.1 -
  294. ;;;   lrd: merged with Rod Whitby's table-driven version (major upgrade)
  295. ;;; 2.2 -
  296. ;;;   rjw: Changed file name to crypt++.el, so archie and lispdir can find it.
  297. ;;; 2.3 -
  298. ;;;   rjw: Separated the hook additions and minor mode alist additions.
  299. ;;; 2.4 -
  300. ;;;   rjw: Fixed the interactive form for crypt-buffer.
  301. ;;; 2.5 - 
  302. ;;;   lrd: doc mods, changed GNU free software notice (was out of date), added 
  303. ;;;   anonymous ftp information
  304. ;;; 2.6 - 
  305. ;;;   lrd: added back in definition of `buffer' in defun crypt-buffer caused 
  306. ;;;   an error when trying to read encrypted file; modified check for minor 
  307. ;;;   mode alist addition; added gzip magic number warning
  308. ;;; 2.7 - [posted to gnu.emacs.sources]
  309. ;;;   lrd: added `TO DO' and `KNOW BUGS' section to header 
  310. ;;; 2.8 - 
  311. ;;;   lrd: added note about updating to v 1.24 of tar-mode.el
  312. ;;;   Thanks to Mark Borges <mdb@noaacrd.Colorado.EDU>
  313. ;;; 2.9 -
  314. ;;;   lrd: moved query about `crypt-freeze-vs-fortran' out of defvar for
  315. ;;;   `crypt-encoding-alist,' an erroneous value of nil was being stuck into
  316. ;;;   alist when user set `crypt-freeze-vs-fortran' was nil, doc mod.
  317. ;;;   Thanks to Mark Borges <mdb@noaacrd.Colorado.EDU>
  318. ;;; 2.10 -
  319. ;;;   rjw: moved query about `crypt-freeze-vs-fortran' back into defvar for
  320. ;;;   `crypt-encoding-alist,' - used append to ignore the erroneous nil.
  321. ;;; 2.11 -
  322. ;;;   rjw: fixed a bug in my fix :-(
  323. ;;; 2.12 -
  324. ;;;   rjw: Defvar crypt-magic-regexp and crypt-magic-regexp-inverse and
  325. ;;;   allow either a regexp or an elisp expression.
  326. ;;;   Suggested by Franc,ois Pinard <pinard@iro.umontreal.ca>.
  327. ;;; 2.13 - 
  328. ;;;   lrd: added in info on lispdir.el, doc mods and some puttering while 
  329. ;;;   looking over rjw's v 2.12 mods.
  330. ;;; 2.14 - 
  331. ;;;   lrd: doc mod - trivial huh? switched `compact' and  `gzip' in 
  332. ;;;   `crypt-encoding-alist' - want gzip near top
  333. ;;; 2.15 - 
  334. ;;;   lrd: added in LCD Archive Entry and modified comments on tar-mode.el 
  335. ;;;   since the version at the elisp-archive now works with crypt++.el
  336. ;;; 2.16 - 
  337. ;;;   lrd: provide `crypt' as well as `crypt++' allowing something like `ln -s 
  338. ;;;   crypt++.el crypt.el' to be meaningful 
  339. ;;;   Suggested (by|as) Per Abrahamsen <amanda@iesd.auc.dk>
  340. ;;; 2.17 -
  341. ;;;   lrd: clarified bug report procedure, added fancy pseudo-graphics, added 
  342. ;;;   to the `TO DO' list, put RCS tags in LCD Archive entry
  343. ;;; 2.18 - [posted to gnu.emacs.sources]
  344. ;;;   lrd: included pointer to elisp archive in crypt-version description,
  345. ;;;   changed "Decode buffer %s? " to "Decode %s? " in crypt-find-file-hook 
  346. ;;;   to be more general (mainly for crypt-insert-file)
  347. ;;; 2.19 -
  348. ;;;   rjw: Added the crypt-compact-vs-C++ switch to distinguish compacted and
  349. ;;;   C++ files.
  350. ;;; 2.20 -
  351. ;;;   lrd: (1) modified interactive form of crypt-buffer. (2) made search 
  352. ;;;   case-insensitive in crypt-submit-report. (3) modified encoded-mode and 
  353. ;;;   crypt-mode so that buffer-modified is not unconditionally set to nil 
  354. ;;;   when the mode is not changed. Thanks to Gerd Hillebrand 
  355. ;;;   <ggh@cs.brown.edu> for suggesting (2) and (3).
  356. ;;; 2.21 -
  357. ;;;   rjw: Added an entry to the TODO list about the hazards of using
  358. ;;;   call-process-region on a large region and not much room in /tmp
  359. ;;;   (David Carlisle <carlisle@computer-science.manchester.ac.uk>).
  360. ;;; 2.22 - 
  361. ;;;   lrd: allow write-file-hooks to contain functions as well as lists. 
  362. ;;;   Contributed by Ken Laprade <laprade@trantor.harris-atd.com>.
  363. ;;; 2.23 - 
  364. ;;;   lrd: made crypt-submit-report list values of more user-defined variables
  365. ;;; 2.24 - 
  366. ;;;   lrd: pass the -q switch to gzip to thwart the possibility of a --verbose
  367. ;;;   in the GZIP environment variable
  368. ;;; 2.25 -
  369. ;;;   lrd: added some more to the TO DO list, clarified some things, also 
  370. ;;;   untabified the entire file (I got tired of the control I's) 
  371. ;;; 2.26 - 
  372. ;;;   lrd: use the long-named options for GNU zip (self-documenting)
  373. ;;; 2.27 - 
  374. ;;;   lrd: included observation by Francois Pinard <pinard@iro.umontreal.ca> 
  375. ;;;   and worked on text in TO DO/KNOWN BUGS list
  376. ;;; 2.28 - 
  377. ;;;   lrd: added two new variables in (crypt-submit-report) to the list stuck
  378. ;;;   at the bottom of the mail message; changed the comments regarding the 
  379. ;;;   user-defined variables.  added in default values in user defined 
  380. ;;;   variables.  added to and removed stuff to the `TO DO' list.
  381. ;;;
  382. ;;;   (encoded-mode): 
  383. ;;;   added in code to remove any auto-save-files that may have been formed
  384. ;;;   before becoming an encoded buffer (for example a plain file saved to
  385. ;;;   disk encoded had orphan auto-save-files left behind).  turning off
  386. ;;;   auto-save-mode disables the creation of auto-save-files, but it also 
  387. ;;;   disables the possibility of these being removed when the buffer is 
  388. ;;;   saved.
  389. ;;; 
  390. ;;;   (crypt-region): 
  391. ;;;   now call the encryption and decryption program directly instead of
  392. ;;;   through the shell.  this is more secure since the shell will expose the
  393. ;;;   password (key).  thanks to Jon Cargille <jcargill@cs.wisc.edu>.  defined
  394. ;;;   two new variables `crypt-decryption-args' and `crypt-encryption-args' to
  395. ;;;   take the arguments separately.  removed (let ((opoint)...)) construct 
  396. ;;;   this was a throw back to some old dead code and was not being used.
  397. ;;; 2.29 - 
  398. ;;;   lrd: added three new variables in (crypt-submit-report); added to the 
  399. ;;;   `TO DO' list.
  400. ;;;  
  401. ;;;   (encode-region,encode-buffer,encoded-mode): fixed interactive forms -
  402. ;;;   the conversion to table version had eliminated some of the interactive
  403. ;;;   features of these.  thanks to Kimball Collins <kpc@ptolemy.arc.nasa.gov>
  404. ;;;   for point this out.  new interactive form uses functions
  405. ;;;   `crypt-get-encoding-type' and `crypt-symbol-alist-to-table' and variable
  406. ;;;   `crypt-default-encoding' to generate completion list of encoding types.
  407. ;;; 
  408. ;;;   (crypt-write-file-hook): two new user-defined variables
  409. ;;;   `crypt-query-if-interactive' and `crypt-no-extension-implies-plain' and
  410. ;;;   the buffer-local variable `buffer-interactive-mode' are used to help
  411. ;;;   determined whether or not plain output is really desired for files
  412. ;;;   without a compression file-name extension.  the default behavior is the
  413. ;;;   same as before.
  414. ;;; 2.30 - 
  415. ;;;   lrd: added test for user-defined variable `crypt-never-ever-decrypt' 
  416. ;;;   when finding a file.  some users may never wish to decrypt files 
  417. ;;;   and like to edit binary files.  thanks to Nelson Minar 
  418. ;;;   <nelson@reed.edu>.  added to doc-strings of 
  419. ;;;   `crypt-magic-regexp[-inverse]' -- these can be set to nil[t] and 
  420. ;;;   accomplish the same thing as setting `crypt-never-ever-decrypt' to t
  421. ;;; 2.31 - 
  422. ;;;   rjw: Updated the comments in the encryption check section.
  423. ;;; 2.32 - [posted to gnu.emacs.sources]
  424. ;;;   lrd: added warning about `crypt-(de|en)cryption-program'; doc mod.
  425. ;;; 2.33 - 
  426. ;;;   lrd: if `crypt-(de|en)cryption-args' are nil then don't pass any
  427. ;;;   arguments to (de|en)cryption program, nil is the default instead of
  428. ;;;   "".  Thanks to Joe Ilacqua <spike@world.std.com>, David J. Schur
  429. ;;;   <djs@idm.com>, Peter Nuth <nuth@ai.mit.edu>, and Greg Larson 
  430. ;;;   <glarson@bnr.ca>.  `-q' exists in gzip 1.0.3 but not `--quiet' changed 
  431. ;;;   GZIP NOTE.  Thanks to Chris Moore <moore@src.bae.co.uk>.
  432. ;;; 2.34 - 
  433. ;;;   lrd: allow `crypt-(de|en)cryption-args' to be a list of strings -- more
  434. ;;;   robust.  query for password (key), if none is set, when writing out file
  435. ;;;   for which `buffer-save-encrypted' is t.  Thanks to John Interrante
  436. ;;;   <interran@uluru.Stanford.EDU>.  (crypt-write-file-hook): check filename
  437. ;;;   extension against regexp `crypt-encryption-file-extension' and query for
  438. ;;;   encryption, unless `crypt-auto-write-buffer-encrypted' is t (don't
  439. ;;;   bother doing reverse check, encrypted to plain, not a common request).
  440. ;;;   (crypt-mode): delete auto-save files (cf., encoded-mode), may exist now.
  441. ;;;   (read-string-no-echo): applied patch from Piet van Oostrum
  442. ;;;   <piet@cs.ruu.nl> -- set `cursor-in-echo-area' _after_ setting buffer
  443. ;;;   (this was screwing up gnews).
  444. ;;; 2.35 - 
  445. ;;;   lrd: doc mod
  446. ;;; 2.36 - 
  447. ;;;   lrd: fixed typo, added RMAIL note.
  448. ;;; 2.37 - [posted to gnu.emacs.sources]
  449. ;;;   lrd: 
  450. ;;;   (crypt-write-file-hook): search user-defined list
  451. ;;;   `crypt-ignored-filenames' for possible match with `buffer-filename'
  452. ;;;   before attempting conversion from compressed to plain format; useful for
  453. ;;;   compressed incoming mail files (e.g., RMAIL, INBOX).
  454. ;;;  
  455. ;;;   (crypt-mode): query for key if not set already; need to switch order of
  456. ;;;   recovering key and toggling crypt-mode in crypt-find-file-hook (thanks
  457. ;;;   to Piet van Oostrum <piet@cs.ruu.nl>).
  458. ;;;  
  459. ;;;   (crypt-buffer) and (encode-buffer): remove interactive form; use
  460. ;;;   (crypt-mode) and (encoded-mode) instead so encryption and compression
  461. ;;;   are done at the very end; leave interactive form in (crypt-region) and
  462. ;;;   (encode-region) may still be used.
  463. ;;;  
  464. ;;;   (set-encryption-key): remove from `command-history' if called
  465. ;;;   interactively - thanks to George M. Georgiou
  466. ;;;   <georgiou@silicon.csci.csusb.edu>.
  467. ;;; 2.38 - 
  468. ;;;   lrd: added `crypt-' prefix to `(read-string-no-echo)' and `(save-point)'
  469. ;;;   changed file extension for gzip files to `.z' _or_ `.gz' (future release
  470. ;;;   of gzip with use later extension by default and so this should be
  471. ;;;   changed to just `.gz' someday).
  472. ;;; 2.39 - 
  473. ;;;   lrd: doc mod. added in patch from jwz - `(crypt-read-string-no-echo)' is
  474. ;;;   more secure, put property 'permanent-local on buffer-locals works for
  475. ;;;   Lucid Emacs and doesn't harm v18 emacs, change `buffer-interactive-mode'
  476. ;;;   to `buffer-interactive-encoded-mode.'
  477. ;;; 2.40 - 
  478. ;;;   lrd: put property 'preserved in case kill-fix.el is being used.
  479. ;;; 2.41 - 
  480. ;;;   lrd: all functions and variables now start with `crypt-', moved REVISION
  481. ;;;   HISTORY to bottom of header, interactive version of
  482. ;;;   `(crypt-encrypt-region)' clearer, `(crypt-read-string-no-echo)' now
  483. ;;;   echos `.'
  484. ;;; 2.42 -
  485. ;;;   lrd: (crypt-check-extension-for-encoding): broke out of
  486. ;;;   `(crypt-write-file-hook)'.  setting user variables
  487. ;;;   `crypt-compact-vs-C++' and `crypt-freeze-vs-fortran' to nil no longer
  488. ;;;   completely disables the reading compact'ed and frozen files but just
  489. ;;;   disables the use of the file-extension tricks of
  490. ;;;   `(crypt-check-extension-for-encoding).'  (crypt-encode-region): allow
  491. ;;;   for a single line message from encoding program at top of region; if it
  492. ;;;   is there, then remove it; kludge for `compact' program.
  493. ;;; 2.43 - 
  494. ;;;   lrd: (crypt-encode-region): generalize the clean up procedure; add
  495. ;;;   element to `crypt-encoding-alist' and introduce new function
  496. ;;;   `(crypt-encoding-cleanup-regexp)' to extract a compression specific
  497. ;;;   regexp for erroneous message or lisp expression for cleanup.
  498. ;;; 2.44 - 
  499. ;;;   lrd: new element for `crypt-encoding-alist' handles whether or not
  500. ;;;   file-name extension tricks may be play with encoding method; compact and
  501. ;;;   freeze values default to `crypt-compact-vs-C++' and
  502. ;;;   `crypt-freeze-vs-fortran' (thanks to rjw);
  503. ;;;   (crypt-encoding-extension-tricks): new defun to handle this;
  504. ;;;   (crypt-check-extension-for-encoding): monitors "tricks" entry of
  505. ;;;   `crypt-encoding-alist' and adjust the bag of tricks it can apply.
  506. ;;; 2.45 - 
  507. ;;;   lrd: (crypt-encode-region): delete entire match of cleanup regexp by
  508. ;;;   requiring newlines in GARBAGE-REGEXP-OR-LISPEXP.  (crypt-submit-report):
  509. ;;;   use Warsaw's reporter.el.
  510. ;;; 2.46 -
  511. ;;;   lrd: (crypt-find-file-hook, crypt-write-file-hook): cleaned, documented,
  512. ;;;   and replaced occurrences of `(cond (C BODY))' with `(if C BODY)';
  513. ;;;   changed `crypt-magic-regexp' to `crypt-encryption-magic-regexp' and
  514. ;;;   `crypt-magic-regexp-inverse' to `crypt-encryption-magic-regexp-inverse'
  515. ;;;   for consistency with other variable names. new user-defined variable
  516. ;;;   `crypt-encryption-minor-mode-name' instead of always "Crypt".  grouped
  517. ;;;   all encryption variables together.
  518. ;;; 2.47 - 
  519. ;;;   lrd: somewhat major change - put program-specific encryption variables
  520. ;;;   into a single table `crypt-encryption-alist' and let the variable
  521. ;;;   `crypt-encryption-type' define the appropriate entry to use; new
  522. ;;;   user-defined variable `crypt-confirm-password,' thanks to Jeff Clark
  523. ;;;   <jclark@src.honeywell.com>. (crypt-submit-report): improved error 
  524. ;;;   handling, thanks to baw. (crypt-write-file-hook): fixed bug with 
  525. ;;;   `crypt-encoding-extension-tricks'
  526. ;;; 2.48 - 
  527. ;;;   lrd: added dummy argument to `crypt-encoding-alist' and
  528. ;;;   `crypt-encryption-alist' and merged all defuns that work on their
  529. ;;;   elements into defuns that all start with `crypt-get-' and look through
  530. ;;;   both lists.  simplifies some of code and closer to treating encryption
  531. ;;;   as a special case of encoding; crypt-minor-mode-alist: replaced (nth *)
  532. ;;;   with `(crypt-get-minor-mode)' call; (crypt-encode-region): allow
  533. ;;;   arguments to be list of strings; renamed (crypt-get-encoding-type) to
  534. ;;;   (crypt-read-encoding-type) for clarity.
  535. ;;; 2.49 - [posted to gnu.emacs.sources]
  536. ;;;   lrd: (crypt-encode-region): ignore `args' if set to t
  537. ;;; 2.50 - 
  538. ;;;   lrd: (crypt-write-file-hook): in v19 we need to call `backup-buffer'
  539. ;;;   ourselves -- we write out the file and return t so `basic-save-buffer'
  540. ;;;   does not do it; also call `set-file-modes'
  541. ;;; 2.51 -
  542. ;;;   lrd: some `defvar's are now `defconst's and tar-mode note was changed.
  543. ;;; 2.52 - 
  544. ;;;   lrd: make doc strings conform to GNU standards.
  545. ;;; 2.53 - 
  546. ;;;   lrd: made header conform to GNU Conventional Headers standard.
  547. ;;; 2.54 -
  548. ;;;   lrd: `crypt-encryption-file-extension', `crypt-freeze-vs-fortran',
  549. ;;;   `crypt-compact-vs-C++', `crypt-encryption-magic-regexp', and
  550. ;;;   `crypt-encryption-magic-regexp-inverse' are used in defining the tables
  551. ;;;   `crypt-encoding-alist' and `crypt-encryption-alist' and so need to be set
  552. ;;;   _before_ loading crypt++.  use `add-hook' if it is available.
  553. ;;; 2.55 - 
  554. ;;;   lrd: new interactive function `crypt-insert-file' mimics `insert-file' 
  555. ;;;   but attempts to decode or decrypt before insertion; bound `C-x i' if
  556. ;;;   `crypt-bind-insert-file' is non-nil.  comment out doc-strings from 
  557. ;;;   internal subroutines, saves space.
  558. ;;; 2.56 -
  559. ;;;   tfb: change the definitions of crypt-{encoding,encryption}-alist, to
  560. ;;;   call the functions crypt-make-{encoding,encryption}-alist resp.
  561. ;;;   Added crypt-reinit which regenerates these variables from their
  562. ;;;   functions, thus allowing this stuff to be preloaded even if people
  563. ;;;   set things in their init files.
  564. ;;;   Tim Bradshaw <tim.bradshaw@mid-heidelberg.de> 
  565. ;;; 2.57 - 
  566. ;;;   lrd: untabify; remove duplicate entry in `crypt-make-encoding-alist';
  567. ;;;   change name of `crypt-make-*-alist' to `crypt-build-*-alist' and
  568. ;;;   `crypt-reinit' to `crypt-rebuild-tables'; (crypt-read-string-no-echo):
  569. ;;;   change local variable `form' to `help-form' so it is defined;
  570. ;;;   `crypt-encryption-alist' and `crypt-encoding-alist' must be defined with
  571. ;;;   `defconst' since we wish crypt++ to initialize these variables
  572. ;;;   unconditionally; modify INSTALLATION section to reflect these changes.
  573. ;;; 2.58 - 
  574. ;;;   lrd: doc mod.
  575. ;;; 2.59 - [posted to gnu.emacs.sources]
  576. ;;;   lrd: (crypt-bind-insert-file): new function for changing "C-x i" in 
  577. ;;;   initialization file or interactively.
  578. ;;; 2.60 - 
  579. ;;;   lrd: add `crypt-rebuild-tables' and `crypt-bind-insert-file' to 
  580. ;;;   `after-init-hook' in GNU emacs v19 and to `term-setup-hook' in Lucid 
  581. ;;;   emacs.  Change INSTALLATION notes.
  582. ;;; 2.61 - [posted to gnu.emacs.sources]
  583. ;;;   lrd: Doc mod.  Clean up the installation of minor mode indicators.
  584. ;;; 2.62 - [posted to gnu.emacs.sources]
  585. ;;;   lrd: installed patch from stig@netcom.com to simplify crypt-get-* defuns
  586. ;;;   (now defmacros).  Don't add to `term-setup-hook' unless no
  587. ;;;   `after-init-hook' _and_ definitely running v19, otherwise Rod gets an 
  588. ;;;   error at home :-<.  Don't assume C-x i had `insert-file' bound to it: 
  589. ;;;   store old binding in `crypt-old-binding' before overwriting and use in 
  590. ;;;   function `crypt-bind-insert-file.'
  591. ;;; 2.63 - 
  592. ;;;   lrd: (crypt-encode-buffer, crypt-encode-region, crypt-encrypt-buffer,
  593. ;;;   crypt-encrypt-region): changed argument list putting optional buffer
  594. ;;;   last and making default action to encode or encrypt. (crypt-encoded-p,
  595. ;;;   crypt-encrypted-p): new functions that do the actual testing of file
  596. ;;;   contents.  (crypt-find-file): uses these new functions.
  597. ;;;   (crypt-rebuild-minor-modes-alist): new function to rebuild
  598. ;;;   `minor-mode-alist' called by function crypt-rebuild-tables.
  599. ;;;   (crypt-build-minor-mode-alist): new function called by
  600. ;;;   `crypt-minor-mode-alist' to create itself.  `crypt-minor-mode-encrypted'
  601. ;;;   removed because defined in function crypt-build-minor-mode-alist.
  602. ;;; 2.64 - 
  603. ;;;   lrd: (crypt-find-file-hook): temporarily remove the encrytion file
  604. ;;;   extension to help determine the major mode, just like is done with the
  605. ;;;   encoding file extension.  In order for this to work properly the file
  606. ;;;   extension in `crypt-encryption-file-extension' and
  607. ;;;   `crypt-encryption-alist' needs to be inside a pair of \\( \\).
  608. ;;; 2.65 - 
  609. ;;;   lrd: (crypt-find-file-hook): move determination of key, password, into
  610. ;;;   (crypt-encrypted-p).
  611. ;;; 2.66 - 
  612. ;;;   lrd: (crypt-set-encryption-key): improve prompt string for encryption 
  613. ;;;   key.
  614. ;;; 2.67 - 
  615. ;;;   lrd: (crypt-write-file-hook): make check for encryption file-name 
  616. ;;;   extension case-sensitive.
  617. ;;; 2.68 - 
  618. ;;;   lrd: fixed check for previous addition to `minor-mode-alist' -- was not
  619. ;;;   working. Check for an `add-hook' function; if one does not exist then
  620. ;;;   use a copy of one from GNU Emacs 19.  When using `add-hook' to append to
  621. ;;;   the `write-file-hooks' make sure that the version accepts the optional
  622. ;;;   APPEND argument -- v19's does but the one in the elisp archive by Dan
  623. ;;;   LaLiberte <liberte@cs.uiuc.edu> does not append.  This causes problems.
  624. ;;;   Thanks to Francesco Potorti` <pot@fly.CNUCE.CNR.IT> for pointing this
  625. ;;;   out.
  626. ;;; 2.69 - [posted to gnu.emacs.sources]
  627. ;;;   lrd: doc mod with regards `after-init-hook' and Lucid Emacs.  Add 
  628. ;;;   pointer to crypt++-fnf.el for people who might be interested.
  629. ;;; 2.70 -
  630. ;;;   lrd: narrow conditions under which crypt-encryption-magic-regexp
  631. ;;;   matches.  Thanks to Philippe Michel <michel@thomson-lcr.fr> and Francois
  632. ;;;   Pinard <pinard@iro.umontreal.ca> for helping explain this with regards 
  633. ;;;   to ISO/Latin-1.
  634. ;;; 2.71 -
  635. ;;;   lrd: applied patches from Darrin Jewell <jewell@bdi.com> for DOS to UNIX
  636. ;;;   support.  DOS entry added to crypt-build-encoding-alist.
  637. ;;;   (crypt-dos-to-unix-region, crypt-unix-to-dos-region): New
  638. ;;;   functions. (crypt-dos-has-ctrl-z): New buffer-local variable.
  639. ;;;   (crypt-encode-region): allow for encoding and decoding programs to be
  640. ;;;   elisp expressions.  If they are then apply them directly to region.
  641. ;;;   Point out that crypt++.el conflicts with dos-mode.el.
  642. ;;; 2.72 - 
  643. ;;;   lrd: The limit for the regular expression search done by
  644. ;;;   `crypt-encrypted-p' is extended to 100 by default.  The enlargement of
  645. ;;;   search field is needed because of previous reduction in size of regexp
  646. ;;;   being searched for.  (crypt-magic-search-limit): New variable defining
  647. ;;;   this new limit.  (crypt-encrypted-p): Uses it and cleaned up.  Doc mod.
  648. ;;;   Thanks to Philippe Michel <michel@thomson-lcr.fr>, Francois Pinard
  649. ;;;   <pinard@iro.umontreal.ca>, and Dave Goldberg <dsg@blackbird.mitre.org>.
  650. ;;; 2.73 - [posted to gnu.emacs.sources]
  651. ;;;   lrd: Apply patch from Kevin Rodgers <kevin@traffic.den.mmc.com> that
  652. ;;;   uses more verbose messages and capitals.  Doc mod.
  653. ;;; 2.74 - 
  654. ;;;   lrd: Untabify.  (crypt-encrypted-p): Check value of
  655. ;;;   `crypt-never-ever-decrypt' before anything else.
  656. ;;; 2.75 - 
  657. ;;;   lrd: (crypt-version): Remove call to `substring'.
  658. ;;; 2.76 - 
  659. ;;;   lrd: (crypt-encryption-magic-regexp-inverse): Add in regexp that will
  660. ;;;   match ksh `.sh_history' files so that they are not interpreted as
  661. ;;;   encrypted files.  Thanks to Francesco Potorti` <pot@fly.CNUCE.CNR.IT>.
  662. ;;; 2.77 - [posted to gnu.emacs.sources]
  663. ;;;   lrd: (crypt-bind-insert-file): Use substitute-key-definition to bind
  664. ;;;   crypt-insert-file to whatever key insert-file is bound to (not
  665. ;;;   necessarily C-x i).  Call crypt-bind-insert-file directly in
  666. ;;;   file. Variable crypt-bind-insert-file: Doc mod.  Remove
  667. ;;;   crypt-old-binding.  Replace `M-x foobar' in doc strings with
  668. ;;;   `\\[foobar]'.
  669. ;;; 2.78 - 
  670. ;;;   lrd: (crypt-auto-write-answer-local): New internal variable.  Holds
  671. ;;;   answer to query about file-extension tricks question per buffer.  Thanks
  672. ;;;   to George Forman <forman@cs.washington.edu>.  Remove Rod from list of
  673. ;;;   maintainers...he's busy enough.  Merge multiple setq forms into single
  674. ;;;   setq forms.
  675. ;;; 2.79 -
  676. ;;;   lrd: (crypt-y-or-n-p): New internal function for querying.  Tests the
  677. ;;;   internal variable crypt-auto-write-answer-local to ensure single query.
  678. ;;;   (crypt-check-extension-for-encoding): Replace all occurrences of queries
  679. ;;;   involving y-or-no-p constructs with crypt-y-or-n-p.
  680. ;;; 2.80 - [posted to gnu.emacs.sources]
  681. ;;;   lrd: (crypt-set-encryption-key): Shorten interactive prompt.  Change
  682. ;;;   documentation.
  683. ;;; 2.81 - 
  684. ;;;   lrd: (crypt-variable-list): Add shell and path variables.
  685. ;;;   (crypt-confirm-password): Fix spelling error in doc.
  686. ;;; 2.82 - 
  687. ;;;   lrd: Applied patch from Noah Friedman <friedman@prep.ai.mit.edu>. 
  688. ;;;   (crypt-encoded-disable-auto-save, crypt-encrypted-disable-auto-save):
  689. ;;;   New user-defined variables. (crypt-encoded-mode, crypt-encrypted-mode):
  690. ;;;   Use them.
  691.  
  692.  
  693. ;;; Code:
  694.  
  695. ;;;; User definable variables.
  696.  
  697. (defvar crypt-encryption-type 'crypt
  698.   "*Method of encryption.  Must be an element of `crypt-encryption-alist.'
  699. If you change this after crypt++ is loaded then do \\[crypt-rebuild-tables].")
  700.  
  701. (defvar crypt-encryption-file-extension nil
  702.   "*Regexp for extension of files encrypted with `crypt-encryption-type.'
  703. Should be of the form \"\\\\(\\\\.foo\\\\)$\".  nil says use default values in
  704. `crypt-encryption-alist.'  If you change this after crypt++ is loaded then do
  705. \\[crypt-rebuild-tables].")
  706.  
  707. (defvar crypt-never-ever-decrypt nil
  708.   "*t says never attempt to decrypt a buffer.")
  709.  
  710. (defvar crypt-auto-write-buffer-encrypted nil
  711.   "*t says files with `crypt-encryption-alist' file extension auto-encrypted.
  712. nil says query.  See `crypt-auto-write-buffer.'")
  713.  
  714. (defvar crypt-confirm-password nil
  715.   "*t says confirm new passwords and when writing a newly encrypted buffer.")
  716.  
  717. (defvar crypt-encoded-disable-auto-save t
  718.   "*If t, turn off auto-save-mode for buffers which are encoded.
  719. If non-nil but not t, then no message is displayed.
  720.  
  721. The default is t is because there isn't any way to tell emacs to encode the
  722. autosave file, so the autosave would be in a different format from the
  723. original.  The disadvantage of turning off autosaves is that any work you
  724. do in that buffer will be completely lost if the changes are not explicitly
  725. saved.
  726.  
  727. It is probably best to set this variable to nil and use buffer-local
  728. variables in files for which you don't actually care about autosaves.
  729. Unencoded recovery data is better than none at all.")
  730.  
  731. (defvar crypt-encrypted-disable-auto-save t
  732.   "*If t, turn off auto-save-mode for buffers which are encrypted.
  733. If non-nil but not t, then no message is displayed.
  734.  
  735. The default is t is because there isn't any way to tell emacs to encrypt
  736. the autosave file, so the autosave would be in cleartext form.  The
  737. disadvantage of turning off autosaves is that any work you do in that
  738. buffer will be completely lost if the changes are not explicitly saved.
  739.  
  740. You might consider setting this variable to nil and use buffer-local
  741. variables in files for which security is more important than data
  742. recovery.")
  743.  
  744. ;;; ENCRYPTION
  745.  
  746. ;;; Encrypted files have no magic number, so we have to hack a way of
  747. ;;; determining when a buffer should be decrypted.  we do this only buffers
  748. ;;; that match a MAGIC-REGEXP very close to beginning of buffer and that do
  749. ;;; _NOT_ match a MAGIC-REGEXP-INVERSE.
  750. ;;;  
  751. ;;; Currently MAGIC-REGEXP matches non-ASCII characters and
  752. ;;; MAGIC-REGEXP-INVERSE will match Sun OS, 4.x BSD, and Ultrix executable
  753. ;;; magic numbers, so binaries can still be edited (heh) without headaches.
  754.  
  755. (defconst crypt-encryption-magic-regexp "[\000\200-\237]"
  756.   "Regexp that must be found very close to beginning of encrypted buffer.
  757. This is intended to be an internal variable \(not user-visible\).  If you
  758. change this after crypt++ is loaded then do \\[crypt-rebuild-tables].")
  759.  
  760. (defconst crypt-encryption-magic-regexp-inverse
  761.   "\\`\201\001\\|^\\(..\\)?\\([\007\010\013]\001\\|\001[\007\010\013]\\)"
  762.   "Regexp that must *not* be found very close to beginning of encrypted buffer.
  763. This is intended to be an internal variable \(not user-visible\).  If you
  764. change this after crypt++ is loaded then do \\[crypt-rebuild-tables].")
  765.  
  766. (defconst crypt-magic-search-limit 100
  767.   "Limit of regular expression search used to recognize encrypted files.
  768. Maximum position in file for presence of `crypt-encryption-magic-regexp' and
  769. absence of `crypt-encryption-magic-regexp-inverse'.")
  770.  
  771. (defun crypt-build-encryption-alist ()
  772.   ;; Returns the encryption alist
  773.   (list
  774.    ;; crypt
  775.    (list 'crypt
  776.          crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
  777.          (or crypt-encryption-file-extension "\\(\\.e\\)$")
  778.          "crypt" "crypt"
  779.          nil
  780.          nil
  781.          "Crypt"
  782.          nil
  783.          t
  784.          )
  785.    ;; DES (Cipher Block Chaining - CBC) [DES' default]
  786.    (list 'des
  787.          crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
  788.          (or crypt-encryption-file-extension "\\(\\.des\\)$")
  789.          "des" "des"
  790.          '("-e" "-k")
  791.          '("-d" "-k")
  792.          "DES-CBC"
  793.          nil
  794.          t
  795.          )
  796.    ;; DES (Electronic Code Book - ECB)
  797.    (list 'des-ecb
  798.          crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
  799.          (or crypt-encryption-file-extension "\\(\\.des\\)$")
  800.          "des" "des"
  801.          '("-e" "-b" "-k")
  802.          '("-d" "-b" "-k")
  803.          "DES-ECB"
  804.          nil
  805.          t
  806.          )
  807.    ;; PGP
  808.    (list 'pgp
  809.          crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
  810.          (or crypt-encryption-file-extension "\\(\\.pgp\\)$")
  811.          "pgp" "pgp"
  812.          '("+batchmode" "+verbose=0" "-c" "-f" "-z")
  813.          '("+batchmode" "+verbose=0" "-f" "-z")
  814.          "PGP"
  815.          nil
  816.          t
  817.          )
  818.    ;; Add new elements here ...
  819.    ))
  820.  
  821. (defconst crypt-encryption-alist (crypt-build-encryption-alist)
  822.   "List of elements describing the encryption methods available.
  823. each element looks like
  824.  
  825.         \(ENCRYPTION-TYPE
  826.           MAGIC-REGEXP MAGIC-REGEXP-INVERSE
  827.           FILE-EXTENSION
  828.           ENCRYPT-PROGRAM DECRYPT-PROGRAM
  829.           ENCRYPT-ARGS
  830.           DECRYPT-ARGS
  831.           MINOR-MODE
  832.           GARBAGE-REGEXP-OR-LISPEXP
  833.           FILE-EXTENSION-TRICKS
  834.          \)
  835.  
  836. ENCRYPTION-TYPE is a symbol denoting the encryption type.
  837.  
  838. MAGIC-REGEXP regexp that must match very close to the beginning of an
  839. encrypted buffer.  This may also be some elisp expression to be evaluated at
  840. \(point-min\) that will return t for an encrypted buffer.  If this is set to
  841. nil then crypt++ will never try to decrypt a buffer.  Currently set to the
  842. internal variable `crypt-encryption-magic-regexp' which will match non-ASCII
  843. characters.
  844.  
  845. MAGIC-REGEXP-INVERSE regexp that must _NOT_ match very close to the beginning
  846. of an encrypted buffer.  This may also be some elisp expression to be
  847. evaluated at \(point-min\) that will return t for a NON-encrypted buffer.
  848. If this is set to t then crypt++ will never try to decrypt a buffer.
  849. Currently set to the internal variable `crypt-encryption-magic-regexp-inverse'
  850. which will match Sun OS, 4.x BSD, and Ultrix executable magic numbers, so
  851. binaries can still be edited (heh) without headaches.
  852.  
  853. FILE-EXTENSION regexp denoting the file extension usually appended the
  854. filename of files encrypted with ENCRYPT-PROGRAM.  The variable
  855. `crypt-encryption-file-extension' will over ride the default.
  856.  
  857. ENCRYPT-PROGRAM name of executable file to be used for encryption.
  858.  
  859. DECRYPT-PROGRAM name of executable file to be used for decryption.
  860.  
  861. ENCRYPT-ARGS arguments to be passed to ENCRYPT-PROGRAM may be a string or a
  862. list of strings or nil.
  863.  
  864. DECRYPT-ARGS arguments to be passed to DECRYPT-PROGRAM may be a string or a
  865. list of strings or nil.
  866.  
  867. MINOR-MODE string denoting the name for the encrypted minor mode as it will
  868. appear in the mode line.
  869.  
  870. GARBAGE-REGEXP-OR-LISPEXP dummy variable for compatibility with encoding.
  871.  
  872. FILE-EXTENSION-TRICKS is t or nil depending on whether or not tricks
  873. converting between different encryption types can be done based on
  874. FILE-EXTENSION; typically t.
  875. ")
  876.  
  877.  
  878. ;;; ENCODING 
  879.  
  880. (defvar crypt-auto-decode-buffer t
  881.   "*t says buffers visiting encoded files will be decoded automatically.
  882. nil means to ask before doing the decoding.")
  883.  
  884. (defvar crypt-auto-write-buffer nil
  885.   "*t says save files with `crypt-encoding-alist' file extensions as encoded.
  886. nil says to ask before doing this encoding.  Similarly, buffers originating
  887. from encoded files to be written to files not ending in `crypt-encoding-alist'
  888. file extensions will be written in plain format automatically.  nil says to
  889. ask before doing this decoding.")
  890.  
  891. ;; This is an internal variable documented here and not in a DOCSTRING in
  892. ;; order to save memory.  If this variable's value has been changed from its
  893. ;; default, then it contains the answer to the question "Write out buffer
  894. ;; foobar using `compression-type'?".  This question is asked only if *plain*
  895. ;; buffer foobar is being written to disk *and* it has a provocative
  896. ;; `compression-type' file-name extension (see DOCSTRING for variable
  897. ;; crypt-auto-write-buffer).  The variable is local to all buffers with a
  898. ;; default value of 'ask so if the situation described above arises, then the
  899. ;; question is asked at least once, unless the user-defined variable
  900. ;; crypt-auto-write-buffer is non-nil.
  901. (defvar crypt-auto-write-answer-local 'ask)
  902. (make-variable-buffer-local 'crypt-auto-write-answer-local)
  903. (setq-default crypt-auto-write-answer-local 'ask)
  904. (put 'crypt-auto-write-answer-local 'permanent-local t) ; for v19 Emacs
  905. (put 'crypt-auto-write-answer-local 'preserved t)       ; for kill-fix.el
  906.  
  907. (defvar crypt-query-if-interactive t
  908.   "*t says ask when saving buffers where `crypt-encoded-mode' was toggled.
  909. nil says that even if filename extension is plain (i.e., not listed in
  910. `crypt-encoding-alist') buffer will be written in an encoded format without
  911. asking.
  912.  
  913. This variable is designed for users that edit a plain file (with plain
  914. extension) and then toggle `(crypt-encoded-mode)' and do not wish to be
  915. queried every time that they save the buffer.
  916.  
  917. NOTE: if `(crypt-encoded-mode)' was not called interactively (the usual
  918. scenario) then the value of this variable has no effect on how the buffer is
  919. written to disk.  In such a case `crypt-no-extension-implies-plain' is then
  920. the relevant variable.")
  921.  
  922. (defvar crypt-no-extension-implies-plain t
  923.   "*t says file extensions not in `crypt-encoding-alist' may be written plain.
  924. if `crypt-auto-write-buffer' is also t then any file ending in a plain
  925. extension is written in plain format automatically, otherwise query user.
  926.  
  927. nil says user works with encoded (compressed) files without file extensions
  928. and will not be queried each time they save these files.
  929.  
  930. NOTE: (1) this does not effect find-file (C-x C-f) since that works with a
  931. magic regexp.  (2) there is no way to distinguish between write-file and
  932. save-buffer so nil will mean that neither will query.")
  933.  
  934. (defvar crypt-freeze-vs-fortran t
  935.   "*t says `.F' file extension denotes a frozen file not a Fortran file.
  936. If you change this variable after crypt++ has been loaded then do
  937. \\[crypt-rebuild-tables].")
  938.  
  939. (defvar crypt-compact-vs-C++ nil
  940.   "*t says `.C' file extension denotes a compacted file not a C++ file.
  941. If you change this variable after crypt++ has been loaded then do
  942. \\[crypt-rebuild-tables].")
  943.  
  944. (defvar crypt-ignored-filenames nil
  945.   "*List of regexp filenames for which encoded to plain conversion is not done.
  946. A filename with a plain extension, in encoded format, that is matched by one of
  947. these elements will be saved in encoded format without a query for conversion to
  948. plain format.
  949.  
  950. This variable is provided for users that want to compress their incoming mail
  951. for RMAIL and VM which look for files `RMAIL' and `INBOX,' respectively, to
  952. store incoming mail.  For example, the gzip extensions on `RMAIL.gz' and
  953. `INBOX.gz' can be removed, this variable set to '\(\"INBOX$\" \"RMAIL$\"\) and
  954. no query about conversion to plain format will be made.")
  955.  
  956. (defvar crypt-default-encoding "gzip"
  957.   "*Default encoding type as string used when `crypt-encoded-mode' is toggled.
  958. Must match one of the elements of `crypt-encoding-alist'.")
  959.  
  960. (defvar crypt-dos-has-ctrl-z nil
  961.   "t if this buffer had a ctrl-z stripped from end, otherwise, nil.
  962. Buffer local and set by `crypt-dos-to-unix-region'")
  963. (make-variable-buffer-local 'crypt-dos-has-ctrl-z)
  964. (setq-default crypt-dos-has-ctrl-z nil)
  965. (put 'crypt-dos-has-ctrl-z 'permanent-local t) ; for v19 Emacs
  966. (put 'crypt-dos-has-ctrl-z 'preserved t)       ; for kill-fix.el
  967.  
  968. (defun crypt-build-encoding-alist ()
  969.   ;; Returns the encoding alist
  970.   (list
  971.    ;; compress 
  972.    (list 'compress
  973.          "\037\235" nil
  974.          "\\(\\.Z\\)$"
  975.          "compress" "uncompress"
  976.          nil nil
  977.          "Compress"
  978.          nil
  979.          t)
  980.    ;; gzip (GNU zip)
  981.    (list 'gzip
  982.          "\037\213" nil
  983.          "\\(\\.g?z\\)$"
  984.          "gzip" "gzip"
  985.          "--quiet" "--decompress --quiet"
  986.          "Zip"
  987.          nil
  988.          t)
  989.    ;; freeze
  990.    (list 'freeze
  991.          "\037\236\\|\037\237" nil
  992.          "\\(\\.F\\)$"
  993.          "freeze" "freeze"
  994.          "" "-d"
  995.          "Freeze"
  996.          nil
  997.          crypt-freeze-vs-fortran)
  998.    ;; compact
  999.    (list 'compact
  1000.          "\377\037" nil
  1001.          "\\(\\.C\\)$"
  1002.          "compact" "uncompact"
  1003.          nil nil
  1004.          "Compact"
  1005.          "^Compression *:.*\n"
  1006.          crypt-compact-vs-C++)
  1007.    ;; DOS
  1008.    (list 'dos
  1009.          "[^\n\r]*\r$" nil
  1010.          "\\(\\.DOS\\)$"
  1011.          'crypt-unix-to-dos-region 'crypt-dos-to-unix-region
  1012.          nil nil
  1013.          "Dos"
  1014.          nil
  1015.          nil)
  1016.    ;; Add new elements here ...
  1017.    ))
  1018.  
  1019. (defconst crypt-encoding-alist (crypt-build-encoding-alist)
  1020.   "List of elements describing the encoding methods available.
  1021. each element looks like
  1022.  
  1023.         \(ENCODING-TYPE
  1024.           MAGIC-REGEXP MAGIC-REGEXP-INVERSE
  1025.           FILE-EXTENSION
  1026.           ENCODE-PROGRAM DECODE-PROGRAM
  1027.           ENCODE-ARGS DECODE-ARGS
  1028.           MINOR-MODE
  1029.           GARBAGE-REGEXP-OR-LISPEXP
  1030.           FILE-EXTENSION-TRICKS
  1031.          \)
  1032.  
  1033. ENCODING-TYPE is a symbol denoting the encoding type.  Currently known
  1034. encodings are (compress compact freeze gzip).
  1035.  
  1036. MAGIC-REGEXP is a regexp that matches the magic number at the
  1037. beginning of files encoded with ENCODING-TYPE.
  1038.  
  1039. MAGIC-REGEXP-INVERSE dummy variable for compatibility with encryption.
  1040.  
  1041. FILE-EXTENSION is a string denoting the file extension usually
  1042. appended the filename of files encoded with ENCODING-TYPE.
  1043.  
  1044. ENCODE-PROGRAM is a string denoting the name of the executable used to
  1045. encode files.
  1046.  
  1047. DECODE-PROGRAM is a string denoting the name of the executable used to
  1048. decode files.
  1049.  
  1050. ENCODE-ARGS arguments to be passed to ENCODE-PROGRAM may be a string or a
  1051. list of strings or nil.
  1052.  
  1053. DECODE-ARGS arguments to be passed to DECODE-PROGRAM may be a string or a
  1054. list of strings or nil.
  1055.  
  1056. MINOR-MODE is a string denoting the name for the encoded minor mode as 
  1057. it will appear in the mode line.
  1058.  
  1059. GARBAGE-REGEXP-OR-LISPEXP is (1) a regexp that matches any extraneous text
  1060. that is produced by the ENCODE-COMMAND including any newlines and will be
  1061. removed from the buffer before saving to disk; (2) a lisp expression that will
  1062. clean up extraneous material in the buffer or nil.  This is normally not
  1063. needed but can be derived for any ENCODE-COMMAND by checking the standard
  1064. error that results from `sh -c \"cat foo | ENCODE-COMMAND > bar\"'.
  1065.  
  1066. FILE-EXTENSION-TRICKS is t or nil depending on whether or not tricks
  1067. converting between different encoding types can be done based on
  1068. FILE-EXTENSION; typically t.
  1069. ")
  1070.  
  1071.  
  1072. ;;; This allows the user to alter contents of the encoding and encryption
  1073. ;;; table variables without having to reload all of crypt++.
  1074. (defun crypt-rebuild-tables ()
  1075.   "Rebuilds the encryption and encoding tables and `minor-mode-alist'.
  1076. Allows user to alter variables used in building these tables.  May be called
  1077. interactively or in an initialization file.  Part of `after-init-hook'."
  1078.   (interactive)
  1079.   (setq crypt-encryption-alist (crypt-build-encryption-alist)
  1080.         crypt-encoding-alist (crypt-build-encoding-alist))
  1081.   (crypt-rebuild-minor-modes-alist))
  1082.  
  1083.  
  1084. ;;; Buffer locals.
  1085.  
  1086. (defvar crypt-buffer-save-encrypted nil
  1087.   "*non-nil says save buffer encrypted with `crypt-encryption-type.'
  1088. local to all buffers.")
  1089. (make-variable-buffer-local 'crypt-buffer-save-encrypted)
  1090. (put 'crypt-buffer-save-encrypted 'permanent-local t) ; for v19 Emacs
  1091. (put 'crypt-buffer-save-encrypted 'preserved t)       ; for kill-fix.el
  1092.  
  1093. (defvar crypt-buffer-encryption-key nil
  1094.   "*Key used for encryption of current buffer.  Local to all buffers.")
  1095. (make-variable-buffer-local 'crypt-buffer-encryption-key)
  1096. (put 'crypt-buffer-encryption-key 'permanent-local t) ; for v19 Emacs
  1097. (put 'crypt-buffer-encryption-key 'preserved t)       ; for kill-fix.el
  1098.  
  1099. (defvar crypt-buffer-save-encoded nil
  1100.   "*non-nil says buffer will be saved encoded.  Local to all buffers.")
  1101. (make-variable-buffer-local 'crypt-buffer-save-encoded)
  1102. (put 'crypt-buffer-save-encoded 'permanent-local t)   ; for v19 Emacs
  1103. (put 'crypt-buffer-save-encoded 'preserved t)         ; for kill-fix.el
  1104.  
  1105. (defvar crypt-buffer-encoding-type nil
  1106.   "*non-nil says buffer is encoded with ENCODING-TYPE.  Local to all buffers.")
  1107. (make-variable-buffer-local 'crypt-buffer-encoding-type)
  1108. (put 'crypt-buffer-encoding-type 'permanent-local t)  ; for v19 Emacs
  1109. (put 'crypt-buffer-encoding-type 'preserved t)        ; for kill-fix.el
  1110.  
  1111. (defvar crypt-buffer-interactive-encoded-mode nil
  1112.   "t says `crypt-encoded-mode' was toggled interactively, almost always nil.
  1113. Local to all buffers.")
  1114. (make-variable-buffer-local 'crypt-buffer-interactive-encoded-mode)
  1115. (put 'crypt-buffer-interactive-encoded-mode 'permanent-local t) ; v19 Emacs
  1116. (put 'crypt-buffer-interactive-encoded-mode 'preserved t)       ; kill-fix.el
  1117.  
  1118.  
  1119. ;;; Functions and macros that search `crypt-encryption-alist' and
  1120. ;;; `crypt-encoding-alist'.
  1121.  
  1122. (defun crypt-get-alist-member (type n)
  1123.   ;; Returns TYPE's Nth element
  1124.   (nth n (or (assoc type crypt-encryption-alist)
  1125.              (assoc type crypt-encoding-alist))))
  1126.  
  1127. (defmacro crypt-get-magic-regexp (type)
  1128.   ;; Returns regexp found at top of files encoded/encrypted with TYPE.
  1129.   (list 'crypt-get-alist-member type 1))
  1130.  
  1131. (defmacro crypt-get-magic-regexp-inverse (type)
  1132.   ;; Returns regexp *not* found at top of files encoded/encrypted with TYPE.
  1133.   (list 'crypt-get-alist-member type 2))
  1134.  
  1135. (defmacro crypt-get-file-extension (type)
  1136.   ;; Returns regexp matching extension of files encoded/encrypted with TYPE.
  1137.   (list 'crypt-get-alist-member type 3))
  1138.  
  1139. (defmacro crypt-get-encoding-program (type)
  1140.   ;; Returns name of program, as string, used to encode/encrypt with TYPE.
  1141.   (list 'crypt-get-alist-member type 4))
  1142.  
  1143. (defmacro crypt-get-decoding-program (type)
  1144.   ;; Returns name of program, as string, used to decode/decrypt with TYPE.
  1145.   (list 'crypt-get-alist-member type 5))
  1146.  
  1147. (defmacro crypt-get-encoding-args (type)
  1148.   ;; Returns arguments passed to program used to encode/encrypt with TYPE.
  1149.   (list 'crypt-get-alist-member type 6))
  1150.  
  1151. (defmacro crypt-get-decoding-args (type)
  1152.   ;; Returns arguments passed to program used to decode/decrypt with TYPE.
  1153.   (list 'crypt-get-alist-member type 7))
  1154.  
  1155. (defmacro crypt-get-minor-mode-name (type)
  1156.   ;; Returns minor mode name, as string, for encoding/encrypting with TYPE.
  1157.   (list 'crypt-get-alist-member type 8))
  1158.  
  1159. (defmacro crypt-get-cleanup-regexp (type)
  1160.   ;; Returns regexp or lisp-exp for cleaning up encoding/encrypting with TYPE.
  1161.   (list 'crypt-get-alist-member type 9))
  1162.  
  1163. (defmacro crypt-get-extension-tricks (type)
  1164.   ;; Returns t if file extension tricks doable for encoding/encrypting with
  1165.   ;; TYPE.
  1166.   (list 'crypt-get-alist-member type 10))
  1167.  
  1168. (defun crypt-buffer-save-name (type)
  1169.   ;; Returns variable `crypt-buffer-save-TYPE', set to t if encoding with TYPE.
  1170.   ;; local to all buffers.
  1171.   (intern (concat "crypt-buffer-save-" (symbol-name type))))
  1172.  
  1173.  
  1174. ;;; Create a buffer-local variable for each type of encoding.
  1175. ;;; These variables are used to trigger the minor mode names.
  1176.  
  1177. (defun crypt-build-minor-mode-alist ()
  1178.   ;; Returns minor mode alist entries for encoded and encrypted buffers.
  1179.   (append
  1180.    ;; First the encrypted minor mode -- only one.
  1181.    (list (list 'crypt-buffer-save-encrypted
  1182.                (concat " " (crypt-get-minor-mode-name crypt-encryption-type))))
  1183.    ;; Now the encoding minor modes.
  1184.    (mapcar
  1185.     (function
  1186.      (lambda (element)
  1187.        (let ((variable (crypt-buffer-save-name (car element))))
  1188.          (make-variable-buffer-local variable)
  1189.          (put variable 'permanent-local t) ; for v19 Emacs
  1190.          (put variable 'preserved t)       ; for kill-fix.el
  1191.          (list variable
  1192.                (concat " " (crypt-get-minor-mode-name (car element)))))))
  1193.     crypt-encoding-alist)))
  1194.  
  1195. (defconst crypt-minor-mode-alist (crypt-build-minor-mode-alist)
  1196.   "Alist containing encoded and encrypted minor modes.
  1197. Derived from variable `crypt-encoding-alist' and function
  1198. `crypt-build-minor-mode-encrypted'")
  1199.  
  1200. (defun crypt-rebuild-minor-modes-alist ()
  1201.   ;; Rebuilds the encryption and encoding minor modes and `minor-mode-alist.'
  1202.   ;; Allows user to alter variables used in building this alist. Called by
  1203.   ;; `crypt-rebuild-tables' and so part of `after-init-hook'."
  1204.  
  1205.   ;; First remove old crypt minor mode entries from `minor-mode-alist'.
  1206.   (if (memq (car crypt-minor-mode-alist) minor-mode-alist)
  1207.       (let ((alist crypt-minor-mode-alist) elt)
  1208.         (while (and alist (setq elt (car alist)))
  1209.           (setq minor-mode-alist (delq elt minor-mode-alist)
  1210.                 alist (cdr alist)))))
  1211.  
  1212.   ;; Get new crypt minor mode entries and add to minor-mode-alist.
  1213.   (setq crypt-minor-mode-alist (crypt-build-minor-mode-alist)
  1214.         minor-mode-alist (append crypt-minor-mode-alist minor-mode-alist)))
  1215.  
  1216.  
  1217. (defmacro crypt-save-point (&rest body)
  1218.   ;; Save value of point, evaluate FORMS, and restore value of point.  If the
  1219.   ;; saved value of point is no longer valid go to (point-max).  This macro
  1220.   ;; exists because, save-excursion loses track of point during some types of
  1221.   ;; deletions.
  1222.   (let ((var (make-symbol "saved-point")))
  1223.     (list 'let (list (list var '(point)))
  1224.           (list 'unwind-protect
  1225.                 (cons 'progn body)
  1226.                 (list 'goto-char var)))))
  1227.  
  1228.  
  1229. (defun crypt-find-file-hook ()
  1230.  
  1231.   ;; Hook run for decoding and/or decrypting the contents of a buffer.  Meant
  1232.   ;; to be called as part of `find-file-hooks'
  1233.  
  1234.   (let ((buffer-file-name buffer-file-name)
  1235.         (old-buffer-file-name buffer-file-name)
  1236.         (old-buffer-modified-p (buffer-modified-p))
  1237.         (case-fold-search nil) ; case-sensitive
  1238.         encrypted encoded buffer-read-only)
  1239.  
  1240.     ;; DECODE AND/OR DECRYPT
  1241.     (crypt-save-point
  1242.  
  1243.      ;; Do we have to DECODE? If not, then move on.
  1244.      (if (and (crypt-encoded-p)
  1245.               (or crypt-auto-decode-buffer
  1246.                   (y-or-n-p (format "Decode %s? " (buffer-name)))))
  1247.  
  1248.          ;; Decode, uncompress, the buffer.
  1249.          (progn
  1250.  
  1251.            (message "Decoding %s..." (buffer-name))
  1252.            (crypt-encode-buffer t)
  1253.  
  1254.            ;; Store the encoding mode.
  1255.  
  1256.            ;; We can not yet go into the minor modes because the major mode
  1257.            ;; may change later on and blow away all local variables (and thus
  1258.            ;; the minor modes).  Only needed for vanilla v18.  Our
  1259.            ;; buffer-locals defined 'permanent-local for v19 Emacs and
  1260.            ;; 'preserved for kill-fix.el.
  1261.  
  1262.            (setq encoded crypt-buffer-encoding-type)
  1263.  
  1264.            ;; Strip encoded file's extension so later we can set buffer's
  1265.            ;; major mode based on its file-name sans encoding extension.
  1266.            (if (string-match (crypt-get-file-extension
  1267.                               crypt-buffer-encoding-type) buffer-file-name)
  1268.                (setq buffer-file-name
  1269.                      (substring buffer-file-name 0 (match-beginning 1))))
  1270.  
  1271.            ;; Decoding ends.
  1272.            (if (not (input-pending-p))
  1273.                (message "Decoding %s... done" (buffer-name)))))
  1274.  
  1275.      ;; Do we have to DECRYPT? If not, then move on.
  1276.      (if (crypt-encrypted-p)
  1277.  
  1278.          ;; Decrypt buffer.
  1279.          (progn
  1280.                  
  1281.            (message "Decrypting %s..." (buffer-name))
  1282.            (crypt-encrypt-buffer crypt-buffer-encryption-key t)
  1283.                  
  1284.            ;; Save key in case major mode blows all buffer-locals. 
  1285.  
  1286.            ;; Only needed for vanilla v18.  Our buffer-locals defined
  1287.            ;; 'permanent-local for v19 Emacs and 'preserved for
  1288.            ;; kill-fix.el.
  1289.                
  1290.            (setq encrypted crypt-buffer-encryption-key)
  1291.                  
  1292.            ;; Strip encrypted file's extension so later we can set buffer's
  1293.            ;; major mode based on its file-name sans encrypting extension.
  1294.            (if (and (crypt-get-extension-tricks crypt-encryption-type)
  1295.                     (string-match (crypt-get-file-extension
  1296.                                    crypt-encryption-type) buffer-file-name))
  1297.                (setq buffer-file-name
  1298.                      (substring buffer-file-name 0 (match-beginning 1))))
  1299.  
  1300.            (if (not (input-pending-p))
  1301.                (message "Decrypting %s... done" (buffer-name))))))
  1302.  
  1303.     ;; MAJOR AND MINOR MODES
  1304.  
  1305.     ;; OK, if any changes have been made to the buffer we need to rerun the
  1306.     ;; code the does automatic selection of major mode.
  1307.  
  1308.     (if (or encoded encrypted)
  1309.  
  1310.         (progn
  1311.  
  1312.           ;; Set the major mode.
  1313.           (set-auto-mode)
  1314.           (hack-local-variables)
  1315.           
  1316.           ;; Now set our own minor mode(s).
  1317.           (if encoded
  1318.               ;; Recover encoding type, may have been smashed by major mode,
  1319.               ;; and toggle encoded mode.
  1320.               (progn (setq crypt-buffer-encoding-type encoded)
  1321.                      (crypt-encoded-mode 1)))
  1322.           
  1323.           (if encrypted
  1324.               ;; Recover encryption key, may have been smashed by major mode,
  1325.               ;; and toggle encrypted mode.
  1326.               (progn (setq crypt-buffer-encryption-key encrypted)
  1327.                      (crypt-encrypted-mode 1)))
  1328.           
  1329.           ;; Restore buffer file name now, so that lock file entry is removed
  1330.           ;; properly.
  1331.           (setq buffer-file-name old-buffer-file-name)
  1332.           
  1333.           ;; Restore buffer modified flag to its previous value.  Will also
  1334.           ;; remove lock file entry for buffer if previous value was nil.
  1335.           ;; This is why buffer-file-name had to be restored manually above.
  1336.           (set-buffer-modified-p old-buffer-modified-p)))))
  1337.  
  1338. (defun crypt-encoded-p (&optional buffer)
  1339.   ;; Returns t if current buffer, or optionally BUFFER, is encoded.
  1340.   ;; Sets `crypt-buffer-encoding-type' to encoding method.
  1341.   (save-excursion
  1342.     (and buffer (set-buffer buffer))
  1343.     (save-restriction
  1344.       (widen)
  1345.       (goto-char (point-min))
  1346.       (let ((alist crypt-encoding-alist) elt found)
  1347.         (while (and alist (setq elt (car alist)) (not found))
  1348.           (if (looking-at (nth 1 elt))
  1349.               (setq crypt-buffer-encoding-type (nth 0 elt)
  1350.                     found t)
  1351.             ;; Decrement
  1352.             (setq alist (cdr alist))))
  1353.         found))))
  1354.  
  1355. (defun crypt-encrypted-p (&optional buffer)
  1356.   ;; Returns t if current buffer, or optionally BUFFER, is encrypted.
  1357.   ;; Look for MAGIC-REGEXP and absence of MAGIC-REGEXP-INVERSE.  If so, then
  1358.   ;; assume it is an encrypted buffer.
  1359.   ;; Sets `crypt-buffer-encryption-key' to password if not set already.
  1360.  
  1361.   ;; Do not try to decrypt buffer if not wanted.
  1362.   (if (not crypt-never-ever-decrypt)
  1363.  
  1364.       (save-excursion
  1365.         (and buffer (set-buffer buffer))
  1366.  
  1367.         (save-restriction
  1368.           (widen)
  1369.           (goto-char (point-min))
  1370.  
  1371.           (let ((magic-regexp (crypt-get-magic-regexp crypt-encryption-type))
  1372.                 (magic-regexp-inverse (crypt-get-magic-regexp-inverse
  1373.                                        crypt-encryption-type))
  1374.                 (limit (min (point-max) crypt-magic-search-limit)))
  1375.  
  1376.             ;; Check all encryption conditions.  If any fail, then return nil
  1377.             ;; value of this if-form, else check for password.
  1378.             (if (and
  1379.  
  1380.                  ;; Check for existence of MAGIC-REGEXP.
  1381.                  (if (stringp magic-regexp)
  1382.                      ;; regular expression
  1383.                      (re-search-forward magic-regexp limit t)
  1384.                    ;; lisp expression
  1385.                    (eval magic-regexp))
  1386.  
  1387.                  (goto-char (point-min))
  1388.  
  1389.                  ;; Check for absence of MAGIC-REGEXP-INVERSE.
  1390.                  (not (if (stringp magic-regexp-inverse)
  1391.                           ;; regular expression
  1392.                           (re-search-forward magic-regexp-inverse limit t)
  1393.                         ;; lisp expression
  1394.                         (eval magic-regexp-inverse))))
  1395.  
  1396.                 (progn
  1397.  
  1398.                   ;; Get key, i.e., the password?
  1399.                   (or crypt-buffer-encryption-key
  1400.                       ;; Do not confirm on reading an encrypted file.
  1401.                       (let ((crypt-confirm-password nil))
  1402.                         (call-interactively 'crypt-set-encryption-key)))
  1403.              
  1404.                   ;; Do not turn on encryption mode if no key: may be a binary
  1405.                   ;; file.  Thanks to Paul Dworkin (paul@media-lab.media.mit.edu).
  1406.                   (if (equal crypt-buffer-encryption-key "")
  1407.                       ;; Return nil.
  1408.                       (progn
  1409.                         (message "No key given.  Assumed normal.")
  1410.                         nil)
  1411.                     ;; Return t.
  1412.                     t))))))))
  1413.  
  1414.  
  1415. ;;; 
  1416.  
  1417. (defun crypt-check-extension-for-encoding ()
  1418.  
  1419.   ;; Checks file extensions for possible toggling of encoding modes.  Used for
  1420.   ;; buffers to be written to disk and called by `crypt-write-file-hook'
  1421.  
  1422.   ;; We try to flag a buffer to be written out in encoded form if the file
  1423.   ;; ends in one of the file-extensions in `crypt-encoding-alist' even if
  1424.   ;; `crypt-buffer-save-encoded' is nil.  Conversely, we try to write out a
  1425.   ;; buffer as a plain file if it does _not_ end in one of these
  1426.   ;; file-extensions even if `crypt-buffer-save-encoded' is non-nil.
  1427.   
  1428.   (let ((alist crypt-encoding-alist)
  1429.         (case-fold-search nil)
  1430.         found elt)
  1431.  
  1432.     ;; Search through the file name extensions for a match.
  1433.     (while (and alist (setq elt (car alist)) (not found))
  1434.       (if (string-match (nth 3 elt) buffer-file-name)
  1435.           (setq found t)
  1436.         ;; Decrement.
  1437.         (setq alist (cdr alist))))
  1438.     
  1439.     ;; Did we find a match? 
  1440.     (if found
  1441.         
  1442.         ;; File name ends in a very provocative extension.
  1443.  
  1444.         ;; Check to see if already an encoded file.
  1445.         (if crypt-buffer-save-encoded
  1446.             
  1447.             ;; Already encoded - do the methods of encoding match?
  1448.             (if (not (eq (nth 0 elt) crypt-buffer-encoding-type))
  1449.                  
  1450.                 ;; A new encoding method is desired.
  1451.  
  1452.                 ;; Can we play some filename extension tricks with the 
  1453.                 ;; destination extension?
  1454.                 (if (crypt-get-extension-tricks (nth 0 elt))
  1455.  
  1456.                     ;; Can play tricks.
  1457.                     ;; Change the method of encoding?
  1458.                     (if (crypt-y-or-n-p (format "Write %s using %s? "
  1459.                                          (buffer-name) (nth 4 elt)))
  1460.                 
  1461.                         ;; Case one.
  1462.                         ;; Turn off original encoding and turn on new encoding.
  1463.                         (progn (crypt-encoded-mode -1)
  1464.                                (setq crypt-buffer-encoding-type (nth 0 elt))
  1465.                                (crypt-encoded-mode 1)))
  1466.  
  1467.                   ;; Can not play tricks - maybe wants a plain file?
  1468.                   (if (crypt-y-or-n-p (format "Write %s a plain file? "
  1469.                                               (buffer-name)))
  1470.  
  1471.                       ;; Case three.
  1472.                       ;; Turn off the minor mode and _then_ the flags.
  1473.                       (progn
  1474.                         (crypt-encoded-mode -1)
  1475.                         (setq crypt-buffer-save-encoded nil
  1476.                               crypt-buffer-encoding-type nil)))))
  1477.           
  1478.           ;; Was a plain file.
  1479.           (if (and
  1480.                ;; Can we play some filename extension tricks?
  1481.                ;; If not then we must abort.
  1482.                (crypt-get-extension-tricks (nth 0 elt))
  1483.  
  1484.                (crypt-y-or-n-p (format "Write %s using %s? "
  1485.                                        (buffer-name) (nth 4 elt))))
  1486.               
  1487.               ;; Case two.
  1488.               ;; Turn on encoding flags and _then_ the minor mode.
  1489.               (progn 
  1490.                 (setq crypt-buffer-save-encoded t
  1491.                       crypt-buffer-encoding-type (nth 0 elt))
  1492.                 (crypt-encoded-mode 1))))
  1493.       
  1494.       ;; No match - a plain-jane file extension - but if the encoded flag is
  1495.       ;; non-nil then the user may really want it written out in plain
  1496.       ;; format so we must override this flag.
  1497.       (if (and crypt-buffer-save-encoded
  1498.                
  1499.                ;; Search the list of files to be ignored.
  1500.                ;; If `crypt-ignored-filenames' is nil then this let form 
  1501.                ;; will return t.  If a match is found this form will return 
  1502.                ;; nil.  Otherwise it will return t.
  1503.                (let ((tlist crypt-ignored-filenames)
  1504.                      case-fold-search found elt)
  1505.  
  1506.                  ;; Search through the list of filenames for a match.
  1507.                  (while (and tlist (setq elt (car tlist)) (not found))
  1508.                    (if (string-match elt buffer-file-name)
  1509.                        (setq found t)
  1510.                      ;; Decrement.
  1511.                      (setq tlist (cdr tlist))))
  1512.                  
  1513.                  ;; Return t if we can _not_ find a match.
  1514.                  (not found))
  1515.  
  1516.                ;; If `(crypt-encoded-mode)' was called interactively, then
  1517.                ;; there is a high probability that no matter what the file
  1518.                ;; name extension the user wishes to write the file out in some
  1519.                ;; encoded format.  Thanks to Kimball Collins
  1520.                ;; <kpc@ptolemy.arc.nasa.gov> for pointing out the need for
  1521.                ;; this.  Unfortunately, still can not distinguish between
  1522.                ;; write-file and save-buffer.  In the former the user may want
  1523.                ;; to write in plain format (or indeed some other format).
  1524.                
  1525.                (if crypt-buffer-interactive-encoded-mode
  1526.                    ;; Interactive
  1527.                    crypt-query-if-interactive 
  1528.                  ;; Non-interactive but still may want encoded format.
  1529.                  crypt-no-extension-implies-plain)
  1530.  
  1531.                (crypt-y-or-n-p (format "Write %s as a plain file? "
  1532.                                        (buffer-name))))
  1533.  
  1534.           ;; Case three.
  1535.           ;; Turn off the minor mode and _then_ the flags.
  1536.           (progn
  1537.             (crypt-encoded-mode -1)
  1538.             (setq crypt-buffer-save-encoded nil
  1539.                   crypt-buffer-encoding-type nil))))))
  1540.  
  1541.  
  1542. (defun crypt-y-or-n-p (prompt)
  1543.   ;; Queries user based on `crypt-auto-write-buffer' and internal buffer-local
  1544.   ;; variable `crypt-auto-write-answer-local'.  Returns value of
  1545.   ;; `crypt-auto-write-answer-local', which is t or nil.
  1546.  
  1547.   ;; Check if we need to ask user.  Should be 'ask, nil, or t.
  1548.   (if (eq crypt-auto-write-answer-local 'ask) ; Default value.
  1549.       ;; We may need to ask.
  1550.       (or crypt-auto-write-buffer
  1551.           ;; Ask and store the answer.  
  1552.           ;; Note: we only store if we asked.
  1553.           (setq crypt-auto-write-answer-local (y-or-n-p prompt)))
  1554.     ;; Use previous answer.
  1555.     crypt-auto-write-answer-local)) ; Will be nil or t.
  1556.  
  1557.  
  1558. ;;; This function should be called ONLY as a write-file hook.
  1559. ;;; Odd things will happen if it is called elsewhere.
  1560.  
  1561. (defun crypt-write-file-hook ()
  1562.   
  1563.   ;; Hook for possibly writing out file, and backup file, in a non-plain
  1564.   ;; format.  Terminates calls in `write-file-hooks' and should be at end of
  1565.   ;; list.
  1566.  
  1567.   ;; Check file-extension for possible toggling of encoding modes.
  1568.   (crypt-check-extension-for-encoding)
  1569.  
  1570.   ;; Check extension for encryption.
  1571.   (if (and
  1572.  
  1573.        ;; Maybe file ends with provocative extension w.r.t. encryption?
  1574.        (stringp (crypt-get-file-extension crypt-encryption-type))
  1575.        (let ((case-fold-search nil)) ; Make case-sensitive.
  1576.          (string-match (crypt-get-file-extension crypt-encryption-type)
  1577.                        buffer-file-name))
  1578.        
  1579.        ;; Can we play tricks?
  1580.        (crypt-get-extension-tricks crypt-encryption-type)
  1581.  
  1582.        ;; Match of filename extension - is file in plain format?
  1583.        (not crypt-buffer-save-encrypted)
  1584.        
  1585.        ;; Query?
  1586.        (or crypt-auto-write-buffer-encrypted
  1587.            (y-or-n-p
  1588.             (format "Write %s as an encrypted file? " (buffer-name)))))
  1589.  
  1590.       (progn
  1591.         ;; Set password and toggle `crypt-encrypted-mode'
  1592.         (call-interactively 'crypt-set-encryption-key)
  1593.         (crypt-encrypted-mode 1)))
  1594.  
  1595.   ;; Now decide whether or not we need to continue with this defun. Does the
  1596.   ;; buffer need to be saved in a non-plain form?  If not then writing is not
  1597.   ;; done here but later in the write-file-hooks - probably at the end.
  1598.  
  1599.   (if (or crypt-buffer-save-encoded crypt-buffer-save-encrypted)
  1600.       
  1601.       (save-excursion
  1602.         (save-restriction
  1603.  
  1604.           (let 
  1605.               
  1606.               ;; BINDINGS
  1607.               ((copy-buffer (get-buffer-create " *crypt copy buffer*"))
  1608.                (selective-display selective-display)
  1609.                (buffer-read-only))
  1610.             
  1611.             ;; FORMS
  1612.             (copy-to-buffer copy-buffer 1 (1+ (buffer-size)))
  1613.             (narrow-to-region (point) (point))
  1614.             
  1615.             (unwind-protect
  1616.                 
  1617.                 ;; BODYFORM
  1618.                 (let (setmodes)
  1619.  
  1620.                   ;; As of v19, if one of functions of the `write-file-hooks'
  1621.                   ;; returns a non-nil value, then `basic-save-buffer' no
  1622.                   ;; longer creates a backup file.  We must do it ourselves. 
  1623.                   ;; this should be a no-op in v18.
  1624.                   (or buffer-backed-up
  1625.                       (setq setmodes (backup-buffer)))
  1626.  
  1627.                   (insert-buffer-substring copy-buffer)
  1628.                   (kill-buffer copy-buffer)
  1629.                   
  1630.                   ;; "Who would cross the Bridge of Death
  1631.                   ;;  Must answer me
  1632.                   ;;  These questions three
  1633.                   ;;  Ere the other side he see."
  1634.                   ;;
  1635.                   ;; Bridgekeeper from Monty Python and the Holy Grail
  1636.                   
  1637.                   ;; [1] selective-display non-nil means we must convert
  1638.                   ;; carriage returns to newlines now, and set the variable
  1639.                   ;; selective-display temporarily to nil.
  1640.                   (if selective-display
  1641.                       (progn
  1642.                         (goto-char (point-min))
  1643.                         (subst-char-in-region (point-min) (point-max) ?\r ?\n)
  1644.                         (setq selective-display nil)))
  1645.                   
  1646.                   ;; [2] encryption
  1647.                   (if crypt-buffer-save-encrypted
  1648.                       (progn
  1649.                         ;; check for password
  1650.                         (if (not crypt-buffer-encryption-key)
  1651.                             (call-interactively 'crypt-set-encryption-key))
  1652.                         (if (null crypt-buffer-encryption-key)
  1653.                             (error "No encryption key set for buffer %s"
  1654.                                    (buffer-name)))
  1655.                         (if (not (stringp crypt-buffer-encryption-key))
  1656.                             (error "Encryption key is not a string"))
  1657.                         (message "Encrypting %s..." (buffer-name))
  1658.                         (crypt-encrypt-buffer crypt-buffer-encryption-key)))
  1659.                   
  1660.                   ;; [3] encoding
  1661.                   (if crypt-buffer-save-encoded
  1662.                       (progn
  1663.                         (message "Encoding %s..." (buffer-name))
  1664.                         (crypt-encode-buffer)))
  1665.                   
  1666.                   ;; Now write buffer/region to disk.
  1667.                   (write-region (point-min) (point-max) buffer-file-name nil t)
  1668.                   (delete-region (point-min) (point-max))
  1669.                   (set-buffer-modified-p nil)
  1670.                   
  1671.                   ;; Now that the file is written, set its modes.
  1672.                   (if setmodes
  1673.                       (condition-case ()
  1674.                           (set-file-modes buffer-file-name setmodes)
  1675.                         (error nil)))
  1676.  
  1677.                   ;; Return t so that `basic-save-buffer' will know that the
  1678.                   ;; save has already been done.
  1679.                   
  1680.                   ;; NOTE: this TERMINATES write-file-hooks so any hooks
  1681.                   ;; following this one will not be executed.
  1682.                   
  1683.                   t )
  1684.  
  1685.               ;; UNWINDFORMS
  1686.               ;; unwind...sit back...take a load off...have a beer 
  1687.  
  1688.               ;; If the encoded and encrypted stuff has already been removed
  1689.               ;; then this is a no-op.  This form is executed if BODYFORM
  1690.               ;; completes normally but the value of BODYFORM is returned -
  1691.               ;; i.e., t is returned.
  1692.  
  1693.               (delete-region (point-min) (point-max))))))))
  1694.  
  1695.               
  1696. ;;;; ENCRYPTION
  1697.  
  1698. (defun crypt-encrypt-region (start end key &optional decrypt)
  1699.   "Encrypt region START to END using KEY and `crypt-encryption-type'.  When
  1700. called interactively START and END default to point and mark \(START being the
  1701. lesser of the two\), and KEY is prompted for.  With optional DECRYPT non-nil,
  1702. decryption is done."
  1703.  
  1704.   (interactive
  1705.    (let (decrypt)
  1706.      (barf-if-buffer-read-only)
  1707.      (list (region-beginning)
  1708.            (region-end)
  1709.            (crypt-read-string-no-echo
  1710.             (concat (if (setq decrypt (y-or-n-p "Decrypt region? ")) "De" "En")
  1711.                     "crypt buffer using key: ")
  1712.             ;; Do not confirm on decrypting region.
  1713.             (if (not decrypt) crypt-confirm-password))
  1714.            decrypt)))
  1715.  
  1716.   (crypt-save-point
  1717.  
  1718.    ;; We define the PROGRAM as the encryption program or decryption program
  1719.    ;; listed for `crypt-encryption-type' of `crypt-encryption-alist.'  These
  1720.    ;; should be just the name of the executable and should _not_ contain any
  1721.    ;; arguments.  `(call-process-region)' would be confused if we tried to
  1722.    ;; pass the arguments as part of the PROGRAM.  The arguments are passed
  1723.    ;; through the encryption args or decryption args listed for
  1724.    ;; `crypt-encryption-type' of `crypt-encryption-alist.'
  1725.  
  1726.    ;; Thanks to Joe Ilacqua <spike@world.std.com> and others for pointing out
  1727.    ;; an error that occurs with some encryption programs (e.g., the crypt from
  1728.    ;; Sun Microsystems, HPUX-8, and BSD) if `args' is `"".'  This will allow
  1729.    ;; nil values and lists of strings for argument.
  1730.  
  1731.    (let (prog args)
  1732.  
  1733.      ;; Get the proper program and arguments.
  1734.      (if decrypt
  1735.          (setq prog (crypt-get-decoding-program crypt-encryption-type)
  1736.                args (crypt-get-decoding-args crypt-encryption-type))
  1737.        (setq prog (crypt-get-encoding-program crypt-encryption-type)
  1738.              args (crypt-get-encoding-args crypt-encryption-type)))
  1739.      
  1740.      ;; Check arguments.
  1741.      (cond
  1742.  
  1743.       ;; nil or "" args - don't pass.
  1744.       ((or (not args) (equal "" args))
  1745.        (call-process-region start end prog t t nil key))
  1746.        
  1747.       ;; Check if the args are in the form of a list - must use apply.
  1748.       ((listp args)
  1749.        (apply 'call-process-region
  1750.               (append (list start end prog t t nil) args (list key))))
  1751.        
  1752.       ;; Default - just a non-null string.
  1753.       (t
  1754.        (call-process-region start end prog t t nil args key))))))
  1755.    
  1756.      
  1757. (defun crypt-encrypt-buffer (key &optional decrypt buffer)
  1758.  
  1759.   ;; Use KEY to encrypt current buffer and with optional DECRYPT decrypt.
  1760.   ;; With optional BUFFER, encrypt or decrypt that buffer.  Not meant to be
  1761.   ;; called interactively, toggle `crypt-encrypted-mode' to encrypt an entire
  1762.   ;; buffer.
  1763.  
  1764.   (or buffer (setq buffer (current-buffer)))
  1765.   (save-excursion (set-buffer buffer)
  1766.                   (crypt-encrypt-region (point-min) (point-max) key decrypt)))
  1767.  
  1768.  
  1769. ;;;; ENCODING
  1770.  
  1771. (defun crypt-encode-region (start end &optional decode)
  1772.  
  1773.   "Encode region START to END.  When called interactively START and END
  1774. default to point and mark \(START being the lesser of the two\).  With
  1775. optional DECODE non-nil, decoding is done.
  1776.  
  1777. If encoding is attempted, then checks for correct magic number at start of
  1778. newly-encoded region.  If not found, then searches and deletes a user-defined
  1779. regexp, or executes a user-defined lisp expression, as defined in
  1780. `crypt-encoding-alist,' and checks again for magic number."
  1781.  
  1782.   (interactive "*r\nP")
  1783.  
  1784.   ;; If called interactively then we may need to determine the encoding type.
  1785.   (if (and (interactive-p) (not crypt-buffer-encoding-type))
  1786.       (crypt-read-encoding-type))
  1787.  
  1788.   (crypt-save-point
  1789.  
  1790.    ;; We define the PROGRAM as `shell-file-name' and have it call the encoding
  1791.    ;; or decoding program with the arguments.
  1792.  
  1793.    (let (prog args)
  1794.  
  1795.      ;; Get the proper program and arguments.
  1796.      (if decode
  1797.          (setq prog (crypt-get-decoding-program crypt-buffer-encoding-type)
  1798.                args (crypt-get-decoding-args crypt-buffer-encoding-type))
  1799.        (setq prog (crypt-get-encoding-program crypt-buffer-encoding-type)
  1800.              args (crypt-get-encoding-args crypt-buffer-encoding-type)))
  1801.  
  1802.      (cond 
  1803.  
  1804.       ;; prog is a string?
  1805.       ((stringp prog)
  1806.  
  1807.        ;; Check arguments.
  1808.        (cond
  1809.         
  1810.         ;; Check if the args are in the form of a list, will catch 'nil.
  1811.         ((listp args)
  1812.          
  1813.          ;; Cat all the strings together.
  1814.          (while args
  1815.            (setq prog (concat prog " " (car args))
  1816.                  args (cdr args))))
  1817.         
  1818.         ;; Check if a non-null string.
  1819.         ((and (not (string= "" args))
  1820.               (not (eq args t))) ; just in case...
  1821.          (setq prog (concat prog " " args))))
  1822.        
  1823.        (call-process-region start end shell-file-name t t nil "-c" prog))
  1824.       
  1825.       ;; Otherwise try and eval it.
  1826.       (t
  1827.        (eval (if args
  1828.                  (list prog start end args)
  1829.                (list prog start end))))))
  1830.    
  1831.    ;; Encoding or decoding region?
  1832.    (if (not decode)
  1833.  
  1834.        ;; Check if encoded region starts with magic number.
  1835.        (let ((magic (crypt-get-magic-regexp crypt-buffer-encoding-type))
  1836.              (clean (crypt-get-cleanup-regexp crypt-buffer-encoding-type))
  1837.              (case-fold-search nil))
  1838.          
  1839.          ;; Top of region.
  1840.          (goto-char start)
  1841.          
  1842.          ;; Check for magic number.
  1843.          (if (not (looking-at magic))
  1844.              
  1845.              ;; Magic number not there. 
  1846.  
  1847.              ;; Some compression programs produce an (inane) standard error
  1848.              ;; message that gets piped into the buffer.  For example, some
  1849.              ;; versions of compact output "Compression : 35.50%."  There may
  1850.              ;; be some way to clean up buffer and check again.
  1851.  
  1852.              (cond
  1853.  
  1854.               ;; No mechanism to clean up - failed.
  1855.               ((eq clean nil)
  1856.                (error "Encoding failed!"))
  1857.  
  1858.               ;; Cleanup a regexp string?
  1859.               ((stringp clean)
  1860.  
  1861.                ;; Is regexp there?
  1862.                (if (looking-at clean)
  1863.  
  1864.                    (progn
  1865.                      ;; Delete the match.
  1866.                      (delete-region (match-beginning 0) (match-end 0))
  1867.  
  1868.                      ;; Check for magic again.
  1869.                      (if (not (looking-at magic))
  1870.                          (error "Encoding failed!")))))
  1871.                
  1872.               ;; Default: evaluate a lisp expression and check again.
  1873.               (t (eval clean)
  1874.                  (if (not (looking-at magic))
  1875.                      (error "Encoding failed!")))))))))
  1876.  
  1877. (defun crypt-encode-buffer (&optional decode buffer)
  1878.  
  1879.   ;; Encode current buffer.  With optional DECODE non-nil decode and optional
  1880.   ;; BUFFER, encode or decode that buffer.  Not meant to be called
  1881.   ;; interactively, toggle `crypt-encoded-mode' to encode an entire buffer.
  1882.  
  1883.   (or buffer (setq buffer (current-buffer)))
  1884.   (save-excursion (set-buffer buffer)
  1885.                   (crypt-encode-region (point-min) (point-max) decode)))
  1886.  
  1887.  
  1888. ;;;; DOS <--> UNIX
  1889. (defun crypt-dos-to-unix-region (start end)
  1890.   "Converts region from START to END, from dos to unix format.
  1891. Replaces \"\\r\\n\" with \"\\n\" and, if exists, removes ^Z at end of file.
  1892. Sets `crypt-dos-has-ctrl-z'."
  1893.   (save-excursion
  1894.     (save-restriction
  1895.       (let ((remove-ctrl-z (equal end (point-max))))
  1896.         (narrow-to-region start end)
  1897.         (goto-char (point-min))
  1898.         (while (search-forward "\r\n" nil t)
  1899.           (replace-match "\n" nil t))
  1900.         (if remove-ctrl-z
  1901.             (progn
  1902.               (goto-char (1- (point-max)))
  1903.               (setq crypt-dos-has-ctrl-z (looking-at "\C-z"))
  1904.               (if crypt-dos-has-ctrl-z (replace-match ""))))))))
  1905.  
  1906. (defun crypt-unix-to-dos-region (start end)
  1907.   "Converts region from START to END, from dos to unix format.
  1908. Replaces \"\\n\" with \"\\r\\n\" and adds a ^Z at end of file if
  1909. `crypt-dos-has-ctrl-z' is non-nil."
  1910.   (save-excursion
  1911.     (save-restriction
  1912.       (let ((add-ctrl-z (and crypt-dos-has-ctrl-z
  1913.                             (equal end (point-max)))))
  1914.         (narrow-to-region start end)
  1915.         (goto-char (point-min))
  1916.         (while (search-forward "\n" nil t)
  1917.           (replace-match "\r\n" nil t))
  1918.         (if add-ctrl-z
  1919.             (progn
  1920.               (goto-char (point-max))
  1921.               (insert "\C-z")))))))
  1922.  
  1923.  
  1924. ;;;; MODES
  1925.  
  1926. (defun crypt-encrypted-mode (&optional arg)
  1927.  
  1928.   "Toggle encrypted mode.  With ARG, turn on iff positive, otherwise turn off.
  1929. minor mode in which buffers are automatically encrypted before being written.
  1930. if toggled and a key has been set for the current buffer, then the current
  1931. buffer is marked modified, since it needs to be rewritten with or without
  1932. encryption.
  1933.  
  1934. Entering encrypted mode causes auto-saving to be turned off in the current
  1935. buffer, as there is no way in Emacs Lisp to force auto save files to be
  1936. encrypted."
  1937.  
  1938.   (interactive "P")
  1939.   (let ((oldval crypt-buffer-save-encrypted))
  1940.     (setq crypt-buffer-save-encrypted
  1941.           (if arg (> arg 0) (not crypt-buffer-save-encrypted)))
  1942.  
  1943.     (if crypt-buffer-save-encrypted
  1944.         ;; We are going to save as encrypted, we will turn off auto-saving.
  1945.         (progn
  1946. ;; NEVER do this.  Turning off auto-saving is one thing.  But if there's
  1947. ;; already an autosave for some other reason, what business does this
  1948. ;; package have tampering with it?
  1949. ;          ;; If an auto-save file already exists, then delete it.
  1950. ;          (if (and (stringp buffer-auto-save-file-name)
  1951. ;                   (file-exists-p buffer-auto-save-file-name))
  1952. ;              (delete-file buffer-auto-save-file-name))
  1953.           ;; If the key is not set then ask for it.
  1954.           (if (not crypt-buffer-encryption-key)
  1955.               (call-interactively 'crypt-set-encryption-key))
  1956.           ;; Turn-off auto-saving if crypt-encrypted-disable-auto-save non-nil.
  1957.           (and crypt-encrypted-disable-auto-save
  1958.                auto-save-default
  1959.                (progn
  1960.                  (auto-save-mode 0)
  1961.                  (if (eq crypt-encrypted-disable-auto-save t)
  1962.                      (message "Auto-save off (in this buffer)")))))
  1963.  
  1964.       ;; We are not going to save as encrypted, we will turn on auto-saving
  1965.       ;; but only if we are editing a file and the default says we should.
  1966.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  1967.  
  1968.     (if crypt-buffer-encryption-key
  1969.         ;; Set buffer-modified flag to t only if the mode has been changed, 
  1970.         ;; old code set unconditionally to nil if mode was not changed .
  1971.         ;; Modification suggested by: Gerd Hillebrand <ggh@cs.brown.edu>
  1972.         (if (not (eq oldval crypt-buffer-save-encrypted))
  1973.             (set-buffer-modified-p t)))))
  1974.  
  1975.  
  1976. ;;; Forgetting encryption keys (by jwz)
  1977. ;;; This is really kind of bogus.  Good behavior would be:
  1978. ;;; - If a crypted buffer has not been "accessed" (edited? selected?
  1979. ;;;   viewed?) in N minutes, kill the buffer (since the plaintext is valuable.)
  1980. ;;; - If a crypted buffer is modified, but "idle", just forget the password
  1981. ;;;   instead of killing the buffer (though the plaintext is valuable, it's
  1982. ;;;   also unsaved...)
  1983. ;;; - The "idleness" of a modified buffer should be reset with every mod, so
  1984. ;;;   that an unsaved buffer that you have been constantly typing at for an
  1985. ;;;   hour doesn't lose its password.
  1986. ;;; - But, if a password for a buffer has been discarded, and then an attempt
  1987. ;;;   is made to save that buffer, then we should confirm that the newly-
  1988. ;;;   typed password is the same as the password used in the file on disk. 
  1989. ;;;   with PGP, we could check that by attempting to decrypt the file on
  1990. ;;;   disk into a scratch buffer and seeing if it contains the PGP error
  1991. ;;;   message.
  1992. ;;; - BUG: if a password has been forgotten, and you save, and are prompted,
  1993. ;;;   the old file has already been renamed to a backup!!  so if you ^G, the
  1994. ;;;   real file name no longer exists on disk - only as a ~ file.
  1995.  
  1996. (defun crypt-forget-encryption-key ()
  1997.   (cond (crypt-buffer-encryption-key
  1998.      (let ((inhibit-quit t))
  1999.        (fillarray crypt-buffer-encryption-key 0)
  2000.        (setq crypt-buffer-encryption-key nil))
  2001.      t)
  2002.     (t nil)))
  2003.  
  2004. (add-hook 'kill-buffer-hook 'crypt-forget-encryption-key)
  2005.  
  2006. (defvar crypt-forget-passwd-timeout (* 60 60)
  2007.   "*Do not retain passwords for encrypted buffers more than this many seconds.
  2008. If nil, keep them indefinitely.")
  2009.  
  2010. (defun crypt-reset-passwd-timer ()
  2011.   (if (fboundp 'get-itimer)    ; XEmacs, or anything with itimer.el loaded.
  2012.       (let ((name "crypt-forget-passwds"))
  2013.     (if (get-itimer name)
  2014.         (delete-itimer name))
  2015.     (if crypt-forget-passwd-timeout
  2016.         (start-itimer name
  2017.               'crypt-reset-passwds-timeout
  2018.               crypt-forget-passwd-timeout)))))
  2019.  
  2020. (defun crypt-reset-passwds-timeout ()
  2021.   ;; run by the timer code to forget all passwords
  2022.   (let ((buffers (buffer-list))
  2023.     (inhibit-quit t)
  2024.     (keep-going nil))
  2025.     (while buffers
  2026.       (save-excursion
  2027.     (set-buffer (car buffers))
  2028.     (cond ((and crypt-buffer-encryption-key
  2029.             (buffer-modified-p))
  2030.            ;; don't forget the password in modified buffers, but
  2031.            ;; do check again later (maybe it will be unmodified.)
  2032.            (setq keep-going t))
  2033.           (crypt-buffer-encryption-key
  2034.            ;; forget the password in unmodified buffers.
  2035.            (crypt-forget-encryption-key)
  2036.            (message "Password discarded in buffer %s"
  2037.             (buffer-name (car buffers))))
  2038.           ))
  2039.       (setq buffers (cdr buffers)))
  2040.     (if keep-going
  2041.     (crypt-reset-passwd-timer))
  2042.     nil))
  2043.  
  2044.  
  2045. ;;; Originally `tek-symbol-alist-to-table' from tek-highlight.el.
  2046. (defun crypt-symbol-alist-to-table (list)
  2047.   ;; Converts an alist of symbols to a table suitable for `completing-read.'
  2048.   ;; Called by `crypt-read-encoding-type'
  2049.   (mapcar (function (lambda (x) (list (symbol-name (car x)))))
  2050.           list))
  2051.  
  2052. (defun crypt-read-encoding-type ()
  2053.  
  2054.   ;; Function called to query user for `crypt-buffer-encoding-type' uses
  2055.   ;; contents of `crypt-encoding-alist' and `crypt-default-encoding.'
  2056.  
  2057.   ;; Use poor man's gmhist (i.e., we could have used gmhist's
  2058.   ;; `completing-read-with-history-in' instead).
  2059.   (let (
  2060.         ;; Find the encoding type desired by user.
  2061.         (type
  2062.          (completing-read
  2063.           (concat "encoding type (? for list): [" crypt-default-encoding "] ")
  2064.           (crypt-symbol-alist-to-table crypt-encoding-alist))))
  2065.     
  2066.     ;; Test length of object returned by `completing-read'.
  2067.     (if (zerop (length type))
  2068.         
  2069.         ;; Nothing there, i.e., user hit return -- use default.
  2070.         (setq crypt-buffer-encoding-type (intern crypt-default-encoding))
  2071.       
  2072.       ;; Use the value from mini-buffer and update the default value.
  2073.       (setq crypt-buffer-encoding-type (intern type)
  2074.             crypt-default-encoding type))))
  2075.  
  2076. (defun crypt-encoded-mode (&optional arg)
  2077.  
  2078.   "Toggle encoded mode.  With ARG, turn on iff positive, otherwise turn off.
  2079. minor mode in which buffers are automatically encoded before being written.  if
  2080. toggled then current buffer is marked modified, since it needs to be written
  2081. with or without encoding.
  2082.  
  2083. Entering encoded mode causes auto-saving to be turned off in the current
  2084. buffer, as there is no way in Emacs Lisp to force auto save files to be
  2085. encoded."
  2086.  
  2087.   (interactive "P")
  2088.  
  2089.   ;; Set flag indicating whether or not `(crypt-encoded-mode)' was called 
  2090.   ;; interactively.
  2091.   (setq crypt-buffer-interactive-encoded-mode (interactive-p))
  2092.  
  2093.   ;; If called interactively then need to determine encoding type.
  2094.   (if (and crypt-buffer-interactive-encoded-mode
  2095.            (not crypt-buffer-encoding-type))
  2096.       (crypt-read-encoding-type))
  2097.  
  2098.   ;; Save old value of `crypt-buffer-save-encoded'.
  2099.   (let ((oldval crypt-buffer-save-encoded))
  2100.  
  2101.     ;; Set the variable `crypt-buffer-save-encoded' to t if the argument is 
  2102.     ;; positive, otherwise toggle its current value.
  2103.     (setq crypt-buffer-save-encoded
  2104.           (if arg (> arg 0) (not crypt-buffer-save-encoded)))
  2105.  
  2106.     ;; Set the variable generated by `(crypt-buffer-save-name)' to the value
  2107.     ;; stored in `crypt-buffer-save-encoded.'
  2108.     (set-variable (crypt-buffer-save-name crypt-buffer-encoding-type)
  2109.                   crypt-buffer-save-encoded)
  2110.  
  2111.     (if crypt-buffer-save-encoded
  2112.         ;; We are going to save as encoded, we might turn off auto-saving.
  2113.         (progn
  2114. ;; NEVER do this.  Turning off auto-saving is one thing.  But if there's
  2115. ;; already an autosave for some other reason, what business does this
  2116. ;; package have tampering with it?
  2117. ;          ;; If an auto-save file already exists, then delete it.
  2118. ;          (if (and (stringp buffer-auto-save-file-name)
  2119. ;                   (file-exists-p buffer-auto-save-file-name))
  2120. ;              (delete-file buffer-auto-save-file-name))
  2121.           ;; Turn-off auto-saving if crypt-encoded-disable-auto-save non-nil.
  2122.           (and crypt-encoded-disable-auto-save
  2123.                auto-save-default
  2124.                (progn
  2125.                  (auto-save-mode 0)
  2126.                  (if (eq crypt-encoded-disable-auto-save t)
  2127.                      (message "Auto-save off (in this buffer)")))))
  2128.  
  2129.       ;; We are not going to save as encoded, we will turn on auto-saving but
  2130.       ;; only if we are editing a file and the default says we should.
  2131.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  2132.  
  2133.     ;; Have we toggled the mode? 
  2134.  
  2135.     ;; If yes, then mark buffer as modified.  If not, then leave
  2136.     ;; buffer-modified flag alone.
  2137.  
  2138.     ;; The old code previously set the variable `set-buffer-modified-p' to a
  2139.     ;; value of t if there was a mode change and (unconditionally) to nil
  2140.     ;; if there was not a mode change.
  2141.  
  2142.     ;; Modification suggested by: Gerd Hillebrand <ggh@cs.brown.edu>.
  2143.  
  2144.     (if (not (eq oldval crypt-buffer-save-encoded))
  2145.         (set-buffer-modified-p t))))
  2146.  
  2147.  
  2148. ;;;; Additional encryption functions
  2149.  
  2150. ;; For Emacs V18 compatibility
  2151. (and (not (fboundp 'buffer-disable-undo))
  2152.      (fboundp 'buffer-flush-undo)
  2153.      (fset 'buffer-disable-undo 'buffer-flush-undo))
  2154.  
  2155. (fset 'crypt-read-string-no-echo 'read-passwd)
  2156.  
  2157. ;(defun crypt-read-string-no-echo (prompt &optional confirm)
  2158. ;
  2159. ;  ;; Read a string from minibuffer, prompting with PROMPT, echoing periods.
  2160. ;  ;; Optional second argument CONFIRM non-nil means that the user will be
  2161. ;  ;; asked to type the string a second time for confirmation and if there is a
  2162. ;  ;; mismatch, the whole process is repeated.
  2163. ;  ;;
  2164. ;  ;;         Line editing keys are --
  2165. ;  ;;           C-h, DEL      rubout
  2166. ;  ;;           C-u, C-x      line kill
  2167. ;  ;;           C-q, C-v      literal next
  2168. ;  
  2169. ;  (catch 'return-value
  2170. ;    (save-excursion
  2171. ;
  2172. ;      (let ((input-buffer (get-buffer-create (make-temp-name " *password*")))
  2173. ;            char hold-password help-form kill-ring)
  2174. ;
  2175. ;        (set-buffer input-buffer)
  2176. ;        ;; Don't add to undo ring.
  2177. ;        (buffer-disable-undo input-buffer)
  2178. ;
  2179. ;        (let ((cursor-in-echo-area t)
  2180. ;              (echo-keystrokes 0))
  2181. ;
  2182. ;          (unwind-protect
  2183. ;
  2184. ;              ;; BODYFORM 
  2185. ;              ;; Repeat until we get a `throw'.
  2186. ;              (while t
  2187. ;                (erase-buffer)
  2188. ;                (message prompt)
  2189. ;
  2190. ;                ;; Read string.
  2191. ;                (while (not (memq (setq char (read-char)) '(?\C-m ?\C-j)))
  2192. ;                  (if (setq help-form
  2193. ;                            (cdr
  2194. ;                             (assq char
  2195. ;                                   '((?\C-h . (delete-char -1))
  2196. ;                                     (?\C-? . (delete-char -1))
  2197. ;                                     (?\C-u . (delete-region 1 (point)))
  2198. ;                                     (?\C-x . (delete-region 1 (point)))
  2199. ;                                     (?\C-q . (quoted-insert 1))
  2200. ;                                     (?\C-v . (quoted-insert 1))))))
  2201. ;                      (condition-case error-data
  2202. ;                          (eval help-form)
  2203. ;                        (error t))
  2204. ;                    ;; Just a plain character - insert into password buffer.
  2205. ;                    (insert char))
  2206. ;
  2207. ;                  ;; I think crypt-read-string-no-echo should echo asterisks.
  2208. ;                  ;; -- Jamie. How about periods like in ange-ftp? -- lrd
  2209. ;                  ;;
  2210. ;                  (message "%s%s" prompt (make-string (buffer-size) ?.)))
  2211. ;                
  2212. ;                ;; Do we have to confirm password?
  2213. ;                (cond
  2214. ;
  2215. ;                 ;; No confirmation requested - terminate.
  2216. ;                 ((not confirm)
  2217. ;                  (throw 'return-value (buffer-string)))
  2218. ;                 
  2219. ;                 ;; Can we compare (confirm) password values yet?
  2220. ;                 (hold-password
  2221. ;                  (if (string= hold-password (buffer-string))
  2222. ;                      ;; The two passwords match - terminate.
  2223. ;                      (throw 'return-value hold-password)
  2224. ;
  2225. ;                    ;; Mismatch - start over.
  2226. ;                    (progn
  2227. ;                      (message (concat prompt "[Mismatch. Start over]"))
  2228. ;                      (beep)
  2229. ;                      (sit-for 2)
  2230. ;                      (fillarray hold-password 0) ; destroy extra copy now
  2231. ;                      (setq hold-password nil))))
  2232. ;                 
  2233. ;                 ;; Store password and read again.
  2234. ;                 (t
  2235. ;                  (setq hold-password (buffer-string))
  2236. ;                  (message (concat prompt "[Retype to confirm]"))
  2237. ;                  (sit-for 2))))
  2238. ;            
  2239. ;            ;; UNWINDFORMS
  2240. ;            ;; Clean up.
  2241. ;            (set-buffer input-buffer)
  2242. ;            (set-buffer-modified-p nil)
  2243. ;            (buffer-disable-undo input-buffer) ; redundant, but why not be safe.
  2244. ;            (widen)
  2245. ;            (goto-char (point-min))
  2246. ;            (while (not (eobp)) (delete-char 1) (insert "*")) ; destroy now
  2247. ;            (kill-buffer input-buffer)))))))
  2248.  
  2249. (defun crypt-set-encryption-key (key &optional buffer)
  2250.  
  2251.   "Set the encryption KEY, a string, for current buffer or optionally BUFFER.
  2252. If buffer is in encrypted mode, then it is also marked as modified, since it
  2253. needs to be saved with the new key."
  2254.  
  2255.   (interactive
  2256.    (progn
  2257.      (barf-if-buffer-read-only)
  2258.      (list (crypt-read-string-no-echo
  2259.             (format "Encryption key for %s? [RET to ignore]: " (buffer-name))
  2260.             crypt-confirm-password))))
  2261.  
  2262.   ;; For security reasons we remove `(crypt-set-encryption-key "password")' 
  2263.   ;; from the `command-history' list if called interactively.
  2264.   (if (interactive-p)
  2265.       (setq command-history (cdr command-history)))
  2266.  
  2267.   (or buffer (setq buffer (current-buffer)))
  2268.  
  2269.   (save-excursion
  2270.     (set-buffer buffer)
  2271.     (if (equal key crypt-buffer-encryption-key)
  2272.         (message "Key is identical to original, no change.")
  2273.  
  2274.       (progn
  2275.     ;; jwz: destroy old string
  2276.     (if (and crypt-buffer-encryption-key
  2277.          (not (eq crypt-buffer-encryption-key key)))
  2278.         (fillarray crypt-buffer-encryption-key 0))
  2279.         (setq crypt-buffer-encryption-key key)
  2280.  
  2281.         ;; Don't touch the modify flag unless we're in `(crypt-encrypted-mode)'.
  2282.         (if crypt-buffer-save-encrypted
  2283.             (set-buffer-modified-p t))
  2284.  
  2285.     (crypt-reset-passwd-timer)
  2286.     ))))
  2287.  
  2288.  
  2289. ;;;; Install hooks and mode indicators.
  2290.  
  2291. ;;; Check if mode indicators are not already installed and then prepend them.
  2292. (and (not (assq 'crypt-buffer-save-encrypted minor-mode-alist))
  2293.      (setq minor-mode-alist (append crypt-minor-mode-alist minor-mode-alist)))
  2294.  
  2295. ;;; Install the hooks. 
  2296.  
  2297. ;;; If add-hook isn't already defined overwrite it with our own.
  2298. ;;; Note the `add-hook' function must take the optional APPEND argument.
  2299. (if (not (fboundp 'add-hook))
  2300.     ;; No add-hook found. 
  2301.     ;; Use `add-hook' from GNU Emacs v19.
  2302.     (defun add-hook (hook function &optional append)
  2303.       "Add to the value of HOOK the function FUNCTION.
  2304. FUNCTION is not added if already present.
  2305. FUNCTION is added (if necessary) at the beginning of the hook list
  2306. unless the optional argument APPEND is non-nil, in which case
  2307. FUNCTION is added at the end.
  2308.  
  2309. HOOK should be a symbol, and FUNCTION may be any valid function.  If
  2310. HOOK is void, it is first set to nil.  If HOOK's value is a single
  2311. function, it is changed to a list of functions."
  2312.       (or (boundp hook) (set hook nil))
  2313.       ;; If the hook value is a single function, turn it into a list.
  2314.       (let ((old (symbol-value hook)))
  2315.         (if (or (not (listp old)) (eq (car old) 'lambda))
  2316.             (set hook (list old))))
  2317.       (or (if (consp function)
  2318.               ;; Clever way to tell whether a given lambda-expression
  2319.               ;; is equal to anything in the hook.
  2320.               (let ((tail (assoc (cdr function) (symbol-value hook))))
  2321.                 (equal function tail))
  2322.             (memq function (symbol-value hook)))
  2323.           (set hook 
  2324.                (if append
  2325.                    (nconc (symbol-value hook) (list function))
  2326.                  (cons function (symbol-value hook)))))))
  2327.  
  2328. ;;; Attach ourselves to the find-file-hooks and find-file-not-found-hooks. 
  2329. (add-hook 'find-file-hooks 'crypt-find-file-hook)
  2330. (add-hook 'find-file-not-found-hooks 'crypt-find-file-hook)
  2331.  
  2332. ;; Take care when appending to write-file-hook.  User's version of add-hook
  2333. ;; may not have APPEND option.  If it fails then do it by hand.  I wish
  2334. ;; everyone would upgrade - lrd 8/31/93.
  2335. (condition-case err
  2336.     (add-hook 'write-file-hooks 'crypt-write-file-hook t) ; *must* append this
  2337.   (error
  2338.    ;; Do it by hand.  Not as robust as `add-hook'.
  2339.  
  2340.    ;; Contributed by Ken Laprade <laprade@trantor.harris-atd.com>
  2341.    ;; Really should use some sort of add-hook - 16 Feb 93 - KCL
  2342.    (or (and (listp write-file-hooks) (not (eq (car write-file-hooks) 'lambda)))
  2343.        (setq write-file-hooks (list write-file-hooks)))
  2344.  
  2345.    (cond
  2346.     ((not (memq 'crypt-write-file-hook write-file-hooks))
  2347.      ;; make this hook last on purpose
  2348.      (setq write-file-hooks (append write-file-hooks
  2349.                                     (list 'crypt-write-file-hook)))))))
  2350.  
  2351. ;; In order that the tables and key-binding correctly reflect user's
  2352. ;; preferences we add ourselves to the `after-init-hook' GNU Emacs v19 and
  2353. ;; Lucid Emacs v 19.8 (or later) or `term-setup-hook' in Lucid Emacs v 19.7
  2354. ;; (or earlier).  These are run *after* ~/.emacs and ../lisp/default.el are
  2355. ;; loaded.  Unfortunately, v18 does not have `after-init-hook' and
  2356. ;; `term-setup-hook' is just a single function.  It is a bit of a pain trying
  2357. ;; to work our functions in properly without overwriting the user's value.
  2358. ;; Therefore, we do nothing and hope they upgrade to v19 soon.
  2359.  
  2360. (cond ((boundp 'after-init-hook)
  2361.        ;; Must be running GNU Emacs v19 :->
  2362.        (add-hook 'after-init-hook 'crypt-rebuild-tables)
  2363.        (add-hook 'after-init-hook 'crypt-rebuild-minor-modes-alist)
  2364.        (add-hook 'after-init-hook 'crypt-bind-insert-file))
  2365.  
  2366.       ((and (string-match "^19" emacs-version) t)
  2367.        ;; Probably running Lucid Emacs v19.7 (or earlier) since it,
  2368.        ;; unfortunately, does not have `after-init-hook'.  Use
  2369.        ;; `term-setup-hook' instead and hope they upgrade to Lucid 19.8 or GNU
  2370.        ;; Emacs 19.
  2371.        (add-hook 'term-setup-hook 'crypt-rebuild-tables)
  2372.        (add-hook 'term-setup-hook 'crypt-rebuild-minor-modes-alist)
  2373.        (add-hook 'term-setup-hook 'crypt-bind-insert-file)))
  2374.  
  2375.  
  2376. ;;; Code for conditionally decoding/decrypting an inserted file
  2377.  
  2378. (defvar crypt-bind-insert-file t
  2379.   "*t value means bind `crypt-insert-file' over `insert-file'.
  2380. If you wish to change this variable after crypt++ has been loaded then do
  2381. \\[crypt-bind-insert-file].")
  2382.  
  2383. (defvar crypt-auto-decode-insert nil
  2384.   "*t says decode/decrypt files that are inserted with `crypt-insert-file'.
  2385. nil says to ask before doing this.")
  2386.  
  2387. ;;; Bind `crypt-insert-file' over wherever `insert-file' is bound?
  2388. (defun crypt-bind-insert-file ()
  2389.  
  2390.   "Bind `crypt-insert-file' in place of `insert-file' or reverse based on
  2391. `crypt-bind-insert-file'.  Part of `after-init-hook'."
  2392.  
  2393.   (interactive)
  2394.  
  2395.   (if (interactive-p)
  2396.       (setq crypt-bind-insert-file
  2397.             (y-or-n-p "Bind crypt-insert-file over insert-file? ")))
  2398.  
  2399.   (if crypt-bind-insert-file
  2400.       (substitute-key-definition
  2401.        'insert-file 'crypt-insert-file (current-global-map))
  2402.     (substitute-key-definition
  2403.      'crypt-insert-file 'insert-file (current-global-map))))
  2404.  
  2405. ;;; Now call it.
  2406. (crypt-bind-insert-file)
  2407.  
  2408. ;;; crypt++ replacement for `insert-file'
  2409. (defun crypt-insert-file (filename)
  2410.   "Insert decoded/decrypted contents of file FILENAME into buffer after point.
  2411. Set mark after the inserted text.
  2412.  
  2413. This function is meant for the user to run interactively.
  2414. Don't call it from programs!  Use `insert-file-contents' instead.
  2415. \(Its calling sequence is different; see its documentation\).
  2416.  
  2417. This version will attempt to decrypt and/or decode file before inserting.
  2418. see variable `crypt-auto-decode-insert'."
  2419.   (interactive "fInsert file: ")
  2420.   (if (file-directory-p filename)
  2421.       (signal 'file-error (list "Opening input file" "file is a directory"
  2422.                                 filename)))
  2423.   (let ((tem (crypt-insert-file-contents filename))) ; use crypt++ to insert
  2424.     (push-mark (+ (point) (car (cdr tem))))))
  2425.  
  2426. (defun crypt-insert-file-contents (file)
  2427.  
  2428.   ;; Similar to `insert-file-contents' except decoding/decrypting of FILE
  2429.   ;; attempted.  See `crypt-insert-file' and `crypt-auto-decode-insert'
  2430.  
  2431.   (let (temp-buffer
  2432.         temp-list
  2433.         (crypt-auto-decode-buffer crypt-auto-decode-insert)
  2434.         (orig-buffer (current-buffer)))
  2435.     
  2436.     ;; Create a temporary buffer and decode and decrypt it.
  2437.     (save-excursion
  2438.       
  2439.       ;; Temporary buffer, use the same name as the file to be inserted.
  2440.       (setq temp-buffer (generate-new-buffer (file-name-nondirectory file)))
  2441.       (set-buffer temp-buffer)
  2442.       
  2443.       ;; Original insert-file-contents - save list.
  2444.       (setq temp-list (insert-file-contents file nil))
  2445.  
  2446.       ;; Make temp-buffer unmodified.
  2447.       (set-buffer-modified-p nil)
  2448.       
  2449.       ;; Need to set buffer name to file name for crypt++.
  2450.       (setq buffer-file-name file)
  2451.       
  2452.       ;; Decode and decrypt, if necessary.
  2453.       (crypt-find-file-hook)
  2454.       
  2455.       ;; Find the length of the file to be inserted. `insert-file-contents' 
  2456.       ;; returns it for the original encoded/encrypted file.
  2457.       (setcdr temp-list (cons (buffer-size) ()))
  2458.       
  2459.       ;; Now insert temp-buffer into original buffer.
  2460.       (set-buffer orig-buffer)
  2461.       (insert-buffer temp-buffer)
  2462.       
  2463.       ;; Kill the temporary buffer.
  2464.       (kill-buffer temp-buffer))
  2465.     
  2466.     ;; Return modified list from `insert-file-contents'.
  2467.     temp-list))
  2468.  
  2469.  
  2470. ;;;; BUG REPORTS
  2471.  
  2472. ;;; This section is provided for reports.
  2473. ;;; Using Barry A. Warsaw's reporter.el
  2474.  
  2475. (defconst crypt-version "2.82"
  2476.   "Revision number of crypt++.el -- handles compressed and encrypted files.
  2477. Type \\[crypt-submit-report] to send a bug report.  Available via anonymous
  2478. ftp in
  2479.  
  2480.    /roebling.poly.edu:/pub/lisp/crypt++.el.gz
  2481.    /archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/misc/crypt++.el.Z")
  2482.  
  2483. (defconst crypt-help-address
  2484.   "dodd@roebling.poly.edu"
  2485.   "Address(es) accepting submission of reports on crypt++.el.")
  2486.  
  2487. (defconst crypt-maintainer "Larry"
  2488.   "First name(s) of people accepting submission of reports on crypt++.el.")
  2489.  
  2490. (defconst crypt-file "crypt++.el"
  2491.   "Name of file containing emacs lisp code.")
  2492.  
  2493. (defconst crypt-variable-list
  2494.   (list 'shell-file-name ; These
  2495.         'load-path       ; are
  2496.         'exec-path       ; useful.
  2497.         'crypt-encryption-type 
  2498.         'crypt-encryption-file-extension
  2499.         'crypt-never-ever-decrypt
  2500.         'crypt-auto-write-buffer-encrypted
  2501.         'crypt-confirm-password
  2502.         'crypt-encrypted-disable-auto-save
  2503.         'crypt-auto-decode-buffer
  2504.         'crypt-auto-write-buffer
  2505.         'crypt-query-if-interactive
  2506.         'crypt-no-extension-implies-plain
  2507.         'crypt-freeze-vs-fortran
  2508.         'crypt-compact-vs-C++
  2509.         'crypt-ignored-filenames
  2510.         'crypt-default-encoding
  2511.         'crypt-encoded-disable-auto-save
  2512.         'crypt-bind-insert-file
  2513.         'crypt-auto-decode-insert
  2514.         'crypt-encoding-alist
  2515.         'crypt-encryption-alist
  2516.         )
  2517.   "List of variables to be appended to reports sent by `crypt-submit-report.'")
  2518.  
  2519. (defun crypt-submit-report ()
  2520.   "Submit via reporter.el a bug report on program.  Send report on `crypt-file'
  2521. version `crypt-version,' to `crypt-maintainer' at address `crypt-help-address'
  2522. listing variables `crypt-variable-list' in the message."
  2523.   (interactive)
  2524.  
  2525.   ;; In case we can't find reporter...
  2526.   (condition-case err
  2527.       (progn
  2528.         ;; Get it if we can.
  2529.         (require 'reporter)
  2530.  
  2531.         (reporter-submit-bug-report
  2532.          crypt-help-address                     ; address
  2533.          (concat crypt-file " " crypt-version)  ; pkgname
  2534.          crypt-variable-list                    ; varlist
  2535.          nil nil                                ; pre-hooks and post-hooks
  2536.          (concat "Yo! " crypt-maintainer ","))) ; salutation
  2537.  
  2538.     ;; ...fail gracefully.
  2539.     (error 
  2540.      (beep)
  2541.  
  2542.      ;; Do they have ange-ftp?
  2543.      (if (and (featurep 'ange-ftp)
  2544.               (y-or-n-p (concat "Sorry, reporter.el not found.  "
  2545.                                 "Can I ange-ftp it for you? ")))
  2546.  
  2547.          ;; Yes.  Then Ange-ftp a copy from roebling.
  2548.          (let ((ange-ftp-generate-anonymous-password t))
  2549.            ;; Might want to use the elisp archive official site?  But
  2550.            ;; then it would have to be uncompressed, etc. Ick!
  2551.            (find-file-other-window
  2552.             "/anonymous@roebling.poly.edu:/pub/reporter.el")
  2553.            (eval-current-buffer)
  2554.            (message (concat "Save reporter.el somewhere in `load-path' "
  2555.                             "and try again.")))
  2556.        
  2557.        ;; No ange-ftp.
  2558.        (message "Sorry, reporter.el not found.")
  2559.        (sit-for 3)
  2560.        (message (concat "Get it from archive.cis.ohio-state.edu "
  2561.                         "or roebling.poly.edu"))))))
  2562.  
  2563. ;;; Provide this package as crypt++ as well as crypt.
  2564. (provide 'crypt++)
  2565. (provide 'crypt)
  2566.  
  2567. ;;; crypt++.el ends here.
  2568.