home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / c / cryptpp.zip / CRYPTPP.EL next >
Text File  |  1993-03-25  |  58KB  |  1,414 lines

  1. ; From: dodd@roebling.poly.edu (Lawrence R. Dodd)
  2. ; Subject: Re: Your E-lisp code (crypt++) has been added to the archive.
  3. ; Date: Thu, 18 Mar 93 11:23:03 -0500
  4. ; Dave,
  5. ;   Here is an update of crypt++.el (version 2.32).
  6. ; Larry
  7. ; dodd@roebling.poly.edu
  8. ; <file: ~/lisp/crypt++.el>
  9. ; ........................... cut along dotted line ...........................
  10. ;;; crypt++.el -- code for handling all sorts of compressed and encrypted files
  11.  
  12. (defconst crypt-version (substring "$Revision: 2.32 $" 11 -2)
  13.   "The revision number of crypt++.el -- code for handling all sorts of
  14. compression and encryption files. To send a bug report type
  15. M-x crypt-submit-report. Complete RCS identity is 
  16.  
  17.    $Id: crypt++.el,v 2.32 1993/03/18 15:55:58 dodd Exp $
  18.  
  19. This file is available via anonymous ftp in:
  20.  
  21.    /roebling.poly.edu:/pub/crypt++.el
  22.  
  23. and
  24.  
  25.    /archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/misc/crypt++.el.Z
  26. ")
  27.  
  28. ;;; Copyright (C) 1993 Rod Whitby and Lawrence R. Dodd
  29. ;;; Copyright (C) 1988, 1989, 1990 Kyle E. Jones
  30. ;;;
  31. ;;; This program is free software; you can redistribute it and/or modify
  32. ;;; it under the terms of the GNU General Public License as published by
  33. ;;; the Free Software Foundation; either version 2 of the License, or
  34. ;;; (at your option) any later version.
  35. ;;;
  36. ;;; This program is distributed in the hope that it will be useful,
  37. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39. ;;; GNU General Public License for more details.
  40. ;;;
  41. ;;; You should have received a copy of the GNU General Public License
  42. ;;; along with this program; if not, write to the Free Software
  43. ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  44.  
  45. ;; LCD Archive Entry:
  46. ;; crypt++|Rod Whitby and Lawrence R. Dodd|dodd@roebling.poly.edu|
  47. ;; Code for handling all sorts of compressed and encrypted files.|
  48. ;; 18-Mar-1993|2.32|~/misc/crypt++.el.Z|
  49.  
  50. ;;; AVAILABLE: 
  51. ;;; 
  52. ;;; via anonymous ftp to roebling.poly.edu [128.238.5.31] in /pub/crypt++.el
  53. ;;; (ange-ftp TAG: /roebling.poly.edu:/pub/crypt++.el)
  54. ;;; 
  55. ;;; via anonymous ftp to archive.cis.ohio-state.edu [128.146.8.52] in 
  56. ;;; /pub/gnu/emacs/elisp-archive/misc/crypt++.el.Z
  57.  
  58. ;;; BUG REPORTS: 
  59. ;;; 
  60. ;;; just type M-x crypt-submit-report to generate a bug report template
  61.  
  62. ;;; please see notes on INSTALLATION below
  63.  
  64. ;;; RESPONSIBLE PARTIES:
  65. ;;;
  66. ;;;   /Northern Hemisphere/
  67. ;;;  
  68. ;;;     Lawrence R. Dodd <dodd@roebling.poly.edu>   -  _    ,__o
  69. ;;;     Department of Chemical Engineering         -  _   , \_<,
  70. ;;;     Polymer Research Institute                  -    (*)/'(*)
  71. ;;;     Polytechnic University                     ~~~~~~~~~~~~~~~~~~ 
  72. ;;;     Six Metrotech
  73. ;;;     Brooklyn, New York, 11201 USA                        
  74. ;;;
  75. ;;;   /Southern Hemisphere/ 
  76. ;;;                                                   _--_|\  
  77. ;;;     Rod Whitby <rwhitby@research.canon.oz.au>    /      \ 
  78. ;;;     Canon Information Systems Research Australia \_.--._/ 
  79. ;;;     1 Thomas Holt Drive                                v 
  80. ;;;     North Ryde, N.S.W., 2113 Australia
  81. ;;; 
  82. ;;;   World-wide coverage!!  Bugs fixed while you sleep!!
  83.  
  84. ;;; VERSION:
  85. ;;;  
  86. ;;; $Id: crypt++.el,v 2.32 1993/03/18 15:55:58 dodd Exp $
  87. ;;; $Date: 1993/03/18 15:55:58 $
  88. ;;; $Revision: 2.32 $
  89. ;;;
  90. ;;; version log
  91. ;;; 1.1 - original version of crypt.el
  92. ;;; 1.2 -
  93. ;;;   jwz: works with tar-mode.el
  94. ;;;   jwz: applied patch from piet, merged with Lawrence Dodd's gzip version
  95. ;;; 1.3 -
  96. ;;;   lrd: fixed compress-magic-regexp 
  97. ;;; 1.4, 1.5, 1.6 -
  98. ;;;   lrd: write-file compresses or gzips based on file extension
  99. ;;; 2.1 -
  100. ;;;   lrd: merged with Rod Whitby's table-driven version (major upgrade)
  101. ;;; 2.2 -
  102. ;;;   rjw: Changed file name to crypt++.el, so archie and lispdir can find it.
  103. ;;; 2.3 -
  104. ;;;   rjw: Separated the hook additions and minor mode alist additions.
  105. ;;; 2.4 -
  106. ;;;   rjw: Fixed the interactive form for crypt-buffer.
  107. ;;; 2.5 - 
  108. ;;;   lrd: doc mods, changed GNU free software notice (was out of date), added 
  109. ;;;   anonymous ftp information
  110. ;;; 2.6 - 
  111. ;;;   lrd: added back in definition of `buffer' in defun crypt-buffer caused 
  112. ;;;   an error when trying to read encrypted file; modified check for minor 
  113. ;;;   mode alist addition; added gzip magic number warning
  114. ;;; 2.7 - [posted to gnu.emacs.sources]
  115. ;;;   lrd: added `TO DO' and `KNOW BUGS' section to header 
  116. ;;; 2.8 - 
  117. ;;;   lrd: added note about updating to v 1.24 of tar-mode.el
  118. ;;;   Thanks to Mark Borges <mdb@noaacrd.Colorado.EDU>
  119. ;;; 2.9 -
  120. ;;;   lrd: moved query about `crypt-freeze-vs-fortran' out of defvar for
  121. ;;;   `crypt-encoding-alist,' an erroneous value of `nil' was being stuck into
  122. ;;;   alist when user set `crypt-freeze-vs-fortran' was nil, doc mod.
  123. ;;;   Thanks to Mark Borges <mdb@noaacrd.Colorado.EDU>
  124. ;;; 2.10 -
  125. ;;;   rjw: moved query about `crypt-freeze-vs-fortran' back into defvar for
  126. ;;;   `crypt-encoding-alist,' - used append to ignore the erroneous `nil'.
  127. ;;; 2.11 -
  128. ;;;   rjw: fixed a bug in my fix :-(
  129. ;;; 2.12 -
  130. ;;;   rjw: Defvar crypt-magic-regexp and crypt-magic-regexp-inverse and
  131. ;;;   allow either a regexp or an elisp expression.
  132. ;;;   Suggested by Franc,ois Pinard <pinard@iro.umontreal.ca>.
  133. ;;; 2.13 - 
  134. ;;;   lrd: added in info on lispdir.el, doc mods and some puttering while 
  135. ;;;   looking over rjw's v 2.12 mods.
  136. ;;; 2.14 - 
  137. ;;;   lrd: doc mod - trivial huh? switched `compact' and  `gzip' in 
  138. ;;;   `crypt-encoding-alist' - want gzip near top
  139. ;;; 2.15 - 
  140. ;;;   lrd: added in LCD Archive Entry and modified comments on tar-mode.el 
  141. ;;;   since the version at the elisp-archive now works with crypt++.el
  142. ;;; 2.16 - 
  143. ;;;   lrd: provide `crypt' as well as `crypt++' allowing something like `ln -s 
  144. ;;;   crypt++.el crypt.el' to be meaningful 
  145. ;;;   Suggested (by|as) Per Abrahamsen <amanda@iesd.auc.dk>
  146. ;;; 2.17 -
  147. ;;;   lrd: clarified bug report procedure, added fancy pseudo-graphics, added 
  148. ;;;   to the `TO DO' list, put RCS tags in LCD Archive entry
  149. ;;; 2.18 - [posted to gnu.emacs.sources]
  150. ;;;   lrd: included pointer to elisp archive in crypt-version description,
  151. ;;;   changed "Decode buffer %s? " to "Decode %s? " in crypt-find-file-hook 
  152. ;;;   to be more general (mainly for crypt-insert-file)
  153. ;;; 2.19 -
  154. ;;;   rjw: Added the crypt-compact-vs-C++ switch to distinguish compacted and
  155. ;;;   C++ files.
  156. ;;; 2.20 -
  157. ;;;   lrd: (1) modified interactive form of crypt-buffer. (2) made search 
  158. ;;;   case-insensitive in crypt-submit-report. (3) modified encoded-mode and 
  159. ;;;   crypt-mode so that buffer-modified is not unconditionally set to `nil' 
  160. ;;;   when the mode is not changed. Thanks to Gerd Hillebrand 
  161. ;;;   <ggh@cs.brown.edu> for suggesting (2) and (3).
  162. ;;; 2.21 -
  163. ;;;   rjw: Added an entry to the TODO list about the hazards of using
  164. ;;;   call-process-region on a large region and not much room in /tmp
  165. ;;;   (David Carlisle <carlisle@computer-science.manchester.ac.uk>).
  166. ;;; 2.22 - 
  167. ;;;   lrd: allow write-file-hooks to contain functions as well as lists. 
  168. ;;;   Contributed by Ken Laprade <laprade@trantor.harris-atd.com>.
  169. ;;; 2.23 - 
  170. ;;;   lrd: made crypt-submit-report list values of more user-defined variables
  171. ;;; 2.24 - 
  172. ;;;   lrd: pass the -q switch to gzip to thwart the possibility of a --verbose
  173. ;;;   in the GZIP environment variable
  174. ;;; 2.25 -
  175. ;;;   lrd: added some more to the TO DO list, clarified some things, also 
  176. ;;;   untabified the entire file (I got tired of the control I's) 
  177. ;;; 2.26 - 
  178. ;;;   lrd: use the long-named options for GNU zip (self-documenting)
  179. ;;; 2.27 - 
  180. ;;;   lrd: included observation by Francois Pinard <pinard@iro.umontreal.ca> 
  181. ;;;   and worked on text in TO DO/KNOWN BUGS list
  182. ;;; 2.28 - 
  183. ;;;   lrd: added two new variables in (crypt-submit-report) to the list stuck
  184. ;;;   at the bottom of the mail message; changed the comments regarding the 
  185. ;;;   user-defined variables.  added in default values in user defined 
  186. ;;;   variables.  added to and removed stuff to the `TO DO' list.
  187. ;;;
  188. ;;;   (encoded-mode): 
  189. ;;;   added in code to remove any auto-save-files that may have been formed
  190. ;;;   before becoming an encoded buffer (for example a plain file saved to
  191. ;;;   disk encoded had orphan auto-save-files left behind).  turning off
  192. ;;;   auto-save-mode disables the creation of auto-save-files, but it also 
  193. ;;;   disables the possibility of these being removed when the buffer is 
  194. ;;;   saved.
  195. ;;; 
  196. ;;;   (crypt-region): 
  197. ;;;   now call the encrytion and decryption program directly instead of
  198. ;;;   through the shell.  this is more secure since the shell will expose the
  199. ;;;   password (key).  thanks to Jon Cargille <jcargill@cs.wisc.edu>.  defined
  200. ;;;   two new variables `crypt-decryption-args' and `crypt-encryption-args' to
  201. ;;;   take the arguments separately.  removed (let ((opoint)...)) construct 
  202. ;;;   this was a throw back to some old dead code and was not being used.
  203. ;;; 2.29 - 
  204. ;;;   lrd: added three new variables in (crypt-submit-report); added to the 
  205. ;;;   `TO DO' list.
  206. ;;;  
  207. ;;;   (encode-region,encode-buffer,encoded-mode): fixed interactive forms -
  208. ;;;   the conversion to table version had eliminated some of the interactive
  209. ;;;   features of these.  thanks to Kimball Collins <kpc@ptolemy.arc.nasa.gov>
  210. ;;;   for point this out.  new interactive form uses functions
  211. ;;;   `crypt-get-encoding-type' and `crypt-symbol-alist-to-table' and variable
  212. ;;;   `crypt-default-encoding' to generate completion list of encoding types.
  213. ;;; 
  214. ;;;   (crypt-write-file-hook): two new user-defined variables
  215. ;;;   `crypt-query-if-interactive' and `crypt-no-extension-implies-plain' and
  216. ;;;   the buffer-local variable `buffer-interactive-mode' are used to help
  217. ;;;   determined whether or not plain output is really desired for files
  218. ;;;   without a compression file-name extension.  the default behavior is the
  219. ;;;   same as before.
  220. ;;; 2.30 - 
  221. ;;;   lrd: added test for user-defined variable `crypt-never-ever-decrypt' 
  222. ;;;   when finding a file.  some users may never wish to decrypt files 
  223. ;;;   and like to edit binary files.  thanks to Nelson Minar 
  224. ;;;   <nelson@reed.edu>.  added to doc-strings of 
  225. ;;;   `crypt-magic-regexp[-inverse]' -- these can be set to `nil[t]' and 
  226. ;;;   accomplish the same thing as setting `crypt-never-ever-decrypt' to `t'
  227. ;;; 2.31 - 
  228. ;;;   rjw: Updated the comments in the encryption check section.
  229. ;;; 2.32 - [posted to gnu.emacs.sources]
  230. ;;;   lrd: added warning about `crypt-(de|en)cryption-program'; doc mod.
  231.  
  232.  
  233. ;; INSTALLATION:
  234. ;;
  235. ;; To use this package, simply put it in a file called "crypt++.el" in a Lisp
  236. ;; directory known to Emacs, byte-compile it, and put the line:
  237. ;;
  238. ;;                      (require 'crypt++)
  239. ;;
  240. ;; in your ~/.emacs file or in the file default.el in the ../lisp directory of
  241. ;; the Emacs distribution.  Do not bother trying to autoload this file; this
  242. ;; package uses find-file and write-file hooks and thus should be loaded the
  243. ;; first time you visit any sort of file.
  244. ;;
  245. ;; An alternative is to stick 
  246. ;; 
  247. ;;                      (require 'crypt) 
  248. ;; 
  249. ;; in your ~/.emacs, if it is not already there, and then make a (symbolic) 
  250. ;; link from crypt++.el to crypt.el
  251. ;; 
  252. ;;                      ln -s crypt++.el crypt.el
  253. ;; 
  254. ;; this will make crypt++ act like a drop-in replacement for the original
  255. ;; crypt since any package requiring crypt will find crypt++ instead.  Thanks
  256. ;; to Per Abrahamsen <amanda@iesd.auc.dk> for this suggestion.
  257. ;;
  258. ;; User-defined variables are:
  259. ;; 
  260. ;;        crypt-encoding-alist
  261. ;;        crypt-default-encoding
  262. ;;        crypt-encryption-program
  263. ;;        crypt-decryption-program
  264. ;;        crypt-encryption-args
  265. ;;        crypt-decryption-args
  266. ;;        crypt-auto-decode-buffer
  267. ;;        crypt-auto-write-buffer
  268. ;;        crypt-query-if-interactive
  269. ;;        crypt-no-extension-implies-plain
  270. ;;        crypt-never-ever-decrypt
  271. ;;        crypt-freeze-vs-fortran
  272. ;;        crypt-compact-vs-C++
  273. ;; 
  274. ;; to find out more about these variables, load this file, put your cursor at 
  275. ;; the end of any of the above lines, and hit C-h v [RET].
  276. ;;  
  277. ;; Users should be aware that `crypt-(de|en)cryption-program' can no longer
  278. ;; contain arguments (switches) since the encryption program is now executed
  279. ;; directly instead of via `shell-file-name.'  Arguments must be defined in
  280. ;; `crypt-(de|en)cryption-args.'
  281.  
  282.  
  283. ;; NOTES ON INTERFACES WITH OTHER PROGRAMS AND PACKAGES:
  284. ;;
  285. ;; GZIP NOTE: the magic number used by gzip (GNU zip) was changed by Jean-loup
  286. ;; Gailly in his Beta version 0.6. The magic regular expression used below in
  287. ;; `crypt-encoding-alist' reflects this change. If you are using a version of
  288. ;; gzip earlier than 0.6, then please upgrade.
  289. ;; 
  290. ;; The addition of the environment variable GZIP in version 1.0.2 of gzip
  291. ;; means that an error is possible with crypt++.  If the user uses GZIP to
  292. ;; define `--verbose' as one of the default options for gzip, then the
  293. ;; standard output messages will be appended to gzip'ed files by crypt++.
  294. ;; This corrupts the files.  The cleanest solution is for crypt++ always to
  295. ;; use the `-q' or `--quiet' switch, of gzip version 1.0.3 or higher, to
  296. ;; cancel the `--verbose' in the GZIP environment variable.  Bottom line: if
  297. ;; you are using a version of gzip earlier than 1.0.3, then please upgrade.
  298. ;; 
  299. ;; TAR-MODE NOTE: crypt++.el does not work properly with version 1.12 of 
  300. ;; tar-mode.el. Please obtain an updated version of tar-mode.el from 
  301. ;; roebling.poly.edu or archive.cis.ohio-state.edu.
  302. ;; 
  303. ;; LISPDIR NOTE: replace the "(require 'crypt)" that appear in lispdir.el (the
  304. ;; Lisp Code Directory formatter and apropos that uses ange-ftp and crypt for
  305. ;; transparent retrieval of LCD entries) with "(require 'crypt++)".  If the
  306. ;; symbolic link suggested above is used, then this is not needed.
  307.  
  308.  
  309. ;; DESCRIPTION:
  310. ;;
  311. ;; The basic purpose of this package of Lisp functions is to recognize
  312. ;; automatically encrypted and encoded (i.e., compressed) files when they are
  313. ;; first visited or written.  The BUFFER corresponding to the file is decoded
  314. ;; and/or decrypted before it is presented to the user.  The file itself is
  315. ;; unchanged on the disk.  When the buffer is subsequently saved to disk, a
  316. ;; hook function re-encodes the buffer before the actual disk write takes
  317. ;; place.
  318. ;;
  319. ;; This package recognizes all sorts of compressed files by a magic number at
  320. ;; the beginning of these files but uses a heuristic to detect encrypted
  321. ;; files.  If you are asked for an encryption key for a file that is in fact
  322. ;; not encrypted, just hit RET and the file will be accepted as is, and the
  323. ;; crypt minor mode will not be entered.
  324. ;;
  325. ;; Other types of encoding programs may be added to crypt++ using the variable
  326. ;; `crypt-encoding-alist' which contains a table of encoding programs such as
  327. ;; compress, gzip (GNU zip), freeze, and compact.
  328. ;;
  329. ;; This new extended version of crypt now monitors the filename extensions of
  330. ;; buffers that are written out using write-file (C-x C-w).  If the filename
  331. ;; extension matches one of the extensions listed in `crypt-encoding-alist,'
  332. ;; then crypt++ will write the file out using the corresponding encoding
  333. ;; (compression) method. This is done whether or not the buffer originated
  334. ;; from a previously encoded (compressed) file.
  335. ;;
  336. ;; Thus, if the user is editing a file that may or may not have been encoded
  337. ;; originally (e.g., foobar.Z or foobar) and decides to write it to a
  338. ;; different file (e.g., barfoo or barfoo.z or barfoo.C).  Crypt++ will examine
  339. ;; the filename extension and write the buffer in plain format or an alternate
  340. ;; encoding (compression) format by searching through the entries in the table
  341. ;; of encoding methods `crypt-encoding-alist.'  This change in encoding state
  342. ;; is done automatically if the variable `crypt-auto-write-buffer' is t
  343. ;; otherwise the user is asked.
  344.  
  345.  
  346. ;; TO DO/KNOWN BUGS/HELP WANTED/APPLY WITHIN: 
  347. ;; 
  348. ;; All Users/hackers out there are strongly encouraged to pursue any of these
  349. ;; matters further (especially those that concern encryption and decryption!).
  350. ;; It is important to future programmers and modifiers of crypt++.el to know
  351. ;; about its perceived limitations.  Since necessity drives invention, users
  352. ;; who find any of the following features of crypt++.el annoying are asked to
  353. ;; make suggestions and send patches (again, especially those that concern
  354. ;; encryption and decryption!).
  355. ;; 
  356. ;; * currently crypt++ assumes that if a file is both encrypted and encoded
  357. ;;   (i.e., compressed) that the order in which it was done was encryption
  358. ;;   first _then_ compression.  As has been pointed by many people compression
  359. ;;   following encryption is useless since the encrypted file is basically
  360. ;;   random.  On the other hand, many agree that doing encryption _following_
  361. ;;   compression is better since it makes it harder to crack the encryption.
  362. ;;   We would like to make the ordering of these two user-configurable or if
  363. ;;   nothing else change the order.
  364. ;; 
  365. ;;   Having read the above however, Francois Pinard <pinard@iro.umontreal.ca> 
  366. ;;   writes that encryption following compression may not be harder to crack 
  367. ;;   since "the fact that the first few uncrypted bytes are expected (the 
  368. ;;   compress signature) facilitates a serious attempt at uncrypting." 
  369. ;; 
  370. ;; * get insert-file, write-region, and append-to-file to handle encoded and 
  371. ;;   encrypted files.  There is a test version of crypt++-insert.el available
  372. ;;   at roebling.poly.edu as well as an interesting low-level encoding package
  373. ;;   by Jay Adams <jka@ece.cmu.edu> called jka-compr.el which might address
  374. ;;   some of these issues.  crypt++-insert will ultimately be incorporated
  375. ;;   into crypt++.  We encourage hackers out there to come up with crypt++
  376. ;;   versions of write-region and append-to-file.  The difficulty is creating
  377. ;;   versions that mimic the originals as closely as possible.
  378. ;;
  379. ;; * instead of using call-process-region (which can fail badly if the region 
  380. ;;   is large and there's not much room in /tmp), write the region to a temp 
  381. ;;   file (with a customisable location) and use call-process directly.
  382. ;;
  383. ;; * users have mentioned trouble using crypt++ and hilit simultaneously since 
  384. ;;   the functions in write-file-hook for both write the file to disk and
  385. ;;   return `t'.  A possible solution is to have one of them write to a
  386. ;;   scratch buffer instead of to disk and return `nil' and then allow the
  387. ;;   other to do its work on the scratch buffer and write it to disk.  Thanks
  388. ;;   to Wayne Folta <folta@cs.UMD.EDU> and Amir J Katz <amir@matis.ingr.com>.
  389. ;;   It would be nice to have another way in emacs to have an
  390. ;;   after-write-file-hook and a before-write-file-hook of some sort.
  391. ;;  
  392. ;; * another possible source of trouble is with encryption (and encoding) 
  393. ;;   programs sticking verbose output into buffers prior to being written to
  394. ;;   disk.  This was definitely occurring with gzip because of --verbose in
  395. ;;   the GZIP environment variable and is solved/hidden with the --quiet
  396. ;;   switch.  However, I suspect that some encryption problems out there are
  397. ;;   capable of similar things so the user should be careful.
  398. ;; 
  399. ;; * integrating crypt++ with a backgrounding package such as Olin Shivers' 
  400. ;;   `background.el' might be useful too.  thanks to Mark Borges 
  401. ;;   <mdb@noaacrd.Colorado.EDU> for suggesting this.
  402. ;; 
  403. ;; * performing encode-buffer or encrypt-buffer and then saving the file may 
  404. ;;   cause errors.  users should be aware that if the value of
  405. ;;   `require-final-newline' is `t' then a newline will be inserted 
  406. ;;   automatically by emacs at the end of the file.  this will confuse the 
  407. ;;   compression programs when decompressing the file later.  it is better to 
  408. ;;   toggle encoded-mode and save instead of using encode-buffer.
  409.  
  410.  
  411. ;; user definable variables
  412.  
  413. (defvar crypt-encryption-program "crypt"
  414.   "*Name of executable file to be used for encryption (see also the variable
  415. `crypt-decryption-program').  DES users should set this to \"des\" and set the
  416. variable `crypt-encryption-args' to \"-ek\".
  417. Default: \"crypt\"")
  418.  
  419. (defvar crypt-decryption-program "crypt"
  420.   "*Name of executable file to be used for decryption (see also the variable
  421. `crypt-encryption-program').  DES users should set this to \"des\" and set the
  422. variable `crypt-decryption-args' to \"-dk\".
  423. Default: \"crypt\"")
  424.  
  425. (defvar crypt-encryption-args ""
  426.   "*Arguments to be passed to the encryption command.  DES users should set
  427. this to \"-ek\" and set the variable `crypt-encryption-program' to \"des\".
  428. Default: \"\"")
  429.  
  430. (defvar crypt-decryption-args ""
  431.   "*Arguments to be passed to the decryption command.  DES users should set
  432. this to \"-dk\" and set the variable `crypt-decryption-program' to \"des\".
  433. Default: \"\"") 
  434.  
  435. (defvar crypt-auto-decode-buffer t
  436.   "*t value means that the buffers associated with encoded files will
  437. be decoded automatically, without requesting confirmation from the user.
  438. `nil' means to ask before doing the decoding.
  439. Default: t")
  440.  
  441. (defvar crypt-auto-write-buffer nil
  442.   "*t value means buffers to be written to files ending in extensions
  443. matching those in `crypt-encoding-alist' will be encoded automatically,
  444. without requesting confirmation from the user. `nil' means to ask before doing
  445. this encoding. Likewise, buffers originating from encoded files to be written
  446. to different files ending in extensions that do not match any of those in
  447. `crypt-encoding-alist' will be written in plain format automatically, without
  448. requesting confirmation from the user. `nil' means to ask before doing this
  449. decoding.
  450. Default: nil")
  451.  
  452. (defvar crypt-query-if-interactive t
  453.   "*t value means that (if needed) the user will be queried when saving a
  454. buffer in which `encoded-mode' was called interactively .  A value of `nil'
  455. means that even if the filename extension is plain (i.e., is not one of the
  456. file-extensions listed in `crypt-encoding-alist') the file will be written in
  457. an encoded format without asking.
  458.  
  459. This variable is designed for users that edit a plain file (with plain
  460. extension) and then toggle `encoded-mode' and do not wish to be queried every
  461. time that they save the buffer.
  462.  
  463. NOTE: if encoded-mode was not called interactively (the usual scenario) then
  464. the value of this variable has no effect on how the buffer is written to disk.
  465. In such a case `crypt-no-extension-implies-plain' is then the relevant
  466. variable.
  467.  
  468. Default: t")
  469.  
  470. (defvar crypt-no-extension-implies-plain t
  471.   "*t value means that if file ends in an extension that does not match one of the
  472. file-extensions listed in `crypt-encoding-alist' then crypt++ will assume that
  473. writing of the file out in plain format _may_ be desired.  If in addition
  474. `crypt-auto-write-buffer' is `t' then any file ending in a plain extension
  475. will be automatically written in plain format, otherwise the user will be
  476. queried.
  477.  
  478. A value of `nil' for this variable means that users who like to work with
  479. encoded (compressed) files without file extensions may do so without being
  480. queried each time they save the file.
  481.  
  482. NOTE: (1) this does not effect find-file (C-x C-f) since that works with a
  483. magic regexp.  (2) there is no way for crypt++ to distinguish between
  484. write-file and save-buffer so setting this to `nil' will mean that neither 
  485. C-x C-w nor C-x C-s will query.
  486.  
  487. Default: t")
  488.  
  489. (defvar crypt-freeze-vs-fortran t
  490.   "*t values means that the .F file extension denotes a frozen file
  491. rather than a Fortran file.
  492. Default: t")
  493.  
  494. (defvar crypt-compact-vs-C++ nil
  495.   "*t values means that the .C file extension denotes a compacted file
  496. rather than a C++ file.
  497. Default: nil")
  498.  
  499. (defvar crypt-encoding-alist
  500.   (append
  501.    (list '(compress "\037\235" "\\(\\.Z\\)$"
  502.                     "compress" "uncompress"
  503.                     "Compress"))
  504.    (list '(gzip "\037\213" "\\(\\.z\\)$"
  505.                 "gzip --quiet" "gzip --decompress --quiet"
  506.                 "Zip"))
  507.    (and crypt-freeze-vs-fortran
  508.         (list '(freeze "\037\236\\|\037\237" "\\(\\.F\\)$"
  509.                        "freeze" "unfreeze"
  510.                        "Freeze")))
  511.    (and crypt-compact-vs-C++
  512.         (list '(compact "\377\037" "\\(\\.C\\)$"
  513.                         "compact" "uncompact"
  514.                         "Compact")))
  515.    ;; Add new elements here ...
  516.    )
  517.   "*A list of elements describing the encoding methods available, each of
  518. which looks like
  519.  
  520.         \(ENCODING-TYPE MAGIC-REGEXP FILE-EXTENSION
  521.                         ENCODE-PROGRAM DECODE-PROGRAM
  522.                         MINOR-MODE
  523.                         \)
  524.  
  525. ENCODING-TYPE is a symbol denoting the encoding type.  Currently known
  526. encodings are (compress compact freeze gzip).
  527.  
  528. MAGIC-REGEXP is a regexp that matches the magic number at the
  529. beginning of files encoded with ENCODING-TYPE.
  530.  
  531. FILE-EXTENSION is a string denoting the file extension usually
  532. appended the filename of files encoded with ENCODING-TYPE.
  533.  
  534. ENCODE-PROGRAM is a string denoting the name of the program used to
  535. encode files plus any arguments.
  536.  
  537. DECODE-PROGRAM is a string denoting the name of the program used to
  538. decode files plus any arguments.
  539.  
  540. MINOR-MODE is a string denoting the name for the encoded minor mode as 
  541. it will appear in the mode line.
  542. ")
  543.  
  544. (defvar crypt-default-encoding "gzip"
  545.   "*string representing the default encoding type for use in an interactive
  546. call of `encoded-buffer.'  This must match one of the elements of the table
  547. `crypt-encoding-alist.'
  548. Default: \"gzip\"")
  549.  
  550. (defvar crypt-never-ever-decrypt nil
  551.   "*t means that crypt++ will never (ever) try to decrypt a buffer.  See also
  552. `crypt-magic-regexp[-inverse].'
  553. Default: nil")
  554.  
  555. ;; Encrypted files have no magic number, so we have to hack a way of
  556. ;; determining which new buffers start in crypt mode.  The current setup is
  557. ;; that we use only buffers that match crypt-magic-regexp very close to
  558. ;; beginning of buffer and that do NOT match crypt-magic-regexp-inverse.
  559. ;; Currently crypt-magic-regexp matches non-ASCII characters and
  560. ;; crypt-magic-regexp-inverse will match Sun OS, 4.x BSD, and Ultrix
  561. ;; executable magic numbers, so binaries can still be edited (heh)
  562. ;; without headaches.
  563.  
  564. (defvar crypt-magic-regexp "[\200-\377]"
  565.   "\
  566. Regexp that must match very close to the beginning of an encrypted
  567. buffer.
  568.  
  569. This may also be some elisp expression to be evaluated at (point-min) that
  570. will return `t' for an encrypted buffer.  If this is set to `nil' then crypt++
  571. will never try to decrypt a buffer.  See also `crypt-never-ever-decrypt.'
  572.  
  573. See also `crypt-magic-regexp-inverse'.
  574. ")
  575.  
  576. (defvar crypt-magic-regexp-inverse
  577.   "^\\(..\\)?\\([\007\010\013]\001\\|\001[\007\010\013]\\)"
  578.   "\
  579. Regexp that must _NOT_ match very close to the beginning of an encrypted
  580. buffer.
  581.  
  582. This may also be some elisp expression to be evaluated at (point-min) that
  583. will return `t' for a NON-encrypted buffer.  If this is set to `t' then
  584. crypt++ will never try to decrypt a buffer. See also
  585. `crypt-never-ever-decrypt.'
  586.  
  587. See also `crypt-magic-regexp'.
  588. ")
  589.  
  590.  
  591. ;; buffer locals
  592.  
  593. (defvar buffer-save-encrypted nil
  594.   "*Non-nil means that when this buffer is saved it will be written out
  595. encrypted, using the commands in variables `crypt-encryption-program' and
  596. `crypt-decryption-program.'  Automatically local to all buffers.")
  597. (make-variable-buffer-local 'buffer-save-encrypted)
  598.  
  599. (defvar buffer-encryption-key nil
  600.   "*Key to use when encrypting the current buffer, prior to saving it.
  601. Automatically local to all buffers.")
  602. (make-variable-buffer-local 'buffer-encryption-key)
  603.  
  604. (defvar buffer-save-encoded nil
  605.   "*Non-nil means that when this buffer is saved it will be written out
  606. encoded with ENCODING-TYPE, as with the ENCODING-PROGRAM command.
  607. Automatically local to all buffers.")
  608. (make-variable-buffer-local 'buffer-save-encoded)
  609.  
  610. (defvar buffer-encoding-type nil
  611.   "*Non-nil means that this buffer is encoded with ENCODING-TYPE.
  612. Automatically local to all buffers.")
  613. (make-variable-buffer-local 'buffer-encoding-type)
  614.  
  615. (defvar buffer-interactive-mode nil
  616.   "t value means that `encoded-mode' was called interactively. otherwise,
  617. `nil'.  Almost always this will be `nil'.  Automatically local to all
  618. buffers.")
  619. (make-variable-buffer-local 'buffer-interactive-mode)
  620.  
  621.  
  622. ;; defuns that work on the encoding-alist
  623.  
  624. (defun encoding-magic-regexp (encoding-type)
  625.   "Returns a regexp that matches the magic number at the beginning of files
  626. encoded with ENCODING-TYPE."
  627.   (let ((elt (assoc encoding-type crypt-encoding-alist)))
  628.     (and elt
  629.          (nth 1 elt))))
  630.  
  631. (defun encoding-file-extension (encoding-type)
  632.   "Returns a regexp that matches the file-extension typically associated with
  633. files encoded with ENCODING-TYPE."
  634.   (let ((elt (assoc encoding-type crypt-encoding-alist)))
  635.     (and elt
  636.          (nth 2 elt))))
  637.  
  638. (defun encoding-encode-program (encoding-type)
  639.   "Returns a string denoting the name of the program used to encode files
  640. encoded with ENCODING-TYPE."
  641.   (let ((elt (assoc encoding-type crypt-encoding-alist)))
  642.     (and elt
  643.          (nth 3 elt))))
  644.  
  645. (defun encoding-decode-program (encoding-type)
  646.   "Returns a string denoting the name of the program used to decode files
  647. encoded with ENCODING-TYPE."
  648.   (let ((elt (assoc encoding-type crypt-encoding-alist)))
  649.     (and elt
  650.          (nth 4 elt))))
  651.  
  652. (defun crypt-buffer-save-name (encoding-type)
  653.   "Returns a variable name. t means that when the buffer is saved it will be
  654. written out using its decoding program.  Automatically local to all buffers."
  655.   (intern (concat "buffer-save-" (symbol-name encoding-type))))
  656.  
  657.  
  658. ;; Create a buffer-local variable for each type of encoding.
  659. ;; These variables are used to trigger the minor mode names.
  660.  
  661. (defvar crypt-minor-mode-encrypted
  662.   '(buffer-save-encrypted " Crypt")
  663.   "Minor mode alist entry for encrypted buffers.")
  664.  
  665. (defvar crypt-minor-mode-alist
  666.   (append
  667.    (list crypt-minor-mode-encrypted)
  668.    (mapcar
  669.     (function
  670.      (lambda (element)
  671.        (let ((variable (crypt-buffer-save-name (car element))))
  672.          (make-variable-buffer-local variable)
  673.          (list variable (concat " " (nth 5 element))))))
  674.     crypt-encoding-alist))
  675. "Alist derived from `crypt-encoding-alist' containing encoded minor modes.")
  676.  
  677.  
  678. (defmacro save-point (&rest body)
  679.   "Save value of point, evaluate FORMS, and restore value of point.
  680. If the saved value of point is no longer valid go to (point-max).
  681. This macro exists because, save-excursion loses track of point during
  682. some types of deletions."
  683.   (let ((var (make-symbol "saved-point")))
  684.     (list 'let (list (list var '(point)))
  685.           (list 'unwind-protect
  686.                 (cons 'progn body)
  687.                 (list 'goto-char var)))))
  688.  
  689.  
  690. (defun crypt-find-file-hook ()
  691.   "Hook run for decoding and/or decrypting the contents of a buffer. Part of
  692. find-file-hooks"
  693.   (let ((buffer-file-name buffer-file-name)
  694.         (old-buffer-file-name buffer-file-name)
  695.         (old-buffer-modified-p (buffer-modified-p))
  696.         found
  697.         elt regexp
  698.         encrypted encoded
  699.         case-fold-search buffer-read-only)
  700.  
  701.     (save-point
  702.      (save-restriction
  703.        (widen)
  704.        (goto-char (point-min))
  705.  
  706.        ;; We can reasonably assume that either compaction or compression will
  707.        ;; be used, or neither, but not both.
  708.  
  709.        ;; find the file type
  710.  
  711.        (let ((alist crypt-encoding-alist))
  712.          (while (and alist (setq elt (car alist)) (not found))
  713.            (if (looking-at (nth 1 elt))
  714.                (progn (setq buffer-encoding-type (nth 0 elt))
  715.                       (setq found t))
  716.              ;; decrement 
  717.              (setq alist (cdr alist)))))
  718.  
  719.        ;; do we have to decode? if not move on
  720.        (if (and found 
  721.                 (or crypt-auto-decode-buffer
  722.                     (y-or-n-p (format "Decode %s? "
  723.                                       (buffer-name)))))
  724.            (progn
  725.              (message "Decoding %s..." (buffer-name))
  726.              (encode-buffer (current-buffer) t)
  727.  
  728.              ;; We can not actually go into encoding mode yet because the
  729.              ;; major mode may change later on and blow away all local
  730.              ;; variables (and thus the minor modes).  So we make a note to go
  731.              ;; into encoding mode later.
  732.  
  733.              (setq encoded buffer-encoding-type)
  734.  
  735.              ;; here we strip the encoded file's extension so that later we
  736.              ;; can set the buffer's major mode based on this modified name
  737.              ;; instead of the name with the extension.
  738.  
  739.              (if (string-match (encoding-file-extension buffer-encoding-type)
  740.                                buffer-file-name)
  741.                  (setq buffer-file-name
  742.                        (substring buffer-file-name 0 (match-beginning 1))))
  743.  
  744.              (if (not (input-pending-p))
  745.                  (message "Decoding %s... done" (buffer-name)))))
  746.  
  747.        ;; Now peek at the file and see if it still looks like a binary file.
  748.        ;; If so, try the crypt-magic-regexp-inverse against it and if it FAILS
  749.        ;; we assume that this is an encrypted buffer.
  750.  
  751.        (cond (
  752.  
  753.               (and (not (eobp))
  754.  
  755.                    ;; Check for existence of crypt-magic-regexp
  756.                    (if (stringp crypt-magic-regexp)
  757.                        (re-search-forward crypt-magic-regexp
  758.                                           (min (point-max) 15) t)
  759.                      (eval crypt-magic-regexp))
  760.  
  761.                    (goto-char (point-min))
  762.  
  763.                    ;; Check for absence of crypt-magic-regexp-inverse
  764.                    (not (if (stringp crypt-magic-regexp-inverse)
  765.                             (re-search-forward crypt-magic-regexp-inverse
  766.                                                (min (point-max) 15) t)
  767.                           (eval crypt-magic-regexp-inverse)))
  768.  
  769.                    ;; shut off crypt mode if `crypt-never-ever-decrypt' is `t'
  770.                    ;; - thanks to Nelson Minar <nelson@reed.edu>. 
  771.                    ;; this is equivalent to user setting `crypt-magic-regexp' 
  772.                    ;; to `nil' and/or `crypt-magic-regexp-inverse' to `t'
  773.                    (not crypt-never-ever-decrypt))
  774.               
  775.               (if (not buffer-encryption-key)
  776.                   (call-interactively 'set-encryption-key))
  777.  
  778.               ;; if user did not enter a key, turn off crypt mode.  good for
  779.               ;; binaries that crypt-magic-regexp-inverse doesn't recognize.
  780.               ;; -- thanx to Paul Dworkin (paul@media-lab.media.mit.edu)
  781.               ;; can now shut off entirely if `crypt-never-ever-decrypt' is 
  782.               ;; `t' see above - lrd.
  783.  
  784.               (if (equal buffer-encryption-key "")
  785.  
  786.                   (message "No key given, buffer %s assumed normal."
  787.                            (buffer-name))
  788.  
  789.                 (message "Decrypting %s..." (buffer-name))
  790.  
  791.                 (crypt-buffer buffer-encryption-key nil)
  792.  
  793.                 ;; Tuck the key away for safe keeping since setting the major
  794.                 ;; mode may well blow it away.
  795.  
  796.                 (setq encrypted buffer-encryption-key)
  797.  
  798.                 (if (not (input-pending-p))
  799.                     (message "Decrypting %s... done" (buffer-name))))))
  800.        ))
  801.  
  802.     ;; OK, if any changes have been made to the buffer we need to rerun the
  803.     ;; code the does automatic selection of major mode.
  804.  
  805.     (cond (
  806.  
  807.            (or encoded encrypted)
  808.            (set-auto-mode)
  809.            (hack-local-variables)
  810.  
  811.            ;; Now set our own minor modes.
  812.            (if encoded
  813.                (progn
  814.                  (setq buffer-encoding-type encoded)
  815.                  (encoded-mode 1)))
  816.  
  817.            (if encrypted
  818.                (progn (crypt-mode 1)
  819.                       (setq buffer-encryption-key encrypted)))
  820.  
  821.            ;; Restore buffer file name now, so that lock file entry is removed
  822.            ;; properly.
  823.  
  824.            (setq buffer-file-name old-buffer-file-name)
  825.  
  826.            ;; Restore buffer modified flag to its previous value.  This will
  827.            ;; also remove the lock file entry for the buffer if the previous
  828.            ;; value was nil; this is why buffer-file-name had to be manually
  829.            ;; restored above.
  830.  
  831.            (set-buffer-modified-p old-buffer-modified-p)))))
  832.  
  833.  
  834. ;; This function should be called ONLY as a write-file hook.
  835. ;; Odd things will happen if it is called elsewhere.
  836.  
  837. (defun crypt-write-file-hook ()
  838.   
  839.   "Writes out file, if need be, in a non-plain format. Note this terminates
  840. the calls in write-file-hooks so should probably be at the end of that list."
  841.   
  842.   ;; We flag a buffer to be written out in encoded form if the file ends in
  843.   ;; one of the file-extensions in crypt-encoding-alist. Conversely, we write
  844.   ;; out a buffer as a plain file if it does _not_ end in one of these
  845.   ;; file-extensions even if buffer-save-encoded is non-`nil'.
  846.   
  847.   (let ((alist crypt-encoding-alist)
  848.         case-fold-search found elt)
  849.     
  850.     ;; search through the file name extensions for a match
  851.     (while (and alist (setq elt (car alist)) (not found))
  852.       (if (string-match (nth 2 elt) buffer-file-name)
  853.           (setq found t)
  854.         ;; decrement
  855.         (setq alist (cdr alist))))
  856.     
  857.     ;; did we find a match? 
  858.     (if found 
  859.         
  860.         ;; file name ends in a very provocative extension
  861.  
  862.         ;; check to see if we should write as an encoded file
  863.         (if buffer-save-encoded
  864.  
  865.             ;; already encoded - do the methods of encoding match? - if not 
  866.             ;; then change the method of encoding
  867.             (if (and 
  868.                  (not (eq (nth 0 elt) buffer-encoding-type))
  869.                  (or crypt-auto-write-buffer
  870.                      (y-or-n-p (concat "write file using " (nth 3 elt) "? "))))
  871.  
  872.                 ;; case one 
  873.                 ;; turn off original encoding and turn on new encoding
  874.                 (progn (encoded-mode -1)
  875.                        (setq buffer-encoding-type (nth 0 elt))
  876.                        (encoded-mode 1)))
  877.           
  878.           ;; was a plain file
  879.           (if (or crypt-auto-write-buffer
  880.                   (y-or-n-p (concat "write file using " (nth 3 elt) "? ")))
  881.  
  882.               ;; case two
  883.               ;; turn on encoding flags and _then_ the minor mode
  884.               (progn (setq buffer-save-encoded t)
  885.                      (setq buffer-encoding-type (nth 0 elt))
  886.                      (encoded-mode 1))))
  887.       
  888.       ;; no match - a plain-jane file extension - but if the encoded flag is
  889.       ;; non-`nil' then the user may really want it written out in plain
  890.       ;; format so we must override this flag
  891.       (if (and buffer-save-encoded
  892.  
  893.                ;; if `encoded-mode' was called interactively, then there is a
  894.                ;; high probability that no matter what the file name extension
  895.                ;; the user wishes to write the file out in some encoded format
  896.                ;; thanks to Kimball Collins <kpc@ptolemy.arc.nasa.gov> for
  897.                ;; pointing out the need for this.  unfortunately, still can 
  898.                ;; not distinguish between write-file and save-buffer.  in the 
  899.                ;; former the user may want to write in plain format (or indeed 
  900.                ;; some other format).
  901.                
  902.                (if buffer-interactive-mode
  903.                    ;; interactive
  904.                    crypt-query-if-interactive 
  905.                  ;; non-interactive but still may want encoded format
  906.                  crypt-no-extension-implies-plain)
  907.  
  908.                (or crypt-auto-write-buffer
  909.                    (y-or-n-p "write as a plain file? ")))
  910.  
  911.           ;; case three
  912.           ;; turn off the minor mode and _then_ the flags
  913.           (progn (encoded-mode -1)
  914.                  (setq buffer-save-encoded nil)
  915.                  (setq buffer-encoding-type nil)))))
  916.  
  917.   ;; Now decide whether or not we need to continue with this defun. Does the
  918.   ;; buffer need to be saved in a non-plain form?  If not then writing is not
  919.   ;; done here but later in the write-file-hooks (probably at the end).
  920.  
  921.   (if (or buffer-save-encoded buffer-save-encrypted)
  922.       
  923.       (save-excursion
  924.         (save-restriction
  925.           (let 
  926.               
  927.               ;; BINDINGS
  928.               ((copy-buffer (get-buffer-create " *crypt copy buffer*"))
  929.                (selective-display selective-display)
  930.                (buffer-read-only))
  931.             
  932.             ;; FORMS
  933.             (copy-to-buffer copy-buffer 1 (1+ (buffer-size)))
  934.             (narrow-to-region (point) (point))
  935.             
  936.             (unwind-protect
  937.                 
  938.                 (progn
  939.                   (insert-buffer-substring copy-buffer)
  940.                   (kill-buffer copy-buffer)
  941.                   
  942.                   ;; selective-display non-`nil' means we must convert
  943.                   ;; carriage returns to newlines now, and set
  944.                   ;; selective-display temporarily to nil.
  945.                   
  946.                   (cond (selective-display
  947.                          (goto-char (point-min))
  948.                          (subst-char-in-region (point-min) (point-max) ?\r ?\n)
  949.                          (setq selective-display nil)))
  950.                   
  951.                   (cond
  952.                    (buffer-save-encrypted
  953.                     (if (null buffer-encryption-key)
  954.                         (error "No encryption key set for buffer %s"
  955.                                (buffer-name)))
  956.                     (if (not (stringp buffer-encryption-key))
  957.                         (error "Encryption key is not a string"))
  958.                     (message "Encrypting %s..." (buffer-name))
  959.                     (crypt-buffer buffer-encryption-key t)))
  960.                   
  961.                   (cond
  962.                    (buffer-save-encoded
  963.                     (message "Encoding %s..." (buffer-name))
  964.                     (encode-buffer)))
  965.                   
  966.                   ;; write buffer/region to disk
  967.                   (write-region (point-min) (point-max) buffer-file-name nil t)
  968.                   (delete-region (point-min) (point-max))
  969.                   (set-buffer-modified-p nil)
  970.                   
  971.                   ;; return t so that basic-save-buffer will
  972.                   ;; know that the save has already been done.
  973.                   
  974.                   ;; NOTE: this TERMINATES write-file-hooks so any hooks
  975.                   ;; following crypt-write-file-hook will not be executed
  976.                   
  977.                   t )
  978.               ;; unwind...sit back...take a load off...have a beer
  979.               ;; If the crypted stuff has already been removed
  980.               ;; then this is a no-op.
  981.               (delete-region (point-min) (point-max))))))))
  982.  
  983.               
  984. ;;;; Defuns that do the actual decoding-encoding and decryption-encryption
  985.  
  986. ;;; ENCRYPTING
  987.  
  988. (defun crypt-region (start end encrypt key)
  989.  
  990.   "Encrypt/decrypt the text in the region. From a program, this function takes
  991. four args: START, END, ENCRYPT and KEY. When called interactively START and
  992. END default to point and mark \(START being the lesser of the two\), KEY is
  993. prompted for. If ENCRYPT is t encryption is done otherwise decrypt is done
  994. using contents of variables `crypt-encryption-program' and
  995. `crypt-decryption-program.'"
  996.  
  997.   (interactive
  998.    (progn
  999.      (barf-if-buffer-read-only)
  1000.      (list (region-beginning) (region-end)
  1001.       (y-or-n-p "Encrypt? ") 
  1002.       (read-string-no-echo "Crypt region using key: "))))
  1003.  
  1004.   (save-point
  1005.  
  1006.    ;; we define the PROGRAM as the variables `crypt-(en|de)cryption-program'
  1007.    ;; these should be just the name of the executable and should _not_ contain
  1008.    ;; any arguments.  `call-process-region' would be confused if we tried to
  1009.    ;; pass the arguments as part of the PROGRAM.  the arguments are passed
  1010.    ;; through `crypt-(en|de)cryption-args'
  1011.    (call-process-region 
  1012.     start end 
  1013.     (if encrypt crypt-encryption-program crypt-decryption-program)
  1014.     t t nil (if encrypt crypt-encryption-args crypt-decryption-args) key)))
  1015.  
  1016. (defun crypt-buffer (key encrypt &optional buffer)
  1017.  
  1018.   "Using KEY, if prefix arg (or ENCRYPT non-nil from a program), then encrypt
  1019. BUFFER \(defaults to the current buffer\), otherwise decrypt."
  1020.  
  1021.   (interactive
  1022.    (progn
  1023.      (barf-if-buffer-read-only)
  1024.      (list (read-string-no-echo
  1025.             (concat (if current-prefix-arg "En" "De")
  1026.                     "crypt buffer using key: "))
  1027.            current-prefix-arg
  1028.            (read-buffer "Crypt buffer: " (current-buffer)))))
  1029.  
  1030.   (or buffer (setq buffer (current-buffer)))
  1031.   (save-excursion (set-buffer buffer)
  1032.                   (crypt-region (point-min) (point-max) encrypt key)))
  1033.  
  1034.  
  1035. ;;; ENCODING
  1036.  
  1037. (defun encode-region (start end &optional undo)
  1038.  
  1039.   "Encode the text in the region. From a program, this function takes three
  1040. args: START, END and UNDO. When called interactively START and END default to
  1041. point and mark \(START being the lesser of the two\).  Prefix arg \(or
  1042. optional second arg non-nil\) UNDO means decode."
  1043.  
  1044.   (interactive "*r\nP")
  1045.  
  1046.   ;; if called interactively then we may need to determine the encoding type
  1047.   (if (and (interactive-p) (not buffer-encoding-type))
  1048.       (crypt-get-encoding-type))
  1049.  
  1050.   (save-point
  1051.  
  1052.    ;; we define the PROGRAM as `shell-file-name' since the variables
  1053.    ;; `encoding-(en|de)code-program' contain arguments in addition to the name
  1054.    ;; of the executable.  call-process-region would be confused if we tried to 
  1055.    ;; define the PROGRAM as `encoding-(en|de)code-program' because of these 
  1056.    ;; arguments.
  1057.    (call-process-region
  1058.     start end shell-file-name t t nil "-c"
  1059.     (if undo (encoding-decode-program buffer-encoding-type)
  1060.       (encoding-encode-program buffer-encoding-type)))
  1061.  
  1062.    (cond ((not undo)
  1063.           (goto-char start)
  1064.           (let (case-fold-search)
  1065.             (if (not (looking-at (encoding-magic-regexp buffer-encoding-type)))
  1066.                 (error "%s failed!" (if undo "Decoding" "Encoding"))))))))
  1067.  
  1068. (defun encode-buffer (&optional buffer undo)
  1069.  
  1070.   "Encode BUFFER \(defaults to the current buffer\). Prefix arg \(or second
  1071. arg non-nil from a program) UNDO means decode." 
  1072.  
  1073.   (interactive (list (current-buffer) current-prefix-arg))
  1074.  
  1075.   ;; if called interactively then we may need to determine the encoding type
  1076.   (if (and (interactive-p) (not buffer-encoding-type))
  1077.       (crypt-get-encoding-type))
  1078.  
  1079.   (or buffer (setq buffer (current-buffer)))
  1080.   (save-excursion (set-buffer buffer)
  1081.                   (encode-region (point-min) (point-max) undo)))
  1082.  
  1083.  
  1084.  
  1085. ;;;; MODES
  1086.  
  1087. (defun crypt-mode (&optional arg)
  1088.  
  1089.   "Toggle crypt mode. With arg, turn crypt mode on iff arg is positive,
  1090. otherwise turn it off. In crypt mode, buffers are automatically encrypted
  1091. before being written.  If crypt mode is toggled and a key has been set for the
  1092. current buffer, then the current buffer is marked modified, since it needs to
  1093. be rewritten with \(or without\) encryption.
  1094.  
  1095. Use \\[set-encryption-key] to set the encryption key for the current buffer.
  1096.  
  1097. Entering crypt mode causes auto-saving to be turned off in the current buffer,
  1098. as there is no way \(in Emacs Lisp\) to force auto save files to be
  1099. encrypted."
  1100.  
  1101.   (interactive "P")
  1102.   (let ((oldval buffer-save-encrypted))
  1103.     (setq buffer-save-encrypted
  1104.           (if arg (> arg 0) (not buffer-save-encrypted)))
  1105.     (if buffer-save-encrypted
  1106.         (auto-save-mode 0)
  1107.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  1108.     (if buffer-encryption-key
  1109.         ;; set buffer-modified flag to `t' only if the mode has been changed, 
  1110.         ;; old code set unconditionally to `nil' if mode was not changed 
  1111.         ;; modification suggested by: Gerd Hillebrand <ggh@cs.brown.edu>
  1112.         (if (not (eq oldval buffer-save-encrypted))
  1113.             (set-buffer-modified-p t)))))
  1114.  
  1115.  
  1116. ;;; originally `tek-symbol-alist-to-table' from tek-highlight.el
  1117. (defun crypt-symbol-alist-to-table (list)
  1118.   "Converts an alist of symbols to a table suitable for `completing-read.'
  1119. Called by `crypt-get-encoding-type'."
  1120.   (mapcar (function (lambda (x) (list (symbol-name (car x)))))
  1121.           list))
  1122.  
  1123. (defun crypt-get-encoding-type ()
  1124.  
  1125.   "Interactive function that will query the user for the
  1126. `buffer-encoding-type' using the list in `crypt-encoding-alist.'"
  1127.  
  1128.   (interactive)
  1129.  
  1130.   ;; use poor man's gmhist (i.e., we could have used gmhist's
  1131.   ;; `completing-read-with-history-in' instead)
  1132.   (let (
  1133.         ;; find the encoding type desired by user
  1134.         (type
  1135.          (completing-read
  1136.           (concat "encoding type (? for list): [" crypt-default-encoding "] ")
  1137.           (crypt-symbol-alist-to-table crypt-encoding-alist))))
  1138.     
  1139.     ;; test length of object returned by `completing-read'
  1140.     (if (zerop (length type))
  1141.         
  1142.         ;; nothing there, i.e., user hit return -- use default
  1143.         (setq buffer-encoding-type (intern crypt-default-encoding))
  1144.       
  1145.       ;; use the value from mini-buffer and update the default value
  1146.       (setq buffer-encoding-type (intern type)
  1147.             crypt-default-encoding type))))
  1148.  
  1149. (defun encoded-mode (&optional arg)
  1150.  
  1151.   "Toggle encoded mode. With arg, turn encoded mode on iff arg is positive,
  1152. otherwise turn it off. In encoded mode, buffers are automatically encoded
  1153. before being written. If encoded mode is toggled, the current buffer is
  1154. marked modified, since it needs to be written with (or without) encoding.
  1155.  
  1156. Entering encoded mode causes auto-saving to be turned off in the current
  1157. buffer, as there is no way (in Emacs Lisp) to force auto save files to be
  1158. encoded."
  1159.  
  1160.   (interactive "P")
  1161.  
  1162.   ;; set flag indicating whether or not `encoded-mode' was called 
  1163.   ;; interactively
  1164.   (setq buffer-interactive-mode (interactive-p))
  1165.  
  1166.   ;; if called interactively then need to determine encoding type
  1167.   (if (and buffer-interactive-mode (not buffer-encoding-type))
  1168.       (crypt-get-encoding-type))
  1169.  
  1170.   ;; save old value of `buffer-save-encoded'
  1171.   (let ((oldval buffer-save-encoded))
  1172.  
  1173.     ;; set the variable `buffer-save-encoded' to `t' if the argument is 
  1174.     ;; positive, otherwise toggle its current value.
  1175.     (setq buffer-save-encoded
  1176.           (if arg (> arg 0) (not buffer-save-encoded)))
  1177.  
  1178.     ;; set the variable generated by `crypt-buffer-save-name' to the value
  1179.     ;; store in `buffer-save-encoded.'
  1180.     (set-variable (crypt-buffer-save-name buffer-encoding-type)
  1181.                   buffer-save-encoded)
  1182.  
  1183.     (if buffer-save-encoded
  1184.         ;; we are going to save as encoded, we will turn off auto-saving.
  1185.         (progn
  1186.           ;; if an auto-save file already exists, then delete it
  1187.           (if (and (stringp buffer-auto-save-file-name)
  1188.                    (file-exists-p buffer-auto-save-file-name))
  1189.               (delete-file buffer-auto-save-file-name))
  1190.           ;; turn-off auto-saving
  1191.           (auto-save-mode 0))
  1192.  
  1193.       ;; we are not going to save as encoded, we will turn on auto-saving but
  1194.       ;; only if we are editing a file and the default says we should.
  1195.       (auto-save-mode (if (and auto-save-default buffer-file-name) 1 0)))
  1196.  
  1197.     ;; have we toggled the mode? 
  1198.  
  1199.     ;; if yes, then mark buffer as modified.  if not, then leave
  1200.     ;; buffer-modified flag alone.
  1201.  
  1202.     ;; the old code previously set the variable `set-buffer-modified-p' to a
  1203.     ;; value of `t' if there was a mode change and (unconditionally) to `nil'
  1204.     ;; if there was not a mode change.
  1205.  
  1206.     ;; modification suggested by: Gerd Hillebrand <ggh@cs.brown.edu>
  1207.  
  1208.     (if (not (eq oldval buffer-save-encoded))
  1209.         (set-buffer-modified-p t))))
  1210.  
  1211.  
  1212. ;;;; Additional crypt defuns 
  1213.  
  1214. (defun read-string-no-echo (prompt &optional confirm)
  1215.  
  1216.   "Read a string from the minibuffer, prompting with PROMPT. Optional second
  1217. argument CONFIRM non-nil means that the user will be asked to type the string
  1218. a second time for confirmation and if there is a mismatch, the process is
  1219. repeated.
  1220.  
  1221.            Line editing keys are --
  1222.              C-h, DEL      rubout
  1223.              C-u, C-x      line kill
  1224.              C-q, C-v      literal next"
  1225.  
  1226.   (catch 'return-value
  1227.     (save-excursion
  1228.       (let ((input-buffer (get-buffer-create " *password*"))
  1229.             (cursor-in-echo-area t)
  1230.             (echo-keystrokes 0)
  1231.             char string help-form done kill-ring)
  1232.         (set-buffer input-buffer)
  1233.         (unwind-protect
  1234.             (while t
  1235.               (erase-buffer)
  1236.               (message prompt)
  1237.               (while (not (memq (setq char (read-char)) '(?\C-m ?\C-j)))
  1238.                 (if (setq form
  1239.                           (cdr
  1240.                            (assq char
  1241.                                  '((?\C-h . (delete-char -1))
  1242.                                    (?\C-? . (delete-char -1))
  1243.                                    (?\C-u . (delete-region 1 (point)))
  1244.                                    (?\C-x . (delete-region 1 (point)))
  1245.                                    (?\C-q . (quoted-insert 1))
  1246.                                    (?\C-v . (quoted-insert 1))))))
  1247.                     (condition-case error-data
  1248.                         (eval form)
  1249.                       (error t))
  1250.                   (insert char))
  1251.                 (message prompt))
  1252.               (cond ((and confirm string)
  1253.                      (cond ((not (string= string (buffer-string)))
  1254.                             (message
  1255.                              (concat prompt "[Mismatch... try again.]"))
  1256.                             (ding)
  1257.                             (sit-for 2)
  1258.                             (setq string nil))
  1259.                            (t (throw 'return-value string))))
  1260.                     (confirm
  1261.                      (setq string (buffer-string))
  1262.                      (message (concat prompt "[Retype to confirm...]"))
  1263.                      (sit-for 2))
  1264.                     (t (throw 'return-value (buffer-string)))))
  1265.           (set-buffer-modified-p nil)
  1266.           (kill-buffer input-buffer))))))
  1267.  
  1268. (defun set-encryption-key (key &optional buffer)
  1269.  
  1270.   "Set the encryption KEY for BUFFER. KEY should be a string. BUFFER should be
  1271. a buffer or the name of one; it defaults to the current buffer.  If BUFFER is
  1272. in crypt mode, then it is also marked as modified, since it needs to be saved
  1273. with the new key."
  1274.  
  1275.   (interactive
  1276.    (progn
  1277.      (barf-if-buffer-read-only)
  1278.      (list
  1279.       (read-string-no-echo
  1280.        (format "Set encryption key for buffer %s: " (buffer-name))))))
  1281.   (or buffer (setq buffer (current-buffer)))
  1282.   (save-excursion
  1283.     (set-buffer buffer)
  1284.     (if (equal key buffer-encryption-key)
  1285.         (message "Key is identical to original, no change.")
  1286.       (setq buffer-encryption-key key)
  1287.       ;; don't touch the modify flag unless we're in crypt-mode.
  1288.       (if buffer-save-encrypted
  1289.           (set-buffer-modified-p t)))))
  1290.  
  1291.  
  1292. ;; Install the hooks, then add the mode indicators to the minor mode alist.
  1293.  
  1294. ;; Check that the hooks are not already installed.
  1295.  
  1296. ;; Contributed by Ken Laprade <laprade@trantor.harris-atd.com>
  1297. ;; Really should use some sort of add-hook - 16 Feb 93 - KCL
  1298. (or (and (listp write-file-hooks) (not (eq (car write-file-hooks) 'lambda)))
  1299.     (setq write-file-hooks (list write-file-hooks)))
  1300.  
  1301. (cond
  1302.  ((not (memq 'crypt-write-file-hook write-file-hooks))
  1303.   ;; make this hook last on purpose
  1304.   (setq write-file-hooks (append write-file-hooks
  1305.                                  (list 'crypt-write-file-hook))
  1306.         find-file-hooks (cons 'crypt-find-file-hook find-file-hooks)
  1307.         find-file-not-found-hooks (cons 'crypt-find-file-hook
  1308.                                         find-file-not-found-hooks))))
  1309.  
  1310. ;; Check that the mode indicators are not already installed.
  1311.  
  1312. (cond
  1313.  ((not (memq crypt-minor-mode-encrypted minor-mode-alist))
  1314.   ;; add the mode indicators
  1315.   (setq minor-mode-alist (append crypt-minor-mode-alist
  1316.                                  minor-mode-alist))))
  1317.  
  1318.  
  1319. ;;;; BUG REPORTS
  1320.  
  1321. ;;; this section is provided for reports.
  1322. ;;; adopted from Barry A. Warsaw's c++-mode.el
  1323.  
  1324. (defvar crypt-mailer 'mail
  1325.   "*Mail package to use to generate report mail buffer.")
  1326.  
  1327. (defconst crypt-help-address
  1328.   "dodd@roebling.poly.edu, rwhitby@research.canon.oz.au"
  1329.   "Address(es) accepting submission of reports on crypt++.el.")
  1330.  
  1331. (defconst crypt-maintainer "Larry and Rod"
  1332.   "First name(s) of people accepting submission of reports on crypt++.el.")
  1333.  
  1334. (defconst crypt-file "crypt++.el"
  1335.   "Name of file containing emacs lisp code.")
  1336.  
  1337. (defun crypt-submit-report ()
  1338.   "Submit via mail a report using the mailer in crypt-mailer, filename in
  1339. crypt-file, to address in crypt-help-address."
  1340.   (interactive)
  1341.   (funcall crypt-mailer)
  1342.   (insert crypt-help-address)
  1343.   (let ((case-fold-search t))
  1344.     (if (re-search-forward "^subject:[ \t]+" (point-max) 'move)
  1345.         (insert "Report on " crypt-file " version " crypt-version))
  1346.     (if (not (re-search-forward mail-header-separator (point-max) 'move))
  1347.         (progn (goto-char (point-max))
  1348.                (insert "\n" mail-header-separator "\n")
  1349.                (goto-char (point-max)))
  1350.       (forward-line 1)))
  1351.   (set-mark (point)) ;user should see mark change
  1352.   (insert "\n\n---------\n")
  1353.   (insert (emacs-version) "\n")
  1354.   (insert "code: " crypt-file ",v " crypt-version)
  1355.   ;;
  1356.   (insert "\n\n")
  1357.   (insert "current values of variables -- \n\n") 
  1358.   ;;
  1359.   (insert "  crypt-encryption-program: ")
  1360.   (insert crypt-encryption-program "\n")
  1361.   ;;
  1362.   (insert "  crypt-decryption-program: ")
  1363.   (insert crypt-decryption-program "\n")
  1364.   ;;
  1365.   (insert "  crypt-encryption-args: ")
  1366.   (insert crypt-encryption-args "\n")
  1367.   ;;
  1368.   (insert "  crypt-decryption-args: ")
  1369.   (insert crypt-decryption-args "\n")
  1370.   ;;
  1371.   (insert "  crypt-auto-decode-buffer: ")
  1372.   (insert (prin1-to-string crypt-auto-decode-buffer) "\n")
  1373.   ;;
  1374.   (insert "  crypt-auto-write-buffer: ")
  1375.   (insert (prin1-to-string crypt-auto-write-buffer) "\n")
  1376.   ;;
  1377.   (insert "  crypt-query-if-interactive: ")
  1378.   (insert (prin1-to-string crypt-query-if-interactive) "\n")
  1379.   ;;
  1380.   (insert "  crypt-no-extension-implies-plain: ")
  1381.   (insert (prin1-to-string crypt-no-extension-implies-plain) "\n")
  1382.   ;;
  1383.   (insert "  crypt-never-ever-decrypt: ")
  1384.   (insert (prin1-to-string crypt-never-ever-decrypt) "\n")
  1385.   ;;
  1386.   (insert "  crypt-freeze-vs-fortran: ")
  1387.   (insert (prin1-to-string crypt-freeze-vs-fortran) "\n")
  1388.   ;;
  1389.   (insert "  crypt-compact-vs-C++: ")
  1390.   (insert (prin1-to-string crypt-compact-vs-C++) "\n")
  1391.   ;;
  1392.   (insert "  crypt-default-encoding: ")
  1393.   (insert crypt-default-encoding "\n")
  1394.   ;;
  1395.   (insert "\n  crypt-encoding-alist: ")
  1396.   (insert (prin1-to-string crypt-encoding-alist))
  1397.   (fill-region (save-excursion (beginning-of-line) (point)) (point))
  1398.   ;;
  1399.   (exchange-point-and-mark)
  1400.   (insert "\n" crypt-maintainer ",\n\n  ")
  1401.   (message "%s, please write the message, use C-c C-c to send" (user-login-name)))
  1402.  
  1403. ;; provide this package as crypt++ as well as crypt
  1404. (provide 'crypt++)
  1405. (provide 'crypt)
  1406. ........................... cut along dotted line ...........................
  1407. <end file: ~/lisp/crypt++.el>
  1408.