+(defcustom epa-file-cache-passphrase-for-symmetric-encryption nil
+ "If t, cache passphrase for symmetric encryption."
+ :type 'boolean
+ :group 'epa-file)
+
+(defvar epa-file-encrypt-to nil
+ "*Recipient(s) used for encrypting files.
+May either be a string or a list of strings.")
+
+;;;###autoload
+(put 'epa-file-encrypt-to 'safe-local-variable
+ (lambda (val)
+ (or (stringp val)
+ (and (listp val)
+ (catch 'safe
+ (mapc (lambda (elt)
+ (unless (stringp elt)
+ (throw 'safe nil)))
+ val)
+ t)))))
+
+(defvar epa-file-handler
+ (cons epa-file-name-regexp 'epa-file-handler))
+
+(defvar epa-file-passphrase-alist nil)
+
+(if (fboundp 'encode-coding-string)
+ (defalias 'epa-file--encode-coding-string 'encode-coding-string)
+ (defalias 'epa-file--encode-coding-string 'identity))
+
+(if (fboundp 'decode-coding-string)
+ (defalias 'epa-file--decode-coding-string 'decode-coding-string)
+ (defalias 'epa-file--decode-coding-string 'identity))
+
+(defun epa-file-passphrase-callback-function (context key-id file)
+ (if (and epa-file-cache-passphrase-for-symmetric-encryption
+ (eq key-id 'SYM))
+ (let ((entry (assoc file epa-file-passphrase-alist))
+ passphrase)
+ (or (copy-sequence (cdr entry))
+ (progn
+ (unless entry
+ (setq entry (list file)
+ epa-file-passphrase-alist (cons entry
+ epa-file-passphrase-alist)))
+ (setq passphrase (epa-passphrase-callback-function context
+ key-id nil))
+ (setcdr entry (copy-sequence passphrase))
+ passphrase)))
+ (epa-passphrase-callback-function context key-id nil)))
+
+(defun epa-file-handler (operation &rest args)
+ (save-match-data
+ (let ((op (get operation 'epa-file)))
+ (if op
+ (apply op args)
+ (epa-file-run-real-handler operation args)))))
+
+(defun epa-file-run-real-handler (operation args)
+ (let ((inhibit-file-name-handlers
+ (cons 'epa-file-handler
+ (and (eq inhibit-file-name-operation operation)
+ inhibit-file-name-handlers)))
+ (inhibit-file-name-operation operation))
+ (apply operation args)))
+
+(defun epa-file-decode-and-insert (string file visit beg end replace)
+ (if (fboundp 'decode-coding-inserted-region)
+ (save-restriction
+ (narrow-to-region (point) (point))
+ (let ((multibyte enable-multibyte-characters))
+ (set-buffer-multibyte nil)
+ (insert string)
+ (set-buffer-multibyte multibyte)
+ (decode-coding-inserted-region
+ (point-min) (point-max)
+ (substring file 0 (string-match epa-file-name-regexp file))
+ visit beg end replace)))
+ (insert (epa-file--decode-coding-string string (or coding-system-for-read
+ 'undecided)))))
+
+(defvar last-coding-system-used)
+(defun epa-file-insert-file-contents (file &optional visit beg end replace)
+ (barf-if-buffer-read-only)
+ (if (and visit (or beg end))
+ (error "Attempt to visit less than an entire file"))
+ (setq file (expand-file-name file))
+ (let ((local-copy (epa-file-run-real-handler #'file-local-copy (list file)))
+ (context (epg-make-context))
+ string length entry)
+ (if visit
+ (setq buffer-file-name file))
+ (epg-context-set-passphrase-callback
+ context
+ (cons #'epa-file-passphrase-callback-function
+ file))
+ (epg-context-set-progress-callback context
+ #'epa-progress-callback-function)
+ (unwind-protect