;;;; chaffwin.el: an Emacs interface to chaff.pl and winnow.pl ;;;; ;;; (See http://theory.lcs.mit.edu/~rivest/chaffing.txt). ;;; ;;; Copyright (C) 1998 Ben Sussman and Karl Fogel ;;; (, ). ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License along ;;; with this program; if not, write to the Free Software Foundation, Inc., ;;; 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ;;; NOTE: these instructions assume middling familiarity with Emacs. ;;; If the text below doesn't make sense to you, then talk to the ;;; Emacs expert at your site. If there isn't an Emacs expert, you'll ;;; need to become one. :-) ;;; ;;; Installation: make sure `chaff.pl' and `winnow.pl' are in your ;;; execution PATH, then put chaffwin.el in a directory in Emacs's ;;; `load-path' (for example, "/usr/local/share/emacs/site-lisp/" on ;;; many systems). Then put these lines in your .emacs, *without* the ;;; semicolons of course: ;;; ;;; (autoload 'chaffwin-map "chaffwin" nil t) ;;; (autoload 'chaffwin-chaff-region "chaffwin" nil t) ;;; (autoload 'chaffwin-winnow-region "chaffwin" nil t) ;;; (autoload 'chaffwin-find-and-winnow-region "chaffwin" nil t) ;;; ;;; Now you can invoke the following functions via Emacs's standard ;;; named-function interactive invocation interface (referred to ;;; hereinafter as the ESNFIII): ;;; ;;; M-x chaffwin-chaff-region ;;; M-x chaffwin-winnow-region ;;; M-x chaffwin-find-and-winnow-region ;;; ;;; You can ignore `chaffwin-map'; it's there for power users who want ;;; to bind all chaffwin commands under a single prefix key-sequence. ;;; Code: ;; Gets us `comint-read-noecho', for reading passwords (require 'comint) (defvar chaffwin-program "chaffwin.pl" "The chaffwin program. It may be marginally more secure to have this be an absolute, rather than relative, path.") (defvar chaffwin-map nil "Keymap containing bindings to chaffwin functions. It is not bound to any key by default: to bind it so that you have a chaffwin prefix, just use `global-set-key' and bind a key of your choice to `chaffwin-map'. All interactive chaffwin functions have a binding in this keymap.") (defvar chaffwin-passphrase-noecho t "*If non-nil, hide chaffwin passphrases as they're being entered.") (defvar chaffwin-chaff-level nil "*If non-nil, the chaff level (the \"-c\" argument to chaffwin.pl).") (define-prefix-command 'chaffwin-map) (define-key chaffwin-map "c" 'chaffwin-chaff-region) (define-key chaffwin-map "w" 'chaffwin-winnow-region) (define-key chaffwin-map "f" 'chaffwin-find-and-winnow-region) (defun chaffwin-call-process-region (pgm b e &rest args) (apply 'call-process-region b e pgm t t t args)) (defun chaffwin-read-pass-phrase () "Read a pass-phrase in the minibuffer." (interactive) ; todo: why does `send-invisible' have "P"? (if chaffwin-passphrase-noecho (comint-read-noecho "Pass phrase: " t) (read-from-minibuffer "Pass phrase: "))) (defun chaffwin-do-region (pgm b e behavior &optional passphrase) "Call PGM on text from B to E, behaving as indicated by BEHAVIOR. BEHAVIOR is \"-e\" or \"-d\". If optional fourth argument PASSPHRASE is non-nil, then use it instead of prompting for one." (interactive "r") (save-excursion (let ((pp (or passphrase (chaffwin-read-pass-phrase))) (msg (if (string-equal behavior "-e") "Chaffing" "Winnowing"))) (message "%s..." msg) (apply 'chaffwin-call-process-region pgm b e behavior "-p" pp (if chaffwin-chaff-level (list "-c" (number-to-string chaffwin-chaff-level)))) (message "%s...done" msg) (setq pp nil)))) (defun chaffwin-chaff-region (b e &optional passphrase) "Chaff text from B to E, prompting for a pass phrase. If optional third argument PASSPHRASE is non-nil, then use it instead of prompting for one." (interactive "r") (chaffwin-do-region chaffwin-program b e "-e" passphrase)) (defun chaffwin-winnow-region (b e &optional passphrase) "Winnow a region. Region is not confirmed with magic cookies, so caller should check those itself. If optional third argument PASSPHRASE is non-nil, then use it instead of prompting for one." (interactive "r") (chaffwin-do-region chaffwin-program b e "-d" passphrase)) (defun chaffwin-find-and-winnow-region (&optional passphrase) "Winnow the chaffed portion of a buffer. If optional argument PASSPHRASE is non-nil, then use it instead of prompting for one." (interactive) (let (b e) (goto-char (point-min)) ;; todo: we need a more robust regexp for this eventually: (re-search-forward "^([0-9]+,") (beginning-of-line) (setq b (point)) (goto-char (point-max)) (re-search-backward "^([0-9]+,") (forward-line 1) (setq e (point)) (chaffwin-winnow-region b e passphrase) (goto-char b)))