(file-exists-p (epg-context-output-file context)))
(delete-file (epg-context-output-file context))))
+(eval-and-compile
+ (if (fboundp 'decode-coding-string)
+ (defalias 'epg--decode-coding-string 'decode-coding-string)
+ (defalias 'epg--decode-coding-string 'identity)))
+
(defun epg--status-USERID_HINT (context string)
(if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
(let* ((key-id (match-string 1 string))
(user-id (match-string 2 string))
(entry (assoc key-id epg-user-id-alist)))
(condition-case nil
- (setq user-id (epg--decode-coding-string user-id 'utf-8))
+ (setq user-id (epg--decode-coding-string
+ (epg--decode-percent-escape user-id)
+ 'utf-8))
(error))
(if entry
(setcdr entry user-id)
(defun epg--status-NEED_PASSPHRASE_PIN (context string)
(setq epg-key-id 'PIN))
+(eval-and-compile
+ (if (fboundp 'clear-string)
+ (defalias 'epg--clear-string 'clear-string)
+ (defun epg--clear-string (string)
+ (fillarray string 0))))
+
+(eval-and-compile
+ (if (fboundp 'encode-coding-string)
+ (defalias 'epg--encode-coding-string 'encode-coding-string)
+ (defalias 'epg--encode-coding-string 'identity)))
+
(defun epg--status-GET_HIDDEN (context string)
(when (and epg-key-id
(string-match "\\`passphrase\\." string))
(y-or-n-p (if entry (cdr entry) (concat string "? ")))))
(defun epg--prompt-GET_BOOL-untrusted_key.override (context string)
- (y-or-n-p (if (equal (car epg-last-status) "USERID_HINT")
- (format "Untrusted key %s. Use anyway? "
- (cdr epg-last-status))
+ (y-or-n-p (if (and (equal (car epg-last-status) "USERID_HINT")
+ (string-match "\\`\\([^ ]+\\) \\(.*\\)"
+ (cdr epg-last-status)))
+ (let* ((key-id (match-string 1 (cdr epg-last-status)))
+ (user-id (match-string 2 (cdr epg-last-status)))
+ (entry (assoc key-id epg-user-id-alist)))
+ (if entry
+ (setq user-id (cdr entry)))
+ (format "Untrusted key %s %s. Use anyway? " key-id user-id))
"Use untrusted key anyway? ")))
(defun epg--status-GET_BOOL (context string)
(condition-case nil
(if (eq (epg-context-protocol context) 'CMS)
(setq user-id (epg-dn-from-string user-id))
- (setq user-id (epg--decode-coding-string user-id 'utf-8)))
+ (setq user-id (epg--decode-coding-string
+ (epg--decode-percent-escape user-id)
+ 'utf-8)))
(error))
(if entry
(setcdr entry user-id)
(if (consp (epg-context-progress-callback context))
(cdr (epg-context-progress-callback context))))))
+(defun epg--status-ENC_TO (context string)
+ (if (string-match "\\`\\([0-9A-Za-z]+\\) \\([0-9]+\\) \\([0-9]+\\)" string)
+ (epg-context-set-result-for
+ context 'encrypted-to
+ (cons (list (match-string 1 string)
+ (string-to-number (match-string 2 string))
+ (string-to-number (match-string 3 string)))
+ (epg-context-result-for context 'encrypted-to)))))
+
(defun epg--status-DECRYPTION_FAILED (context string)
(epg-context-set-result-for context 'decryption-failed t))
(user-id (match-string 2 string))
(entry (assoc key-id epg-user-id-alist)))
(condition-case nil
- (setq user-id (epg--decode-coding-string user-id 'utf-8))
+ (setq user-id (epg--decode-coding-string
+ (epg--decode-percent-escape user-id)
+ 'utf-8))
(error))
(if entry
(setcdr entry user-id)
(defun epg--list-keys-1 (context name mode)
(let ((args (append (if epg-gpg-home-directory
(list "--homedir" epg-gpg-home-directory))
- (list "--with-colons" "--no-greeting" "--batch"
- "--with-fingerprint"
- "--with-fingerprint"
- (if (memq mode '(t secret))
- "--list-secret-keys"
- (if (memq mode '(nil public))
- "--list-keys"
- "--list-sigs")))
+ '("--with-colons" "--no-greeting" "--batch"
+ "--with-fingerprint" "--with-fingerprint")
(unless (eq (epg-context-protocol context) 'CMS)
- '("--fixed-list-mode"))
- (if name (list name))))
+ '("--fixed-list-mode"))))
+ (list-keys-option (if (memq mode '(t secret))
+ "--list-secret-keys"
+ (if (memq mode '(nil public))
+ "--list-keys"
+ "--list-sigs")))
+ (coding-system-for-read 'binary)
keys string field index)
+ (if name
+ (progn
+ (unless (listp name)
+ (setq name (list name)))
+ (while name
+ (setq args (append args (list list-keys-option (car name)))
+ name (cdr name))))
+ (setq args (append args (list list-keys-option))))
(with-temp-buffer
(apply #'call-process
(if (eq (epg-context-protocol context) 'CMS)
If MODE is nil or 'public, only public keyring should be searched.
If MODE is t or 'secret, only secret keyring should be searched.
Otherwise, only public keyring should be searched and the key
-signatures should be included."
+signatures should be included.
+NAME is either a string or a list of strings."
(let ((lines (epg--list-keys-1 context name mode))
- keys cert pointer pointer-1)
+ keys cert pointer pointer-1 index string)
(while lines
(cond
((member (aref (car lines) 0) '("pub" "sec" "crt" "crs"))
(cons (epg--make-sub-key-1 (car lines))
(epg-key-sub-key-list (car keys)))))
((equal (aref (car lines) 0) "uid")
+ ;; Decode the UID name as a backslash escaped UTF-8 string,
+ ;; generated by GnuPG/GpgSM.
+ (setq string (copy-sequence (aref (car lines) 9))
+ index 0)
+ (while (string-match "\"" string index)
+ (setq string (replace-match "\\\"" t t string)
+ index (1+ (match-end 0))))
+ (condition-case nil
+ (setq string (epg--decode-coding-string
+ (car (read-from-string (concat "\"" string "\"")))
+ 'utf-8))
+ (error
+ (setq string (aref (car lines) 9))))
(epg-key-set-user-id-list
(car keys)
(cons (epg-make-user-id
epg-key-validity-alist)))
(if cert
(condition-case nil
- (epg-dn-from-string (aref (car lines) 9))
- (error (aref (car lines) 9)))
- (aref (car lines) 9)))
+ (epg-dn-from-string string)
+ (error string))
+ string))
(epg-key-user-id-list (car keys)))))
((equal (aref (car lines) 0) "fpr")
(epg-sub-key-set-fingerprint (car (epg-key-sub-key-list (car keys)))
(setq pointer (cdr pointer)))
keys))
-(if (fboundp 'make-temp-file)
- (defalias 'epg--make-temp-file 'make-temp-file)
- (defvar temporary-file-directory)
- ;; stolen from poe.el.
- (defun epg--make-temp-file (prefix)
- "Create a temporary file.
+(eval-and-compile
+ (if (fboundp 'make-temp-file)
+ (defalias 'epg--make-temp-file 'make-temp-file)
+ (defvar temporary-file-directory)
+ ;; stolen from poe.el.
+ (defun epg--make-temp-file (prefix)
+ "Create a temporary file.
The returned file name (created by appending some random characters at the end
of PREFIX, and expanding against `temporary-file-directory' if necessary),
is guaranteed to point to a newly created empty file.
You can then use `write-region' to write new data into the file."
- (let (tempdir tempfile)
- (setq prefix (expand-file-name prefix
- (if (featurep 'xemacs)
- (temp-directory)
- temporary-file-directory)))
- (unwind-protect
- (let (file)
- ;; First, create a temporary directory.
- (while (condition-case ()
- (progn
- (setq tempdir (make-temp-name
- (concat
- (file-name-directory prefix)
- "DIR")))
- ;; return nil or signal an error.
- (make-directory tempdir))
- ;; let's try again.
- (file-already-exists t)))
- (set-file-modes tempdir 448)
- ;; Second, create a temporary file in the tempdir.
- ;; There *is* a race condition between `make-temp-name'
- ;; and `write-region', but we don't care it since we are
- ;; in a private directory now.
- (setq tempfile (make-temp-name (concat tempdir "/EMU")))
- (write-region "" nil tempfile nil 'silent)
- (set-file-modes tempfile 384)
- ;; Finally, make a hard-link from the tempfile.
- (while (condition-case ()
- (progn
- (setq file (make-temp-name prefix))
- ;; return nil or signal an error.
- (add-name-to-file tempfile file))
- ;; let's try again.
- (file-already-exists t)))
- file)
- ;; Cleanup the tempfile.
- (and tempfile
- (file-exists-p tempfile)
- (delete-file tempfile))
- ;; Cleanup the tempdir.
- (and tempdir
- (file-directory-p tempdir)
- (delete-directory tempdir))))))
-
-(if (fboundp 'clear-string)
- (defalias 'epg--clear-string 'clear-string)
- (defun epg--clear-string (string)
- (fillarray string 0)))
-
-(if (fboundp 'encode-coding-string)
- (defalias 'epg--encode-coding-string 'encode-coding-string)
- (defalias 'epg--encode-coding-string 'identity))
-
-(if (fboundp 'decode-coding-string)
- (defalias 'epg--decode-coding-string 'decode-coding-string)
- (defalias 'epg--decode-coding-string 'identity))
+ (let (tempdir tempfile)
+ (setq prefix (expand-file-name prefix
+ (if (featurep 'xemacs)
+ (temp-directory)
+ temporary-file-directory)))
+ (unwind-protect
+ (let (file)
+ ;; First, create a temporary directory.
+ (while (condition-case ()
+ (progn
+ (setq tempdir (make-temp-name
+ (concat
+ (file-name-directory prefix)
+ "DIR")))
+ ;; return nil or signal an error.
+ (make-directory tempdir))
+ ;; let's try again.
+ (file-already-exists t)))
+ (set-file-modes tempdir 448)
+ ;; Second, create a temporary file in the tempdir.
+ ;; There *is* a race condition between `make-temp-name'
+ ;; and `write-region', but we don't care it since we are
+ ;; in a private directory now.
+ (setq tempfile (make-temp-name (concat tempdir "/EMU")))
+ (write-region "" nil tempfile nil 'silent)
+ (set-file-modes tempfile 384)
+ ;; Finally, make a hard-link from the tempfile.
+ (while (condition-case ()
+ (progn
+ (setq file (make-temp-name prefix))
+ ;; return nil or signal an error.
+ (add-name-to-file tempfile file))
+ ;; let's try again.
+ (file-already-exists t)))
+ file)
+ ;; Cleanup the tempfile.
+ (and tempfile
+ (file-exists-p tempfile)
+ (delete-file tempfile))
+ ;; Cleanup the tempdir.
+ (and tempdir
+ (file-directory-p tempdir)
+ (delete-directory tempdir)))))))
(defun epg--args-from-sig-notations (notations)
(apply #'nconc
(epg-context-result-for context 'error))))
(epg-reset context)))
+(defun epg--decode-percent-escape (string)
+ (let ((index 0))
+ (while (string-match "%\\(\\(%\\)\\|\\([0-9A-Fa-f][0-9A-Fa-f]\\)\\)"
+ string index)
+ (if (match-beginning 2)
+ (setq string (replace-match "%" t t string)
+ index (1- (match-end 0)))
+ (setq string (replace-match
+ (string (string-to-number (match-string 3 string) 16))
+ t t string)
+ index (- (match-end 0) 2))))
+ string))
+
(defun epg--decode-hexstring (string)
(let ((index 0))
(while (eq index (string-match "[0-9A-Fa-f][0-9A-Fa-f]" string index))
- (setq string (replace-match "\\\\x\\&" t nil string)
- index (+ index 4)))
- (car (read-from-string (concat "\"" string "\"")))))
+ (setq string (replace-match (string (string-to-number
+ (match-string 0 string) 16))
+ t t string)
+ index (1- (match-end 0))))
+ string))
(defun epg--decode-quotedstring (string)
(let ((index 0))
(while (string-match "\\\\\\(\\([,=+<>#;\\\"]\\)\\|\
-\\([0-9A-Fa-f][0-9A-Fa-f]\\)\\|\\(.\\)\\)"
+\\([0-9A-Fa-f][0-9A-Fa-f]\\)\\)"
string index)
(if (match-beginning 2)
(setq string (replace-match "\\2" t nil string)
- index (1+ index))
+ index (1- (match-end 0)))
(if (match-beginning 3)
- (setq string (replace-match "\\\\x\\3" t nil string)
- index (+ index 4))
- (setq string (replace-match "\\\\\\\\\\4" t nil string)
- index (+ index 3)))))
- (car (read-from-string (concat "\"" string "\"")))))
+ (setq string (replace-match (string (string-to-number
+ (match-string 0 string) 16))
+ t t string)
+ index (- (match-end 0) 2)))))
+ string))
(defun epg-dn-from-string (string)
"Parse STRING as LADPv3 Distinguished Names (RFC2253).