X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=epg.el;h=87e8c5c07e17dbe676994057f0ef533d7d416bf3;hb=d5cea182d74c39645d405af8941e5c10c572c984;hp=cd66283a85b808dcf1bda50f860e8805cef22763;hpb=b9ec19fa3eb2806d2fdea35fc7c19c7c9ee4bc89;p=elisp%2Fepg.git diff --git a/epg.el b/epg.el index cd66283..87e8c5c 100644 --- a/epg.el +++ b/epg.el @@ -25,26 +25,7 @@ ;;; Code: -(defgroup epg () - "The EasyPG Library" - :group 'emacs) - -(defcustom epg-gpg-program "gpg" - "The `gpg' executable." - :group 'epg - :type 'string) - -(defcustom epg-gpgsm-program "gpgsm" - "The `gpgsm' executable." - :group 'epg - :type 'string) - -(defcustom epg-gpg-home-directory nil - "The directory which contains the `gpg' configuration files." - :group 'epg - :type '(choice (const :tag "Default" nil) directory)) - -(defconst epg-version-number "0.0.4") +(require 'epg-config) (defvar epg-user-id nil "GnuPG ID of your default identity.") @@ -57,7 +38,6 @@ (defvar epg-pending-status-list nil) (defvar epg-key-id nil) (defvar epg-context nil) -(defvar epg-debug nil) (defvar epg-debug-buffer nil) ;; from gnupg/include/cipher.h @@ -206,7 +186,7 @@ (vector (or protocol 'OpenPGP) armor textmode include-certs cipher-algorithm digest-algorithm compress-algorithm #'epg-passphrase-callback-function - #'epg-progress-callback-function + nil nil nil nil nil nil))) (defun epg-context-protocol (context) @@ -785,7 +765,7 @@ This function is for internal use only." (cond ((eq (epg-new-signature-type new-signature) 'detached) "Detached signature ") ((eq (epg-new-signature-type new-signature) 'clear) - "Clear text signature ") + "Cleartext signature ") (t "Signature ")) (cdr (assq (epg-new-signature-pubkey-algorithm new-signature) @@ -808,6 +788,8 @@ This function is for internal use only." (let* ((args (append (list "--no-tty" "--status-fd" "1" "--yes") + (if (epg-context-progress-callback context) + (list "--enable-progress-filter")) (if epg-gpg-home-directory (list "--homedir" epg-gpg-home-directory)) (unless (eq (epg-context-protocol context) 'CMS) @@ -948,39 +930,55 @@ This function is for internal use only." (setq epg-key-id 'PIN)) (defun epg--status-GET_HIDDEN (context string) - (if (and epg-key-id - (string-match "\\`passphrase\\." string)) - (let (inhibit-quit - passphrase - passphrase-with-new-line) - (unwind-protect - (condition-case nil - (progn - (setq passphrase - (funcall - (if (consp (epg-context-passphrase-callback context)) - (car (epg-context-passphrase-callback context)) - (epg-context-passphrase-callback context)) - context - epg-key-id - (if (consp (epg-context-passphrase-callback context)) - (cdr (epg-context-passphrase-callback context))))) - (when passphrase - (setq passphrase-with-new-line (concat passphrase "\n")) - (fillarray passphrase 0) - (setq passphrase nil) - (process-send-string (epg-context-process context) - passphrase-with-new-line))) - (quit - (epg-context-set-result-for - context 'error - (cons '(quit) - (epg-context-result-for context 'error))) - (delete-process (epg-context-process context)))) - (if passphrase - (fillarray passphrase 0)) - (if passphrase-with-new-line - (fillarray passphrase-with-new-line 0)))))) + (when (and epg-key-id + (string-match "\\`passphrase\\." string)) + (unless (epg-context-passphrase-callback context) + (error "passphrase-callback not set")) + (let (inhibit-quit + passphrase + passphrase-with-new-line + encoded-passphrase-with-new-line) + (unwind-protect + (condition-case nil + (progn + (setq passphrase + (funcall + (if (consp (epg-context-passphrase-callback context)) + (car (epg-context-passphrase-callback context)) + (epg-context-passphrase-callback context)) + context + epg-key-id + (if (consp (epg-context-passphrase-callback context)) + (cdr (epg-context-passphrase-callback context))))) + (when passphrase + (setq passphrase-with-new-line (concat passphrase "\n")) + (epg--clear-string passphrase) + (setq passphrase nil) + (if epg-passphrase-coding-system + (progn + (setq encoded-passphrase-with-new-line + (encode-coding-string + passphrase-with-new-line + epg-passphrase-coding-system)) + (epg--clear-string passphrase-with-new-line) + (setq passphrase-with-new-line nil)) + (setq encoded-passphrase-with-new-line + passphrase-with-new-line + passphrase-with-new-line nil)) + (process-send-string (epg-context-process context) + encoded-passphrase-with-new-line))) + (quit + (epg-context-set-result-for + context 'error + (cons '(quit) + (epg-context-result-for context 'error))) + (delete-process (epg-context-process context)))) + (if passphrase + (epg--clear-string passphrase)) + (if passphrase-with-new-line + (epg--clear-string passphrase-with-new-line)) + (if encoded-passphrase-with-new-line + (epg--clear-string encoded-passphrase-with-new-line)))))) (defun epg--status-GET_BOOL (context string) (let ((entry (assoc string epg-prompt-alist)) @@ -1308,53 +1306,13 @@ This function is for internal use only." (format "Passphrase for %s %s: " key-id (cdr entry)) (format "Passphrase for %s: " key-id))))))) -(defun epg-progress-callback-function (context what char current total - handback) - (message "%s: %d%%/%d%%" what current total)) - -;;;###autoload -(defun epg-configuration () - "Return a list of internal configuration parameters of `epg-gpg-program'." - (let (config type) - (with-temp-buffer - (apply #'call-process epg-gpg-program nil (list t nil) nil - '("--with-colons" "--list-config")) - (goto-char (point-min)) - (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t) - (setq type (intern (match-string 1)) - config (cons (cons type - (if (memq type - '(pubkey cipher digest compress)) - (mapcar #'string-to-number - (delete "" (split-string - (match-string 2) - ";"))) - (match-string 2))) - config)))) - config)) - -;;;###autoload -(defun epg-check-configuration (config) - "Verify that CONFIGURATION is sufficient." - (let ((entry (assq 'version config)) - major minor teeny) - (unless (and entry - (stringp (cdr entry)) - (string-match "\\`\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)" - (cdr entry))) - (error "Undetermined version: %S" entry)) - (setq major (string-to-number (match-string 1 (cdr entry))) - minor (string-to-number (match-string 2 (cdr entry))) - teeny (string-to-number (match-string 3 (cdr entry)))) - (unless (or (> major 1) - (and (= major 1) - (or (> minor 4) - (and (= minor 4) - (>= teeny 3))))) - (error "Unsupported version: %s" (cdr entry))))) +(make-obsolete 'epg-passphrase-callback-function + 'epa-passphrase-callback-function) (defun epg--list-keys-1 (context name mode) - (let ((args (append (list "--with-colons" "--no-greeting" "--batch" + (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)) @@ -1531,6 +1489,11 @@ You can then use `write-region' to write new data into the file." (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))) + ;;;###autoload (defun epg-cancel (context) (if (buffer-live-p (process-buffer (epg-context-process context))) @@ -1546,7 +1509,7 @@ You can then use `write-region' to write new data into the file." ;;;###autoload (defun epg-start-decrypt (context cipher) "Initiate a decrypt operation on CIPHER. -CIPHER is a data object. +CIPHER must be a file data object. If you use this function, you will need to wait for the completion of `epg-gpg-program' by using `epg-wait-for-completion' and call @@ -1557,7 +1520,7 @@ If you are unsure, use synchronous version of this function (error "Not a file")) (epg-context-set-operation context 'decrypt) (epg-context-set-result context nil) - (epg--start context (list "--decrypt" (epg-data-file cipher))) + (epg--start context (list "--decrypt" "--" (epg-data-file cipher))) ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed. (unless (eq (epg-context-protocol context) 'CMS) (epg-wait-for-status context '("BEGIN_DECRYPTION")))) @@ -1610,7 +1573,7 @@ If PLAIN is nil, it returns the result as a string." SIGNATURE and SIGNED-TEXT are a data object if they are specified. For a detached signature, both SIGNATURE and SIGNED-TEXT should be set. -For a normal or a clear text signature, SIGNED-TEXT should be nil. +For a normal or a cleartext signature, SIGNED-TEXT should be nil. If you use this function, you will need to wait for the completion of `epg-gpg-program' by using `epg-wait-for-completion' and call @@ -1622,9 +1585,10 @@ If you are unsure, use synchronous version of this function (if signed-text ;; Detached signature. (if (epg-data-file signed-text) - (epg--start context (list "--verify" (epg-data-file signature) + (epg--start context (list "--verify" "--" (epg-data-file signature) (epg-data-file signed-text))) - (epg--start context (list "--verify" (epg-data-file signature) "-")) + (epg--start context (list "--verify" "--" (epg-data-file signature) + "-")) (if (eq (process-status (epg-context-process context)) 'run) (process-send-string (epg-context-process context) (epg-data-string signed-text))) @@ -1632,8 +1596,8 @@ If you are unsure, use synchronous version of this function (process-send-eof (epg-context-process context)))) ;; Normal (or cleartext) signature. (if (epg-data-file signature) - (epg--start context (list "--verify" (epg-data-file signature))) - (epg--start context (list "--verify")) + (epg--start context (list "--" (epg-data-file signature))) + (epg--start context '("-")) (if (eq (process-status (epg-context-process context)) 'run) (process-send-string (epg-context-process context) (epg-data-string signature))) @@ -1645,8 +1609,10 @@ If you are unsure, use synchronous version of this function "Verify a file SIGNATURE. SIGNED-TEXT and PLAIN are also a file if they are specified. -For a detached signature, both SIGNATURE and SIGNED-TEXT should be string. -For a normal or a clear text signature, SIGNED-TEXT should be nil." +For a detached signature, both SIGNATURE and SIGNED-TEXT should be +string. For a normal or a cleartext signature, SIGNED-TEXT should be +nil. In the latter case, if PLAIN is specified, the plaintext is +stored into the file after successful verification." (unwind-protect (progn (if plain @@ -1660,9 +1626,6 @@ For a normal or a clear text signature, SIGNED-TEXT should be nil." (epg-start-verify context (epg-make-data-from-file signature))) (epg-wait-for-completion context) -; (if (epg-context-result-for context 'error) -; (error "Verify failed: %S" -; (epg-context-result-for context 'error))) (unless plain (epg-read-output context))) (unless plain @@ -1674,8 +1637,10 @@ For a normal or a clear text signature, SIGNED-TEXT should be nil." "Verify a string SIGNATURE. SIGNED-TEXT is a string if it is specified. -For a detached signature, both SIGNATURE and SIGNED-TEXT should be string. -For a normal or a clear text signature, SIGNED-TEXT should be nil." +For a detached signature, both SIGNATURE and SIGNED-TEXT should be +string. For a normal or a cleartext signature, SIGNED-TEXT should be +nil. In the latter case, this function returns the plaintext after +successful verification." (let ((coding-system-for-write 'binary) input-file) (unwind-protect @@ -1691,9 +1656,6 @@ For a normal or a clear text signature, SIGNED-TEXT should be nil." (epg-make-data-from-string signed-text))) (epg-start-verify context (epg-make-data-from-string signature))) (epg-wait-for-completion context) -; (if (epg-context-result-for context 'error) -; (error "Verify failed: %S" -; (epg-context-result-for context 'error))) (epg-read-output context)) (epg-delete-output-file context) (if (and input-file @@ -1708,7 +1670,7 @@ PLAIN is a data object. If optional 3rd argument MODE is t or 'detached, it makes a detached signature. If it is nil or 'normal, it makes a normal signature. -Otherwise, it makes a clear text signature. +Otherwise, it makes a cleartext signature. If you use this function, you will need to wait for the completion of `epg-gpg-program' by using `epg-wait-for-completion' and call @@ -1731,7 +1693,7 @@ If you are unsure, use synchronous version of this function (car (epg-key-sub-key-list signer))))) (epg-context-signers context))) (if (epg-data-file plain) - (list (epg-data-file plain))))) + (list "--" (epg-data-file plain))))) ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed. (unless (eq (epg-context-protocol context) 'CMS) (epg-wait-for-status context '("BEGIN_SIGNING"))) @@ -1748,7 +1710,7 @@ If you are unsure, use synchronous version of this function If SIGNATURE is nil, it returns the result as a string. If optional 3rd argument MODE is t or 'detached, it makes a detached signature. If it is nil or 'normal, it makes a normal signature. -Otherwise, it makes a clear text signature." +Otherwise, it makes a cleartext signature." (unwind-protect (progn (if signature @@ -1773,7 +1735,7 @@ Otherwise, it makes a clear text signature." "Sign a string PLAIN and return the output as string. If optional 3rd argument MODE is t or 'detached, it makes a detached signature. If it is nil or 'normal, it makes a normal signature. -Otherwise, it makes a clear text signature." +Otherwise, it makes a cleartext signature." (unwind-protect (progn (epg-context-set-output-file context @@ -1824,7 +1786,7 @@ If you are unsure, use synchronous version of this function (car (epg-key-sub-key-list recipient))))) recipients)) (if (epg-data-file plain) - (list (epg-data-file plain))))) + (list "--" (epg-data-file plain))))) ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed. (unless (eq (epg-context-protocol context) 'CMS) (if sign @@ -1948,7 +1910,7 @@ If you are unsure, use synchronous version of this function (epg-context-set-operation context 'import-keys) (epg-context-set-result context nil) (epg--start context (if (epg-data-file keys) - (list "--import" (epg-data-file keys)) + (list "--import" "--" (epg-data-file keys)) (list "--import"))) (when (epg-data-string keys) (if (eq (process-status (epg-context-process context)) 'run) @@ -2084,7 +2046,7 @@ If you are unsure, use synchronous version of this function (epg-context-set-operation context 'generate-key) (epg-context-set-result context nil) (if (epg-data-file parameters) - (epg--start context (list "--batch" "--genkey" + (epg--start context (list "--batch" "--genkey" "--" (epg-data-file parameters))) (epg--start context '("--batch" "--genkey")) (if (eq (process-status (epg-context-process context)) 'run)