3 (defcustom epg-file-name-regexp "\\.gpg\\'"
4 "Regexp that matches filenames that are assumed to be encrypted
9 (defun epg-file-handler (operation &rest args)
10 (let ((epg-file-operation (get operation 'epg-file)))
11 (if epg-file-operation
12 (apply epg-file-operation args)
13 (epg-file-run-real-handler operation args))))
15 (defun epg-file-run-real-handler (operation args)
16 (let ((inhibit-file-name-handlers
17 (cons 'epg-file-handler
18 (and (eq inhibit-file-name-operation operation)
19 inhibit-file-name-handlers)))
20 (inhibit-file-name-operation operation))
21 (apply operation args)))
23 (defun epg-file-write-region (start end filename &optional append visit
25 (let* ((visit-file (if (stringp visit)
26 (expand-file-name visit)
27 (expand-file-name filename)))
28 ;; XXX: Obtain the value returned by choose_write_coding_system
29 (coding-system (condition-case nil
30 (epg-file-run-real-handler
31 'write-region (list start end "/"))
32 (file-error last-coding-system-used)))
33 ;; start and end are normally buffer positions
34 ;; specifying the part of the buffer to write.
35 ;; If start is nil, that means to use the entire buffer contents.
36 ;; If start is a string, then output that string to the file
37 ;; instead of any buffer contents; end is ignored.
38 (string (encode-coding-string (cond
44 (buffer-substring start end)))
47 (set-buffer-multibyte nil)
48 ;; Optional fourth argument append if non-nil means
49 ;; append to existing file contents (if any). If it is an integer,
50 ;; seek to that offset in the file before writing.
51 (if (and append (file-exists-p filename))
52 ;; Enable passphrase cache on this temp buffer
53 (let ((coding-system-for-read 'binary))
54 ;; set visit to t so that passphrase is cached
55 (insert-file-contents filename t)
56 (setq buffer-file-name nil)))
57 ;; Insert data to encrypt
58 (goto-char (if (integerp append) (1+ append) (point-max)))
59 (delete-region (point) (min (+ (point) (length string)) (point-max)))
62 (let ((coding-system-for-write 'binary)
63 (coding-system-for-read 'binary)
64 (context (epg-make-context))
66 (when (setq cipher (epg-encrypt-string context (buffer-string) nil))
67 (if (memq system-type '(ms-dos windows-nt))
68 (setq buffer-file-type t))
69 (epg-file-run-real-handler
71 (list cipher nil filename nil 'not-visit lockname mustbenew)))))
72 ;; Optional fifth argument visit, if t or a string, means
73 ;; set the last-save-file-modtime of buffer to this file's modtime
74 ;; and mark buffer not modified.
75 ;; If visit is a string, it is a second file name;
76 ;; the output goes to filename, but the buffer is marked as visiting visit.
77 ;; visit is also the file name to lock and unlock for clash detection.
78 ;; If visit is neither t nor nil nor a string,
79 ;; that means do not display the "Wrote file" message.
80 (when (or (eq visit t) (stringp visit))
81 (setq buffer-file-name filename)
82 (set-visited-file-modtime))
84 (setq buffer-file-name visit))
85 (when (or (eq visit t) (eq visit nil) (stringp visit))
86 (message "Wrote %s" visit-file))
87 (setq last-coding-system-used coding-system)
90 (defun epg-file-insert-file-contents (filename &optional visit beg end replace)
91 (barf-if-buffer-read-only)
92 (setq filename (expand-file-name filename))
93 (let ((filename (expand-file-name filename))
95 (if (file-exists-p filename)
97 (let ((inhibit-file-name-operation
98 (when (eq inhibit-file-name-operation
99 'insert-file-contents)
101 (file-local-copy filename)))
102 (coding-system-for-read 'binary)
103 (context (epg-make-context))
107 (setq string (epg-decrypt-file context (or local-file
109 length (length string))
111 (goto-char (point-min)))
113 (let ((buffer-file-name (if visit nil buffer-file-name)))
115 (narrow-to-region (point) (point))
116 (insert (decode-coding-string string 'undecided)))
118 (delete-region (point) (point-max))))))
119 (when (and local-file (file-exists-p local-file))
120 (delete-file local-file)))))
121 ;; If second argument visit is non-nil, the buffer's visited filename
122 ;; and last save file modtime are set, and it is marked unmodified.
125 (setq buffer-file-name filename)
126 (set-visited-file-modtime))
128 ;; If visiting and the file does not exist, visiting is completed
129 ;; before the error is signaled.
130 (if (and visit (not (file-exists-p filename)))
131 (signal 'file-error (list "Opening input file" filename)))
133 ;; Returns list of absolute file name and number of characters inserted.
134 (list filename length)))
136 (put 'write-region 'epg-file 'epg-file-write-region)
137 (put 'insert-file-contents 'epg-file 'epg-file-insert-file-contents)
139 (unless (assoc epg-file-name-regexp file-name-handler-alist)
140 (setq file-name-handler-alist
141 (cons (cons epg-file-name-regexp 'epg-file-handler)
142 file-name-handler-alist)))
144 (unless (assoc epg-file-name-regexp auto-mode-alist)
145 (setq auto-mode-alist
146 (cons (list epg-file-name-regexp nil 'strip-suffix)