;;; openSSL hacks

(defvar ssl-program "openssl")
(defvar ssl-pass-phrases '())
(defvar ssl-encoding "bf")

(defun ssl-pass-phrase (file)
  (let* ((xfile (expand-file-name file))
	 (ssl-metadata (assoc xfile ssl-pass-phrases)))
    (read-passwd "SSL passphrase: " nil
		 (if ssl-metadata (cdr ssl-metadata) nil))))

(defun ssl-add-write-hook ()
  (if (not (member 'ssl-write-file-data-hook
		   write-file-data-hooks))
      (setq write-file-data-hooks (cons 'ssl-write-file-data-hook
					write-file-data-hooks))))

(defun ssl-find-file (file)
  (interactive "fFind encrypted file: ")
  (let* ((xfile (expand-file-name file))
	 (ssl-metadata (assoc xfile ssl-pass-phrases))
	 (pass-phrase (read-passwd "SSL passphrase: " nil
				   (if ssl-metadata (cdr ssl-metadata) nil))))
    (if ssl-metadata
	(setcdr ssl-metadata pass-phrase)
      (setq ssl-pass-phrases (cons (cons xfile pass-phrase) ssl-pass-phrases)))

    (let ((buffer (or (find-buffer-visiting xfile)
		      (create-file-buffer xfile))))
      (call-process ssl-program xfile buffer t
		    "enc" "-d" (format "-%s" ssl-encoding)
		    "-k" pass-phrase)
      (switch-to-buffer buffer)
      (set-visited-file-name xfile)
      (setq buffer-auto-save-file-name nil)
      (ssl-add-write-hook)
      (set-buffer-modified-p nil)
      (goto-char (point-min))
      )))

(defun ssl-write-file (file)
  (interactive "FWrite encrypted file: ")
  (let* ((xfile (expand-file-name file))
	 (pass-phrase (ssl-pass-phrase xfile))
	 (ssl-buffer (get-buffer-create "*SSL Output*")))

    (if (not (equal xfile (expand-file-name (buffer-file-name))))
	(set-visited-file-name xfile))

    (cond ((not
	    (= 0
	       (call-process-region (point-min) (point-max)
				    ssl-program
				    nil ssl-buffer t
				    "enc" "-e" (format "-%s" ssl-encoding)
				    "-k" pass-phrase
				    "-out" xfile)))
	   (switch-to-buffer-other-window ssl-buffer)
	   nil)
	  (t
	   (setq buffer-auto-save-file-name nil)
	   (ssl-add-write-hook)
	   (set-buffer-modified-p nil)
	   t))
    ))

(defun ssl-write-file-data-hook (file)
  (let* ((xfile (expand-file-name file)))
    (and (assoc xfile ssl-pass-phrases)
	 (ssl-write-file xfile)
	 )))

