1 ;;; tinypgp.el --- PGP minor mode, remailing, keyring management
3 ;; This file is not part of Emacs
7 ;; Copyright (C) 1996-2007 Jari Aalto
8 ;; Keywords: extensions
10 ;; Maintainer: Jari Aalto
12 ;; To get information on this program, call M-x tinypgp-version.
13 ;; Look at the code with folding.el
17 ;; This program is free software; you can redistribute it and/or modify it
18 ;; under the terms of the GNU General Public License as published by the Free
19 ;; Software Foundation; either version 2 of the License, or (at your option)
22 ;; This program is distributed in the hope that it will be useful, but
23 ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 ;; This file is not part of Emacs
33 ;; ....................................................... &t-install ...
35 ;; THIS FILE IS UNMAINTAINED - AND NOT WORKING IN ANY WAY
37 ;; Put this file on your Emacs-Lisp load path, add following into your
38 ;; ~/.emacs startup file.
42 ;; or use this; your ~/.emacs loads quicker
44 ;; (autoload 'tinypgp-mode "tinypgp" "" t)
45 ;; (autoload 'turn-on-tinypgp-mode "tinypgp" "" t)
46 ;; (autoload 'turn-off-tinypgp-mode "tinypgp" "" t)
47 ;; (autoload 'tinypgp-install "tinypgp" "" t)
49 ;; (add-hook 'message-mode-hook 'turn-on-tinypgp-mode)
50 ;; (add-hook 'mail-mode-hook 'turn-on-tinypgp-mode)
51 ;; (add-hook 'rmail-mode-hook 'turn-on-tinypgp-mode)
52 ;; (add-hook 'vm-mode-hook 'turn-on-tinypgp-mode)
53 ;; (add-hook 'gnus-startup-hook 'tinypgp-install)
54 ;; (add-hook 'gnus-article-edit-mode 'turn-on-tinypgp-mode)
56 ;; Put your customizations to separate file and add this.
58 ;; (setq tinypgp-:load-hook
59 ;; '(lambda () (require 'rc-tinypgp "~/elisp/rc/emacs-rc-tinypgp")))
61 ;; to automatically sign all your outgoing mail, add this to your .emacs
62 ;; For more personal signing, see manual
64 ;; (add-hook 'mail-send-hook 'tinypgp-sign-mail-auto-mode-on)
65 ;; (add-hook 'message-send-hook 'tinypgp-sign-mail-auto-mode-on)
67 ;; Suggested mode binding, "m" prefix for all minor mode toggles.
68 ;; If these are occupied, then choose some other bindings.
70 ;; ;; note, Mailcrypt's prefix key is C-c / which is also
71 ;; ;; this package's prefix key unless you use the setq below.
73 ;; ;; Personally I like the "-" because it's easier to reach than "/"
76 ;; (setq tinypgp-:mode-prefix-key "\C-c-")
77 ;; (global-set-key "\C-cm-" 'tinypgp-mode)
78 ;; (global-set-key "\C-cm'" 'tinypgp-key-mode)
80 ;; See the end of file for additional examples.
81 ;; If you want to contact maintainer, always use this function
83 ;; M-x tinypgp-submit-bug-report -- send feedback or bug report
88 ;; ..................................................... &t-commentary ...
99 ;;; ......................................................... &require ...
102 (require 'tinylibmail)
103 (require 'mail-utils)
106 (ti::package-use-dynamic-compilation)
112 ** tinypgp.el: Notice dated 2000-02-10
113 THIS FILE IS NOT CURRENTLY MAINTAINED. You can expect that the pgp
114 interface is non-functional and compiling this file gives errors.")
116 (when (and (ti::win32-p)
117 (ti::nil-p (getenv "PGPPATH")))
118 (error "TinyPgp: environment variable PGPPATH not set for secring.*"))
120 (ti::package-package-require-timer)
122 (autoload 'rmail-edit-current-message "rmailedit" t t)
123 (autoload 'rmail-cease-edit "rmailedit" t t)
124 (autoload 'rmail-add-label "rmailkwd")
125 (autoload 'rmail-kill-label "rmailkwd")
127 (defvar vm-frame-per-edit t) ;See vm-vars.el
128 (autoload 'vm-edit-message "vm-edit" t t)
129 (autoload 'vm-edit-message-end "vm-edit" t t)
130 (autoload 'vm-delete-message-labels "vm-undo" t t)
131 (autoload 'vm-add-message-labels "vm-undo" t t)
132 (autoload 'vm-update-summary-and-mode-line "vm" t t)
134 (defvar mail-send-hook nil)
135 (defvar mail-mode-hook nil)
137 (defvar message-mode-hook nil)
138 (autoload 'message-send-and-exit "message")
140 (autoload 'mail-send-and-exit "sendmail")
141 (autoload 'mail-setup "sendmail")
142 (autoload 'mail-do-fcc "sendmail")
144 (autoload 'adelete "assoc")
146 ;; TM mime available at
147 ;; ftp://ftp.jaist.ac.jp:/pub/GNU/elisp/mime/
149 (defvar mime/editor-mode-flag nil)
150 (autoload 'mime-editor/exit "tm-edit")
151 (autoload 'mime-editor/enclose-signed-region "tm-edit")
152 (autoload 'mime-editor/enclose-encrypted-region "tm-edit")
153 (autoload 'mime-viewer/quit "tm-view")
155 (autoload 'timi-mail "tinymail")
157 (autoload 'bbdb-search-simple "bbdb")
158 (autoload 'bbdb-record-getprop "bbdb")
160 (autoload 'gnus-inews-do-gcc "gnus-msg")
161 (autoload 'gnus-summary-edit-article "gnus-sum" t t)
162 (autoload 'gnus-article-edit-done "gnus-art" t t)
164 ;; The expect code is needed only in Pgp 5.x
165 ;; Only if that backend is used the expect.el is loaded.
167 (autoload 'expect-make-info "expect" nil nil)
168 (autoload 'expect-info-process "expect" nil nil 'macro)
169 (autoload 'expect-info-message "expect" nil nil 'macro)
170 (autoload 'expect-info-point "expect" nil nil 'macro)
171 (autoload 'expect-info-set-point "expect" nil nil 'macro)
172 (autoload 'expect-info-sentinels "expect" nil nil 'macro)
173 (autoload 'expect-info-set-sentinels "expect" nil nil 'macro)
174 (autoload 'expect-info-timer "expect" nil nil 'macro)
175 (autoload 'expect-info-set-timer "expect" nil nil 'macro)
176 (autoload 'expect-info-queries "expect" nil nil 'macro)
177 (autoload 'expect-info-set-queries "expect" nil nil 'macro)
178 (autoload 'expect-find-info "expect" nil nil 'macro)
179 (autoload 'with-expect "expect" nil nil 'macro)
180 (autoload 'expect-start-process "expect" nil nil)
181 (autoload 'with-expect-asynchronous "expect" nil nil 'macro)
182 (autoload 'expect "expect" nil nil 'macro)
183 (autoload 'expect-cond "expect" nil nil 'macro)
184 (autoload 'expect-exit "expect" nil nil 'macro)
185 (autoload 'expect-send "expect" nil nil 'macro)
186 (autoload 'expect-setup "expect" nil nil)
187 (autoload 'expect-shutdown "expect" nil nil)
188 (autoload 'expect-kill "expect" nil nil)
189 (autoload 'expect-wait "expect" nil nil)
190 (autoload 'expect-1 "expect" nil nil)
191 (autoload 'expect-exit-1 "expect" nil nil)
192 (autoload 'expect-filter "expect" nil nil)
193 (autoload 'expect-sentinel "expect" nil nil)
194 (autoload 'expect-find-event "expect" nil nil)
195 (autoload 'expect-setup-timer "expect" nil nil)
196 (autoload 'expect-cancel-timer "expect" nil nil)
198 ;; When file is byte compiled, the expand-file-name might eventually
199 ;; call this function, so let emacs know where it is.
201 (autoload 'ange-ftp-real-expand-file-name "ange-ftp" t t))
203 ;;; ......................................................... &v-group ...
205 (defgroup TinyPgp nil
206 "Emacs PGP and Remailer interface.
208 TinyPgp is intended to be a 2nd generation Emacs PGP interface
209 and it supports all major pgp commands from inside
210 emacs. Remailing and anonymous account handling in different
211 servers is included."
214 :tag "Keyserver home"
215 "http://geronimo.uit.no/cc/tjenester/PGP/servruit.eng.html")
218 :tag "Pgp mailing list"
219 "http://pgp.rivertown.net/")
222 :tag "Norway's keyserver"
223 "http://www.ifi.uio.no/pgp/")
226 :tag "Remailer Faq (Galactus)"
227 "http://www.stack.urc.tue.nl/~galactus/remailers/")
230 :tag "PGP faq alt.security.pgp"
231 "ftp://ftp.prairienet.org/pub/providers/pgp/pgpfaq.txt")
234 :tag "X-Pgp header specififacion"
235 "ftp://cs.uta.fi/pub/ssjaaa/pgp-xhd.html")
238 :tag "TinyPgp Manu page"
239 "ftp://cs.uta.fi/pub/ssjaaa/tinypgp.html")
244 ;;; .................................................... &v-group-mode ...
246 (defgroup tinypgp-mode-definitions nil
247 "Mode names, menu names and prefix key settings."
251 (defgroup tinypgp-mode nil
252 "Options that directly address basic PGP commands in minor modes."
256 (defgroup tinypgp-header nil
257 "Options that deal with Email message headers."
261 (defgroup tinypgp-file nil
262 "Files used when communicating with PGP. You shouldn't rename these.
263 Do not add any extension to files, because PGP itself may append extension
264 .asc or .pgp or .bak. change only directory location.
266 When you load the package first time the directory name is initialized
267 from `tinypgp-:file-directory' or if it is nil a wild guess will be taken
268 See function documentation `tinypgp-path' for details.
273 (defgroup tinypgp-hook nil
274 "Variables where you can put your own functions."
278 (defgroup tinypgp-function nil
279 "Variables where you can put your own functions."
283 (defgroup tinypgp-pgp nil
284 "Options that relate to PGP executable and shell envinronment."
288 ;;; .................................................... &v-group-misc ...
290 (defgroup tinypgp-interface nil
291 "Variables to configure connections to outside world (ftp, http, email)"
295 (defgroup tinypgp-remail nil
296 "Remailer interface settings."
300 (defgroup tinypgp-remail-hook nil
301 "Remailer interface hooks."
303 :group 'tinypgp-remail)
305 (defgroup tinypgp-nymserver nil
306 "Anonymous service (paid) anon.nymserver.com settings.
307 Similar to anon.penet.fi, which has been closed permanently."
310 :tag "Nymserver main page"
311 "http://www.nymserver.com")
314 :tag "Nymserver html doc (a bit old)"
315 "ftp://cs.uta.fi/pub/ssjaaa/nymserv.html")
320 (defgroup tinypgp-newnym nil
321 "Anonymous PGP service newnym type remailers."
325 "http://www.stack.nl/~galactus/remailers/nym.html")
331 ;;{{{ setup: predefined functions
333 (defcustom tinypgp-:file-directory nil
334 "*Directory where to store temporary files. Must not be public; like /tmp/.
335 You should store files under your private directory. If this variable
336 is nil; then `tinypgp-path' guesses the right location for you. See function
337 documentations for more."
339 :group 'tinypgp-file)
341 ;;; ----------------------------------------------------------------------
342 ;;; Define this function becore it is used in variables.
347 (defun tinypgp-expand-file-name (file &optional type)
348 "Expand file under correct OS. TYPE overrides: 'unix 'win32."
353 (ti::file-name-forward-slashes-cygwin (expand-file-name file))))
357 (ti::file-name-backward-slashes (expand-file-name file))))
359 (expand-file-name file))))
361 (defun tinypgp-path (file &optional try-paths)
362 "Add path to FILE with TRY-PATHS. See also `tinypgp-:file-directory'.
365 `tinypgp-:file-directory'
370 If FILE already includes path, do nothing."
373 (error "FILE is missing."))
375 (if (string-match "[~/]" (substring file 0 1))
376 (tinypgp-expand-file-name file) ;Already had path
377 (dolist (try (or try-paths
378 (list tinypgp-:file-directory
383 (setq try (ti::string-verify-ends try "/"))
384 (when (file-directory-p try)
387 (if (not (file-exists-p path))
388 (error "Can't find path %s" path))
389 (tinypgp-expand-file-name (concat path file))))))
391 ;;; ----------------------------------------------------------------------
396 (defun tinypgp-binary-get-version (&optional ret-type call-shell)
397 "Return version number of current pgp.
401 RET-TYPE How the information is returned.
402 If this is nil then return STRING.
403 If this is non-nil then return 'us (2.6.2) or
404 'international (2.6.3i)
406 CALL-SHELL if nil, then look variable `tinypgp-:pgp-binary'.
407 If there is no variable or it is not string, then
408 call shell to find out pgp exe's version number
415 (if (and (null call-shell)
416 (boundp 'tinypgp-:pgp-binary)
417 (setq ret (get 'tinypgp-:pgp-binary 'version)))
419 (setq ret (ti::mail-pgp-exe-version-string)))
421 (if (and ret-type (stringp ret))
422 (if (string-match "i" ret)
423 (setq ret 'international)
430 ;;; ...................................................... &vp-version ...
431 ;;; the version information is needed in the variable definitions later.
434 (defconst tinypgp-:version-id
435 "$Id: tinypgp.el,v 2.57 2007/05/07 10:50:10 jaalto Exp $"
436 "Latest modification time and version number.")
437 (defun tinypgp-version-number ()
438 "Return version number as string."
439 (ti::string-match "\\([0-9]+\\.[0-9]+\\)" 1 tinypgp-:version-id)))
441 ;;; ----------------------------------------------------------------------
444 (defun tinypgp-version (&optional arg)
445 "Show version information. ARG instruct to print message in echo area only."
447 (ti::package-version-info "tinypgp.el" arg))
449 ;;; ----------------------------------------------------------------------
452 (defun tinypgp-version-message ()
455 (message tinypgp-:version-id))
460 ;; ......................................................... &v-hooks ...
462 (defcustom tinypgp-:load-hook nil
463 "*Hook that is run when package is loaded."
465 :group 'tinypgp-hook)
467 (defcustom tinypgp-:mode-hook nil
468 "*Hook run when minor mode is turned on."
470 :group 'tinypgp-hook)
472 (defcustom tinypgp-:key-mode-hook nil
473 "*Hook run when minor mode is turned on."
475 :group 'tinypgp-hook)
477 (defcustom tinypgp-:summary-mode-hook nil
478 "*Hook run when minor mode is turned on."
480 :group 'tinypgp-hook)
482 (defcustom tinypgp-:mail-send-hook-list
485 mh-before-send-letter-hook)
486 "*List of hooks that are called by Mail agents before sending mail."
488 :group 'tinypgp-hook)
490 (defcustom tinypgp-:turn-on-hook-list
495 gnus-article-mode-hook ; When selecting the article.
496 gnus-article-edit-mode-hook
497 news-reply-mode-hook ; 'f' key reply, GNUS 4 only
500 "*List of hooks where to install pgp mode.
501 Call `add-hook' only inside `tinypgp-:load-hook', because the defvar
502 installs many default hooks."
504 :group 'tinypgp-hook)
506 (defcustom tinypgp-:sig-from-header-hook nil
507 "*Hook run at the end of `tinypgp-pgp-move-sig-from-header' function.
508 If there is no PGP header, hook is not called."
510 :group 'tinypgp-hook)
512 (defcustom tinypgp-:sig-to-header-hook nil
513 "*Hook run at the end of `tinypgp-signature-move-to-header function' function.
514 If there is no PGP header, hook is not called."
516 :group 'tinypgp-hook)
518 (defcustom tinypgp-:sign-loose-info-hook nil
519 "*Hook run when the `tinypgp-sign-loose-info' function has completed."
521 :group 'tinypgp-hook)
523 (defcustom tinypgp-:define-keys-hook nil
524 "*List of functions to define all keys and menus."
526 :group 'tinypgp-hook)
528 (defcustom tinypgp-:key-mode-define-keys-hook nil
529 "*List of functions to define all keys and menus."
531 :group 'tinypgp-hook)
533 (defcustom tinypgp-:summary-mode-define-keys-hook nil
534 "*List of functions to define all keys and menus."
536 :group 'tinypgp-hook)
538 (defcustom tinypgp-:newnym-mode-define-keys-hook nil
539 "*List of functions to define all keys and menus."
541 :group 'tinypgp-hook)
543 (defvar tinypgp-:do-command-region-before-hook nil
544 "Hook run in tmp buffer where containing data for pgp.
545 The PGP shell command is at this point stored into variable
546 `tinypgp-:last-pgp-exe-command'.
550 If function in this hook returns non-nil, the rest of the functions are
557 (defvar tinypgp-:do-command-region-after-hook nil
558 "Hook run in tmp buffer after the PGP shell command has completed.
562 If function in this hook returns non-nil, the rest of the functions are
568 (defvar tinypgp-:cmd-macro-before-hook nil
569 "Hook which run before the pgp sequence initiates in current buffer.
570 See function `tinypgp-cmd-macro' for arguments.
574 First function that returns non-nil terminates running the
575 rest of the functions. User functions must be at the end of hook
576 (use add-hook's 3rd parameter)
580 cmd user msg string")
582 (defvar tinypgp-:cmd-macro-after-hook nil
583 "Hook which run after the pgp sequence has been completed.
584 See function `tinypgp-cmd-macro' for arguments.
588 First function that returns non-nil terminates running the
589 rest of the functions. User functions must be at the end of hook
590 (use add-hook's 3rd 'append parameter)
598 if the CMD is 'cancel, then the function in this hook must not
599 do any modification, but only restore any state that may have
600 been opened in the *before* hook. (Eg. closing rmail-edit-mode).
601 The 'cancel indicates that `error' command is about to be called soon.")
603 (defcustom tinypgp-:verify-before-hook nil
604 "*Hook run before verify function is called.
605 Every function in the hook is called with 2 args: region-beg region-end
606 The function should return non-nil if it doesn't want to allow other
607 functions in the hook to continue."
609 :group 'tinypgp-hook)
611 (defcustom tinypgp-:verify-after-hook nil
612 "*Hook run when verify function is done.
616 First function that returns non-nil terminates running the
617 rest of the functions.
621 region-beg region-end verify-string-ret-val."
623 :group 'tinypgp-hook)
625 (defcustom tinypgp-:read-email-after-hook '(tinypgp-email-substitution-default)
626 "*This hook is called after email address list has been read.
627 The list is used e.g. for decrypting the message to multiple
630 It may be desiradble to change some email address to something else;
631 supposes that you're sending encrypted message to foo2@site.com, but
632 you have key from him only that refers to email foo1@site.com. If you
633 try to encrypt according to \"To: foo2@site.com\" you get PGP error,
634 because there is no such key in the active keyring. That's why
635 you modify list and change the foo2@site.com to foo1@site.com.
641 Function should return:
643 list ,original list if no changes.
646 :group 'tinypgp-hook)
648 (defcustom tinypgp-:insert-file-sign-base64-hook
649 'ti::process-tar-zip-view-maybe-command
650 "*Hook to run before the file is inserted to current point.
651 There is default function to this hook for tar/zip files, which inserts
652 the file listing into the buffer.
656 If some function return non-nil the rest of the functions are not run.
657 The buffer is temporary buffer for inserted data where hook is run,
658 point sits at `point-min' and buffer holds the base64 signed file.
664 :group 'tinypgp-hook)
666 (defcustom tinypgp-:auto-action-before-hook nil
667 "*Hook run before `tinypgp-auto-action' processes anything."
669 :group 'tinypgp-hook)
671 (defcustom tinypgp-:auto-action-defeat-hook '(tinypgp-auto-action-defeat-p)
672 "*If any the functions return non-nil, the auto action is defeated.
673 Called from `tinypgp-auto-action'. The default function
674 `tinypgp-auto-action-defeat-p' inhibits processing MIME messages."
676 :group 'tinypgp-hook)
678 ;;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. others . .
680 (defcustom tinypgp-:finger-discard-email-hook
681 '(tinypgp-finger-discard-by-regexp)
682 "*This hook is called before finger spawned to fetch public key.
683 You should discard any email addresses that refer to your account.
686 `tinypgp-finger-discard-by-regexp'
687 --> uses variable `tinypgp-:finger-discard-by-regexp'
689 Function call arguments:
691 string or list of strings '(email email ..)
693 Function should return:
695 modified list or string
696 nil ,do not finger anything.
698 Example code, which is also the idea of default function:
700 (add-hook 'tinypgp-:finger-discard-email-hook
701 'my-tinypgp-finger-discard-email)
703 (setq my-:tinypgp-me \"me.surname@\\|myOtherAccount@foo\\|3rd@bix.com\")
705 (defun my-tinypgp-finger-discard-email (string-or-list)
706 ;; Discard addresses that point to me
712 (if (not (string-match my-:tinypgp-me x))
714 ;; convert string to list if needed.
715 (ti::list-make string-or-list))
718 :group 'tinypgp-hook)
720 (defcustom tinypgp-:find-by-guess-hook nil
721 "*Functions called to find public key and keyring.
725 First function that return non-nil terminates calling other
728 PLEASE THINK CAREFULLY WHICH IS THE FIND ORDER, if you
729 use your own function; use add-hook's 3rd parameter to
730 add your methods last in the hook.
732 Function call arguments:
734 string usually email address(key id)
736 Function should return:
738 string (filename) keyring where the key is available
741 :group 'tinypgp-hook)
743 (defcustom tinypgp-:auto-action-encrypt-ok-hook nil
744 "*Hook to determine if sending auto encrypted mail is ok.
745 This hook is called only if some recipent matches
746 `tinypgp-:auto-action-encrypt-regexp'
748 Function call arguments:
751 list list of To and Cc recipients.
753 Function should return:
755 boolean non-nil says that encrypting is ok"
757 :group 'tinypgp-hook)
759 ;;; ...................................................... &v-function ...
760 ;;; These are not in defcustom. Experts user know what to look
761 ;;; for from source code if they need to change these.
763 (defcustom tinypgp-:encrypt-after-function 'tinypgp-encrypt-add-remailer-tag
764 "Function run after the buffer is encrypted.
765 The default function `tinypgp-encrypt-add-remailer-tag' adds the
766 'Encrypted: PGP' tag to the beginning of encryopted block. It is needed
767 when the message is sent to remailer.
769 If you put your function inside this, be sure that you supply that tag
770 if you're writing message to remailer.
775 -----BEGIN PGP MESSAGE-----
778 Function call arguments:
781 Function should return:
787 at the beginnning of message"
791 (defcustom tinypgp-:filter-email-function 'tinypgp-mail-abbrevs-filter
792 "*Function to filter out unwanted mailabbrevs.
793 When making the completion list of email address out of the
794 mail-abbrev table, the obarray may contain some _old_, unwanted, or
795 invalid email addresses. Perhaps you just don't want to have all
796 email addresses for PGP encryption: that's what this filter
801 list list of email addresses.
805 list list of valid email addresses.")
809 (defcustom tinypgp-:verify-message-function nil
810 "*Function called to print the verify status.
811 This function is called with one argument: STRING, when verify status
812 is displayed. For example; sometimes PGP could display
814 Good signature from user \"0f00bc000\".
816 Which isn't quite enlightling. By supplying your own function you
817 can check cases like this and convert the message into something
822 (setq tinypgp-:verify-message-function 'my-tinypgp-verify-message)
824 (defun my-tinypgp-verify-message (str)
825 \"Display more meaningful message\"
826 (let* ((pfx \"Good signature from: \"))
828 ((string-match \"0f00bc095\" str)
829 (setq str (concat pfx \"Foo Bar\"))))
834 (defcustom tinypgp-:pgp-encrypted-p-function 'tinypgp-pgp-encrypted-p-default
835 "*Function to return PGP data type for message.
836 When you call `tinypgp-decrypt-mail' interactively, the
837 PGP type is asked. However, you can automate the type checking if you
838 know the type of PGP data.
840 The default function `tinypgp-pgp-encrypted-p-default' check the CTB bits
841 and return correct type.
847 Function should return:
849 string 'pgp', 'base64', 'conventional' or nil"
853 (defcustom tinypgp-:pgp-decrypt-arg-function
854 'tinypgp-decrypt-arg-function
855 "*How to Honour variable `tinypgp-:decrypt-arg-interpretation'.
856 The default function `tinypgp-decrypt-arg-function' treats writable and read
857 only buffers differently."
861 (defcustom tinypgp-:pgp-command-compose-function nil
862 "*Hook to run after pgp executable command has been composed.
863 If this hook doesn't modify the command, it should return CMD untouched.
875 (defcustom tinypgp-:secring-crypt-function 'tinypgp-crypt-do-with-pgp
876 "*Function to crypt the secring.
878 Default values available:
880 'tinypgp-crypt-do-with-pgp
881 'tinypgp-crypt-do-with-crypt ;; not recommended
887 password TO crypted by using this
891 Function should detect by looking FROM file if it is already
892 in encrypted format and convert it to back to regular file.
893 Kinda flip-flop. It should also signal error and terminate if
894 wrong password were used for opening the file (that is, if it
895 is possible to determine that condition)"
899 (defcustom tinypgp-:encrypt-with-function nil
900 "*When message is encrypted, this function return additional keyIds.
902 For example if you want to encrypt all messages to yourself but only
903 when they are not sent to remailers, then you could use this setup.
904 All messages would be then readable by you also.
906 (setq tinypgp-:encrypt-with-function 'my-tinypgp-encrypt-with)
908 (defun my-tinypgp-encrypt-with ()
909 (unless (ti::re-search-check \"remail\")
910 ;; Or your explicit PGP keyID if the name is not unique enough
911 (list tinypgp-:user-primary)))
919 list of additional keyIds (strings) used in encryption or nil."
923 ;;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. remailer . .
925 (defcustom tinypgp-:r-post-before-hook nil
926 "*Hook run before post is converted into Anon format."
928 :group 'tinypgp-remail-hook)
930 (defcustom tinypgp-:r-post-after-hook nil
931 "*Hook run after post is converted into Anon format."
933 :group 'tinypgp-remail-hook)
935 (defcustom tinypgp-:nymserver-post-hook nil
936 "*Hook run after `tinypgp-nymserver-post' function finishes."
938 :group 'tinypgp-nymserver)
940 (defcustom tinypgp-:r-init-hook nil
941 "*Hook run after the remailer support has been initialised.
942 See `tinypgp-r-init'."
944 :group 'tinypgp-remail-hook)
946 (defcustom tinypgp-:r-get-list-hook nil
947 "*Hook run after the Levien list file is inserted into temporary buffer.
948 This is your chance to check and modify the Remailer Levien list.
949 See `tinypgp-r-get-list'."
951 :group 'tinypgp-remail-hook)
954 ;;{{{ setup: mode variables
956 ;;; .......................................................... &v-mode ...
958 (defvar tinypgp-mode nil
959 "Minor mode variable.")
961 (make-variable-buffer-local 'tinypgp-mode)
963 (defvar tinypgp-:mode-name nil
965 This is not a user variable because the string is modified dynamically.")
966 (make-variable-buffer-local 'tinypgp-:mode-name)
968 (defcustom tinypgp-:mode-menu-name "TPgp"
969 "*Menu name for pgp mode."
971 :group 'tinypgp-mode-definitions)
973 (defvar tinypgp-:mode-map nil
976 (defvar tinypgp-:mode-menu nil
979 (defcustom tinypgp-:mode-prefix-key "\C-c/"
981 :type '(string :tag "Key sequence")
982 :group 'tinypgp-mode-definitions)
984 ;;; ................................................ &v-key-management ...
986 (defvar tinypgp-key-mode nil
987 "Minor mode variable.")
988 (make-variable-buffer-local 'tinypgp-key-mode)
990 (defconst tinypgp-:key-mode-name nil
992 This is not a user variable because the string is modified dynamically.")
993 (make-variable-buffer-local 'tinypgp-:key-mode-name)
995 (defvar tinypgp-:key-mode-map nil
998 (defvar tinypgp-:key-mode-menu nil
1001 (defcustom tinypgp-:key-mode-menu-name "TPk"
1002 "*Menu name for pgp key mode."
1004 :group 'tinypgp-mode-definitions)
1006 (defcustom tinypgp-:key-mode-prefix-key "\C-c'"
1009 :group 'tinypgp-mode-definitions)
1011 ;;; .................................................. &v-summary-mode ...
1013 (defvar tinypgp-summary-mode nil
1014 "Minor mode variable.")
1015 (make-variable-buffer-local 'tinypgp-summary-mode)
1017 (defconst tinypgp-:summary-mode-name nil
1018 "Minor mode name. Changed dynamically.")
1019 (make-variable-buffer-local 'tinypgp-:summary-mode-name)
1021 (defvar tinypgp-:summary-mode-map nil
1022 "Minor mode map. \\[tinypgp-:summary-mode-map].")
1024 (defvar tinypgp-:summary-mode-menu nil
1027 (defcustom tinypgp-:summary-mode-menu-name "TPsum"
1028 "*Menu name for mode."
1030 :group 'tinypgp-mode-definitions)
1032 (defcustom tinypgp-:summary-mode-prefix-key tinypgp-:mode-prefix-key
1035 :group 'tinypgp-mode-definitions)
1037 ;;; ................................................... &v-newnym-mode ...
1039 (defvar tinypgp-newnym-mode nil
1040 "Minor mode variable.")
1041 (make-variable-buffer-local 'tinypgp-newnym-mode)
1043 (defvar tinypgp-:newnym-mode-name " Nym"
1045 (make-variable-buffer-local 'tinypgp-:newnym-mode-name)
1047 (defvar tinypgp-:newnym-mode-map nil
1048 "Minor mode map. \\[tinypgp-:newnym-mode-map].")
1050 (defvar tinypgp-:newnym-mode-menu nil
1053 (defcustom tinypgp-:newnym-mode-menu-name "TPnym"
1054 "*Menu name for mode."
1056 :group 'tinypgp-mode-definitions)
1058 ;; escreen.el uses same prefix; so change this if you use that package.
1059 ;; Also the (enable-flow-control) takes over C-\ key.
1061 (defcustom tinypgp-:newnym-mode-prefix-key "\C-\\"
1064 :group 'tinypgp-mode-definitions)
1066 ;;; ................................................. &v-mode-remailer ...
1068 ;; In HP the keys "/." are next to each other on the lower right
1071 (defcustom tinypgp-:mode-prefix-key-remailer "\C-c/.r"
1072 "*Key map prefix for remailer commands."
1074 :group 'tinypgp-mode-definitions)
1076 (defcustom tinypgp-:mode-prefix-key-newnym "\C-c/.n"
1077 "*Keymap prefix for newnym type anon server commands.
1078 The default prefix key is C - c / . n; where p refers to (n)ewnym
1079 account; similar to famous nym.alias.net"
1081 :group 'tinypgp-mode-definitions)
1083 (defcustom tinypgp-:mode-prefix-key-nymserver "\C-c/.y"
1084 "*Keymap prefix for nymserver type anon server commands.
1085 The default prefix key is C - c / . y; where p refers to n(y)mserver
1086 account; similar to ex-anon.penet.fi.
1088 As of writing this, the only active remailer that resembles 'penet' is
1091 :group 'tinypgp-mode-definitions)
1094 ;;{{{ setup: user config
1096 ;;; ........................................................ &v-config ...
1097 ;;; PGP executable settings
1099 (defvar tinypgp-:pgp-binary-interactive-option
1102 '(format "+comment=\"Processed by Emacs TinyPgp %s\""
1103 (tinypgp-version-number)))
1104 "*Extra encrypt option passed to PGP; use only \"+comment=\\\"\\\"\".
1105 This variable is EVALUATED; so it can contain lisp FORM.
1106 Must be nil in PCP platform.")
1108 ;; See tinypgp-binary-header-field-fix
1110 (put 'tinypgp-:pgp-binary-interactive-option
1112 (format "Processed by %sEmacs TinyPgp %s"
1113 (if (ti::win32-p) "WinNT " "")
1114 (tinypgp-version-number)))
1116 (put 'tinypgp-:pgp-binary-interactive-option 'original
1117 tinypgp-:pgp-binary-interactive-option)
1119 ;;; ....................................................... &v-pgp-exe ...
1121 ;; This variable also has property
1122 ;; 'crypt The absolute path for 'crypt'.
1124 ;; In variable tinypgp-:hash you find following properties
1125 ;; Note: this is not in the hash table itself, but in symbol's plist,
1126 ;; because hash table is resetted in regular intervals.
1129 ;; 'secring The whole secring.pgp
1131 (defvar tinypgp-:pgp-binary nil
1132 "Property list of PGP executables.
1133 The value of variable is always nil (not used). Property list values are:
1135 'version string, PGP version number
1137 'ppg2 symbol 'ok if found
1138 'ppg2-type symbol 'unix or 'win32
1140 'pgp5 symbol 'ok if found
1141 'ppg5-type symbol 'unix or 'win32
1144 'gpg-type symbol 'unix or 'win32
1146 'pgp string, pgp 2.6.x executable path
1148 'pgp{koves} string, pgp 5 executable paths
1150 'pgp-now symbol 'pgp2, 'pgp5, `gpg;
1151 What pgp version is used currently
1152 'pgp-now-type 'unix 'win32
1153 What kind of pgp version is in use: Unix/Cygwin or Win32")
1155 (defconst tinypgp-:pgp-binary-support-table
1156 '( ;; will generate a file with the specified filename, containing <nnn>
1157 ;; random bytes, to allow other programs to benefit from PGP's
1158 ;; strong random-number generator.
1160 (random "+makerandom=")
1162 ;; This prints trust parameters
1165 "Support table of undocumented commands for your PGP binary.
1166 These commands are usually available in 2.6.3, but they just aren't
1167 include in PGP documentation.")
1169 (defcustom tinypgp-:pgp-binary-charset "noconv"
1170 "*See PGP documentation.
1171 If you change this value, you have to reload tinypgp.el.
1173 Possible choices according to Pgp 2.6.3ia manual:
1175 noconv No conversion [prefer this]
1177 koi8 Eastern countries e.g. Russia
1178 cp850 ms-dos users in Europe"
1185 :group 'tinypgp-pgp)
1187 (defvar tinypgp-:pgp-sh-exe
1191 (or (setq path-win32 (executable-find "cmdproxy.exe"))
1193 TinyPgp: `tinypgp-:pgp-sh-exe' - cmdproxy.exe not in exec-path?")))
1195 (when (and (null (setq path-unix (executable-find "sh")))
1196 (not (ti::win32-p)))
1198 TinyPgp: `tinypgp-:pgp-sh-exe' - /bin/sh not in exec-path?"))
1200 (list 'unix (or path-unix "/bin/sh")
1201 (list 'win32 (or path-win32 "cmdproxy.exe")))))
1203 "*Shell executables. Use absolute path names for greater speed.
1205 '((win32 \"cmdproxy.exe\")
1206 (unix \"/bin/sh\"))")
1208 ;;; ......................................................... &v-files ...
1210 ;;; Please do not add exension to these files!
1211 ;;; --> PGP itself adds extension if it needs to create any additional files.
1213 (defcustom tinypgp-:file-source
1216 (tinypgp-path "pgp-src"))
1217 "*Source file fed to PGP. Region is written to this file.
1218 Must reside in C:/ root directory in PC platform due to total command
1219 length restrictions."
1221 :group 'tinypgp-file)
1223 (defcustom tinypgp-:file-output
1226 (tinypgp-path "pgp-out"))
1227 "*Output file produced by PGP when it gets `tinypgp-:file-source'.
1228 Must reside in C:/ root directory in PC platform."
1230 :group 'tinypgp-file)
1232 (defcustom tinypgp-:file-password
1235 (tinypgp-path "pgp-pwd"))
1236 "*File where to save the password only during calling PGP.
1237 The file is immediately deleted after PGP has finished.
1238 Must reside in C:/ root directory in PC platform due to total command
1239 length restrictions."
1241 :group 'tinypgp-file)
1243 (defcustom tinypgp-:file-user-list
1246 (tinypgp-path "pgp-lst"))
1247 "*File where to store user list. (e.g. when encrypting).
1248 Must reside in C:/ root directory in PC platform due to total command
1249 length restrictions."
1251 :group 'tinypgp-file)
1253 (defcustom tinypgp-:file-key-cache (tinypgp-path "tinypgp-cache")
1254 "*File where to store key cache."
1256 :group 'tinypgp-file)
1258 (defcustom tinypgp-:file-secring
1260 (cons 'pgp2 (tinypgp-path "secring.pgp"))
1261 (cons 'pgp5 (tinypgp-path "secring.skr"))
1262 (cons 'gpg (tinypgp-path "secring.gpg"
1264 (getenv "GNUPGHOME")
1266 "*Secring path. If you change this you must reload TinyPgp.
1268 '((pgp2 . \"/absolute/path/secring.pgp\")
1269 (pgp5 . \"/absolute/path/secring.skr\"))"
1271 :group 'tinypgp-file)
1273 (defcustom tinypgp-:file-secring-encrypted (tinypgp-path "secring.enc")
1274 "*Where to store the encrypted secring."
1276 :group 'tinypgp-file)
1278 ;;; .......................................................... &v-user ...
1280 (defcustom tinypgp-:user-primary
1281 (or (car-safe (ti::mail-email-from-string user-mail-address))
1284 TinyPgp: tinypgp-:user-primary, Set user-mail-address to foo@site.com: '%s'"
1286 "*Variable is used when you decrypt mail in buffer.
1288 o whatever your logical user id may
1289 be currently, it is changed to this
1291 After decrypt has finished, the previous user identity is restored.
1292 This should provide smooth processing of incoming encrypted messages,
1293 while you may be doing something else."
1295 :group 'tinypgp-mode)
1297 (defcustom tinypgp-:user-identity-table nil
1298 "*When decrypting, this table is consulted for right active pgp user.
1302 '((\"key-hex-id\" \"key-id\")
1305 The encrypted PGP ascii armor is examined and if the found
1306 hex key-id match, then switch to key-i (usually mode descriptive
1307 email string) as a current PGP user.
1311 (setq tinypgp-:user-identity-table
1313 ;; My known public keyid firtsname.surname@site.com
1314 (\"12345670\" \"firsname.surname\")
1316 ;; If I receive pgp message from nymserver, then use my
1317 ;; nymserver user id
1319 (\"12345678\" \"an12345@anon.nymserver\")))"
1322 (string :tag "Key-id (8 hex)"
1323 (string :tag "Clear text User id"))))
1324 :group 'tinypgp-mode)
1326 ;;; .......................................................... &v-misc ...
1328 (defcustom tinypgp-:register ?/
1329 "*Register used to store the contents of PGP output."
1331 :group 'tinypgp-mode)
1333 (defcustom tinypgp-:password-protection
1337 "*If this variable is non-nil, use extra caution to protect the password.
1338 Set this to t only if you're in UNIX system where
1339 the processes commands can be seen by running 'ps'. This variable
1340 prohibits using PGP's -z flag and forces using file descriptors
1341 which cannot be snooped so easily.
1343 Set the variable to t only if your PGP understands env variable PGPPASSFD
1344 and that it can use many file descriptors.
1346 In default WinNT this variable must be nil."
1348 :group 'tinypgp-pgp)
1350 (defcustom tinypgp-:password-keep-time (* 15 60) ;; 15 minutes default
1351 "*How many seconds to keep password in memory before forgetting it.
1352 Set to nil, if you want to be asked password every time when you sign
1355 :group 'tinypgp-mode)
1357 (defcustom tinypgp-:decrypt-arg-interpretation nil
1358 "*How to interpret prefix argument to `tinypgp-decrypt-mail' (interacive only).
1359 This variable is used _only_ if function is called interactively.
1362 then meaning of the prefix arg passed to function
1363 `tinypgp-decrypt-mail' is reversed.
1366 As in non-nil but also the the content of the decrypted message is
1367 displayed in a separate buffer"
1369 :group 'tinypgp-mode)
1371 (defcustom tinypgp-:finger-discard-by-regexp (user-login-name)
1372 "*When fingering email addresses, discard those that match regexp.
1373 Please look at variable `tinypgp-:finger-discard-email-hook' for more."
1375 :group 'tinypgp-mode)
1377 ;;; ........................................................ &v-labels ...
1379 (defcustom tinypgp-:label-table
1385 "*Labels to attach to messages.
1386 There are two ways to use labels in your mail agent. Here is one style,
1387 where a general label is attached first and then the short flags. The advantage
1388 of this is that you can summarise a) all 'pgp' labels b) summarise
1389 'pgp' labels _and_ decrypted messages 'd'. See TinyRmail.el That adds
1390 new command to RMAIL to do this kind of label _and_ operation.
1392 pgp,v+ PGP message, verified
1393 pgp,v+,d PGP message, verified and decrypted
1394 pgp,v-,d PGP message, verify failed and decrypted
1396 Or you could leave out the general label out and mark each pgp actions with
1402 Choose your style, but remember that shortest labels are the best.
1405 '((v (OK-VERIFY-LABEL NOK-VERIFY-LABEL)
1409 (pgp PGP-GENERAL-LABEL) << can be empty string or nil
1412 (list (const v :tag "verify") (list string string))
1413 (list (const s :tag "sign") string)
1414 (list (const d :tag "decrypt") string)
1415 (list (const e :tag "encrypt") string)
1416 (list (const pgp :tag "pgp") string))
1419 ;;; ................................................... &v-tables-misc ...
1421 (defcustom tinypgp-:pubring-table
1422 (let* ((file2 (tinypgp-path "pubring.pgp"))
1423 (file5 (tinypgp-path "pubring.pkr"))
1424 (gpg (tinypgp-path "pubring.gpg"
1426 (getenv "GNUPGHOME")
1428 (if (and (not (file-exists-p file2))
1429 (not (file-exists-p file5))
1430 (not (file-exists-p gpg)))
1432 TinyPgp: tinypgp-:pubring-table, Please configure, cannot auto-install.
1433 File pubring.pgp or pubring.pkr couldn't be found. Check PGPPATH."))
1436 (list 'pgp2 (if file2
1437 (list (list "default" file2 "-"))))
1438 (list 'pgp5 (if file5
1439 (list (list "default" file5 "-"))))
1441 (list (list "default" gpg "-"))))))
1442 "*Pubrings, alias names and mode line indicators.
1446 Possible pubrings user can select. Make sure your primary
1447 pubring is first in the list and that the others come
1448 in order of importance. The last one is least unimportant
1449 keyring. When searching for key, this is the search order.
1453 Your primary pubring must be first.
1455 Your merged keyring must be last. When you're encrypting to
1456 multiple people, pgp needs one big pubring which contains
1457 all keys for those people that your encrypting the message. When
1458 program sees that you have multiple CC, BCC or To recipients,
1459 it automatically sets the active pubring to the last one in this
1464 Please use some common convention when creating new pubring, e.g.
1465 use name \"pr-\" to denote pubring and add the descriptor after it.
1466 pr-elisp.pgp ;; my pgp keys for my elisp mates
1467 pr-news.pgp ;; occasional users from newsgroups
1468 pr-pgpnews.pgp ;; the pgp newsgroup people pubring
1470 pr-temp.pgp ;; temporary storage that I may discard any time
1471 pr-all.pgp ;; Merged, pubring for all. maybe keyserver ring.
1476 (COMPLETION-STRING PUBRING-FILE MODE-STRING) (COMP PUB-F MODE-S)
1479 (COMPLETION-STRING PUBRING-FILE MODE-STRING) (COMP PUB-F MODE-S)
1482 BACKEND is either 'pgp2 or 'pgp5
1484 COMPLETION-STRING is 'nice name' for the pubring.
1486 PUBRING-FILE is the absolute filename where pubring resides.
1488 MODE-STRING is displayed in the mode line to show which pubring
1489 you have active. Please choose some non-word character to give
1490 you enough visible hint which pubring you use currently. Eg.
1494 * special, whole keyserver pubring."
1498 (string :tag "Pubring completion name")
1499 (file :tag "Pubring filename")
1500 (string :tag "String, One character modeline indicator")))
1501 :group 'tinypgp-mode)
1503 (defcustom tinypgp-:header-sign-table
1504 ;; Always use these fields
1505 '(("@" ("subject" "reply-to" )))
1506 "*List of headers that should be signed along with the message.
1510 '((REGEXP '(HEADER-NAME-STRING HEADER-NAME-STRING ..) [NO-XPGP-MODE])
1515 Definition of fields:
1517 REGEXP If matches To-field or Newsgroup-field, the HEADER-LIST is used.
1518 You should not sign reply-to field if the destination
1519 address changes the field contents. Many times mailing
1521 HEADER-LIST If it is empty, no headers are included in signing.
1522 NO-XPGP-MODE This field is optional. If it is non-nil, then when you
1523 do signing, this flag is consulted. If the to-field matches
1524 the no X-Pgp signing is done, no matter what the
1525 `tinypgp-:xpgp-signing-mode' says currently. In some cases
1526 you can't send X-pgp signed messages to the destination
1531 `tinypgp-:xpgp-signing-mode'"
1534 (regexp :tag "Regexp matching To/Newsgroups")
1535 (repeat (string :tag "Header field to be signed"))))
1536 :group 'tinypgp-header)
1538 (defcustom tinypgp-:keyserver-mail-table
1541 ("pgp" "pgp-public-keys@keys.pgp.net")
1543 ;; 1998-03 http://www.prairienet.org/~jalicqui/pgpfaq.txt
1544 ("uk" "pgp-public-keys@keys.uk.pgp.net")
1545 ("de" "pgp-public-keys@keys.de.pgp.net")
1546 ("no" "pgp-public-keys@keys.no.pgp.net")
1547 ("us" "pgp-public-keys@keys.us.pgp.net")
1548 ("nl" "pgp-public-keys@keys.nl.pgp.net")
1549 ("fi" "pgp-public-keys@keys.fi.pgp.net")
1550 ("es" "pgp-public-keys@keys.es.pgp.net")
1551 ("hr" "pgp-public-keys@keys.hr.pgp.net")
1552 ("tw" "pgp-public-keys@keys.tw.pgp.net")
1553 ("pl" "pgp-public-keys@keys.pl.pgp.net")
1554 ("au" "pgp-public-keys@keys.au.pgp.net"))
1555 "*List of available Email keyservers.
1556 See PGP faq \"8.2. What public key servers...\" for updated list.
1557 http://www.pgp.net/mail-help/email-help-en.html
1560 '((COMPLETION-NAME EMAIL-ADDRESS))
1563 :link '(url-link :tag "PGP keyservers"
1564 "http://www.pgp.net/mail-help/email-help-en.html")
1565 :type '(repeat (list string string))
1566 :group 'tinypgp-interface)
1568 ;; http://geronimo.uit.no/pgp/servruit.eng.html
1569 ;; http://www-swiss.ai.mit.edu/~bal/bal-home.html
1571 (defcustom tinypgp-:keyserver-http-table
1574 ;; Maintainer: <grobi@uni-paderborn.de>
1575 ;; http://math-www.uni-paderborn.de/pgp/
1577 ("wwwkeys.pgp.net:11371"
1578 "/pks/lookup?op=get&search=%s")
1580 ;; Hm, this is nowadays PGP 5 keyserver
1583 "/htbin/pks-extract-key.pl?op=get&search=%s")
1585 ("goliat.upc.es:1137" ;; <marc@mit.edu>
1586 "/pks/lookup?op=index&search=%s"))
1587 "*List of available http keyservers.
1588 Be sure that you put your nearest/fastest keyserver first in the list.
1589 It is offered as default connection.
1593 '((KEYSERVER COMMAND)
1596 :type '(repeat (list string string))
1597 :group 'tinypgp-interface)
1599 ;;; ................................................... &v-auto-action ...
1601 (defcustom tinypgp-:sign-mail-p-function nil
1602 "*Function to decide if message should be signed.
1603 Auto signing mode is active when function is called.
1604 See `tinypgp-sign-mail-auto-mode'.
1606 Function return values:
1608 t Yes, sign this mail
1609 nil Ignore signing for this message
1613 ;; Do not sign messages that are sent to my fellow
1614 ;; workers at domain 'foo'. Ie. sign messages to the outside
1617 (setq tinypgp-:sign-mail-p-function
1619 (not (string-match \"foo\" (or (mail-fetch-field \"to\") \"\")))))"
1621 :group 'tinypgp-mode)
1623 (defcustom tinypgp-:auto-action-encrypt-regexp nil
1624 "*Bulk encryption regexp to match all members in To, CC, BCC.
1625 This is special auto action variable and it is used only if
1626 there is more than _one_ address where you're sending a message.
1627 Typical situation: You want to send encrypted mail to Cc'd
1628 members who also have pgp.
1630 The regexp s matched individually against each member in To, Cc and Bcc
1631 fields. If regexp didn't match for each member, then the auto encryption
1634 You must know for sure who have pgp and those people's keys must
1635 be stored in big pubring 'all'. (see `tinypgp-:pubring-table')"
1637 :group 'tinypgp-mode)
1639 (defcustom tinypgp-:auto-action-table nil
1640 "*Automatic encrypt and sign control table.
1641 When there is only _one_ email destination (no CC, BCC and one entry in To)
1643 Alternative way, see also:
1644 `tinypgp-:bbdb-field'
1645 Note: `tinypgp-:auto-action-table' overrides BBDB
1649 '((EVAL-OR-REGEXP [SIGN-KEY-ID] [ENCRYPT] [MIME] [XPGP] [KEYRING])
1654 ;; To automatically send PGP/MIME encrypted messages to
1655 ;; foo and bar, signed by you:
1657 '((\"foo@bar.com\" 'my-pgp-key-id@site.com 'encrypt 'mime)
1658 (\"bar@bar.com\" 'my-pgp-key-id@site.com 'encrypt 'mime))
1660 Definition of fields:
1662 EVAL-OR-REGEXP: string or lisp list
1663 Regexp means matching on To field contents.
1664 *Note* To field must have address including @ character otherwise no
1667 If you use EVAL, then you can refer to variable 'to-field' in the
1668 form that builds up eval. You can also search the buffer for specific
1669 strings before determining if the actions defined should be
1672 SIGN-KEY-ID: string or symbol
1673 If this contains string key-id, that is used to sign the message. If
1674 value is SYMBOL instead of string _and_ the ENCRYPT is non-nil, then the
1675 result is 'one pass' encrypt and sign and not a separate encrypt + sign.
1678 If non-nil, the message is encrypted according to TO field content.
1679 See also `tinypgp-:email-substitution-table' if you want to encrypt
1680 using some other key.
1684 'mime use PGP/MIME interface with TM or SEMI if mime interface is present.
1687 If non-nil means signing by using X-Pgp headers;
1688 if this is nil, then use regular signing. This overrides any existing mode.
1690 KEYRING: string; absolute filename
1691 tells which file to use as pubring when doing the encryption/signing.
1692 It defaults to current keyring in use.
1694 The following example demonstrates EVAL-use of this variable, there are
1695 three entries in this list.
1697 o If newsgroup field is found from the message and
1698 it matches to pgp groups, then sign every mail.
1699 o if to-field matches person foo@site.com, then the mail
1700 is encrypted and signed. (in this order)
1701 o If message is sent somewhere else than my current domain,
1704 (setq tinypgp-:auto-action-table
1707 ((let ((grp (mail-fetch-field \"Newsgroups\")))
1708 ((string-match \"pgp\" (or grp \"\"))))
1712 (\"foo@site.com\" \"me@foo\" 'enc)
1715 ((not (string-match \"@mysite.com\" to-field))
1720 If message _already_ contains some Pgp data (signed; encrypted)
1721 this variable is not used, because it's supposed that the user is
1722 controlling the layout of PGP message.
1726 This variable is used only if you send message to _one_
1727 destination. If any CC or BCC is found from the message or if To:
1728 field contains comma, then this variable is not used.
1732 All mode settings are overridden. Toggling modes on/off do not
1733 affect auto-action command.
1737 The order of regexp elements is important: first one matched is used
1738 and the rest of the list is forgotten."
1742 (sexp :tag "To field regexp")
1743 (boolean :tag "Sign flag")
1744 (boolean :tag "X-pgp flag")
1745 (file :tag "Keyring file used:")))
1746 :group 'tinypgp-mode)
1751 ;;; ........................................................ &v-header ...
1753 (defcustom tinypgp-:xpgp-signing-mode nil
1754 "*Non-nil if X-Pgp signing is used.
1757 `tinypgp-:header-sign-table' ,this overrides `tinypgp-:xpgp-signing-mode'
1759 See \\[tinypgp-xpgp-header-mode-toggle]"
1761 :group 'tinypgp-header)
1763 (defcustom tinypgp-:xpgp-user-info
1764 '(format "Comment= \"Processed by Emacs TinyPgp.el %s\""
1765 (tinypgp-version-number))
1766 "*Additional information added to X-Pgp header.
1767 Set this variable to STRING-OR-EVAL-FORM that you wish to include
1768 in X-Pgp. The correct keywords are defined in X-Pgp standard.
1769 ftp://cs.uta.fi/pub/ssjaaa/pgp-xhd.html#additional_keywords:_telling_how_to
1773 DO NOT put newline code at the end of string.
1774 Put 2 spaces before each statement line (except first line).
1775 Every keyword must end to semicolon!
1776 Enclose strings in double quotes.
1780 (setq tinypgp-:xpgp-user-info
1782 \" Fingerprint=\\\"12 92 9C E4 60 DF 62 CD FC AD 18 47 9A 74 E7 D1\\\";\\n\"
1783 \" Length=1024; Id=0x17D57681;\"
1784 \" Access-type=Finger; Address=foo@site.com;\\n\"
1785 (format \" Comment=\\\"Processed by Emacs TinyPgp.el %s\\\";\"
1786 (tinypgp-version-number))))
1788 Recommended Example (only essential keywords):
1790 (setq tinypgp-:xpgp-user-info
1792 \" Id=0x17D57681; Access-type=Finger; Address=foo@site.com;\\n\"
1793 (format \" Comment=\\\"Processed by Emacs TinyPgp.el %s\\\";\"
1794 (tinypgp-version-number))))"
1795 :type '(sexp :tag "String of Form")
1796 :group 'tinypgp-header)
1799 ;;{{{ setup: remail private
1801 ;;; ....................................................... &vp-remail ...
1804 (defvar tinypgp-:r-levien-table nil
1805 "Updated by program. List of remailers and their properties.")
1807 (defvar tinypgp-:r-host-table nil
1808 "Updated by program. List of accepted remailers and their properties.")
1810 (defvar tinypgp-:r-history nil
1813 ;; Raph's list is not always right. This variable is for experts only
1814 ;; and you should not touch it if you don't what you're doing.
1816 (defconst tinypgp-:r-control-list nil
1817 ;;; '(("replay" ("ek")) ;does no support this
1818 ;;; ("dustbin" nil ("post")) ;supports this
1819 ;;; ("haystack" nil ("post")) ;supports this
1821 "List of remailers and additional property control.
1825 '((REMAILER (REMOVE-PLIST) (ADD-PLIST))
1828 For each remailer a property is either removed or added.
1832 (setq tinypgp-:r-control-list
1833 ;; dustbin supported one day the property post.
1834 '((\"dustbin\" nil (\"post\"))))")
1836 (defvar tinypgp-:r-mode-indication-flag nil
1837 "Non-nil means that current message should be treated with caution.
1838 Eg. if you encrypt the message, there will be no extra
1839 PGP 'Comment' keywords included that may reveal your identity.")
1841 (make-variable-buffer-local 'tinypgp-:r-mode-indication-flag)
1842 (put 'tinypgp-:r-mode-indication-flag 'permanent-local t)
1845 ;;{{{ setup: remail user config
1847 ;;; ................................................... &v-remail-hook ...
1849 (defcustom tinypgp-:r-post-before-hook '(tinypgp-r-post-before-default)
1850 "*Things to do before converting message to anonymous format.
1851 Turn off/exit all minor modes that may interfere the process."
1853 :group 'tinypgp-remail)
1855 (defcustom tinypgp-:r-reply-block-basic-hook nil
1856 "*Hook that is run after reply block is added."
1858 :group 'tinypgp-remail-hook)
1860 ;;; ........................................................ &v-remail ...
1863 (defcustom tinypgp-:r-list-file
1864 (let ((file "~/.remailer.lst"))
1866 ;; Suppose we have low quota account; use .gz file if it exists.
1867 ;; the regular file is not checked here: it is checked when
1868 ;; user uses the remail functions.
1870 (if (file-exists-p (concat file ".gz"))
1874 "*Remailer list file. See `tinypgp-r-update-remailer-list'."
1876 :group 'tinypgp-remail)
1878 (defcustom tinypgp-:r-user-mail-address user-mail-address
1879 "*Email address of your reply block.
1880 This account may be different from your regular email address."
1882 :group 'tinypgp-remail)
1884 ;; 1998-01 #finger also rlist@anon.lcs.mit.edu
1885 (defcustom tinypgp-:r-list-finger "remailer-list@kiwi.cs.berkeley.edu"
1886 "*Finger address where to get updated remailer list."
1888 :group 'tinypgp-remail)
1890 (defcustom tinypgp-:r-mail2news-remailer "replay"
1891 "*Remailer alias through which you want to send you Usenet posts.
1892 Variable is not a email address, but the remailer alias name according
1893 to Levien remailer list. This variable can contain lisp FORM.
1895 Must support properties: POST PGP HASH CUTMARKS."
1897 :group 'tinypgp-remail)
1899 (defcustom tinypgp-:r-chain nil
1900 "*Remailer chain table. List of remailer.
1901 Only remailers that at least have properties PGP HASH EK are allowed.
1906 [vector or (lisp-form-to-evaluate; must return vector)
1908 latent-time this is optional
1909 encrypt-key) this is optional
1917 (defconst tinypgp-:r-chain
1918 '((\"1-way\" [(\"replay\" \"+0:05r\" \"ZepHyR1x\")])
1919 ;; Select random path
1920 (\"hide\" (progn (shuffle-vector [(\"replay\") (\"dustbin\")])))
1921 ;; Use some reliable remailer, but hide identity better
1922 (\"milkyway\" [\"replay\" \"replay\" \"replay\"])))"
1924 :group 'tinypgp-remail)
1926 (defcustom tinypgp-:r-subject-table
1929 " ignore this message"
1930 " Regarding your previous message"
1931 " As for the www and html..."
1932 " Re: about the last subject..."
1933 " Re: Programming langueges.. ")
1934 "*List of dummy Subject sentences that are used in your Remailer message.
1935 The subject should be such that it doesn't draw your sysadm's attention."
1936 :type '(repeat (list string))
1937 :group 'tinypgp-remail)
1939 (defcustom tinypgp-:r-reply-block-table nil
1940 "*Correct reply block for each remailer.
1941 Suggested filename could be ~/.r-dustbin for dustbin remailer.
1942 You can place anything after the last -----END PGP MESSAGE-----
1943 because the reply block is only read from `point-min' to this
1944 tag line and rest of the file is ignored.
1949 Request-Remailing-To: remailer@replay.com
1955 -----BEGIN PGP MESSAGE-----
1958 hIkDPRWysueuweUBA+jLifdDpkCxcUYA
1960 -----END PGP MESSAGE-----
1964 # this is another comment
1969 '((REMAILER-ALIAS FILE)
1975 (string :tag "Remailer alias")
1976 (file :tag "Reply block File")))
1977 :group 'tinypgp-remail)
1979 (defcustom tinypgp-:r-header-keep-list '("Gcc" "Fcc")
1980 "*In addition to strict RFC headers; keep these headers too.
1981 When you compose anon post, all the unnecessary headers will be
1982 killed so that your identity is not revealed by accident.
1983 This is list f headers that are preserved in addition to RFC headers.
1984 Please do not include colon or spaces.
1987 '(\"hdr1\" \"hdr2\" ..)"
1988 :type '(repeat string)
1989 :group 'tinypgp-remail)
1991 ;;; ........................................................ &v-newnym ...
1993 (defcustom tinypgp-:r-newnym-stamp-file-prefix
1994 (tinypgp-path "~/.emacs.tinypgp-stamp.")
1995 "*Newnym type accounts expire in 120 days.
1996 This file is touched every time user sends a newnym account
1997 request or remail. It is compared to current sate and a warning
1998 is issued after 100 days if user hasn't used the account.
2000 The filenames are manfgled to protect reading the Newnym server and
2001 account information from them.
2003 User must send `request' message to the account to keep it alive."
2005 :group 'tinypgp-newnym)
2007 (defcustom tinypgp-:r-newnym-default-account-table nil
2008 "*List of newnym servers and accounts you have.
2009 The active default server and login information are stored
2010 into properties 'default-server and 'default-account. If these properties
2011 are nil, then no default values are set.
2014 '((COMPLETION-NAME NYM-SERVER NYM-ACCOUNT MODELINE-CHAR)
2016 Important: NYM-ACCOUNT must not have @site.suffix.com; only the account name
2019 '((\"weasel\" \"weasel\" \"my-weasel-login-name\" \"W\")
2020 (\"nym\" \"nym\" \"my-nym-login-name\" \"N\")
2021 (\"nym2\" \"nym\" \"my-nym-login-name2\" \"N2\")
2022 (\"efga\" \"efga\" \"my-efga-login-name\" \"E\"))"
2023 :type '(repeat (list string string string))
2024 :group 'tinypgp-newnym)
2026 (defcustom tinypgp-:r-newnym-mail2news-address
2027 "mail2news_nospam@anon.lcs.mit.edu"
2028 "*Email address through which the newsgroup posts are sent.
2029 This variable is evaled to get the email address.
2031 Aug 13 1997 there was a list of gateways available at
2032 http://students.cs.byu.edu/~don/mail2news.html and the list below
2033 is copied from there.
2037 The default value is mail2news_nospam@anon.lcs.mit.edu which creates
2040 From: Bogus Name <Use-Author-Address-Header@[127.1]>
2041 Author-Address: Name <AT> nym <DOT> alias <DOT> net
2043 If you would use regular mail2news_nospam@anon.lcs.mit.edu; then your
2044 headers were as they would. But expect to get UCE mail through your newnym
2045 account as soon as you post to usenet.
2047 From: Sam Bogus <name@nym.alias.net> ????
2049 Sites that scan headers:
2051 mail2news@anon.lcs.mit.edu CONFIRMED Jun97
2052 mail2news@news.wsnet.com NOT FUNCTIONAL
2054 Sites that parse the email address:
2056 group.name.usenet@alpha.jpunix.com DO NOT USE
2057 m2n-YYYYMMDD-group.name+group.name@alpha.jpunix.com CONFIRMED Aug97
2058 post-group.name@newspost.zippo.com CONFIRMED Mar97
2059 group.name@news.cs.dal.ca PROBABLY NOT FUNCTIONAL
2060 no.group.name@news.uninett.no
2061 (uninett only reported to carry norwegian news) CONFIRMED Jul96
2062 group.name@news.uni-stuttgart.de CONFIRMED Mar97
2063 mail2news-YYYYMMDD-group.name+group.name@anon.lcs.mit.edu CONFIRMED Jul97
2064 group.name@myriad.alias.net CONFIRMED Jun97"
2066 :group 'tinypgp-newnym)
2068 (defcustom tinypgp-:r-newnym-help-file nil
2069 "*Remailer 'newnym' help file."
2071 :group 'tinypgp-newnym)
2073 (defconst tinypgp-:newnym-cmd-table
2075 "per-message: automatic acknowledgment of successfully remailed message."
2076 "Default: -acksend")
2078 "per-message: automatic PGP signing of any outgoing mail."
2079 "Default: -signsend")
2081 "automatic encryption with your nym's public key."
2082 "Default: +cryptrecv")
2084 "all messages padded to exactly the same size (roughly 10K)"
2085 "Default: -fixedsize")
2087 "4 Megabytes per day disables account, notified if this happens."
2088 "Default: -disable. Re-enable account with -disable.")
2090 "Allow people to finger <yournym@weasel.owl.de> for you PGP key."
2091 "Default: -fingerkey")
2094 Describe text of nym >> From: YOUR-NAME-DESC-HERE <yournym@weasel.owl.de>"
2095 "Default: name=\"\". Example: name=\"Your Alias Name\"")
2098 Create fails if a nym exists. Use Create? for updating nym. (sign message)."
2099 "Example: create/create?")
2101 "Deletes your alias and wipes your reply block. Acknowledged."
2102 "<no other options>")
2105 Counce bcc, only To, Cc, Resent-To, or Resent-Cc accepted. (SPAM protect)"
2107 "Newnym command table.
2109 '((COMMAND DESC cmd-example-or-default-value)
2110 (COMMAND DESC cmd-example-or-default-value)
2113 ;;; ....................................................... &vp-remail ...
2114 ;;; Private variables.
2116 (defvar tinypgp-:r-reply-block-cache nil
2120 '((BUFFER PGP-BEG PGP-END)
2125 ;;{{{ setup: Nymserver
2127 ;;; ....................................................... &nymserver ...
2129 (defcustom tinypgp-:nymserver-request-encrypt nil
2130 "*To send every command to 'nymserver' account in encrypted format.
2131 NOTE: You must have inserted the Server's PGP key into the keyring."
2133 :group 'tinypgp-nymserver)
2135 ;;; Currently this is not user variable
2136 ;;; There is only one nymserver type remailer currently active.
2138 (defconst tinypgp-:nymserver-table
2140 tinypgp-nymserver-create-1 "request@anon.nymserver.com"
2141 "anon@anon.nymserver.com"
2143 "Table of 'nymserver' type services.
2146 '((SERVER-ALIAS-STRING
2147 ACCOUNT-CREATE-FUNCTION
2148 ACCOUNT-CREATE-EMAIL-ADDRESS
2149 SERVER-EMAIL-POST-TO
2150 NEWSGROUP-POST-COUNT-LIMIT)
2154 ;;; When you receive account creation confirmation; update
2155 ;;; this variable immediately.
2157 (defcustom tinypgp-:nymserver-account-table nil
2158 "*Your nymserver account information table.
2160 '((SERVER-ALIAS-STRING
2163 [ACCOUNT-NICKNAME-STRING | nil ]
2164 [FROM-ADDRESS | nil ]
2165 [HELP-FILE | nil ]))
2167 You get the slots ACCOUNT-EMAIL, ACCOUNT-PASSWORD when you order an
2168 account from the server. The ACCOUNT-NICKNAME-STRING can be nil,
2169 because nymserver also controls your Nickname. This overrides
2174 is important. When you ordered account from nymserver, it
2175 allocates only your current address and handles only messages sent from
2178 aa@a.com --> you ordered anon account here.
2179 bb@b.com you have another normal account here
2180 cc@c.com you have yet another normal account here
2182 Suppose you want to post from account bb@b.com as anon. Can't
2183 do that because nymserver expects you to be only in aa@a.com, in the
2184 site where you initially ordered the anon account.
2186 Now, if you set FROM-ADDRESS to aa@a.com, then the From-field is inserted
2187 into the message pretending that the mail is coming from aa@a.com and
2188 now you can use your Anon account from different sites.
2192 If the E-mail message that contained the server manual which explains
2193 all its features. Store the mail to this file;
2197 (defconst tinypgp-:nymserver-account-table
2199 \"an1111@anon.nymserver.com\"
2202 \"my.name@address.com\"
2203 \"~/txt/nymserver.hlp\"
2206 (const "nymserver" :tag "Server")
2207 (string :tag "Account email")
2208 (string :tag "Account ppassword")
2212 (string :tag "nickname")
2213 (string :tag "From address")
2214 (file :tag "Help file"))
2215 :group 'tinypgp-nymserver)
2219 ;;{{{ setup: private
2221 ;;; ...................................................... &vp-private ...
2223 (defvar tinypgp-:timer-elt nil
2224 "Timer process that e.g. expires passwords.")
2226 (defvar tinypgp-:key-cache nil
2227 "Cache: '((key-id, pubring, public-key) (...)).")
2229 (defvar tinypgp-:key-cache-last nil
2230 "Last accessed 'get element in cache. See function `tinypgp-key-cache'.
2231 (ORIGINAL-EMAIL (CACHE-KEY PUBRING ..))")
2233 (defvar tinypgp-:return-value nil
2234 "Common return value between functions.
2235 This variable is used as a signal to TinyPgp when it has called
2236 some user function or hook. The usage is explained in
2237 the functions that use it. It will contain properties too.")
2239 (defvar tinypgp-:buffer-tmp-shell "*tinypgp-shell-tmp*"
2240 "Temporary buffer.")
2242 (defvar tinypgp-:buffer-tmp-finger " *tinypgp-finger-tmp*"
2243 "Temporary buffer.")
2245 (defvar tinypgp-:buffer-tmp-copy " *tinypgp-copy-tmp*"
2246 "Temporary buffer.")
2248 (defvar tinypgp-:buffer-tmp-article " *tinypgp-article*"
2250 If user doesn't want to replace the contents of the
2251 buffer in mail-like modes, then the content is copied to
2252 this buffers first, so that any text properties or overlays can beremoved
2253 without invoking edit mode.")
2255 (defvar tinypgp-:buffer-tmp-http " *tinypgp-http-tmp*"
2256 "Temporary buffer.")
2258 (defvar tinypgp-:buffer-tmp-kring " *tinypgp-kring-tmp*"
2259 "Temporary buffer.")
2261 (defvar tinypgp-:buffer-tmp-show " *tinypgp-show-tmp*"
2262 "Temporary buffer.")
2264 (defvar tinypgp-:buffer-tmp-mail " *tinypgp-mail-tmp*"
2265 "Temporary mail buffer.")
2267 (defvar tinypgp-:buffer-tmp " *tinypgp-tmp*"
2268 "Temporary buffer.")
2270 (defvar tinypgp-:buffer-newnym "*mail-newnym*"
2271 "Newnym remailer mail buffer.")
2273 (defvar tinypgp-:buffer-comint "tinypgp-comint"
2274 "Interactive comint buffer to talk with PGP.
2275 This buffer name will automatically have stars over the name.")
2277 (defvar tinypgp-:buffer-view "*tinypgp-view*"
2278 "Interactive comint buffer to talk with PGP.
2279 This buffer name will automatically have stars over the name.")
2281 (defvar tinypgp-:original-buffer nil
2282 "Original buffer storage. Set in macro `tinypgp-run-in-tmp-buffer'.")
2284 (defvar tinypgp-:pgp-email-list nil
2285 "List of email addresses in ~/.emailrc.")
2287 (defvar tinypgp-:pgp-email-abbrev-list nil
2288 "List of abbrevs and their expansions: '((\"abb\" . \"expa\") ..).")
2290 (defvar tinypgp-:pgp-email-list-completions nil
2291 "Email assoc menu for completion. '((\"a@b.com\" . 1) ..)
2292 This variable is initialised to the contents of your
2295 (defvar tinypgp-:sign-data nil
2296 "Stored sign information for current message.
2297 Used for checking message tampering afterwards.
2300 number ,message body length in characters.")
2301 (make-variable-buffer-local 'tinypgp-:sign-data)
2302 (put 'tinypgp-:sign-data 'permanent-local t)
2304 ;;; ....................................................... &vp-colors ...
2306 (defvar tinypgp-:face-mark 'highlight
2307 "The face for text marking.")
2309 (defvar tinypgp-:face-error 'bold
2310 "The face for pointing out errors.")
2312 ;;; ...................................................... &vp-history ...
2314 (defvar tinypgp-:history-key-info nil
2315 "History of used key info strings.")
2317 (defvar tinypgp-:history-email nil
2318 "User email history.")
2320 (defvar tinypgp-:history-newnym-account nil
2321 "Nym account name history.")
2323 (defvar tinypgp-:history-r-chain nil
2324 "Remailer chain selection history.")
2326 (defvar tinypgp-:history-r-chain nil
2327 "Remailer chain selection history.")
2329 (defvar tinypgp-:history-http-keyserver nil
2330 "History of used key servers.")
2332 (defvar tinypgp-:history-http-keyserver-string nil
2333 "History of used key server search strings.")
2335 ;;; ..................................................... &vp-commands ...
2337 (defconst tinypgp-:pgp-command-options
2338 (let* ((charset (ti::string-remove-whitespace
2339 (if (ti::nil-p tinypgp-:pgp-binary-charset)
2341 tinypgp-:pgp-binary-charset)))
2342 (secring (cdr (assq 'pgp2 tinypgp-:file-secring))))
2345 ;; These options are best to left out from the commands in WinNT.
2346 ;; The maximum command line parameter length is 255 or was it 180 ?
2348 ;; The PGP compress ratio is like 1,6M text --> 600k
2354 (concat " +secring=" secring)
2358 " +showpass=off" ;There is no cmd line arg
2359 " +encrypttoself=off"
2362 " +language=en" ;don't use language modules
2363 " +armorlines=0" ;No separate UU chunks
2364 " +charset=" charset
2367 "Default 2.6.x options for every pgp command.
2368 Notice that in PC platform there may be restrictions.")
2370 ;; #todo: tinypgp-:pgp-command-options5 for Unix?
2372 (defconst tinypgp-:pgp-command-options5
2373 (let* ((charset (ti::string-remove-whitespace
2374 (if (ti::nil-p tinypgp-:pgp-binary-charset)
2376 tinypgp-:pgp-binary-charset))))
2377 ;;; (secring (cdr (assq 'pgp5 tinypgp-:file-secring)))
2383 " +encrypttoself=off "
2385 " +language=en " ;don't use language modules
2386 " +armorlines=0 " ;No separate UU chunks
2388 ;; " WarnOnMixRSADiffieHellman=on "
2389 ;; " WarnOnRSARecipAndNonRSASigner=on "
2391 ;; batchmode; You must not add this to the switches, because
2392 ;; then PGP 5.x won't ask for pass phrase, but expects to get
2393 ;; it from PGPPASSFD. We don't use PGPASSFD in Unix, but the expect.el
2394 ;; will feed the pass phrase to the prompt.
2398 ;; " -v " ;; Verbose mode
2400 " +charset=" charset
2402 "Default 5.x options for every pgp command.
2403 Notice that in PC platform there may be restrictions.")
2405 (defconst tinypgp-:gpg-command-table
2406 (let* ((common2 tinypgp-:pgp-command-options) ;Without batch mode
2414 " echo #password #bin "
2416 " --passphrase-fd 0 ")))
2419 ;; Encrypt and output ascii #todo
2422 (concat common " -f -u xx_test -z xx_test #SOURCE-FILE"))
2427 (concat passwd-scheme
2428 " #OUT-FILE -e -a #MUSER #SOURCE-FILE "))
2433 " --textmode --sign -e -a #MUSER #PGP-USER #password"))
2437 (concat passwd-scheme " #OUT-FILE --decrypt #USER #SOURCE-FILE "))
2441 (concat (concat common " -f ")))
2445 (concat common2 " -a -c "))
2451 " #OUT-FILE --textmode --clearsign -a #USER #SOURCE-FILE "))
2455 (concat common " -bsatf #USER #password "))
2459 (concat common " --verify "))
2463 (concat common " -kaf "))
2467 (concat common " -kvc "))
2471 (concat common " -fka "))
2475 (concat common " -fkxa "))
2479 (concat common2 " -kg "))
2483 (concat common " +force -kr "))
2487 (concat common " +force -kr "))
2491 (concat common " +force #USER -ks "))
2495 (concat common " +force #USER -krs "))))
2496 "GPG 1.0.4 command table.")
2498 (defconst tinypgp-:pgp-command-table
2499 (let* ((common2 tinypgp-:pgp-command-options) ;Without batch mode
2506 ;; To use a Unix-style filter mode, reading from standard
2507 ;; input and writing to standard output, use -f option
2509 ;; converted to recipient's local text
2510 ;; line conventions, add the -t (text)
2513 ;; Encrypt and output ascii ascii
2516 (concat common " #PUBRING -f -u xx_test -z xx_test #SOURCE-FILE"))
2521 (concat common " #PUBRING -eatf #SOURCE-FILE #MUSER "))
2525 (concat common " #PUBRING -eatfs #MUSER #PGP-USER #password"))
2529 (concat common " #PUBRING -f #password "))
2533 (concat common " -f "))
2537 (concat common2 " -a -c "))
2541 (concat common " #PUBRING -satf #USER #password "))
2545 (concat common " #PUBRING -bsatf #USER #password "))
2549 (concat common " #PUBRING -f "))
2553 (concat common " #PUBRING -kaf "))
2557 (concat common " #PUBRING -kvc "))
2561 (concat common " #PUBRING -fka "))
2565 (concat common " #PUBRING -fkxa "))
2569 (concat common2 " #PUBRING -kg "))
2573 (concat common " +force #PUBRING -kr "))
2577 (concat common " +force #PUBRING -kr "))
2581 (concat common " +force #PUBRING #USER -ks "))
2585 (concat common " +force #PUBRING #USER -krs "))))
2586 "PGP 2.6.x command table.")
2588 ;; #todo: #PUBRING is not in the switches.
2589 ;; #todo: I have no idea if these work in Unix
2591 (defconst tinypgp-:pgp-command-table5
2592 (let* ((common tinypgp-:pgp-command-options5))
2594 ;; Encrypt and output ascii ascii
2597 (concat common " -f -u xx_test -z xx_test #SOURCE-FILE"))
2601 (concat common " -atf #OUT-FILE #MUSER #SOURCE-FILE"))
2607 " -atf -s #OUT-FILE #USER #MUSER #password #SOURCE-FILE "))
2611 (concat common " -f #OUT-FILE #password #SOURCE-FILE"))
2615 (concat common " -f #OUT-FILE #SOURCE-FILE"))
2619 (concat common " -a -c #SOURCE-FILE"))
2625 " -atv #USER #password #OUT-FILE #SOURCE-FILE "))
2631 " -b -atv #USER #password #OUT-FILE #SOURCE-FILE "))
2635 ;; option -z requires pass phrase argument.
2637 (concat common " #OUT-FILE #SOURCE-FILE "))
2641 (concat common " -kaf "))
2645 (concat common " -ll "))
2649 (concat common " -a "))
2653 (concat common " -xa "))
2657 (concat common " -g "))
2661 (concat common " -r "))
2665 (concat common " -kr "))
2669 (concat common " #USER -ks "))
2673 (concat common "#USER -krs "))))
2674 "PGP 5.0.x command table.")
2676 (defconst tinypgp-:pgp-binary-exit-code-table
2679 ;; Possible error exit codes - not all of these are used. Note that
2680 ;; we don't use the ANSI EXIT_SUCCESS and EXIT_FAILURE. To make
2681 ;; things easier for compilers which don't support enum we use
2684 (0 'EXIT_OK "JumBoJumboMamboBaile")
2685 (1 'INVALID_FILE_ERROR)
2686 (2 'FILE_NOT_FOUND_ERROR)
2687 (3 'UNKNOWN_FILE_ERROR)
2692 ;; /* Keyring errors: Base value = 10 */
2694 (11 'NONEXIST_KEY_ERROR)
2695 (12 'KEYRING_ADD_ERROR)
2696 (13 'KEYRING_EXTRACT_ERROR)
2697 (14 'KEYRING_EDIT_ERROR)
2698 (15 'KEYRING_VIEW_ERROR)
2699 (16 'KEYRING_REMOVE_ERROR)
2700 (17 'KEYRING_CHECK_ERROR)
2701 (18 'KEY_SIGNATURE_ERROR)
2702 (19 'KEYSIG_REMOVE_ERROR)
2703 ;; /* Encode errors: Base value = 20 */
2704 (20 'SIGNATURE_ERROR)
2705 (21 'RSA_ENCR_ERROR)
2707 (23 'COMPRESS_ERROR)
2708 ;; /* Decode errors: Base value = 30
2709 (30 'SIGNATURE_CHECK_ERROR)
2710 (31 'RSA_DECR_ERROR)
2712 (33 'DECOMPRESS_ERROR))))
2713 "Error codes of PGP versions.
2715 '((PGP-VERSION-REGEXP .((EXIT-CODE ERROR-SYMBOL [ERROR-REGEXP] ..)))
2716 (P-V-R . ((EX ES ER) (EX ES ER) ..))))
2718 If ERROR-REGEXP is not specified, then ERROR-SYMBO should be used to
2719 show the error to user.")
2721 (defconst tinypgp-:pgp-binary-error-regexp
2724 "\\|user ID is required"
2725 "\\|Unable to get terminal"
2726 "\\|Transport armor stripping failed"
2727 "\\|Encryption error"
2728 "\\|No such file or directory"
2729 "\\|Cannot find the public key"
2730 "\\|Output file.*already exists"
2731 "\\|You do not have the secret key needed to decrypt this file\\."
2732 "\\|We need to generate.*bits" ;; Can I handle this in the prg?
2734 ;; If you encrypt with multiple keys, then missing key is flagged
2736 "\\|This user will not be able to decrypt this message"
2738 "\\|Key matching userid.*not found in file"
2739 "\\|Key matching.*not found in file"
2741 ;;; Signature validation....
2742 ;;; "\\|Key matching expected Key ID.*not found in file"
2744 "\\|Keyring extract error\\."
2746 ;; When removing keys...
2748 "\\|Do you also want to remove it from.*[?]"
2750 ;; When you try to verify detached sig file and say that some file
2751 ;; XXX holds sig (when it doesn't)
2753 "\\|Error:.*is not a ciphertext, signature, or key file."
2755 ;; Eg. From conventional crypt error
2757 "\\|You need a pass phrase to decrypt this file"
2759 ;; PGP 5.x Error! Unable to load string PRIVATE_KEY_MISSING.
2761 "\\|Error!.*Unable to load string.")
2762 "All error messages from PGP executable.
2763 These are case sensitive sentences.")
2765 (defconst tinypgp-:pgp-binary-error-regexp-quiet
2768 "\\|Cannot find the public key"
2769 "\\|Key matching userid.*not found in file"
2770 "\\|Key matching.*not found in file")
2771 "List of errors that does not bring up the Shell Error buffer.
2772 The buffer contain the last PGP executable call.
2773 Consider these errors so familiar that you don't have to
2774 examine the shell error message better.")
2776 (defvar tinypgp-:error nil
2777 "Last error message.")
2779 (defvar tinypgp-:last-pgp-exe-command nil
2780 "Last command sent to PGP exe.")
2782 ;;; .................................................... &vp-pass-hash ...
2784 (defvar tinypgp-:hash-password (make-vector 127 0)
2785 "Stored passwords, expired periodically.")
2787 ;; Some variables must be stored locally, but some variables must
2788 ;; be globally visible; becfause on error conditions the
2789 ;; current buffer may have changed and in order to restore
2790 ;; situation, we must do lookup from GLOBAL array, because we don't
2791 ;; know any more what was the starting buffer.
2793 (defvar tinypgp-:hash nil
2794 "General _local_ hash storage.")
2795 (make-variable-buffer-local 'tinypgp-:hash)
2797 (defvar tinypgp-:hash-global nil
2798 "General _global_ hash storage.")
2800 (defvar tinypgp-:secring-crypt-mode nil
2801 "If Non-nil, use encrypted secring.
2802 This is NOT A USER VARIABLE. Use \\[tinypgp-secring-crypt-mode-toggle]
2803 Variable's value should not be trusted at all; but instead set it
2804 by calling function `tinypgp-secring-crypt-mode-detect' and only
2805 then trusting the value.")
2807 ;;; ......................................................... &vp-misc ...
2809 (defvar tinypgp-:header-sign-smf-info nil
2810 "The header SMF data that was constructed is stored here.")
2812 (defvar tinypgp-:pubring-now nil
2813 "Current pubring in use.
2814 This will be initialised in `tinypgp-backend-select'")
2816 (defvar tinypgp-:user-now
2817 (let* ((em user-mail-address))
2821 TinyPgp: tinypgp-:user-now, user-mail-address is not str like foo@site.com"))
2823 ;; If you have <> in user-mail-address that messes up From
2826 ((string-match "<.*@.*>" em)
2828 TinyPgp: tinypgp-:user-now, please remove <> from user-mail-address")))
2829 (car (ti::mail-email-from-string em)))
2832 (defvar tinypgp-:last-network-error nil
2833 "Last finger call error text.")
2837 ;;; ########################################################### &Funcs ###
2841 ;;; ........................................................... &debug ...
2843 (defvar tinypgp-:debug-buffer-size 100000
2844 "The buffer size after which the debug buffer is emptied.
2845 If you don't see all the information, increase size.")
2847 (defvar tinypgp-:debug t
2850 (defvar tinypgp-:debug-buffer "*tinypgp-debug*"
2853 ;;; ----------------------------------------------------------------------
2855 (defmacro tinypgpd (&rest args)
2856 "Generate debug if debug is on and output ARGS."
2858 (when tinypgp-:debug
2859 (let* ( ;; write to package's private buffer.
2860 (ti:m-debug-buffer tinypgp-:debug-buffer))
2862 (ti::d!! (,@ args) "\n")
2863 ;; don't let it grow without limit....
2864 (with-current-buffer ti:m-debug-buffer
2865 (if (and (integerp tinypgp-:debug-buffer-size)
2866 (> (buffer-size) tinypgp-:debug-buffer-size))
2867 (erase-buffer))))))))
2869 ;;; ----------------------------------------------------------------------
2871 (defun tinypgp-debug-buffer-clear ()
2872 "Clear the debug buffer."
2874 (ti::temp-buffer tinypgp-:debug-buffer 'clear)
2876 (message "TinyPgp: Debug buffer cleared.")))
2878 ;;; ----------------------------------------------------------------------
2880 (defun tinypgp-password-wipe-buffer (&optional force)
2881 "Wipe password strings from buffer. This may not succeed if cache is empty.
2882 if passwords are not in cache any more this function is no-op.
2884 If FORCE is non-nil ask interactively.
2885 If force is nil, then get the passwords from cache and
2887 Normally getting passwords from cache is performed in `mail-send-hook'"
2888 (interactive (list (interactive-p)))
2889 (let ((fid "tinypgp-password-wipe-buffer:")
2895 (setq passwd (tinypgp-password-set "\
2896 I need pass phrase to wipe out all references to it: "))
2899 serv-passwd (tinypgp-nymserver-password
2900 (tinypgp-nymserver-ask
2901 "Nymserver server you have used: "))))
2904 (if (ti::vector-table-get tinypgp-:hash-password tinypgp-:user-now)
2905 (setq passwd (ti::vector-table-property
2906 tinypgp-:hash-password tinypgp-:user-now 'password)))
2908 ;; Actually there may be multiple passwords if user has several PGP
2909 ;; keys (common, if you use remailers)
2911 ;; #todo: We don't know nymserver password, because it is not in hash
2918 tinypgp-:hash-password)))
2920 ;; finally, scramble any pass pharases, so that they are not sent
2923 (ti::save-line-column-macro nil nil
2924 (when (stringp passwd)
2925 (ti::mail-hmax 'move)
2926 (replace-string passwd "#PASSWD-WAS-HERE"))
2928 (when (stringp serv-passwd)
2929 (ti::mail-hmax 'move)
2930 (replace-string serv-passwd "#PASSWD-WAS-HERE-ANON")))
2931 (tinypgpd fid "out:" (current-buffer))
2932 ;; Clean return value
2935 ;;; ----------------------------------------------------------------------
2937 (defun tinypgp-submit-bug-report ()
2938 "Submit bug report or feedback.
2939 When you call this function it automatically includes all needed
2940 buffers. Please leave the *Backtrace* buffer before you call this function
2941 and it will be copied too.
2943 If this is feedback call, then do not include any extra buffers.
2944 \[Answer 'n' when to insert questions]"
2946 (ti::package-submit-bug-report
2949 '(tinypgp-:version-id
2960 gnus-article-mode-hook
2962 news-reply-mode-hook
2965 mh-before-send-letter-hook
2971 tinypgp-:turn-on-hook-list
2972 tinypgp-:sig-from-header-hook
2973 tinypgp-:sig-to-header-hook
2974 tinypgp-:sign-loose-info-hook
2975 tinypgp-:key-mode-define-keys-hook
2976 tinypgp-:do-command-region-before-hook
2977 tinypgp-:do-command-region-after-hook
2978 tinypgp-:cmd-macro-before-hook
2979 tinypgp-:cmd-macro-after-hook
2980 tinypgp-:verify-before-hook
2981 tinypgp-:verify-after-hook
2982 tinypgp-:read-email-after-hook
2983 tinypgp-:find-by-guess-hook
2984 tinypgp-:finger-discard-email-hook
2985 tinypgp-:r-post-before-hook
2986 tinypgp-:r-post-after-hook
2987 tinypgp-:nymserver-post-hook
2988 tinypgp-:r-post-before-hook
2989 tinypgp-:r-reply-block-basic-hook
2990 tinypgp-:define-keys-hook
2992 tinypgp-:pgp-encrypted-p-function
2993 tinypgp-:decrypt-arg-interpretation
2994 tinypgp-:pgp-decrypt-arg-function
2995 tinypgp-:pgp-command-compose-function
2998 ;;; tinypgp-:mode-menu-name
2999 ;;; tinypgp-:mode-map
3000 tinypgp-:mode-prefix-key
3001 tinypgp-:mode-prefix-key-remailer
3002 tinypgp-:mode-prefix-key-nymserver
3004 ;;; tinypgp-:key-mode-map
3005 ;;; tinypgp-:key-mode-menu
3006 tinypgp-:key-mode-menu-name
3007 tinypgp-:key-mode-prefix-key
3008 tinypgp-:xpgp-user-info
3009 tinypgp-:pgp-binary-charset
3012 tinypgp-:file-source
3013 tinypgp-:file-output
3014 tinypgp-:file-password
3015 tinypgp-:file-user-list
3016 tinypgp-:file-key-cache
3017 tinypgp-:file-secring-encrypted
3021 tinypgp-:finger-discard-by-regexp
3022 tinypgp-:password-protection
3023 tinypgp-:password-keep-time
3024 tinypgp-:user-primary
3025 tinypgp-:filter-email-function
3026 tinypgp-:sign-mail-p-function
3028 ;;; Do not send this to maintainer!
3029 ;;; tinypgp-:user-identity-table
3030 tinypgp-:header-sign-table
3031 ;;; tinypgp-:keyserver-mail-table
3032 tinypgp-:auto-action-table
3033 tinypgp-:pubring-table
3034 tinypgp-:r-levien-table
3035 tinypgp-:r-host-table
3037 tinypgp-:r-mode-indication-flag
3038 tinypgp-:r-list-file
3039 tinypgp-:r-user-mail-address
3040 tinypgp-:r-list-finger
3041 tinypgp-:r-newnym-help-file
3042 tinypgp-:r-mail2news-remailer
3044 tinypgp-:r-reply-block-table
3045 tinypgp-:r-reply-block-cache
3046 tinypgp-:nymserver-request-encrypt
3047 tinypgp-:nymserver-account-table
3049 tinypgp-:debug-buffer-size
3050 ;;; tinypgp-:key-cache
3051 tinypgp-:key-cache-last
3052 tinypgp-:return-value
3053 tinypgp-:buffer-tmp-shell
3054 tinypgp-:buffer-tmp-finger
3055 tinypgp-:buffer-tmp-copy
3056 tinypgp-:buffer-tmp-http
3057 tinypgp-:buffer-tmp-kring
3058 tinypgp-:buffer-tmp-show
3059 tinypgp-:buffer-tmp-mail
3061 tinypgp-:buffer-comint
3062 tinypgp-:buffer-view
3063 tinypgp-:original-buffer
3064 tinypgp-:xpgp-signing-mode
3065 tinypgp-:history-email
3066 ;;; tinypgp-:pgp-email-list
3067 ;;; tinypgp-:pgp-email-abbrev-list
3068 ;;; tinypgp-:pgp-email-list-completions
3070 tinypgp-:history-key-info
3072 tinypgp-:last-pgp-exe-command
3073 ;;; tinypgp-:hash-password
3075 tinypgp-:header-sign-smf-info
3076 tinypgp-:pubring-now
3078 tinypgp-:last-network-error
3079 tinypgp-:nymserver-echo-menu-use-p
3081 tinypgp-:key-mode-name
3082 tinypgp-:pgp-binary-interactive-option
3083 tinypgp-:pgp-binary-support-table
3084 ;;; tinypgp-:keyserver-http-table
3085 tinypgp-:r-control-list
3086 ;;; tinypgp-:r-subject-table
3087 tinypgp-:nymserver-table))
3088 ;;; tinypgp-:pgp-command-table
3089 ;;; tinypgp-:pgp-binary-error-regexp
3090 ;;; tinypgp-:nymserver-echo-menu
3096 (when (get-buffer "*Backtrace*")
3097 (insert "\n\n#BACKTRACE BEGIN-------------\n")
3098 (insert-buffer (get-buffer "*Backtrace*")) (ti::pmax)
3099 (insert "\n\n#BACKTRACE END-------------\n"))
3101 (when (and (get-buffer tinypgp-:buffer-tmp-shell)
3102 (y-or-n-p "Insert PGP shell buffer contents? "))
3103 (insert "\n\n#SHELL BEGIN-------------\n")
3104 (insert-buffer (get-buffer tinypgp-:buffer-tmp-shell)) (ti::pmax)
3105 (insert "\n\#SHELL END-------------\n"))
3110 (null (get-buffer tinypgp-:debug-buffer))
3112 "No debug buffer: Are you sure maintainer doesn't need it? "))
3113 (y-or-n-p "Insert the debug buffer contents too? "))
3114 (insert "\n\n#DEBUG BEGIN-------------\n")
3115 (insert-buffer tinypgp-:debug-buffer) (ti::pmax)
3116 (insert "\n\#DEBUG END-------------\n")))
3118 (tinypgp-password-wipe-buffer 'force))
3119 (ti::read-char-safe-until
3120 "[press]Please check that your pass phrase wasn't included..."))
3123 ;;{{{ macros: test-p
3125 ;;; ----------------------------------------------------------------------
3127 (defsubst tinypgp-backend-now ()
3128 "Return 'gpg 'pgp2 or 'pgp5"
3129 (get 'tinypgp-:pgp-binary 'pgp-now))
3131 ;;; ----------------------------------------------------------------------
3133 (defsubst tinypgp-backend-type (&optional backend)
3134 "Return BACKEND type: 'unix or 'win32."
3135 (let* ((prop (intern (concat (symbol-name
3137 (tinypgp-backend-now)))
3139 (get 'tinypgp-:pgp-binary prop)))
3141 ;;; ----------------------------------------------------------------------
3143 (defun tinypgp-backend-file (file)
3144 (concat file "." (symbol-name (tinypgp-backend-now))))
3146 ;;; ----------------------------------------------------------------------
3148 (defsubst tinypgp-backend-pgp2-p ()
3149 "Return non-nil is if pgp 2.6.x is in use."
3150 (eq (tinypgp-backend-now) 'pgp2))
3152 ;;; ----------------------------------------------------------------------
3154 (defsubst tinypgp-backend-gpg-p ()
3155 "Return non-nil is if gpg is in use."
3156 (eq (tinypgp-backend-now) 'gpg))
3158 ;;; ----------------------------------------------------------------------
3160 (defsubst tinypgp-backend-list ()
3161 "Return available backends: 'pgp2 'pgp5"
3162 (get 'tinypgp-:pgp-binary 'pgp-backends))
3164 ;;; ----------------------------------------------------------------------
3166 (defsubst tinypgp-backend-exist-pgp2 ()
3167 "Return non-nil if pgp2 is available"
3168 (memq 'pgp2 (tinypgp-backend-list)))
3170 ;;; ----------------------------------------------------------------------
3172 (defsubst tinypgp-backend-exist-pgp5 ()
3173 "Return non-nil if pgp5 is aailable"
3174 (memq 'pgp5 (tinypgp-backend-list)))
3176 ;;; ----------------------------------------------------------------------
3178 (defsubst tinypgp-sign-data-same-p ()
3179 "Compare previous signing info against current buffer content.
3180 If this function returns non-nil, the buffer has been changed and
3181 it should be resigned."
3182 (eq (ti::mail-message-length) tinypgp-:sign-data))
3184 ;;; ----------------------------------------------------------------------
3186 (defsubst tinypgp-sign-data-set ()
3187 "Store sign information."
3188 (if (ti::mail-mail-p)
3189 (setq tinypgp-:sign-data (ti::mail-message-length))))
3191 ;;; ----------------------------------------------------------------------
3193 (defsubst tinypgp-sign-mail-auto-mode-on-p ()
3194 "Check if auto sign is active."
3195 (memq 'tinypgp-sign-mail-func mail-send-hook))
3197 ;;; ----------------------------------------------------------------------
3199 (defsubst tinypgp-mail-buffer-p (&optional msg-flag)
3200 "Check if buffer look like mail message.
3201 Non-nil MSG-FLAG displays message if test is nil."
3202 ;; Gnus uses message-mode
3204 (if (ti::mail-mail-p)
3206 (tinypgpd "tinypgp-mail-buffer-p")
3208 (message "This PGP action is available only in mail, news")
3212 ;;; ----------------------------------------------------------------------
3214 (defsubst tinypgp-hidden-p ()
3215 "Check if the PGP BLOCK is hidden.
3218 (point . invisible-property-value)"
3219 (let* ((point (point-min)) ;Before widen
3220 (pmax (+ (point-max) (* 80 6))) ;lookahead about 6 full lines
3223 ;; first find our property. Then see if it's invisible
3226 ;; In RMAIL buffer this widens a lot!
3228 (setq pos (text-property-any
3230 ;; Select lookahead or point-max.
3231 ;; In RMAIL the pmax is selected.
3233 (min pmax (point-max))
3235 (setq prop (get-text-property pos 'invisible)))
3238 ;;; ----------------------------------------------------------------------
3240 (defsubst tinypgp-user-list (&optional list)
3241 "Add to LIST users from `tinypgp-:encrypt-with-function'."
3242 (let* ((add (if tinypgp-:encrypt-with-function
3243 (funcall tinypgp-:encrypt-with-function))))
3245 (ti::list-merge-elements list add)
3248 ;;; ----------------------------------------------------------------------
3250 (defun tinypgp-user-find-current ()
3253 If buffer is read-only (supposing RMAIL, VM):
3255 look at the PGP stream in buffer and consult `tinypgp-:user-identity-table'.
3257 If buffer is writable:
3259 Do nothing special."
3260 (let ((fid "tinypgp-user-find-current:")
3261 (type (tinypgp-hash 'action 'get 'now nil 'global))
3265 (tinypgpd fid "TYPE" type "READ-ONLY" buffer-read-only (buffer-name)
3266 "remail" tinypgp-:r-mode-indication-flag)
3269 ((or (and (not (member (buffer-name) '("RMAIL" "INBOX")))
3270 (not buffer-read-only))
3271 tinypgp-:r-mode-indication-flag)
3274 (setq type (save-excursion
3276 (ti::mail-pgp-stream-forward-and-study)))
3278 (when (and (eq (car type) 'enc)
3279 (setq key-id (nth 3 type))
3283 tinypgp-:user-identity-table key-id))))
3286 ;;; ----------------------------------------------------------------------
3288 (put 'tinypgp-interactive-enable 'lisp-indent-function 2)
3289 (defmacro tinypgp-interactive-enable (type)
3290 "Check TYPE condition and display MSG if function usage is prohibited."
3293 ((eq (, type) 'remail)
3294 (unless (tinypgp-install-menu-bar-remail)
3295 (message "You haven't configured TinyPgp to use remailers yet.")
3297 (error "See TinyPgp Manual and 'tinypgp-:r-levien-table'")))
3299 ((eq (, type) 'newnym)
3300 (unless (tinypgp-install-menu-bar-newnym)
3302 You haven't ordered newnym account or configured TinyPgp to use it.")
3304 (error "See TinyPgp Manual and 'tinypgp-:r-levien-table'")))
3306 ((eq (, type) 'nymserver)
3307 (unless (tinypgp-install-menu-bar-nymserver)
3309 You haven't ordered nymserver account or configured TinyPgp to use it.")
3311 (error "See TinyPgp Manual and `tinypgp-:nymserver-account-table'")))
3313 (error "Not know type. %s" (, type))))))
3315 (defsubst tinypgp-r-i-enable ()
3316 "Interactive check."
3317 (tinypgp-interactive-enable 'remail))
3319 (defsubst tinypgp-newnym-i-enable ()
3320 "Interactive check."
3321 (tinypgp-interactive-enable 'newnym))
3323 (defsubst tinypgp-nymserver-i-enable ()
3324 "Interactive check."
3325 (tinypgp-interactive-enable 'nymserver))
3328 ;;{{{ macros: misc and inline defsubst
3330 ;;; .......................................................... ¯os ...
3331 ;;; Macros must be defined before used --> keep them at the top of file
3333 ;;; ----------------------------------------------------------------------
3335 (defsubst tinypgp-email-or-string (string)
3336 "Return email address from STRING or STRING itself."
3337 (or (ti::string-match "[^< \t]+@[^ >\t]+" 0 string)
3340 ;;; ----------------------------------------------------------------------
3342 (defsubst tinypgp-comint-buffer ()
3343 "Return comint buffer name."
3344 (concat "*" tinypgp-:buffer-comint "*"))
3346 ;;; ----------------------------------------------------------------------
3347 ;;; - This "stringifies" a regexp :-)
3349 (defsubst tinypgp-cnv (string)
3350 "Remove possible anchor tag or other RE tags from STRING."
3351 (replace-regexp-in-string "[\n\r?$^]+" "" string))
3353 ;;; ----------------------------------------------------------------------
3355 (defsubst tinypgp-pubring-table ()
3356 "Return backend's pubring table."
3357 (or (nth 1 (assq (tinypgp-backend-now) tinypgp-:pubring-table))
3358 (error "tinypgp-:pubring-table is corrupt. No backend %s: %s"
3359 (tinypgp-backend-now)
3360 tinypgp-:pubring-table)))
3362 ;;; ----------------------------------------------------------------------
3364 (defsubst tinypgp-pubring-set-big ()
3365 "Set `tinypgp-:pubring-now' to point to big pubring."
3366 (setq tinypgp-:pubring-now
3367 (nth 1 (car (reverse (tinypgp-pubring-table))))))
3369 ;;; ----------------------------------------------------------------------
3371 (defmacro tinypgp-do-shell-env (&rest body)
3372 "Execute BODY in specific shell environment."
3374 (let* ((pgp-type (tinypgp-backend-type))
3375 (shell (nth 1 (assq pgp-type tinypgp-:pgp-sh-exe)))
3376 (explicit-shell-file-name (or shell
3377 explicit-shell-file-name
3379 (shell-file-name (or shell shell-file-name)))
3380 (if (null explicit-shell-file-name) ;; nop-op Quiet XE ByteCompiler
3381 (setq explicit-shell-file-name nil))
3384 ;;; ----------------------------------------------------------------------
3386 (put 'tinypgp-save-state-macro 'lisp-indent-function 0)
3387 (defmacro tinypgp-save-state-macro (&rest body)
3388 "Save key values of program and execute BODY."
3390 (let ((TINYPGP-user tinypgp-:user-now) ;Mixed case: Prevent variable suicide
3391 (TINYPGP-userp tinypgp-:user-primary)
3392 (TINYPGP-pring tinypgp-:pubring-now)
3393 (TINYPGP-h-s-t tinypgp-:header-sign-table)
3394 (TINYPGP-x-s-m tinypgp-:xpgp-signing-mode))
3395 (prog1 (progn (,@ body))
3396 (setq tinypgp-:user-now TINYPGP-user
3397 tinypgp-:user-primary TINYPGP-userp
3398 tinypgp-:pubring-now TINYPGP-pring
3399 tinypgp-:header-sign-table TINYPGP-h-s-t
3400 tinypgp-:xpgp-signing-mode TINYPGP-x-s-m)))))
3402 ;;; ----------------------------------------------------------------------
3404 (defsubst tinypgp-clone-buffer ()
3405 "Copy content of current buffer to `tinypgp-:buffer-tmp-article'."
3406 (tinypgp-copy-to-buffer (tinypgp-ti::temp-buffer 'article)))
3408 ;;; ----------------------------------------------------------------------
3410 (defun tinypgp-copy-to-buffer (buffer)
3411 "Copy content of current buffer to BUFFER and remove all properties."
3412 (let ((data-buffer (current-buffer)))
3413 (tinypgpd "tinypgp-copy-to-buffer" buffer)
3414 (with-current-buffer (get-buffer-create buffer)
3416 (insert-buffer data-buffer)
3418 ;; SIG may be hidden; Gnus hides headers with properties
3420 (ti::buffer-text-properties-wipe (point-min) (point-max))
3421 (ti::overlay-remove-region (point-min) (point-max))
3424 ;;; ----------------------------------------------------------------------
3426 (put 'tinypgp-run-in-tmp-buffer 'lisp-indent-function 1)
3427 (defmacro tinypgp-run-in-tmp-buffer (buffer &rest body)
3428 "Use BUFFER, which is copy of current buffer, and do BODY.
3429 All text properties in the copy are removed. If BUFFER is nil,
3430 then use internal temporary buffer.
3433 The `set-buffer' command leaves pointer to copy buffer.
3436 `tinypgp-:original-buffer' is set to buffer from where the text was copied."
3438 (let ((Data-buffeR (current-buffer))
3440 (setq BuffeR (or (, buffer) (tinypgp-ti::temp-buffer 'copy)))
3441 (tinypgpd "tinypgp-run-in-tmp-buffer" BuffeR)
3443 (setq tinypgp-:original-buffer Data-buffeR) ;save position
3444 (tinypgp-copy-to-buffer BuffeR)
3446 (with-current-buffer BuffeR
3449 ;;; ----------------------------------------------------------------------
3451 (put 'tinypgp-set-pgp-env-macro 'lisp-indent-function 2)
3452 (defmacro tinypgp-set-pgp-env-macro (user-list &optional verb &rest body)
3453 "Set environment. Find correct keyring and switch to it temporarily.
3454 But only if USER-LIST length is 1; if list is longer, use big pubring
3455 that holds all keys. The VERB parameter must also be set. Do BODY.
3457 Error is signalled if we can't find keyring."
3459 (tinypgp-save-state-macro
3460 ;; Let's be a little user friendly and try finding the key
3463 ((stringp (, user-list))
3466 ((and (ti::listp (, user-list))
3467 (eq 1 (length (, user-list))))
3468 (car (, user-list)))))
3475 (if (not (setq kring (tinypgp-key-find-by-guess user)))
3476 (error "Sorry, can't set keyring '%s'. Fetch key first." user)
3477 (tinypgpd "tinypgp-set-pgp-env-macro" (, user-list) kring )
3478 (setq tinypgp-:pubring-now kring)))
3480 ((ti::listp (, user-list))
3481 ;; Multiple users, set pubring to point to BIG RING
3483 (tinypgpd "tinypgp-set-pgp-env-macro: LAST KRING")
3484 (tinypgp-pubring-set-big))))
3485 (tinypgpd "tinypgp-set-pgp-env-macro: BODY " verb (, user-list)
3486 tinypgp-:pubring-now)
3490 ;;; ----------------------------------------------------------------------
3492 (put 'tinypgp-user-change-macro 'lisp-indent-function 0)
3493 (defmacro tinypgp-user-change-macro (&rest body)
3494 "Change pgp user if From field address match `tinypgp-:user-identity-table'.
3495 If there is no From field or match this macro does nothing to BODY."
3498 (if (setq UseR (tinypgp-user-find-current))
3499 (setq tinypgp-:user-now UseR))
3500 (tinypgpd "tinypgp-user-change-macro: " tinypgp-:user-now)
3503 ;;; ----------------------------------------------------------------------
3505 (defsubst tinypgp-name2alias (str table)
3506 "Return Nth 0 when NTH 1 STR is given from TABLE."
3509 (when (string= str (nth 1 elt))
3514 ;;; ----------------------------------------------------------------------
3516 (defsubst tinypgp-alias2name (str table)
3517 "Return Nth 1 when NTH 0 STR is given from TABLE."
3518 (nth 1 (assoc str table)))
3520 ;;; ----------------------------------------------------------------------
3522 (defsubst tinypgp-x-headers-deinstall ()
3523 "Move X-pgp signature to normal format (if X-pgp exist)."
3524 (tinypgpd "tinypgp-x-headers-deinstall")
3525 (if (ti::mail-pgp-headers-p)
3526 ;; Move X-pgp headers to their normal places
3528 (tinypgp-signature-from-header)))
3530 ;;; ----------------------------------------------------------------------
3532 (defsubst tinypgp-pubring-complete (&optional prompt init)
3533 "Read the pubring name with PROMPT and INIT. Return nil or selected string."
3536 (or prompt "Select pubring: ")
3537 (ti::list-to-assoc-menu (mapcar 'car (tinypgp-pubring-table)))
3545 ;;; ----------------------------------------------------------------------
3547 (defsubst tinypgp-pubring-alias2file (name)
3548 "Find real pubring behind completion NAME."
3550 (tinypgp-expand-file-name
3551 (nth 1 (assoc name (tinypgp-pubring-table))))))
3553 ;;; ----------------------------------------------------------------------
3555 (defun tinypgp-pubring-file2alias (name)
3556 "Find alias for real pubring NAME. Return nil if no match."
3558 (setq name (tinypgp-expand-file-name name))
3559 (dolist (elt (tinypgp-pubring-table))
3560 (when (string= name (tinypgp-expand-file-name (nth 1 elt)))
3561 (setq ret (car elt))
3564 (error "Can't find alias for: %s"))))
3566 ;;; ----------------------------------------------------------------------
3568 (defsubst tinypgp-pubring-list ()
3569 "Return all pubrings known to program."
3571 (dolist (elt (tinypgp-pubring-table))
3572 (push (tinypgp-expand-file-name (nth 1 elt)) list))
3575 ;;; ----------------------------------------------------------------------
3577 (defsubst tinypgp-pubring-many-p ()
3578 "Return non nil if there are many pubrings."
3579 (> (length (tinypgp-pubring-table)) 1))
3581 ;;; ----------------------------------------------------------------------
3583 (defsubst tinypgp-pubring-default ()
3584 "Return first pubring< which is supposed to be default."
3585 (nth 1 (car (tinypgp-pubring-table))))
3587 ;;; ----------------------------------------------------------------------
3589 (defsubst tinypgp-pubring-change-to-current ()
3590 "Change to pubring relative to current user.
3591 Calling function should possibly save the `tinypgp-:pubring-now'."
3592 (setq tinypgp-:pubring-now
3593 (or (tinypgp-key-find-by-cache tinypgp-:user-now)
3594 tinypgp-:pubring-now)))
3596 ;;; ----------------------------------------------------------------------
3598 (defsubst tinypgp-user-change-to-primary ()
3599 "Change current variable settings to reflect primary user.
3600 The calling function should copy the key values of TinyPgp
3601 before calling this function.
3603 This also changes the pubring.
3606 `tinypgp-save-state-macro'"
3607 (tinypgpd "tinypgp-user-change-to-primary" tinypgp-:user-primary )
3608 (setq tinypgp-:user-now tinypgp-:user-primary)
3609 (setq tinypgp-:pubring-now
3610 (tinypgp-expand-file-name
3611 (if (tinypgp-key-find-by-cache
3613 (nth 1 (car (tinypgp-pubring-table)))))))
3615 ;;; ----------------------------------------------------------------------
3617 (defsubst tinypgp-randseed-file ()
3618 "Return randseed filename."
3619 (or (getenv "RANDSEED")
3621 (tinypgp-expand-file-name (or (getenv "PGPPATH") "~/.pgp"))
3624 ;;; ----------------------------------------------------------------------
3626 (defsubst tinypgp-finger-email-filter (list)
3627 "Filter out unwanted entries from email LIST."
3629 (setq list (tinypgp-email-discard-default list))
3630 (when tinypgp-:finger-discard-email-hook
3631 (setq list (run-hook-with-args-until-success
3632 'tinypgp-:finger-discard-email-hook list)))
3635 ;;; ----------------------------------------------------------------------
3637 (defun tinypgp-email-find-region (beg end)
3638 "Read all email addressed from BEG END and filter out unwanted ones.
3639 See. `tinypgp-:finger-discard-email-hook'."
3640 (tinypgp-finger-email-filter
3641 (ti::mail-email-find-region beg end 'no-dupes)))
3645 ;;{{{ misc: messages, error; hash; whatever...
3647 ;;; ----------------------------------------------------------------------
3649 (defun tinypgp-error (message)
3650 "Generate error using MESSAGE and show buffer `tinypgp-:buffer-tmp-shell'.
3651 If the error is in list `tinypgp-:pgp-binary-error-regexp-quiet' then the
3652 shell buffer is not shown."
3654 (tinypgpd "tinypgp-error" message tinypgp-:cmd-macro-after-hook)
3656 (if (not (string-match tinypgp-:pgp-binary-error-regexp-quiet message))
3657 (ti::pop-to-buffer-or-window tinypgp-:buffer-tmp-shell))
3659 ;; We must close the EDIT-RMAIL etc. before calling error.
3661 (run-hook-with-args-until-success 'tinypgp-:cmd-macro-after-hook 'cancel)
3662 (tinypgp-password-expire-now 'keep-tmp-files)
3664 (when (eq '1pass (tinypgp-hash 'action 'get 'detail 'global))
3669 "[possible cause: you don't have all the keys in this keyring.]")))
3670 (error "[PGP executable signalled error] %s" message))
3672 ;;; ----------------------------------------------------------------------
3674 (defun tinypgp-unfinished-function ()
3676 (if (not (string= (getenv "USER") "jaalto"))
3678 Function you tried to call is not yet ready; it's on todo list.")))
3680 ;;; ----------------------------------------------------------------------
3682 (defun tinypgp-initial-message ()
3686 1999-12-10 Development of this package has been stalled and there is no
3687 guarrantees that it will continue to work in new Emacs versions. The last
3688 update was more than year ago and since then I've been busy elswhere.
3689 I do appreciate bug reports, even if I can't adress any of the defects
3690 raised by the reports --The Maintainer.
3692 Emacs debug and TinyPgp debug is now ON."
3694 (let* ((win (selected-window)))
3697 (insert (documentation 'tinypgp-initial-message) "\n\n")
3699 (select-window win)))
3701 ;;; ----------------------------------------------------------------------
3703 (defun tinypgp-hash (var-sym mode &optional property value global)
3704 "Set or get data from obarray.
3705 This function is used for internal data handling for current buffer.
3709 VAR-SYM variable name as symbol
3710 MODE 'put or 'get and 'def checks if defined
3711 PROPERTY property name
3712 VALUE value for property
3713 GLOBAL Instead of using buffer local hash, use global hash table
3717 `tinypgp-:hash-global'"
3719 ;; Make sure these two are initialized.
3720 (unless (vectorp tinypgp-:hash)
3721 (ti::vector-table-init tinypgp-:hash))
3722 ;;; (tinypgpd "HASH INIT" tinypgp-:hash)
3724 ;;; (tinypgpd "HASH" var-sym mode property tinypgp-:hash)
3726 (or (vectorp tinypgp-:hash-global)
3727 (ti::vector-table-init tinypgp-:hash-global))
3729 (let* ((hash (if global
3730 tinypgp-:hash-global
3733 (if (symbolp var-sym)
3734 (setq var-sym (symbol-name var-sym))
3735 (error "TinyPgp: Must give a symbol '%s' " var-sym))
3739 (let* ((sym (ti::vector-table-get hash var-sym)))
3740 (if (null property) ;Check only if variable exist.
3741 (ti::vector-table-get hash var-sym)
3742 (when sym ;Check property list
3743 (memq property (symbol-plist sym))))))
3746 (if (ti::vector-table-get hash var-sym) ;Exist ?
3747 (ti::vector-table-property hash var-sym property)))
3750 (ti::vector-table-get hash var-sym 'allocate)
3751 (ti::vector-table-property hash var-sym property value 'set))
3753 (error "TinyPgp: No such mode '%s' ." mode)))))
3755 ;;; ----------------------------------------------------------------------
3757 (defun tinypgp-update-modeline ()
3758 "Set correct mode name."
3759 (let* ((fid "tinypgp-update-modeline:")
3761 ((tinypgp-backend-pgp2-p)
3763 ((tinypgp-backend-gpg-p)
3771 (setq elt nil)) ;No-op, byteComp silencer
3773 ;; This makes sense only if mode is on.
3776 (tinypgpd fid "BEGIN" (point))
3778 ;; ................................................ update hooks ...
3779 ;; Keep the hooks in proper order, Call function only
3780 ;; periodically every 20th time. (it's too heavy operation to
3781 ;; run all the time)
3783 (inline (tinypgp-install-menu-bar))
3785 (unless (setq elt (tinypgp-hash 'vital-hook 'get 'counter nil 'global))
3787 (tinypgp-hash 'vital-hook 'put 'counter 0 'global))
3789 (when (zerop (% (incf elt) 20))
3790 (tinypgp-install-hooks-vital)
3793 (tinypgp-hash 'vital-hook 'put 'counter elt 'global)
3795 (if D (tinypgpd fid "1" (point)))
3797 ;; ............................................... install check ...
3798 ;; Confirm proper installation. If we see any new packages since last
3799 ;; modeline update, these trigger auto installation.
3801 (if (and (featurep 'gnus) (null (get 'tinypgp-:hash 'gnus-check)))
3802 (tinypgp-install-gnus))
3804 (inline (tinypgp-install-mime-pgp))
3806 (if (and (featurep 'vm) (null (get 'tinypgp-:hash 'vm-check)))
3807 (tinypgp-install-vm))
3809 ;; .............................................. update pubring ...
3810 (setq elt (tinypgp-pubring-elt))
3812 (setq str (concat ;Set pubring indicator
3816 Internal error tinypgp-:pubring-table tinypgp-:pubring-now conflict"))))
3818 (if D (tinypgpd fid "2" (point)))
3820 ;; ..................................................... secring ...
3822 (inline (tinypgp-secring-crypt-mode-detect))
3824 (when tinypgp-:secring-crypt-mode
3825 (setq str (concat str "c")))
3827 ;; ...................................................... remail ...
3829 (if tinypgp-:r-mode-indication-flag
3830 (setq str (concat str "r")))
3832 (when tinypgp-:read-email-after-hook
3833 (if (tinypgp-key-id-conversion-check)
3834 (setq str (concat str "E"))
3835 (setq str (concat str "e"))))
3837 ;; Hmm, Should I call (tinypgp-header-sign-active-list)
3838 ;; Which tells if this message will have headers?
3840 ;; Right now I just show the mode.
3842 (if tinypgp-:header-sign-table
3843 (setq str (concat str "h")))
3845 (if tinypgp-:xpgp-signing-mode
3846 (setq str (concat str "x")))
3848 (when (tinypgp-sign-mail-auto-mode-on-p)
3849 (if (inline (tinypgp-sign-mail-auto-p))
3850 (setq str (concat str "A"))
3851 (setq str (concat str "a"))))
3853 (if D (tinypgpd fid "3" (point)))
3855 ;;; (if (tinypgp-nymserver-mail-p)
3856 ;;; (setq str (concat str "n")))
3858 (when (setq elt (get 'tinypgp-:r-newnym-default-account-table
3859 'default-completion))
3863 (or (nth 3 (assoc elt tinypgp-:r-newnym-default-account-table))
3866 (if D (tinypgpd fid "3.5" (point)))
3870 (if D (tinypgpd fid "3.510" (point)))
3871 (tinypgp-auto-action-multiple-addresses-p))
3872 (if D (tinypgpd fid "3.511" (point)))
3873 (setq str (concat str "$"))
3874 (unless (tinypgp-hash 'auto-action 'get 'user-mode)
3875 (setq str (concat str "-"))))
3878 (if D (tinypgpd fid "3.520" (point)))
3879 (tinypgp-auto-action-on-p))
3880 (if D (tinypgpd fid "3.521" (point)))
3881 (setq str (concat str "!"))
3882 (unless (tinypgp-hash 'auto-action 'get 'user-mode)
3883 (setq str (concat str "-")))))
3885 (if D (tinypgpd fid "4" (point)))
3887 ) ;; check if we know this person: is the
3888 ;; public key pubring info in cache?
3890 (when (and (null buffer-read-only) ;skip RMAIL
3891 (inline (ti::mail-mail-p))
3892 (setq elt (car-safe (ti::mail-email-from-string
3893 (mail-fetch-field "to"))))
3895 ;; Call the conversion if it is activated,
3896 ;; save possibly one function call
3898 (or (and tinypgp-:read-email-after-hook
3899 (setq elt (car-safe (tinypgp-key-id-conversion elt))))
3901 (inline (tinypgp-key-find-by-cache elt "modeline")))
3902 ;; Yes, key is known
3903 (setq str (concat str "k")))
3904 (setq tinypgp-:mode-name str)
3905 (tinypgpd fid "END" (point))
3906 (ti::compat-modeline-update))
3908 ;; These modes may have dynamic mode name later
3909 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. key mode . .
3911 (when tinypgp-key-mode
3912 (setq tinypgp-:key-mode-name " pgpK")
3913 (ti::compat-modeline-update))
3915 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. summary mode . .
3917 (when tinypgp-summary-mode
3918 (setq tinypgp-:summary-mode-name " pgp-sum")
3919 (ti::compat-modeline-update))))
3921 ;;; ----------------------------------------------------------------------
3923 (defun tinypgp-highlight
3924 (regexp &optional level point face ov-type arg1 arg2 arg3)
3926 If Emacs does not support highlight, this function does nothing.
3930 REGEXP string to search
3931 This can also be symbol with special meaning.
3932 Additional arguments are passed in other variables.
3933 'delet-all remove all _tinypgp_ overlays
3934 'wipe-all delete ALL overlays and faces
3935 'match mark matched text
3937 LEVEL which level in string to match, defaults to 0
3938 POINT from which point forward, defaults to `point-min'
3939 FACE defaults to `tinypgp-:face-mark'
3940 OV-TYPE overlay type information. Defaults to 'mark
3941 ARG1 additional arguments to 'match
3944 (when (ti::colors-supported-p)
3946 (let* ((fid "tinypgp-highlight: ")
3949 (setq face (or face tinypgp-:face-mark)
3951 ov-type (or ov-type 'mark)) ;used to be overlay type
3953 (setq plist ;property list
3954 (list 'owner 'tinypgp
3958 (tinypgpd fid "r" regexp "l" level "point" point face ov-type
3964 (goto-char (or point (point-min)))
3965 (ti::text-re-search regexp nil level nil plist))
3968 (tinypgpd fid "level" level arg1 arg2)
3969 (ti::text-match-level level plist arg1 arg2))
3971 ((eq regexp 'delete-all)
3972 (ti::text-clear-region-properties
3973 (point) (point-max) '(owner tinypgp) ))
3975 ((eq regexp 'wipe-all)
3976 (set-text-properties (point) (point-max) nil))
3979 (error "TinyPgp: No such action as '%s'" regexp)))))))
3981 ;;; ----------------------------------------------------------------------
3983 (defun tinypgp-set-session-parameters (action)
3984 "Set program flags according to ACTION.
3985 In some cases the program's parameters must be in certain state
3986 before ACTION 'sign 'encrypt 'decrypt 'verify is carried out.
3988 Here is one reason to do so:
3990 When you sign create command to 'newnym' account: the X-Pgp
3991 signing must not be used, No headers must be signed.
3993 This function should be inside wrapper macro that saves the previous
3994 state of session. Use `tinypgp-save-state-macro'.
3999 (when (ti::mail-mail-p)
4000 (let* ((to (or (mail-fetch-field "to") ""))
4004 "@weasel\\|@squirrel\\|efga\\|nym.alias" to) ;Newnym remailers
4005 (setq tinypgp-:header-sign-table nil
4006 tinypgp-:xpgp-signing-mode nil
4010 ;;; ----------------------------------------------------------------------
4012 (defun tinypgp-add-signature-if-signing ()
4013 "Insert `mail-signature-file' in mail. Do nothing in `message-mode'."
4014 (when (and (boundp 'mail-signature-file)
4018 ;; message-mode , Gnus
4020 (let* ((file (symbol-value 'mail-signature-file))
4023 ;; Gnus composes messages in message-mode,
4025 ;; that buffer because Gnus 5 can add signature when
4026 ;; you compose the mail.
4028 (file-exists-p file)
4029 (null (ti::mail-signature-p))
4031 ;; If we're signing whole mail buffer, then ask if
4032 ;; signature should be added before signing.
4035 "Tinypgp: Add .signature before sign? "))))
4039 (insert-file-contents file)
4040 ;; According to RFC there must be "-- \n" before signature.
4041 (ti::mail-signature-insert-break))
4044 ;;; ----------------------------------------------------------------------
4046 (defun tinypgp-after-pgp-command (&optional cmd &rest args)
4047 "Example function: run after you have executed and some PGP command.
4048 If buffer contains diff (after decrypting) and you have tinydiff.el
4049 loaded, call function `tinydiff-patch' to apply that diff.
4052 CMD ,'encrypt 'sign 'verify ...
4054 (if (and (fboundp 'tinydiff-patch)
4055 ;; We suppose that we're in incoming RMAIL or VM buffer
4057 (memq major-mode '(rmail-mode vm-mode))
4058 (memq cmd '(verify decrypt))
4059 (ti::buffer-diff-type-p)) ;Is there diff
4060 (call-interactively 'tinydiff-patch))
4064 ;;{{{ misc: file control; abbrevs
4066 ;;; ........................................................ &pgp-misc ...
4068 ;;; ----------------------------------------------------------------------
4070 (defun tinypgp-show-last-finger-error ()
4071 "Show last finger error message in echo area."
4073 (if (stringp tinypgp-:last-network-error)
4074 (message tinypgp-:last-network-error)
4075 (message "No Finger error information.")))
4077 ;;; ----------------------------------------------------------------------
4079 (defun tinypgp-view-register (&optional noerr)
4080 "View content of register.
4081 Do not signal error if the register `tinypgp-:register' is empty and
4082 NOERR is non nil. NOERR is automatically t if function is called
4085 (let* ((reg tinypgp-:register)
4086 (msg (format "TinyPgp: register '%c' doesn't contain data yet."
4089 (if (not (stringp (get-register reg)))
4094 (setq win (get-buffer-window tinypgp-:buffer-view t))
4097 (pop-to-buffer (ti::temp-buffer tinypgp-:buffer-view 'clear))
4098 (raise-frame (window-frame win))
4102 (insert-register tinypgp-:register)
4104 (when (interactive-p)
4105 (message "Content of register '%c'" tinypgp-:register)
4108 ;;; ----------------------------------------------------------------------
4110 (defun tinypgp-file-control (mode &optional arg)
4111 "Do file operation according to MODE and ARG.
4123 (tinypgpd "file-control in:" mode arg)
4126 ((eq 'all-kill mode)
4129 tinypgp-:file-source
4130 tinypgp-:file-output
4131 tinypgp-:file-password
4132 tinypgp-:file-user-list))
4133 (if (file-exists-p file)
4134 (delete-file file))))
4136 ((eq 'password-write mode)
4137 (ti::file-delete-safe tinypgp-:file-password)
4139 (with-current-buffer (tinypgp-ti::temp-buffer)
4140 (buffer-disable-undo (current-buffer))
4144 (ti::vector-table-property
4145 tinypgp-:hash-password tinypgp-:user-now 'password)))
4147 (set-buffer-modified-p nil)
4148 (write-region (point-min) (point-max) tinypgp-:file-password)
4150 ;; Don't leave password traces in the buffer
4152 (if (fboundp 'passwd-erase-buffer)
4153 (ti::funcall 'passwd-erase-buffer) ;passwd.el
4154 (let ((s (* (buffer-size) 3))) ;Code copied from passwd.el
4161 (ti::file-mode-protect tinypgp-:file-password)))
4163 ((eq 'password-kill mode)
4164 (if (file-exists-p tinypgp-:file-password)
4165 (delete-file tinypgp-:file-password)))
4167 ((eq 'source-kill mode)
4168 (if (file-exists-p tinypgp-:file-source)
4169 (delete-file tinypgp-:file-source)))
4171 ((eq 'source-write mode)
4172 ;; When wring the file out, it must be exactly
4173 ;; as it appears in buffer
4175 (let* ((require-final-newline nil))
4176 (ti::file-delete-safe
4177 (list tinypgp-:file-source
4178 (concat tinypgp-:file-source ".asc")))
4180 ;; I don't think this is good for Multibyte Chars
4182 ;;; (if (fboundp 'as-binary-process)
4183 ;;; (as-binary-process
4184 ;;; (write-region (point) (point-max) tinypgp-:file-source))
4186 (write-region (point) (point-max) tinypgp-:file-source)
4188 (ti::file-mode-protect tinypgp-:file-source)))
4190 ((eq 'users-write mode)
4191 (ti::file-delete-safe tinypgp-:file-user-list)
4192 (setq buffer (tinypgp-ti::temp-buffer))
4194 (error "No USER LIST"))
4196 (with-current-buffer buffer
4198 (dolist (elt (ti::list-make arg))
4199 (unless (stringp elt)
4200 (error "Users corrupt. Check tinypgp-:encrypt-with-function"))
4201 (insert (ti::string-remove-whitespace elt) "\n"))
4203 (ti::file-delete-safe tinypgp-:file-user-list)
4204 (write-region (point-min) (point-max) tinypgp-:file-user-list)
4205 (ti::file-mode-protect tinypgp-:file-user-list)))
4208 (error "Unknown mode")))))
4210 ;;; ----------------------------------------------------------------------
4212 (defun tinypgp-mail-abbrevs-filter (email-list)
4213 "Filter invalid entries out form EMAIL-LIST.
4214 Every entry must have .xx or .xxx extension, which refers to country
4215 name or organisation form."
4217 (dolist (elt email-list)
4218 (if (string-match "\\....?$" (car (ti::mail-email-from-string elt)))
4222 ;;; ----------------------------------------------------------------------
4224 (defun tinypgp-update-mail-abbrevs ()
4225 "Update mail abbrevs.
4226 You need to do this is you have modified ~/.mailrc.
4227 Call mail abbrev.el first to read the file."
4229 (let* ((sym 'timi-:mail-aliases-alist)
4231 (tinypgpd "update-mail-abbrevs 1:")
4233 ;; since the tinymail.el and tinypgp.el use the same
4234 ;; abbrevs list, it isn't worth to build 2 separate lists,
4235 ;; because creating alist is slow!
4237 ;; Now we share the same list and the abbrevs are built by
4238 ;; tinymail, which we copy here.
4240 (if (and (featurep 'tinymail)
4241 (boundp 'timi-:mail-aliases-alist))
4242 (setq tinypgp-:pgp-email-abbrev-list (symbol-value sym))
4243 (setq tinypgp-:pgp-email-abbrev-list (ti::mail-abbrev-get-alist)))
4245 (tinypgpd "update-mail-abbrevs 2:")
4246 (setq tinypgp-:pgp-email-list
4247 (ti::mail-mail-abbrevs-email-list tinypgp-:pgp-email-abbrev-list))
4249 (tinypgpd "update-mail-abbrevs 3:")
4251 ;; maybe not all are valid in the obarray...
4253 (setq list (funcall tinypgp-:filter-email-function
4254 tinypgp-:pgp-email-list))
4256 (tinypgpd "update-mail-abbrevs 4:")
4257 (setq tinypgp-:pgp-email-list-completions
4258 (ti::list-to-assoc-menu list))
4262 ;;; ----------------------------------------------------------------------
4264 (defun tinypgp-update-mail-abbrevs-hook ()
4265 "Reparse the ~/.mailrc file when it is saved.
4266 This function is installed into `write-file-hooks'."
4267 (when (string-match "\\.mailrc" (or buffer-file-name "#noName"))
4268 (message "Updating mail abbrevs for TinyPgp...")
4269 (tinypgpd "update-mail-abbrevs-hook in:")
4270 (tinypgp-update-mail-abbrevs)
4271 (message "Updating mail abbrevs for TinyPgp...done")
4272 nil)) ;Hook return value
4274 ;;; ----------------------------------------------------------------------
4276 (defun tinypgp-invisible-region (beg end &optional show)
4277 "Make BEG END invisible. Optionally SHOW it."
4278 ;; We also say that these properties belong to "tinypgp"
4279 (let* (buffer-read-only) ;allow writing
4280 (with-buffer-modified
4282 (set-text-properties beg end '(invisible t owner tinypgp))
4283 (set-text-properties beg end '(invisible nil owner tinypgp))))))
4286 ;;{{{ misc: test-p, or or primitives
4288 ;;; ........................................................... &tests ...
4290 ;;; ----------------------------------------------------------------------
4292 (defun tinypgp-pgp-encrypted-p-default ()
4294 ;; this function returns symbol, convert it to string
4297 (if (setq stat (ti::mail-pgp-data-type))
4298 (symbol-name stat)))))
4300 ;;; ----------------------------------------------------------------------
4302 (defun tinypgp-password-time-valid-p ()
4303 "Return non-nil, if it's not yet time to forget password.
4304 The returned value is number of seconds left."
4310 ((not (integerp tinypgp-:password-keep-time))
4313 (if (null (tinypgp-hash 'password-time 'get 'tick nil 'global))
4314 (tinypgp-hash 'password-time 'put 'tick (current-time) 'global))
4316 (setq val (tinypgp-hash 'password-time 'get 'tick nil 'global)
4317 secs-was (nth 1 val)
4318 secs-now (nth 1 (current-time))
4319 diff (- secs-now secs-was)
4320 diff (- tinypgp-:password-keep-time diff))
4325 ;; How much is left, counts down...
4329 ;;{{{ misc: email and substitutions
4331 ;;; ........................................................... &email ...
4333 (defvar tinypgp-:email-substitution-table nil
4334 "Where this variable is used:
4336 Change email addresses if needed to get right public key.
4338 Say, the PGP key-id shows <foo@site.com> as email, but the person also
4339 has mailing address <foo@x-site.com>. If we receive mail from
4340 foo@x-site.com, PGP wouldn't find it from the database if we used
4341 that. Instead we must immediately tell 'hey, this person is known as
4342 <foo@site.com>' which is listed in his key-id field.
4344 How this variable is used:
4346 List of email substitution. When REGEXP is matches then SUBST is used.
4347 SUBST is should match unique key entry in your keyrings. Best if
4348 SUBST is 0xFFFF key id, but many times it more descriptive to use
4349 alternative email address.
4351 Where this variable is used
4353 In function `tinypgp-email-substitution-default' which is installed
4354 to `tinypgp-:read-email-after-hook'
4358 WE CHANGE THIS VARIABLE WITH FUNCTION `tinypgp-email-substitution-add'
4360 ;; List of email addresses that are not in the person's pgp-key id
4361 ;; Use the right Hand key when left hand matches.
4363 (defconst my-:tinypgp-email-substitution-table
4365 (cons \"xxx@.*lycaeum\" \"yyy@lycaeum.org\")
4366 (cons \"xxx.*jena.de\" \"zzz.foo@Jena.Thur.De\")
4368 ;; This one has multiple keys and we want to use one particular.
4369 ;; The 0xFFFF is unique way to tell which key to use
4371 (cons \"valkyr\" \"0xA73B5E6D\"))
4372 \"*My email substitutions that will be added to
4373 `tinypgp-:email-substitution-table'\")
4375 ;; Now add my substitutions
4377 (tinypgp-email-substitution-add my-:tinypgp-email-substitution-table)
4380 '((REGEXP SUBST) (R S) ..)")
4382 ;;; ----------------------------------------------------------------------
4384 (defun tinypgp-email-make-choices (email)
4385 "Make new choices from EMAIL.
4386 If you try to encrypt with EMAIL and it fails; it may be
4387 the case that the email address is not added to user's PGP key-id field.
4389 This function examines EMAIL and constructs some suitable
4390 choices that may match better when doing new lookup.
4401 ;; firstname.surname@site.com --> "Firstname Surname"
4403 (when (string-match "^\\(.*\\)\\.\\(.*\\)@" email)
4404 (setq s1 (capitalize (match-string 1 email))
4405 s2 (capitalize (match-string 2 email)))
4407 ;; Because the firsh name may be shortened
4408 ;; "Rich" is actually "Richard", we want to add the surname
4409 ;; by it self to the list too
4411 (push (concat s1 " " s2) list)
4414 ;; many times the 'server' is local and is not
4415 ;; included in the key id
4417 ;; @server.domain.here.com --> "domain.here.com"
4419 (if (setq str (ti::string-match "@[^.]+\\.\\(.*\\..*\\)" 1 email))
4424 ;;; ----------------------------------------------------------------------
4426 (defun tinypgp-email-discard-default (list)
4427 "Toss away addresses from LIST that are not finger sites.
4429 In-Reply-To: <199611101605.LAA18736@site.com> from Foo Bar at..
4432 (tinypgpd "tinypgp-email-discard-default in: " list )
4435 (dolist (elt (ti::list-make list))
4436 (when (and (not (string-match
4438 "\\(19[89][0-9]\\|200[0-9]\\)[0-9][0-9]"
4439 "\\|^foo\\|^ba[zr]@\\|@site.com"
4440 "\\|[^-_0-9a-zA-Z+]@")
4442 ;; leave only real email addresses
4443 (string-match "@" elt))
4445 (tinypgpd "tinypgp-email-discard-default out: " ret )
4449 ;;; ----------------------------------------------------------------------
4451 (defun tinypgp-email-substitution-add-1 (cons-cell &optional remove)
4452 "Add new CONS-CELL (RE . SUBST) to `tinypgp-:email-substitution-table'.
4453 IF REMOVE is non-nil, search for SUBST and delete the entry
4459 nil ;already exist(add) or not exist(remove)"
4462 (setq elt (rassoc (cdr cons-cell) tinypgp-:email-substitution-table))
4466 (setq tinypgp-:email-substitution-table
4467 (delete elt tinypgp-:email-substitution-table))
4470 ((null elt) ;Add new element if not there.
4471 (setq ret cons-cell)
4472 (push cons-cell tinypgp-:email-substitution-table)))
4475 ;;; ----------------------------------------------------------------------
4477 (defun tinypgp-email-substitution-add (cons-list &optional remove)
4478 "Add CONS-LIST or REMOVE it from list of email substitutions.
4479 The CONS-LIST must be in format:
4481 '((RE . SUBST) (R . S) ..)"
4486 (tinypgp-email-substitution-add-1 x remove)))
4489 ;;; ----------------------------------------------------------------------
4491 (defun tinypgp-email-substitution-default (list)
4492 "Check LIST of email addresses and subtitute them with suitable pgp-ids.
4493 `tinypgp-:email-substitution-table' takes precedence over BBDB record `pgp-id'.
4496 `tinypgp-:email-substitution-table'
4497 `tinypgp-:read-email-after-hook'."
4502 (dolist (email (ti::list-make list))
4504 (dolist (elt tinypgp-:email-substitution-table)
4505 (setq re (car elt) subst (cdr elt))
4507 ((string-match re email)
4508 (setq email subst) ;; substitute and stop loop
4510 ((setq bbdb-pgp-id (tinypgp-bbdb-id email))
4511 (setq email bbdb-pgp-id)
4517 ;;; ----------------------------------------------------------------------
4519 (defun tinypgp-email-substitution-toggle (&optional mode)
4520 "Toggle email substitution.
4521 It is possible that you have coded an email substitution function
4522 and installed it into `tinypgp-:read-email-after-hook'.
4524 If there is such a function; it probably converts some email addresses
4525 to some relevant PGP key ids. However sometimes you may want to turn
4526 off this feature completely to be sure that when reading the
4527 email address eg from TO: field, it will also be used when calling
4530 This functions toggles email substitution functions on/off by
4531 clearing/restoring the `tinypgp-:read-email-after-hook'
4538 (let* ((sym 'tinypgp-:read-email-after-hook))
4540 ;; Not recorded; record original value
4542 (if (null (get sym 'original))
4543 (put sym 'original (symbol-value sym)))
4546 ((or (memq mode '(0 -1))
4549 (message "Email substitution off."))
4551 (set sym (get sym 'original))
4552 (message "Email substitution restored to original.")))
4554 (tinypgp-update-modeline)))
4556 ;;; ----------------------------------------------------------------------
4558 (defun tinypgp-key-id-conversion (single-or-list)
4559 "Modify SINGLE-OR-LIST and return possibly modified list.
4560 Function is used to convert any email address in the list to a suitable pgp
4561 key-id that can be used in place of the 'email' string.
4563 This function stores the list to hash table and reads the
4564 conversion from there if it exist in symbol 'key-id property
4569 `tinypgp-:read-email-after-hook'"
4570 (let* ((fid "tinypgp-key-id-conversion: ")
4571 ;; Make hash access key property
4572 (prop (when single-or-list
4576 (ti::list-make single-or-list)
4580 ;; Because you use the key-id conversion in the program all the
4581 ;; time (called multiple times) and the conversion will
4582 ;; always be same, we save the converted list into hash table
4585 ;; 1. the hash-key is all list strings concatenated
4586 ;; together "me@foo.siteyou@bar.site"
4588 ;; 2. If that hash entry is not found, then we call conversion
4589 ;; function and store the result to hash
4591 ;; 3. Next time the conversion is already available for us
4592 ;; from quick cache.
4594 ;; This should result faster response, becuse calling hook
4595 ;; functions is real slow.
4597 (tinypgpd fid 'KEY prop 'LIST single-or-list)
4599 (when single-or-list
4601 ((tinypgp-hash 'key-id-conversion 'def prop)
4602 (when (setq val (tinypgp-hash 'key-id-conversion 'get prop))
4603 (setq single-or-list val))
4604 (tinypgpd fid 'HASH single-or-list))
4606 (tinypgpd fid 'HOOK tinypgp-:read-email-after-hook)
4607 (dolist (func (ti::list-make tinypgp-:read-email-after-hook))
4608 (setq single-or-list (funcall func single-or-list)))
4610 (tinypgp-hash 'key-id-conversion 'put prop single-or-list)
4611 (tinypgpd fid 'OUT single-or-list))))
4613 (when single-or-list
4614 (ti::list-make single-or-list))))
4616 ;;; ----------------------------------------------------------------------
4618 (defun tinypgp-key-id-conversion-check ()
4619 "Return non-nil if the the conversion happens on TO field.
4620 To field must contain only one address."
4622 (when (ti::mail-mail-p)
4623 ;; Will conversion happen?
4624 ;; - To field must have something
4625 ;; - there must be only one email
4626 ;; - the conversion has changed email.
4628 ((and (not (ti::nil-p (setq elt (mail-fetch-field "To"))))
4629 (not (string-match "," elt))
4630 (not (string= elt (or (car-safe (tinypgp-key-id-conversion elt))
4632 (or (car-safe (tinypgp-key-id-conversion elt))
4637 ;;; ----------------------------------------------------------------------
4639 (defun tinypgp-key-id-conversion-check-verbose ()
4640 "Check if email address conversion is about to happen in To field."
4644 ((null (ti::mail-mail-p))
4645 (message "Email conversion: not a mail buffer, can't read To field."))
4647 (setq stat (tinypgp-key-id-conversion-check))
4649 ((null tinypgp-:read-email-after-hook)
4650 (message "You have turned off Email conversion mode. %s"
4651 (if stat (format "[cnv: %s" stat))))
4654 (message "Conversion to: %s" stat)
4655 (message "No Email conversion trigges"))))))))
4657 ;;; ----------------------------------------------------------------------
4659 (defun tinypgp-key-id-find ()
4660 "Try to find 'Id' 0x12345678 from current buffer. X-Pgp is searched first."
4661 (let* ((list (tinypgp-xpgp-get-info))
4665 ((and list ; Id=0xF72ED579;
4666 (setq elt (assoc "id" list)))
4667 (setq ret (nth 1 elt)))
4668 (t ;No other methods yet.
4674 ;;{{{ buffer: generate, show
4676 ;;; ----------------------------------------------------------------------
4678 (defun tinypgp-ti::temp-buffer (&optional choice arg1 arg2 arg3)
4679 "Create tmp buffer for TinyPgp.el. CHOICE ARG1 ARG2 ARG3 are internal."
4680 (let ((fid "tinypgp-ti::temp-buffer:")
4681 mail-setup-hook ;No hooks now (slow) !
4685 (tinypgpd fid choice arg1 arg2 arg3)
4687 ;; ByteComp silencer, this is no-op
4688 (if mail-setup-hook (setq mail-setup-hook nil))
4689 (if mail-mode-hook (setq mail-setup-hook nil))
4695 (ti::temp-buffer tinypgp-:buffer-tmp-shell 'clear))
4698 (ti::temp-buffer tinypgp-:buffer-tmp-copy 'clear))
4700 ((eq choice 'article)
4701 (ti::temp-buffer tinypgp-:buffer-tmp-article 'clear))
4703 ((eq choice 'finger)
4704 (ti::temp-buffer tinypgp-:buffer-tmp-finger 'clear))
4707 (ti::temp-buffer tinypgp-:buffer-tmp-http 'clear))
4710 (ti::temp-buffer tinypgp-:buffer-tmp-kring 'clear))
4713 (ti::temp-buffer tinypgp-:buffer-tmp-show 'clear))
4716 (ti::kill-buffer-safe tinypgp-:buffer-tmp-mail)
4717 (setq buffer (ti::temp-buffer tinypgp-:buffer-tmp-mail 'clear))
4718 (with-current-buffer buffer
4719 (setq tinypgp-:hash nil) ;Clear hash array
4721 ;; to subject in-reply-to cc replybuffer actions
4723 (mail-setup arg1 arg2 nil arg3 nil nil))
4724 (tinypgpd fid "MAIL OUT")
4728 (ti::temp-buffer tinypgp-:buffer-tmp 'clear))
4730 (error "TinyPgp: No such mode '%s'" choice))))
4732 (with-current-buffer buffer
4733 (defconst font-lock-mode nil)
4734 (defconst lazy-lock-mode nil)
4735 ;; one time scratch buffer
4736 (buffer-disable-undo (current-buffer)))
4740 ;;; ----------------------------------------------------------------------
4742 (defun tinypgp-show-buffer-general (type)
4743 "Pop to buffer TYPE."
4746 ((eq type 'comint) (tinypgp-comint-buffer))
4747 ((eq type 'debug) tinypgp-:debug-buffer)
4748 ((eq type 'finger) tinypgp-:buffer-tmp-finger)
4749 ((eq type 'http) tinypgp-:buffer-tmp-http)
4750 ((eq type 'shell) tinypgp-:buffer-tmp-shell)
4751 ((eq type 'tmp) tinypgp-:buffer-tmp))))
4754 (error "TinyPgp: Wrong type '%s' " type))
4755 ((get-buffer buffer)
4756 (pop-to-buffer buffer))
4758 (message "Buffer does not exist: '%s'" buffer)))))
4760 (defun tinypgp-show-buffer-comint ()
4762 (interactive) (tinypgp-show-buffer-general 'comint))
4764 (defun tinypgp-show-buffer-debug ()
4766 (interactive) (tinypgp-show-buffer-general 'debug))
4768 (defun tinypgp-show-buffer-finger ()
4770 (interactive) (tinypgp-show-buffer-general 'finger))
4772 (defun tinypgp-show-buffer-http ()
4774 (interactive) (tinypgp-show-buffer-general 'http))
4776 (defun tinypgp-show-buffer-shell ()
4778 (interactive) (tinypgp-show-buffer-general 'shell))
4780 (defun tinypgp-show-buffer-tmp ()
4782 (interactive) (tinypgp-show-buffer-general 'tmp))
4787 ;;; ----------------------------------------------------------------------
4789 (defun tinypgp-pubring-elt ()
4790 "Return active pubring ELT."
4791 (let* ((ring (tinypgp-expand-file-name tinypgp-:pubring-now))
4794 (dolist (elt (tinypgp-pubring-table))
4795 (setq kring (nth 1 elt))
4798 ;; Second element must be filename string
4799 (when (string= ring (tinypgp-expand-file-name kring))
4803 (error "Invalid format: tinypgp-:pubring-table, please check."))))
4806 (error "tinypgp-:pubring-table, can't find tinypgp-:pubring-now?"))
4810 ;;; ----------------------------------------------------------------------
4812 (defun tinypgp-pubring-ask (&optional msg)
4813 "Ask pubring with MSG and offer 'alias' completion.
4820 (tinypgp-pubring-complete
4824 "Ok to use pubring '%s' [ret=yes]? "
4825 (or (tinypgp-pubring-file2alias tinypgp-:pubring-now)
4828 (if (not (ti::nil-p ret))
4829 (setq ret (tinypgp-pubring-alias2file ret))
4832 (tinypgpd "tinypgp-pubring-ask out: " ret )
4835 ;;; ----------------------------------------------------------------------
4837 (defun tinypgp-pubring-in-use-confirm ()
4838 "Change pubring if it is not the first entry in `tinypgp-pubring-table'.
4839 Ask confirmation for the change. The calling
4840 function should bound variable `tinypgp-pubring-table' locally,
4841 because it may be changed here.
4844 `tinypgp-save-state-macro'"
4845 (let ((first (tinypgp-expand-file-name
4846 (nth 1 (car (tinypgp-pubring-table)))))
4847 (now (tinypgp-expand-file-name tinypgp-:pubring-now)))
4848 (when (not (string= first now))
4849 (setq now (tinypgp-pubring-ask))
4851 (setq tinypgp-:pubring-now now)
4852 (tinypgpd "tinypgp-pubring-in-use-confirm out: "
4853 tinypgp-:pubring-now)))))
4856 ;;{{{ pubring: interactive
4858 ;;; ----------------------------------------------------------------------
4860 (defun tinypgp-pubring-display ()
4861 "Show current pubring in use."
4863 (message "Current pubring: %s" tinypgp-:pubring-now)
4864 (sit-for 1)) ;; If drawn from menu, the mouse move wipes it away..
4866 ;;; ----------------------------------------------------------------------
4868 (defun tinypgp-pubring-set-current (alias)
4869 "Set active pubring using ALIAS and update mode line."
4870 (interactive (list (tinypgp-pubring-complete "Set active pubring to: ")))
4872 (setq tinypgp-:pubring-now
4873 (tinypgp-expand-file-name (nth 1 (assoc alias
4874 (tinypgp-pubring-table)))))
4876 (if (not (file-exists-p tinypgp-:pubring-now))
4877 (error "No pubring file %s" tinypgp-:pubring-now))
4879 (tinypgpd "tinypgp-pubring-set-current out: " alias tinypgp-:pubring-now)
4881 (tinypgp-update-modeline)
4883 (tinypgp-pubring-display))))
4886 ;;{{{ user: general, interactive
4888 ;;; ----------------------------------------------------------------------
4890 (defun tinypgp-user-in-use-confirm (&optional msg)
4891 "Change user if Primary user is not active ask confirmation with MSG."
4896 "Not primary, change user id to [empty = no change]: "))
4897 (if (and (not (string-match
4898 (regexp-quote tinypgp-:user-primary) tinypgp-:user-now))
4901 (setq ans (read-from-minibuffer msg tinypgp-:user-now)))))
4902 (setq tinypgp-:user-now ans))))
4904 ;;; ----------------------------------------------------------------------
4906 (defun tinypgp-user-display ()
4909 (ti::read-char-safe-until (concat "Current user: " tinypgp-:user-now)))
4911 ;;; ----------------------------------------------------------------------
4913 (defun tinypgp-user-set-current (user)
4918 (format "[%s] Set pgp user to: " tinypgp-:user-now)
4919 tinypgp-:pgp-email-list-completions
4921 'tinypgp-:history-email)))
4923 (if (ti::nil-p user)
4924 (error "Invalid input."))
4926 (setq tinypgp-:user-now user)
4928 (tinypgp-user-display)))
4933 ;;; ----------------------------------------------------------------------
4935 (defun tinypgp-key-cache (mode &optional data1 data2 data3)
4936 "Function to control caching of key-id and.
4937 The cache hook tells if the entry should be cached when MODE is 'put
4939 When inserting new keys into cache, every 3rd key triggers saving
4944 `tinypgp-:key-cache'
4945 `tinypgp-:key-cache-last'
4949 'get look for data1 from cache and return cache entry or nil
4950 'put cache entries data1, data2, data3
4951 'del remove named entry from cache. Do nothing if no such entry.
4961 (let ((last tinypgp-:key-cache-last)
4962 (data1-orig data1) ;Email may be changed
4963 (debug nil) ;developer's manual debug flag
4964 (fid "tinypgp-key-cache: ")
4967 ;; The cache is used only if user has multiple pubrings
4968 (when (tinypgp-pubring-many-p)
4970 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. fast case . .
4971 ;; Remember that modeline calls us many times
4973 (cond ;Is the entry in QUICK cache?
4974 ((and last ;bypass everything if we find it
4975 (eq mode 'get) ;many time we call 'get successively
4976 (string= (car last) data1))
4977 (setq ret (nth 1 (nth 1 last)))
4980 (tinypgpd fid "fast get" data1 ret )))
4983 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . normal case ..
4985 ;;; (ti::d! "C in: " mode data1 data2)
4987 (setq data1 (ti::remove-properties data1))
4990 (setq data2 (ti::remove-properties data2)))
4993 (tinypgpd fid "in:" 'MODE mode 'DATA1 data1 'DATA2 data2))
4995 ;;; (ti::d! "Cache name>>" data1 data2)
4997 ;; Note: I used elp.el to check if the obarray method
4998 ;; would be faster, but it seems that at least for single entry
4999 ;; the list implementation is faster? I was suprised..
5001 (if (not (listp tinypgp-:key-cache)) ;make sure this is a list
5002 (setq tinypgp-:key-cache nil))
5007 (when (setq ret (assoc data1 tinypgp-:key-cache))
5008 (setq tinypgp-:key-cache-last (list data1-orig ret))
5009 (setq ret (nth 1 ret))))
5012 (if (setq ret (assoc data1 tinypgp-:key-cache))
5013 (adelete 'tinypgp-:key-cache (car ret))))
5016 (if (and (null (assoc data1 tinypgp-:key-cache)) ;; Already there ?
5017 (< (length tinypgp-:key-cache) 300)) ;Hard limit
5018 (push (list data1 data2 data3) tinypgp-:key-cache ))
5020 ;; Save every 3rd new entry.
5022 (if (eq (% (length tinypgp-:key-cache) 3) 0)
5023 (tinypgp-key-cache-save)))))))
5026 (tinypgpd fid "out: RET" ret))
5030 ;;; ----------------------------------------------------------------------
5032 (defun tinypgp-key-cache-save (&optional load)
5033 "Save or LOAD the key cache file.
5034 If the underlying cache file has recent copy; the SAVE is not
5035 performed, but the newer copy reloaded and evaluated.
5037 Signal no erro if LOAD cannot find cache file."
5038 (let* ((fid "tinypgp-key-cache-save:")
5039 (file (or (tinypgp-backend-file tinypgp-:file-key-cache)
5040 (error "TinyPgp: Internal cache error")))
5041 (list tinypgp-:key-cache)
5043 (olen (tinypgp-hash 'cache 'get 'len nil 'global))
5046 (tinypgpd fid "in: FILE" file 'LEN len 'OLEN olen 'LOAD-FLAG load)
5050 (when (file-exists-p file)
5051 (with-current-buffer (find-file-noselect file)
5052 (if (fboundp 'eval-buffer) ;XE 19.14
5053 (ti::funcall 'eval-buffer)
5054 (ti::funcall 'eval-current-buffer))
5057 ;; ......................................................... save ...
5059 ;; There may be several emacsen running, and they may have saved the
5060 ;; cache too. Reload the file if it is newer that the buffer
5061 ;; in this emacs (it has been saved by some other emacs)
5063 (when (and (buffer-live-p (setq buffer (find-buffer-visiting file)))
5064 (with-current-buffer buffer (ti::file-changed-on-disk-p)))
5065 (with-current-buffer buffer
5066 (revert-buffer t t) ;No confirmations
5067 (if (fboundp 'eval-buffer) ;XE 19.14
5068 (ti::funcall 'eval-buffer)
5069 (ti::funcall 'eval-current-buffer)
5072 (when (and (null done)
5073 ;; Something to save? Has Length changed
5074 (or (not (eq len olen))
5076 (not (file-exists-p file))))
5077 (tinypgp-hash 'cache 'put 'len len 'global)
5078 (with-current-buffer (find-file-noselect file)
5080 (insert ";;\n;;\tEmacs TinyPgp.el: key cache file\n;;\n\n")
5081 (insert "(defconst tinypgp-:key-cache\n '(\n")
5082 (dolist (elt list) (insert " " (prin1-to-string elt) "\n"))
5083 (insert " ))\n\n;; End of file\n")
5087 ;;; ----------------------------------------------------------------------
5089 (defun tinypgp-key-cache-display (&optional verb)
5090 "Print contents of cache. VERB."
5092 (tinypgp-key-cache-save) ;; Save latest first
5093 (let* ((fid "tinypgp-key-cache-display:")
5094 (file (tinypgp-backend-file tinypgp-:file-key-cache))
5095 (buffer (or (find-buffer-visiting file)
5096 (and (file-exists-p file)
5097 (find-file-noselect file)))))
5098 (tinypgpd fid file buffer)
5100 (error "Can't display %s" file)
5101 (display-buffer buffer))))
5103 ;;; ----------------------------------------------------------------------
5105 (defun tinypgp-key-cache-remove-entry-last ()
5106 "Clear last fast cache entry."
5108 (setq tinypgp-:key-cache-last nil)
5110 (message "Cleared last cache entry.")))
5112 ;;; ----------------------------------------------------------------------
5114 (defun tinypgp-key-cache-remove-entry (string &optional raw-entry)
5115 "Read email addresses from string and remove it from cache.
5118 STRING String ==> email address is picked from it
5119 RAW-ENTRY if nono-nil, then bypass call to
5120 `tinypgp-:read-email-after-hook' which may change the string"
5121 (let* ((fid "tinypgp-key-cache-remove-entry: ")
5123 (tinypgpd fid "in:" raw-entry string )
5125 (when (tinypgp-pubring-many-p)
5129 (tinypgp-key-cache 'del string))
5132 (or (setq list (ti::mail-email-from-string string))
5133 (setq list (list string)))
5135 (when elt ;; Should we change the keyId that is read from field?
5136 (setq elt (car (tinypgp-key-id-conversion elt))))
5137 (tinypgp-key-cache 'del elt))))
5139 (tinypgp-key-cache-remove-entry-last))))
5141 ;;; ----------------------------------------------------------------------
5143 (defun tinypgp-key-generate
5144 (key-bit-choice user-id pass-phrase &optional verb)
5145 "Generate new key. Only default key sizes are supported.
5148 KEY-BIT-CHOICE 1,2 or 3
5162 (setq key (completing-read "Key size: " key-list nil 'match-it "768"))
5163 (if (null (setq key (tinypgp-alias2name key key-list)))
5164 (error "No key choice found."))
5166 (setq user (read-from-minibuffer "User id for your public key: "))
5167 (if (ti::nil-p user)
5168 (error "Empty user id."))
5170 (setq pass (ti::compat-read-password "Pass phrase: "))
5171 (if (ti::nil-p pass)
5172 (error "Empty pass phrase"))
5174 (list key user pass)))
5176 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... body . .
5178 (if (not (and (memq key-bit-choice '(1 2 3))
5180 (stringp pass-phrase)))
5181 (error "Arg error."))
5183 (let* ( ;; (BCMD (tinypgp-binary-get-cmd 'key-generate))
5184 ;; (cmd (tinypgp-cmd-compose BCMD user-id pass-phrase))
5187 (tinypgp-unfinished-function)
5189 (tinypgp-save-state-macro
5190 (if verb (tinypgp-pubring-in-use-confirm)))
5193 (message "Generating new user-id...done."))
5199 ;;{{{ misc: auto-action
5201 ;;; ..................................................... &auto-action ...
5203 ;;; ----------------------------------------------------------------------
5205 (defun tinypgp-auto-action-on-modeline-p ()
5206 "Check if mode line string say that auto action in 'on'."
5207 (and (stringp tinypgp-:mode-name)
5208 (string-match "!$\\|!k" tinypgp-:mode-name)))
5210 ;;; ----------------------------------------------------------------------
5212 (defun tinypgp-auto-action-on-p ()
5213 "Check is user has allowed action and if action exists."
5214 ;; There is no auto action for read only buffer like RMAIL
5215 (tinypgpd "tinypgp-auto-action-on-p: "
5217 (tinypgp-hash 'auto-action 'def 'user-mode)
5218 (tinypgp-hash 'auto-action 'get 'user-mode))
5220 (when (and (null buffer-read-only)
5222 (unless (tinypgp-hash 'auto-action 'def 'user-mode)
5223 ;; Not defined, initialize
5224 (tinypgpd "tinypgp-auto-action-on-p: SET DEFAULT")
5225 (tinypgp-hash 'auto-action 'put 'user-mode t))
5226 (tinypgp-auto-action-p 'read-hash)))
5228 ;;; ----------------------------------------------------------------------
5230 (defun tinypgp-auto-action-defeat-p ()
5231 "Check if auto action should be cancelled."
5232 ;; Forget mime multiparts/PGP signed.
5233 (ti::mail-mime-maybe-p))
5235 ;;; ----------------------------------------------------------------------
5237 (defun tinypgp-auto-action-verbose ()
5238 "Show auto-action entry to user.
5239 If auto action is found it is also available from `tinypgp-:register'."
5242 (tinypgpd "tinypgp-auto-action-verbose in:")
5245 ((ti::mail-mime-maybe-p)
5246 (message "TinyPgp; Looks like MIME message, no auto action allowed"))
5248 ((tinypgp-auto-action-multiple-addresses-p 'force)
5249 (message "TinyPgp; encryption to multiple recipients pending."))
5251 ((setq elt (tinypgp-auto-action-p))
5252 (message "TinyPgp; Auto-action triggers: %s" (prin1-to-string elt))
5253 (set-register tinypgp-:register (prin1-to-string elt)))
5256 (message "TinyPgp; There is no auto action that would activate.")))
5257 (tinypgp-update-modeline)))
5259 ;;; ----------------------------------------------------------------------
5261 (defun tinypgp-auto-action-update-modeline ()
5262 "Do auto action check and update mode line."
5263 (tinypgp-auto-action-p)
5264 (tinypgp-update-modeline))
5266 ;;; ----------------------------------------------------------------------
5268 (defun tinypgp-auto-action-p (&optional read-hash)
5269 "Check if auto-action entry is defined for current (email) buffer.
5270 If buffer is read only, this does nothing.
5271 Any MIME message in buffer suppresses auto-action.
5275 Multiple recipients are not checked, Only To address.
5276 See `tinypgp-auto-action-multiple-addresses-p' for that.
5280 `tinypgp-:auto-action-table'
5284 READ-HASH non-nil instructs to read the value
5285 from storage, if the TO: address hasn't changed.
5286 This is faster than evaluating the list every time.
5290 elt entry from action table"
5291 (let ( ;; (EVAL-OR-STRING SIGN-FLAG [ENCRYPT-FLAG] [KEYRING])
5292 (fid "tinypgp-auto-action-p: ")
5293 (tbl tinypgp-:auto-action-table)
5295 ;; We don't enable this because timer calls us
5296 ;; Only when we debug the function
5300 ;; These tags must be broken in this file so that TM won't get upset
5303 ;; -- } - <<signed>>
5304 ;; -- } - <<encrypted>>
5306 (mime-p (ti::re-search-check "--[}]-<<"))
5313 ;; This function is called from a timer process to update the
5314 ;; modeline, that's why we can't afford to rescan the auto-action
5315 ;; list all the time: it takes too much time.
5317 ;; Instead, we store the found ACTION to hash table and read the
5318 ;; hash entry. The drawback is that if user goes and changes
5319 ;; the auto action table, we can't tell about it in the modeline.
5321 ;; Used local hash properties on variable 'auto-action
5322 ;; 'user-mode bool t = ok, nil = defeated by user
5323 ;; 'to-field string to field contents
5324 ;; 'elt lisp stored auto action.
5326 ;; If not yet defined, set the auto action to 't'
5327 ;; User may defeat the action manually.
5329 (if (tinypgp-hash 'auto-action 'def 'user-mode)
5330 (setq user-mode (tinypgp-hash 'auto-action 'get 'user-mode))
5331 (tinypgp-hash 'auto-action 'put 'user-mode t)
5334 ;; Should always be a string otherwise lot of code breaks.
5336 (unless (stringp tinypgp-:user-now)
5338 Tinypgp: Warning, tinypgp-:user-now is not a string. Fixing...")
5340 (setq tinypgp-:user-now (user-login-name)))
5342 ;; TO FIELD: see what we have in the hash table
5344 (setq val (tinypgp-hash 'auto-action 'get 'to-field))
5348 "read-only" buffer-read-only
5349 "USER-MODE" user-mode
5350 "mail" (ti::mail-mail-p)
5351 "pgp" (ti::mail-pgp-p)
5352 "MIME" (ti::mail-mime-maybe-p) mime-p
5353 "remail" tinypgp-:r-mode-indication-flag
5354 "READ HASH" read-hash
5356 "to-field" (mail-fetch-field "to")))
5358 (when (and (ti::mail-mail-p)
5359 (null buffer-read-only)
5361 ((or (ti::mail-mime-maybe-p) mime-p)
5362 ;; MIME found, defeat auto action immediately.
5364 (tinypgp-hash 'auto-action 'put 'elt nil)
5368 ;; only if there is no previous PGP,
5369 ;; If there is PGP, let go through is there is
5370 ;; remailer message Eg. newnym account create where
5371 ;; you send you PGP key in buffer.
5373 (if (ti::mail-pgp-p)
5374 (if tinypgp-:r-mode-indication-flag
5378 (not (ti::nil-p (setq to-field (mail-fetch-field "to"))))
5379 (not (string-match "," to-field)) ;skip multiple addresses
5380 (ti::nil-p (mail-fetch-field "cc")))
5382 ;; .................................................. hash check ...
5386 val ;previous TO field in HASH ?
5387 (string= to-field val)) ;compare previous with current TO
5388 (setq val (tinypgp-hash 'auto-action 'get 'elt))
5389 (when debug (tinypgpd fid "hash ret"))
5392 ;; .................................................. raw check ...
5396 ;; Empty field with spaces does not come here
5397 ;; To field has changed, we must calculate new entry
5398 ;; OR the hash-get wasn't set.
5400 (tinypgp-hash 'auto-action 'put 'to-field to-field)
5401 (tinypgp-hash 'auto-action 'put 'elt nil)
5402 (when debug (tinypgpd fid "evaluate"))
5404 ;; First check BBDB entry
5406 (setq ret (tinypgp-bbdb-entry))
5407 (when debug (tinypgpd fid to-field "BBDB" ret))
5409 ;; And this table overrrides bbdb
5412 (setq val (nth 0 elt))
5413 (when debug (tinypgpd fid "action tbl" val))
5414 (when (or ;Try to match
5416 (string-match val to-field))
5417 (and (symbolp val) (not (ti::bool-p val))
5423 (tinypgp-hash 'auto-action 'put 'elt ret))))) ;Save it!
5426 (tinypgpd fid "RET" ret))
5429 ;;; ----------------------------------------------------------------------
5431 (defun tinypgp-auto-action ()
5432 "Determine right auto action for mail message.
5433 If auto-action has been disabled or if `tinypgp-mode' is off, do nothing.
5437 `tinypgp-:header-sign-table'
5438 `tinypgp-:auto-action-table'
5439 `tinypgp-:auto-action-defeat-hook'"
5440 (tinypgpd "tinypgp-auto-action: function entry")
5441 (let ((fid "tinypgp-auto-action: ")
5442 (umode (tinypgp-hash 'auto-action 'get 'user-mode))
5443 (multi-flag (tinypgp-auto-action-multiple-addresses-p 'force))
5444 (pgp-p (ti::mail-pgp-p))
5446 sign enc mime-mua xpgp keyr
5451 (tinypgpd fid 'user-mode umode 'multi-flag multi-flag 'pgp-p pgp-p)
5454 (run-hooks 'tinypgp-:auto-action-before-hook)
5457 ;; ............................................ user defeat ...
5460 (run-hook-with-args-until-success
5461 'tinypgp-:auto-action-defeat-hook))
5462 (tinypgpd fid "defeated")
5465 ;; ........................................... nymserver-cc ...
5467 ((and (tinypgp-nymserver-mail-p)
5468 (tinypgp-nymserver-send)) ;Maybe no multi-CC ?
5469 (tinypgpd fid "Nymserver"))
5471 ;; ............................................... defeated ...
5473 ((not umode) ;User has defeated the action
5474 (tinypgpd fid "Umode")
5477 ;; ............................................ encrypt-to-many ...
5480 (tinypgpd fid "Multi")
5481 (tinypgp-auto-action-multiple-addresses))
5483 ;; ............................................ auto-action ...
5485 ((and (not (ti::nil-p (setq to-field (mail-fetch-field "to"))))
5487 ;; The Addresses must be expanded so that they have @
5489 (string-match "@" to-field)
5491 ;; Force reading real action. If user has made changes
5492 ;; in his rc file; this guarrantees that we see them.
5494 (setq elt (tinypgp-auto-action-p))
5496 ;; returns a list of email strings
5498 (setq email (ti::mail-email-from-string to-field)))
5500 (tinypgpd fid "--Action--" 'TO to-field 'EMAIL email 'ELT elt)
5502 (setq len (length elt)
5504 keyr tinypgp-:pubring-now)
5506 ;; Should we change the key-id that is read from field?
5508 (setq email (car-safe (tinypgp-key-id-conversion email)))
5512 (setq enc (if (> len 2) (nth 2 elt))
5513 mime-mua (if (> len 3) (nth 3 elt))
5514 xpgp (if (> len 4) (nth 4 elt))
5515 keyr (tinypgp-expand-file-name
5519 ((tinypgp-key-find-by-keyrings email))
5521 tinypgp-:pubring-now))))
5523 ;; XE byteCompiler 19.14 has bug here, it reports that
5524 ;; variable 'xpgp bound but not referenced, allthoug
5525 ;; it is used in 'let' stement underneath! The following
5526 ;; silences byteCompiler.
5528 (if (null xpgp) (setq xpgp nil))
5530 (tinypgpd fid "addr" email "ENC" enc "SIGN" sign "XP" xpgp
5531 "KEY" keyr "MUA" mime-mua elt)
5534 (null (ti::mail-mime-tm-featurep-p))
5535 (null (ti::mail-mime-semi-featurep-p)))
5538 Auto-action: PGP/MIME requested but no TM/SEMI mime support present.")
5544 ;; These only add the TAGS into the buffer. SEMI/TM
5545 ;; hook handles the actual work of turning then to PGP/MIME
5546 ;; --> It calls TinyPgp to do it.
5548 (if sign (ti::mail-mime-sign-region))
5549 (if enc (ti::mail-mime-encrypt-region)))
5551 (tinypgp-save-state-macro
5552 (if sign (setq tinypgp-:user-now
5553 (if (and (not (ti::bool-p sign))
5554 (symbolp sign)) ;One pass encrypt/sign
5557 (if keyr (setq tinypgp-:pubring-now keyr))
5558 (setq tinypgp-:xpgp-signing-mode xpgp)
5560 (tinypgpd fid "SIGN" sign "KEY" keyr tinypgp-:user-now "KRING" keyr)
5562 ;; ............................................ do encrypt ...
5565 (when (and (not (ti::bool-p sign)) (symbolp sign))
5566 (tinypgp-password-set
5567 (format "[%s] Auto-action sign password: "
5568 tinypgp-:user-now)))
5569 (tinypgp-encrypt-mail
5571 (not 'register-insert)
5572 (if (and (not (ti::bool-p sign)) (symbolp sign))
5577 ;; ......................................... possibly sign ...
5579 (when (and sign (stringp sign))
5580 (tinypgp-password-set
5581 (format "Auto-action, Sign pass phrase %s: " tinypgp-:user-now))
5583 ;; The previous function call may have changed the user,
5584 ;; keep the pubring also in sync
5586 (tinypgp-pubring-change-to-current)
5587 (call-interactively 'tinypgp-sign-mail))))))
5589 ;; ........................................... auto-encrypt ...
5590 ;; If there is no auto action, we check if we have previously
5591 ;; encrypted to that person.
5593 ((and (null (ti::mail-pgp-p)) ;No previsou pgp
5594 (not (ti::nil-p (setq to-field (mail-fetch-field "to"))))
5596 (tinypgp-key-find-by-cache
5597 (car-safe (ti::mail-email-from-string to-field)))))
5598 (tinypgpd fid "encrypt guess" to-field elt)))
5600 ;; We actually do nothing here...but the code is ready
5601 ;; (tinypgp-encrypt-mail email)
5603 (tinypgpd fid "out:" (current-buffer))
5605 ;; ..................................................... restore ...
5607 ;; If this was nym create request, restore pgp user
5608 ;; - If there are these buffer local variables and PGP msg found
5609 ;; - If saver "now" is "now"; ie. user hasn't changed active user
5610 ;; after the create request was started.
5611 ;; - THEN restore the original pgp user
5613 (when (and (boundp 'tinypgp-pgp-user-original)
5614 (boundp 'tinypgp-pgp-user-now)
5616 (let* ((orig (symbol-value 'tinypgp-pgp-user-original))
5617 (now (symbol-value 'tinypgp-pgp-user-now)))
5618 (if (string= now tinypgp-:user-now)
5619 (setq tinypgp-:user-now orig))))
5621 ;;; (ti::d! "AUTO-ACT done" email)
5624 ;;; ----------------------------------------------------------------------
5626 (defun tinypgp-auto-action-multiple-addresses-p (&optional force)
5627 "Check multiple address auto-action. Optionally FORCE raw check."
5628 (and (null (tinypgp-nymserver-mail-p))
5629 (tinypgp-auto-action-multiple-addresses 'check force)))
5631 ;;; ----------------------------------------------------------------------
5633 (defun tinypgp-auto-action-multiple-addresses (&optional mode force)
5634 "Determine if multiple address encryption will be done.
5635 Function does nothing if buffer is read only
5639 MODE If 'check, then return nil or t if auto-action
5640 is in progress. Any other value starts auto-encryption
5641 if the conditions are met.
5643 FORCE Force re-evaluating the buffer check (normally read result
5644 from stored value in hash table)
5648 non-nil auto action in progress. All recipientsents have PGP
5649 LIST '(email email ..) There were many recipients
5650 but not all members members have PGP. This is list of email
5651 addresses that had PGP.
5656 `tinypgp-:auto-action-encrypt-regexp'
5657 `tinypgp-:auto-action-encrypt-ok-hook'"
5658 (let* ((re tinypgp-:auto-action-encrypt-regexp)
5659 (fid "tinypgp-auto-action-multiple-addresses: ")
5660 (debug nil) ;func is Called by timer...
5669 ;; Because this function is called from timer process, the
5670 ;; 'check must be very quick in order not to decrease
5671 ;; emacs performance
5674 ;; We count the length of the header area and put that value
5675 ;; into property. If the size has changed, we reread
5676 ;; the To,CC,BCC headers again and do the checking
5678 ;; If the headers have not changed, then we don't do time
5679 ;; consuming parse, but assume thet 'many-addr-hsize value
5680 ;; is valid (No changes compared to last parse)
5683 ;; Holds value t or nil if auto action should be engaged.
5685 (if debug (tinypgpd fid
5688 'mail (ti::mail-mail-p)
5691 (when (and (ti::mail-mail-p) ;Only do in mail buffers
5692 (null buffer-read-only))
5693 (setq hsize (ti::mail-header-area-size)
5694 hsize-prev (tinypgp-hash 'auto-action 'get 'many-addr-hsize))
5700 (ti::mail-get-all-email-addresses
5701 nil tinypgp-:pgp-email-abbrev-list)
5705 (if force (setq hsize nil hsize-prev 1)) ;Re-evaluate.
5708 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .
5709 ((and (eq hsize hsize-prev)
5711 ;; return the precalculated status
5713 (setq ret (tinypgp-hash 'auto-action 'get 'many-addr-stat))
5714 (if debug (tinypgpd fid 'cond1-hash ret (point))))
5716 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .
5718 ((eq hsize hsize-prev) ;Not check mode, do action
5719 (if debug (tinypgpd fid 'cond2-enc ret (point)))
5720 (if (and (tinypgp-hash 'auto-action 'get 'many-addr-stat)
5721 (not (ti::mail-pgp-p))) ;No previous pgp
5722 (tinypgp-encrypt-mail-verbose)))
5724 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. recalculate . .
5725 ;; *) The size has changed, so update it immediately.
5726 ;; *) put initial value into the property, because we may not enter
5727 ;; the case at all if list is empty
5729 ;; The rest of the 'and' are real tests
5732 (tinypgp-hash 'auto-action 'put 'many-addr-hsize hsize)
5733 (tinypgp-hash 'auto-action 'put 'many-addr-stat nil))
5734 (setq list (ti::mail-get-all-email-addresses
5735 nil tinypgp-:pgp-email-abbrev-list))
5736 (> (setq len (length list)) 1))
5737 (if debug (tinypgpd fid 'cond3 len list (point)))
5738 ;;; (ti::d! "HZ" hsize (tinypgp-hash 'auto-action 'get 'many-addr-hsize))
5740 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. do checking ..
5741 ;; Is there regexp defined in the table ?
5744 ;; See if there is hit for all recipinets,
5745 ;; then we want t'1o encrypt this mail.
5747 ;; Other times; this may be just regular CC mail
5752 (tinypgpd fid 'dolist-match
5753 (string-match re elt)
5754 (if (string-match re elt)
5755 (match-string 0 elt))
5758 (if (string-match re elt)
5759 (push elt pgp-ok-list)
5760 (push elt pgp-nok-list)))
5762 (if debug (tinypgpd fid (ti::mail-pgp-p)))
5764 (tinypgp-hash 'auto-action 'put 'many-addr-ok-list pgp-ok-list)
5765 (tinypgp-hash 'auto-action 'put 'many-addr-nok-list pgp-nok-list)
5767 ;; There must not be no PGP already in the buffer!
5769 (if (ti::mail-pgp-p)
5770 (tinypgp-hash 'auto-action 'put 'many-addr-stat nil)
5771 (tinypgp-hash 'auto-action 'put 'many-addr-stat pgp-ok-list)))
5773 (setq ret (tinypgp-hash 'auto-action 'get 'many-addr-stat))
5775 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. return action ..
5776 (when (and ret (null mode))
5777 (setq pgp-ok-list (tinypgp-hash 'auto-action 'get 'many-addr-ok-list)
5778 pgp-nok-list (tinypgp-hash 'auto-action 'get 'many-addr-nok-list))
5779 (if (null pgp-nok-list)
5780 (tinypgp-encrypt-mail-verbose)
5782 ;; #todo: send each message separately: those who have PGP
5783 ;; #todo: and those that don't? Hmm.. this function
5784 ;; is run from `mail-send-hook' so we have to send non-pgp first.
5786 (message "TinyPgp: auto-action info, not all recipients have pgp")
5790 Would you like to send separate PGP and plain mail messages?")
5791 (let* ((orig (current-buffer))
5792 (buffer (tinypgp-ti::temp-buffer 'mail "" "")))
5793 (with-current-buffer buffer
5795 (insert-buffer orig)
5796 (ti::mail-set-recipients pgp-nok-list pgp-ok-list 'cc-all)
5797 ;;; (pop-to-buffer buffer)
5798 (mail-send-and-exit nil))
5799 ;; Now it's time to encrypt this message for recipients that
5802 (ti::mail-set-recipients pgp-ok-list pgp-nok-list)
5803 (tinypgp-encrypt-mail (tinypgp-key-id-conversion pgp-ok-list)))))))
5806 (if debug (tinypgpd fid 'RET ret 'pgp-p (ti::mail-pgp-p) 'point (point) "\n"))
5808 ;; If we decided it was okay to send multiple encrypted message,
5809 ;; let user say final word
5811 (if (and ret tinypgp-:auto-action-encrypt-ok-hook)
5812 (setq ret (run-hook-with-args
5813 tinypgp-:auto-action-encrypt-ok-hook
5816 (if debug (tinypgpd fid 'after-user-hook ret))
5820 ;;; ----------------------------------------------------------------------
5822 (defun tinypgp-auto-action-toggle (&optional mode verb)
5823 "If the auto action is detected for this buffer, toggle MODE on/off.
5824 Otherwise if no auto action is present, do nothing. VERB."
5826 (let* ((act (tinypgp-auto-action-p))
5830 (if verb (message "TinyPgp: no action entry found for this buffer."))
5831 (setq val (tinypgp-hash 'auto-action 'get 'user-mode))
5833 (ti::bool-toggle val mode)
5834 (tinypgp-hash 'auto-action 'put 'user-mode val)
5835 (tinypgp-update-modeline)
5838 (message (format "TinyPgp auto action: %s"
5839 (if (not val) "pending" "defeated")))))))
5842 ;;{{{ misc: functions
5844 ;;; ----------------------------------------------------------------------
5846 (defsubst tinypgp-require-final-newline ()
5847 "Make sure there is empty line at the end."
5850 (if (not (looking-at "^[ \t]*$"))
5853 ;;; ----------------------------------------------------------------------
5855 (defun tinypgp-xpgp-get-info ()
5856 "Return X-pgp info '((MIME-KEY DATA) (MIME-K DATA) ..) or nil.
5857 This function caches the read X-Pgp information so that the parsing
5858 doesn't take effect in every call. The cache will be expired if the buffer
5859 size has changed and the new data parsing will be done."
5860 (let* ((fid "tinypgp-xpgp-get-info:")
5861 (size (- (point-max) (point-min)))
5865 ((and (eq size (tinypgp-hash 'xpgp-info 'get 'size))
5866 (setq list (tinypgp-hash 'xpgp-info 'get 'data)))
5867 (tinypgpd fid "cache"))
5868 ((setq field (mail-fetch-field "X-Pgp-signed"))
5869 (setq list (ti::mail-mime-parse-header field 'downcase))
5870 (tinypgp-hash 'xpgp-info 'put 'size size)
5871 (tinypgp-hash 'xpgp-info 'put 'data list)))
5872 (tinypgpd fid (current-buffer) list)
5875 ;;; ----------------------------------------------------------------------
5877 (defun tinypgp-xpgp-key-address (type &optional message)
5878 "Return TYPE (Finger or http) URL if can be found from X-Pgp header.
5879 Print optional MESSAGE if there is no such information.
5888 (let* ((elt (tinypgp-xpgp-get-info))
5892 ((and (eq type 'finger)
5893 (setq elt (assoc "address" elt)))
5894 (setq ret (nth 1 elt)))
5895 ((and (eq type 'http)
5896 (setq elt (assoc "url" elt)))
5897 (setq ret (nth 1 elt)))))
5903 ;;; ----------------------------------------------------------------------
5905 (defun tinypgp-header-sign-mode-toggle (&optional mode)
5906 "Toggle signing of selected headers `tinypgp-:header-sign-table' with MODE.
5907 When the mode if OFF, the `tinypgp-:header-sign-table' is ignored."
5909 (let* ((sym 'tinypgp-:header-sign-table))
5910 ;; Not recorded; record original value
5912 (if (null (get sym 'original))
5913 (put sym 'original (symbol-value sym)))
5916 ((or (memq mode '(0 -1))
5919 (message "Headers are not signed: tinypgp-:header-sign-table is ignored."))
5921 (set sym (get sym 'original))
5922 (message "Header list tinypgp-:header-sign-table is used.")))
5923 (tinypgp-update-modeline)))
5925 ;;; ----------------------------------------------------------------------
5927 (defun tinypgp-header-list-show ()
5928 "See what headers will be signed for this message."
5930 (tinypgp-header-sign-active-list 'display))
5932 ;;; ----------------------------------------------------------------------
5934 (defun tinypgp-header-sign-active-list (&optional display)
5935 "See what headers we should sign. Optionally DISPLAY to user.
5936 Subject is the only safe field to sign when you for example
5937 send a message to some mailing list that may alter all other fields.
5940 `tinypgp-:header-sign-table'"
5941 (let* ((list tinypgp-:header-sign-table)
5945 (setq to (or (mail-fetch-field "To")
5946 (mail-fetch-field "Newsgroups")))
5947 (not (ti::nil-p to))
5948 (setq elt (ti::list-find list to)))
5952 (message "Header sign info: Can't find field To or Newsgroups."))
5954 (message "Header sign info: To or Newsgroup header does not trigger."))
5956 (message "Header sign info: %s" (ti::list-to-string (nth 1 elt))))))
5960 ;;; ----------------------------------------------------------------------
5962 (defun tinypgp-header-move-to-body (&optional opt1 opt2)
5963 "Move headers into body and anonymize them. See source for OPT1 and OPT2"
5965 (ti::mail-pgpr-anonymize-headers
5966 (or opt1 'move-to-body-maybe) opt2 "message" "dummy"))
5968 ;;; ----------------------------------------------------------------------
5970 (defun tinypgp-header-kill (&optional add-list)
5971 "Kill all but the most crucial headers.
5972 ADD-LIST is additional headers to keep."
5973 (let* ((hlist (ti::list-merge-elements
5979 tinypgp-:r-header-keep-list)
5980 (ti::mail-required-headers))))
5981 (ti::mail-kill-non-rfc-fields hlist)))
5983 ;;; ----------------------------------------------------------------------
5985 (defun tinypgp-header-sign-make-smf (&optional read-xpgp &optional header-list)
5986 "Construct header SMF (a stripped message format).
5987 Read header field names and their contents from the message. If some
5988 header does not exist or is empty in message, then that header is ignored.
5992 `tinypgp-:header-sign-table' Read from
5993 `tinypgp-:header-sign-smf-info' Written to
5997 READ-XPGP ,The headers that were signed are told in X-Pgp.
5998 If cannot read all headers, signal error.
5999 HEADER-LIST ,list of headers names
6002 (string (hdr hdr ..)) ,SMF'd header-string and headers included
6005 (let* ((fid "tinypgp-header-sign-make-smf:")
6007 (list (or header-list
6008 (if (setq elt (tinypgp-header-sign-active-list))
6018 (tinypgpd fid "in" read-xpgp header-list "list" elt)
6019 ;; Clear this global
6021 (setq tinypgp-:header-sign-smf-info nil)
6024 (setq fld (mail-fetch-field "X-Pgp-signed"))
6025 (when (setq fld (ti::string-match "SignedHeaders=\\([^;]+\\);" 1 fld))
6026 ;; Remove newlines, because the field may continue
6028 (setq fld (subst-char-with-string fld ?\n " "))
6029 (setq list (split-string fld "[ ,]+"))))
6031 (when (ti::listp list)
6032 (setq buffer (tinypgp-ti::temp-buffer))
6038 (when (setq str (ti::mail-get-field elt nil 'pure))
6040 ;; this code is inside loop, because outside loop
6041 ;; we don't know if we got any headers
6043 (unless flag ;Do only once
6044 (setq flag t) ;Remailer type header hash ##
6045 (ti::append-to-buffer buffer "##\n"))
6047 ;; We want to store the real header name, not the "list"
6048 ;; names that can be "reply-to", where real header name is like
6052 (setq hdr-name (ti::string-match "^\\([^:]+\\):" 1 str))
6053 (tinypgpd fid "READ" elt "NAME" hdr-name str)
6054 (ti::nconc hlist hdr-name)
6056 (ti::append-to-buffer
6058 (format "%s\n" (ti::string-remove-whitespace str) )))))
6061 ;; Add final newline after the headers.
6063 (ti::append-to-buffer buffer "\n")
6064 (with-current-buffer buffer
6065 (setq ret (buffer-substring (point-min) (point-max))))))
6067 (tinypgpd fid "ret" ret hlist)
6070 (setq tinypgp-:header-sign-smf-info (list ret hlist)))))
6075 ;;; .......................................................... &timers ...
6077 ;;; ----------------------------------------------------------------------
6079 (defun tinypgp-timer-process ()
6080 "PGP timer process. Expires stored password and update mode line."
6081 ;; Run only if some visible windows has tinypgp-mode on.
6084 (dolist (win (ti::window-list))
6085 (with-current-buffer (window-buffer win)
6086 (when tinypgp-mode (setq do-it t wlist nil))))
6088 (if do-it (tinypgp-update-modeline))
6089 (if (not (tinypgp-password-time-valid-p))
6090 (tinypgp-password-expire-now))
6093 ;;; ----------------------------------------------------------------------
6095 (defun tinypgp-timer-control (&optional remove verb)
6096 "Keep the password expiration timer alive. Optionally REMOVE it. VERB."
6098 (let* ((fid "tinypgp-timer-control: ")
6099 (timer tinypgp-:timer-elt))
6102 (tinypgpd fid "in:" timer)
6104 (ti::compat-timer-cancel-function 'tinypgp-timer-process)
6107 (setq tinypgp-:timer-elt (run-at-time "10 sec" 10 'tinypgp-timer-process)))
6111 (message "TinyPgp timer process installed")
6112 (message "TinyPgp timer process removed.")))))
6115 ;;{{{ password control
6117 ;;; ........................................................ &password ...
6119 ;;; ----------------------------------------------------------------------
6121 (defun tinypgp-password-expire-now (&optional no-file-kill verb)
6122 "Expire all PGP passwords including used files.
6125 NO-FILE-KILL if non-nil, then temporary files are not removed.
6126 VERB Display verbose message."
6129 (tinypgpd "tinypgp-password-expire-now" no-file-kill verb)
6131 ;; Do not leave traces to memory (gc)
6133 (let* ((gc-cons-threshold (* 1024 1024)))
6134 (ti::vector-table-clear tinypgp-:hash-password))
6138 (ti::vector-table-init tinypgp-:hash-password)
6140 ;; This command also may contains the password, wipe it
6142 (setq tinypgp-:last-pgp-exe-command nil)
6143 (tinypgp-hash 'password-time 'put 'tick nil 'global)
6145 (if (null no-file-kill)
6146 (tinypgp-file-control 'all-kill))
6148 (when (or verb (interactive-p))
6149 ;; If user called us; expire also secring password
6151 (tinypgp-secring-crypt-expire-password)
6152 (message "TinyPgp: all pass phrases and files expired.")))
6154 ;;; ----------------------------------------------------------------------
6156 (defun tinypgp-password-get ()
6158 (let* ((sym tinypgp-:user-now)
6159 (type (tinypgp-hash 'action 'get 'now nil 'global))
6161 (tinypgpd "tinypgp-password-get:" sym type)
6163 ;; This may be "pgp" decrypt or "conventional". pick right
6164 ;; password from hash.
6166 (when (string= "conventional" type)
6167 (setq sym "conventional"))
6169 (tinypgp-password-set
6171 (if (string= "conventional" type)
6175 (ti::vector-table-property
6176 tinypgp-:hash-password sym 'password))
6177 (error "Internal error. Password hash corrupt."))
6181 ;;; ----------------------------------------------------------------------
6183 (defun tinypgp-password-set (&optional prompt type)
6184 "Set pass phrase for `tinypgp-:user-now' or ask again with PROMPT (expired).
6185 Eg. if last PGP command terminated to error, that had expired all
6190 prompt string, Prompt to user
6191 TYPE symbol, if 'conventional, set conventional password.
6192 If 'e-s, set one pass encrypt&sign password
6195 t if password available"
6196 (let* ((fid "tinypgp-password-set:")
6197 (sym (if (and (not (ti::bool-p type))
6207 ((equal type 'conventional)
6208 "Conventional decrypt password: ")
6210 (format "[%s] One pass encrypt&Sign password: " tinypgp-:user-now))
6211 (t (format "[%s] Pass phrase: " tinypgp-:user-now)))))
6213 (tinypgpd fid "in:" tinypgp-:user-now prompt type sym)
6215 (if (and (ti::vector-table-get tinypgp-:hash-password sym)
6216 (ti::vector-table-property tinypgp-:hash-password sym 'password)
6217 (tinypgp-password-time-valid-p)
6218 (null tinypgp-:error))
6219 (setq ret t) ;Ok, was in hash
6221 ;; unwind: Makes sure 'pass' is wiped away
6225 (setq pass (ti::compat-read-password prompt))
6226 (when tinypgp-:password-keep-time
6228 ;; Create new user to hash table
6230 (intern sym tinypgp-:hash-password)
6232 ;; Set user's password in the hash
6234 (ti::vector-table-property tinypgp-:hash-password sym 'password pass 'force)
6235 (tinypgp-hash 'password-time 'put 'tick nil 'global)
6236 (setq tinypgp-:error nil)
6238 ;;; Hmm; this also wipes the password from hash; why?
6239 ;;; (if pass (fillarray pass 0))
6241 (tinypgpd fid "out:" tinypgp-:user-now prompt type ret)
6247 ;;{{{ installation funcs
6249 ;;; ----------------------------------------------------------------------
6250 ;;; We can't initialize the substitution table in defvar, because
6251 ;;; it may be possible that some user sats (setq ...) and then these
6252 ;;; definitions aren't there any more.
6254 (defun tinypgp-install-default-substitutions (&optional remove)
6255 "Add default email substitutions or REMOVE."
6256 (let* ((nymserver-re
6261 '("anon" "finger" "ping" "remove" "help"
6263 "newpassword" "newalias" "newpgp" "newaddress"
6264 "vacation" "noarchive" "setnon" "paranoid"
6265 "pgpencrypt" "pgpsign" "sendmix"
6268 "\\)@anon.nymserver.com"))
6270 (weasel-re "@weasel.owl.de\\|@squirrel.owl.de"))
6272 (tinypgp-email-substitution-add
6274 ;; the 2nd entry is found from PGP key id.
6275 (cons nymserver-re "Nymserver at anon.nymserver.com")
6277 ;; You can get the Weasel 'newnym' PGP key from
6278 ;; <info@weasel.owl.de>
6279 ;; Johannes Kroeger <jkroeger@squirrel.owl.de>
6281 ;; Squirrel.owl.de and weasel.owl.de offer the following mail services:
6282 ;; 1. The Squirrel Remailer, a Mixmaster/Ghio remailer combination:
6284 ;; The capabilities of the Ghio remailer are: $remailer{"squirrel"} =
6285 ;; "<mix@squirrel.owl.de> cpunk mix pgp pgponly hash latent cut ek" The
6286 ;; abbrevs are explained in http://www.publius.net/rlist.html
6288 ;; It accepts only PGP messages encrypted
6290 (cons weasel-re "config@weasel.owl.de"))
6293 ;;; ----------------------------------------------------------------------
6295 (defun tinypgp-install-send-mail-hook (&optional remove)
6296 "Install right hook order to `' or REMOVE hooks."
6300 ;; Hook chain is this:
6302 ;; tinypgp-password-wipe-buffer
6303 ;; tinypgp-sign-modify-check
6304 ;; tinypgp-auto-action
6305 ;; --> rest of the user hooks.
6307 ;; The REST user hooks that do something TO BUFFER before sending
6308 ;; message, should be in tinypgp-cmd-
6309 ;; or to `tinypgp-:auto-action-before-hook'.
6312 (setq hook tinypgp-:mail-send-hook-list
6313 func '(tinypgp-auto-action
6314 tinypgp-sign-modify-check
6315 tinypgp-password-wipe-buffer))
6317 ;; First remove then add --> puts hooks to the beginning.
6320 ;; tinypgp-auto-action --> add SEMI tags
6321 ;; mime-edit-maybe-translate --> translate tags and make PGP/MIME
6323 ;; So, TM/SEMI hook must be after TinyPgp hooks.
6325 (ti::add-hooks hook func 'remove)
6327 ;; Add the hooks in right order
6330 (ti::add-hooks hook func))))
6332 ;;; ----------------------------------------------------------------------
6334 (defun tinypgp-install-hooks-vital (&optional remove)
6335 "Install and keep vital functions in right order. Optionally REMOVE."
6340 ;; .............................................. kring find hooks ...
6343 '(tinypgp-key-find-by-cache
6344 tinypgp-key-find-by-keyrings-verbose
6345 tinypgp-key-find-by-finger-verbose
6346 tinypgp-key-find-by-http-url-verbose
6347 tinypgp-key-find-by-http-keyserver-verbose))
6349 (ti::add-hooks 'tinypgp-:find-by-guess-hook list 'remove)
6350 (unless remove (ti::add-hooks 'tinypgp-:find-by-guess-hook (nreverse list)))
6352 ;; ................................................. control hooks ...
6354 (remove-hook 'tinypgp-:cmd-macro-after-hook
6355 'tinypgp-mode-specific-control-after)
6357 (add-hook 'tinypgp-:cmd-macro-after-hook
6358 'tinypgp-mode-specific-control-after 'append))
6360 ;; .......................................................... mail ...
6362 (tinypgp-install-send-mail-hook remove)
6364 ;; ...................................................... external ...
6365 ;; It is essential that mime translate hooks is after TinyPgp
6366 ;; or otherwise eg when you send patch:
6368 ;; o content is made quoted printble (=3D ...)
6369 ;; o auto action triggers encrypting
6370 ;; --> receiving end doesn't get clean patch
6372 (setq func 'mime-editor/maybe-translate ;TM.el
6373 list '(mail-send-hook
6377 (when (and (boundp hook)
6378 (memq func (symbol-value hook)))
6379 (remove-hook hook func)
6380 ;; Make sure it is last
6381 (add-hook hook func 'append)))))
6383 ;;; ----------------------------------------------------------------------
6385 (defun tinypgp-install-hooks (&optional remove)
6386 "Install package hooks. Optionally REMOVE installation.
6387 Can't restore changes to key maps."
6390 (ti::add-hooks 'find-file-hooks 'turn-on-tinypgp-mode-maybe remove)
6392 (ti::add-hooks tinypgp-:turn-on-hook-list 'turn-on-tinypgp-mode remove)
6394 (ti::add-hooks 'tinypgp-:define-keys-hook ;; just to make sure they are there.
6395 '(tinypgp-mode-define-menu
6396 tinypgp-mode-define-keys))
6398 (ti::add-hooks 'tinypgp-:key-mode-define-keys-hook
6399 '(tinypgp-key-mode-define-menu
6400 tinypgp-key-mode-define-keys))
6402 (ti::add-hooks 'tinypgp-:summary-mode-define-keys-hook
6403 '(tinypgp-summary-mode-define-menu
6404 tinypgp-summary-mode-define-keys))
6406 (ti::add-hooks 'tinypgp-:newnym-mode-define-keys-hook
6407 '(tinypgp-newnym-mode-define-menu
6408 tinypgp-newnym-mode-define-keys))
6410 (ti::add-hooks '(rmail-show-message-hook
6411 vm-display-buffer-hook
6416 (ti::add-hooks '( ;; RMAIL summary is handled elswhere
6417 vm-summary-mode-hook
6418 gnus-summary-mode-hook
6420 'turn-on-tinypgp-summary-mode
6423 (ti::add-hooks 'gnus-select-article-hook 'tinypgp-hide-gnus remove) ;Gnus 4
6425 (tinypgp-install-hooks-vital remove)
6427 ;; This must be after the mode specific hook has finished.
6430 (add-hook 'tinypgp-:cmd-macro-after-hook
6431 'tinypgp-after-pgp-command 'append))
6433 (ti::add-hooks 'tinypgp-:verify-before-hook
6434 'tinypgp-mode-specific-control-before
6437 (ti::add-hooks 'tinypgp-:verify-after-hook
6438 'tinypgp-mode-specific-control-after
6441 (ti::add-hooks 'write-file-hooks ; ~/.mailrc parsing
6442 'tinypgp-update-mail-abbrevs-hook
6445 (ti::add-hooks 'tinypgp-:r-reply-block-basic-hook
6446 'tinypgp-r-mail-mode-init
6449 ;;; ----------------------------------------------------------------------
6451 (defun tinypgp-install-menu-bar-remail ()
6452 "Disable or enable items from menubar."
6453 (if (tinypgp-hash 'remail 'get 'init nil 'global) ;If initialised
6454 (put 'tinypgp-:mode-menu 'remail t)
6455 (put 'tinypgp-:mode-menu 'remail nil)))
6457 ;;; ----------------------------------------------------------------------
6459 (defun tinypgp-install-menu-bar-newnym ()
6460 "Disable or enable items from menubar."
6461 ;; Hmm. Let me think of some test here later; Now it is enabled always.
6463 (if (tinypgp-hash 'remail 'get 'init nil 'global)
6464 (put 'tinypgp-:mode-menu 'newnym t)
6465 (put 'tinypgp-:mode-menu 'newnym nil)))
6467 ;;; ----------------------------------------------------------------------
6469 (defun tinypgp-install-menu-bar-nymserver ()
6470 "Disable or enable items from menubar."
6471 ;; Enable only if user has ordered Nymserver account
6472 (if (ti::listp tinypgp-:nymserver-account-table)
6473 (put 'tinypgp-:mode-menu 'nymserver t)
6474 (put 'tinypgp-:mode-menu 'nymserver nil)))
6476 ;;; ----------------------------------------------------------------------
6478 (defun tinypgp-install-menu-bar ()
6479 "Disable or enable items from menubar."
6480 (tinypgp-install-menu-bar-remail)
6481 (tinypgp-install-menu-bar-newnym)
6482 (tinypgp-install-menu-bar-nymserver))
6484 ;;; ----------------------------------------------------------------------
6486 (defun tinypgp-install-check-environment ()
6487 "Check basic environment variabler or die on error.
6488 PGP uses TMP for temporary files, make sure directory is accessible."
6489 (let* ((dir (getenv "TMP"))
6492 ;; PGP 2.6.x uses TMP env variable. See pgp.doc
6495 (message "TinyPgp: WARNING, environment variable TMP is not set.")
6497 (dolist (directory '("/tmp" "/temp"))
6498 (when (file-directory-p directory)
6499 (setenv "TMP" directory)
6500 (setq dir directory)
6501 (message "TinyPgp: Setenv TMP ==> %s" directory)
6504 (when (file-directory-p dir)
6505 (setq file (ti::file-make-path dir "tinypgp.tmp")))
6509 (error "TinyPgp: environment variable TMP is not set."))
6511 ((not (file-directory-p dir))
6512 (error "TinyPgp: environment variable TMP is not pointing to directory"))
6514 ((not (file-writable-p file))
6515 (error "TinyPgp: Can't write to TMP dir: %s" dir))
6517 ;; Actually try to write, one day I got weir error from my TMP
6518 ;; file system. This neede fcsk run because disk had inode broken.
6520 ;; echo test > test.txt
6521 ;; test.txt: No such device or address.
6525 (write-region (point-min) (point-max) file) ;Breaks if not ok
6527 (delete-file file))))))
6529 ;;; ----------------------------------------------------------------------
6531 (defun tinypgp-install (&optional remove)
6532 "Install whole package or REMOVE installation.
6533 This is main installation controller."
6535 (tinypgpd "tinypgp-install in:" remove)
6536 (tinypgp-install-check-environment)
6538 (tinypgp-binary-path-set)
6540 ;; Set the backenmd if thsi is firt time when program loads
6542 (unless (get 'tinypgp-:pgp-binary 'pgp-now)
6543 (tinypgp-backend-select-auto))
6545 (tinypgp-secring-crypt-mode-detect)
6546 (tinypgp-install-default-substitutions)
6548 (tinypgp-install-hooks remove)
6549 (tinypgp-timer-control remove)
6551 ;;; this is run from 'update modeline' Do not call here; because
6552 ;;; we're in wrong buffer and TP mode is not on.
6554 ;;; (tinypgp-install-menu-bar)
6557 (tinypgp-key-cache-save 'load))
6558 (tinypgpd "tinypgp-install out:"))
6560 ;;; ----------------------------------------------------------------------
6562 (defun tinypgp-install-to-current-emacs ()
6563 "Examine every emacs buffer and turn on PGP minor mode when needed."
6566 ;; Forced install. Clear these
6568 (put 'tinypgp-:hash 'vm-check nil) (tinypgp-install-vm)
6569 (put 'tinypgp-:hash 'gnus-check nil) (tinypgp-install-gnus)
6571 (put 'tinypgp-:hash 'mime-backend-in-use nil)
6572 (put 'tinypgp-:hash 'mime-backend-in-use nil)
6573 (tinypgp-install-mime-pgp)
6575 ;; If user loads TinyPgp, it should immediately install itself to
6576 ;; appropriate buffers. Otherwise user has to call manually
6577 ;; `tinypgp-mode' for every mail buffer and that is not very nice.
6580 (dolist (elt (buffer-list))
6583 ((memq major-mode '(vm-mode
6589 gnus-article-edit-mode
6590 mime/viewer-mode)) ;TM
6591 (unless tinypgp-mode (tinypgp-mode 1)))
6593 ((memq major-mode '(vm-summary-mode
6596 (unless tinypgp-summary-mode
6597 (tinypgp-summary-mode 1)))))))
6599 ;;; ----------------------------------------------------------------------
6601 (defun tinypgp-install-gnus-do ()
6602 "Add Headers to GNUS."
6603 (let* ((h "X-pgp-signed")
6604 (hdr "\\|X-pgp-signed:")
6605 (h2 "^X-pgp-signed:")
6609 ;; Bytecomp silencer with symbols
6611 (dolist (sym '(gnus-saved-headers gnus-visible-headers))
6612 (setq val (symbol-value sym))
6613 (if (not (stringp val))
6614 (error "Install problem1: See manual for GNUS installation.")
6615 (unless (string-match h val)
6616 (set sym (concat val hdr)))))
6618 (setq sym 'gnus-sorted-header-list val (symbol-value sym))
6620 (if (not (ti::listp val))
6621 (error "Install problem2: See manual for GNUS installation.")
6622 (unless (member h2 val)
6624 (set sym (append val (list h2)) )))))
6626 ;;; ----------------------------------------------------------------------
6628 (defun tinypgp-install-gnus (&optional force)
6629 "Check that GNUS is configured right. Optionally FORCE."
6630 (when (and (featurep 'gnus)
6631 (or (boundp 'gnus-saved-headers) ;Gnus check
6632 ;; Not bound, this is old gnus. Do not install
6634 (prog1 nil (put 'tinypgp-:hash 'gnus-check t)))
6635 (null (get 'tinypgp-:hash 'gnus-check)))
6636 (tinypgp-install-gnus-do)
6637 ;; Done, do not repeat
6638 (put 'tinypgp-:hash 'gnus-check t)))
6640 ;;; ----------------------------------------------------------------------
6642 (defun tinypgp-install-mime-tm-do ()
6643 "Install package to TM."
6644 (unless (featurep 'tm-tinypgp-setup)
6645 (or (load "tm-tinypgp-setup" 'noerr)
6648 "tm-tinypgp-setup.el not found. Couldn't auto-install to TM")
6651 ;;; ----------------------------------------------------------------------
6653 (defun tinypgp-install-mime-semi-do ()
6654 "Install package to SEMI."
6655 (unless (featurep 'mime-tinypgp-setup)
6656 (or (load "mime-tinypgp-setup" 'noerr)
6659 "mime-tinypgp-setup.el not found. Couldn't auto-install to SEMI")
6662 ;;; ----------------------------------------------------------------------
6664 (defun tinypgp-install-mime-tm (&optional force)
6665 "Check that GNUS is configured right. Optionally FORCE."
6666 (when (and (null (get 'tinypgp-:hash 'mime-backend-in-use))
6667 (ti::mail-mime-tm-featurep-p))
6668 (when (ti::mail-mime-semi-featurep-p)
6670 TinyPgp: Conflict; Trying to use TM while SEMI is present. Restart Emacs."))
6671 (tinypgp-install-mime-tm-do)
6672 ;; Done, do not repeat
6673 (put 'tinypgp-:hash 'mime-backend-in-use 'tm)))
6675 ;;; ----------------------------------------------------------------------
6677 (defun tinypgp-install-mime-semi (&optional force)
6678 "Check that GNUS is configured right. Optionally FORCE."
6679 (when (and (null (get 'tinypgp-:hash 'mime-backend-in-use))
6680 (ti::mail-mime-semi-featurep-p))
6681 (when (ti::mail-mime-tm-featurep-p)
6683 TinyPgp: Conflict; Trying to use SEMI while TM is present. Restart Emacs."))
6684 (tinypgp-install-mime-semi-do)
6685 (put 'tinypgp-:hash 'mime-backend-in-use 'semi)))
6687 ;;; ----------------------------------------------------------------------
6689 (defun tinypgp-install-mime-pgp (&optional force)
6690 "Install PGP/MIME support or possible FORCE install. Need TM or SEMI."
6693 (null (get 'tinypgp-:hash 'mime-backend-in-use)))
6695 ((ti::mail-mime-tm-featurep-p)
6696 (tinypgp-install-mime-tm)
6697 (tinypgp-install-hooks-vital)) ;Arrange TM look last
6699 ((ti::mail-mime-semi-featurep-p)
6700 (tinypgp-install-mime-semi)
6701 ;; Arrange SEMI hook last
6702 (tinypgp-install-hooks-vital)))))
6704 ;;; ----------------------------------------------------------------------
6706 (defun tinypgp-install-vm ()
6707 "Install minor mode indication to VM summary buffer."
6708 ;; 1. User loads TinyPgp and VM is not loaded yet
6709 ;; --> this function does nothing
6710 ;; 2. When user uses commands afterwards in VM, this function
6711 ;; is called to chek the situation.
6713 (when (and (featurep 'vm)
6714 (null (get 'tinypgp-:hash 'vm-check)))
6715 (let* ((sym 'vm-mode-line-format)
6716 (val (symbol-value sym))
6717 (hdr "X-Pgp-Signed:"))
6719 ;; The modeline format is defined in vm-vars.el::vm-mode-line-format,
6720 ;; but it does not have variable minor-mode-alist. That's why TPsum
6721 ;; mode is not shown in summary buffer.
6724 (dolist (buffer (buffer-list))
6726 (when (and (eq major-mode 'vm-summary-mode)
6727 (not (memq 'minor-mode-alist val)))
6728 ;; Add this and update modeline
6729 (ti::nconc val 'minor-mode-alist)
6730 (ti::compat-set-mode-line-format val)
6731 (vm-update-summary-and-mode-line))))
6733 (setq sym 'vm-visible-headers val (symbol-value sym))
6734 (tinypgpd "tinypgp-install-vm:" sym val)
6736 (if (not (ti::listp val))
6737 (error "Install problem: See manual for VM installation.")
6738 (unless (member hdr val)
6740 (set sym (append val (list hdr))) ))
6742 (put 'tinypgp-:hash 'vm-check t))))
6745 ;;{{{ install: modes, keys
6747 ;;; ----------------------------------------------------------------------
6749 (defun tinypgp-install-modes (&optional remove)
6750 "Install or REMOVE minor modes.
6751 Calling this always removes old mode and does reinstall."
6755 (ti::keymap-add-minor-mode 'tinypgp-mode nil nil 'remove)
6756 (ti::keymap-add-minor-mode 'tinypgp-key-mode nil nil 'remove)
6757 (ti::keymap-add-minor-mode 'tinypgp-summary-mode nil nil 'remove))
6760 (setq tinypgp-:mode-map (make-sparse-keymap)) ;; always refresh
6761 (run-hooks 'tinypgp-:define-keys-hook)
6762 (ti::keymap-add-minor-mode 'tinypgp-mode nil nil 'remove)
6763 (ti::keymap-add-minor-mode 'tinypgp-mode
6767 (setq tinypgp-:key-mode-map (make-sparse-keymap)) ;; always refresh
6768 (run-hooks 'tinypgp-:key-mode-define-keys-hook)
6769 (ti::keymap-add-minor-mode 'tinypgp-key-mode nil nil 'remove)
6770 (ti::keymap-add-minor-mode 'tinypgp-key-mode
6771 'tinypgp-:key-mode-name
6772 tinypgp-:key-mode-map)
6774 (setq tinypgp-:summary-mode-map (make-sparse-keymap)) ;; always refresh
6775 (run-hooks 'tinypgp-:summary-mode-define-keys-hook)
6776 (ti::keymap-add-minor-mode 'tinypgp-summary-mode nil nil 'remove)
6777 (ti::keymap-add-minor-mode 'tinypgp-summary-mode
6778 'tinypgp-:summary-mode-name
6779 tinypgp-:summary-mode-map)
6781 (setq tinypgp-:newnym-mode-map (make-sparse-keymap)) ;; always refresh
6782 (run-hooks 'tinypgp-:newnym-mode-define-keys-hook)
6783 (ti::keymap-add-minor-mode 'tinypgp-newnym-mode nil nil 'remove)
6784 (ti::keymap-add-minor-mode 'tinypgp-newnym-mode
6785 'tinypgp-:newnym-mode-name
6786 tinypgp-:newnym-mode-map))))
6792 (put 'tinypgp-:mode-menu 'nymserver nil)
6794 ;;; ------------------------------------------------------------ &menu ---
6796 (defun tinypgp-mode-define-menu ()
6800 (if (ti::xemacs-p) nil (list tinypgp-:mode-map))
6803 tinypgp-:mode-menu-name
6804 ["Next action" tinypgp-next-action-mail t]
6805 ["Sign" tinypgp-sign-mail t]
6806 ["Sign, base64" tinypgp-sign-mail-base64 t]
6807 ["Sign, detached" tinypgp-sign-mail-detached t]
6808 ["Sign, PGP/MIME" tinypgp-sign-mail-mime t]
6810 ["Encrypt" tinypgp-encrypt-mail t]
6811 ["Encrypt and sign (one pass)" tinypgp-encrypt-mail-sign t]
6812 ["Encrypt PGP/MIME" tinypgp-encrypt-mail-mime t]
6814 ["Decrypt" tinypgp-decrypt-mail t]
6815 ["Verify" tinypgp-verify-mail t]
6816 ["Verify detached signature on file" tinypgp-verify-detached-signature t]
6817 ["Conventional crypt" tinypgp-crypt-mail t]
6818 ["Insert file, base64 signed" tinypgp-sign-base64-insert-file t]
6824 ["Sign" tinypgp-sign-region t]
6825 ["Sign, base64" tinypgp-sign-region-base64 t]
6826 ["Sign, detached" tinypgp-sign-region-detached t]
6827 ["Encrypt" tinypgp-encrypt-region t]
6828 ["Encrypt and sign (one pass)" tinypgp-encrypt-region-sign t]
6829 ["Decrypt" tinypgp-decrypt-region t]
6830 ["Verify" tinypgp-verify-region t])
6834 ["Fetch by finger" tinypgp-key-find-by-finger t]
6835 ["Fetch by http [keyserver]" tinypgp-key-find-by-http-guess t]
6836 ["Fetch by email keysrv request" tinypgp-key-find-by-email t]
6837 ["Fetch by guess" tinypgp-key-find-by-guess t]
6839 ["Insert with batch to pubring" tinypgp-key-add-region-batch t]
6840 ["Insert with ask to pubring" tinypgp-key-add-region-interactive t]
6841 ["Extract to point" tinypgp-key-extract-to-point t]
6844 ;;; ["Generate new key" tinypgp-key-generate t]
6845 ["Remove from keyring" tinypgp-key-delete-region t]
6847 ["Info insert matches" tinypgp-key-info-insert t]
6848 ["Info show matches" tinypgp-key-info-at-point-show t])
6851 "Pubring and user control"
6852 ["Pubring show" tinypgp-pubring-display t]
6853 ["Pubring change" tinypgp-pubring-set-current t]
6855 ["User show" tinypgp-user-display t]
6856 ["User change" tinypgp-user-set-current t])
6860 ["Flip x-pgp header/regular pgp" tinypgp-xpgp-header-toggle t]
6861 ["Flip Signature hide/show" tinypgp-hide-show-toggle t]
6863 ["Mode Auto action on/off" tinypgp-auto-action-toggle t]
6864 ["Mode Auto signing on/off" tinypgp-sign-mail-auto-mode t]
6865 ["Mode Header sign on/off" tinypgp-header-sign-mode-toggle t]
6866 ["Mode x-pgp on/off" tinypgp-xpgp-header-mode-toggle t]
6868 ["Mode Secring crypt on/off" tinypgp-secring-crypt-mode-toggle t]
6869 ["Mode Email substitution on/off" tinypgp-email-substitution-toggle t])
6875 ["Info Show Encrypt keys used" tinypgp-encrypt-info t]
6876 ["Info Show auto action entry" tinypgp-auto-action-verbose t]
6877 ["Info Show email conversion" tinypgp-key-id-conversion-check-verbose t]
6878 ["Info Show header signing fields" tinypgp-header-list-show t]
6879 ["Info Show last finger error" tinypgp-show-last-finger-error t]
6881 ["Info Describe mode" tinypgp-mode-describe t]
6882 ["Info View pgp register" tinypgp-view-register t]
6883 ["Info Sudy PGP stream forward." tinypgp-pgp-stream-forward-study t]
6885 ["Wash Anonymize headers" tinypgp-header-move-to-body t]
6886 ["Wash expire pass phrases/files" tinypgp-password-expire-now t]
6887 ["Wash expire secring password"
6888 tinypgp-secring-crypt-expire-password t]
6889 ["Wash loose signing information" tinypgp-sign-loose-info t]
6890 ["Wash wipe passwords from buffer" tinypgp-password-wipe-buffer t]
6891 ["Wash delete running PGP processes" tinypgp-delete-processes t]
6893 ["Send email: .plan has no PGP key" tinypgp-sendmail-key-not-in-plan t]
6894 ["Send email: keyserver cmd" tinypgp-keysrv-send-email-command t])
6899 ["Post as Anon " tinypgp-r-post
6900 (get 'tinypgp-:mode-menu 'remail)]
6901 ["Encrypt-Remail message once" tinypgp-r-chain-1
6902 (get 'tinypgp-:mode-menu 'remail)]
6903 ["Encrypt-Remail message using chain" tinypgp-r-chain
6904 (get 'tinypgp-:mode-menu 'remail)]
6906 ["Initialize remailer support" tinypgp-r-init t]
6907 ["Update remailer list" tinypgp-r-update-remailer-list t]
6910 ["Make basic reply block" tinypgp-r-reply-block-basic
6911 (get 'tinypgp-:mode-menu 'remail)]
6912 ["Construct remailer reply block" tinypgp-r-reply-block-insert
6913 (get 'tinypgp-:mode-menu 'remail)]
6914 ["Test defined reply blocks" tinypgp-r-reply-block-test
6915 (get 'tinypgp-:mode-menu 'remail)])
6919 ["Show or get account help" tinypgp-newnym-help
6920 (get 'tinypgp-:mode-menu 'newnym)]
6921 ["Default account in use/not in use" tinypgp-newnym-default-toggle
6922 tinypgp-:r-newnym-default-account-table]
6923 ["Default account select" tinypgp-newnym-default-set
6924 tinypgp-:r-newnym-default-account-table]
6925 ["Post as Anon " tinypgp-newnym-post
6926 (get 'tinypgp-:mode-menu 'newnym)]
6930 ["acksend" tinypgp-newnym-req-acksend
6931 (get 'tinypgp-:mode-menu 'newnym)]
6932 ["cryptrecv" tinypgp-newnym-req-cryptrecv
6933 (get 'tinypgp-:mode-menu 'newnym)]
6934 ["disable" tinypgp-newnym-req-disable
6935 (get 'tinypgp-:mode-menu 'newnym)]
6936 ["fingerkey" tinypgp-newnym-req-fingerkey
6937 (get 'tinypgp-:mode-menu 'newnym)]
6938 ["fixedsize" tinypgp-newnym-req-fixedsize
6939 (get 'tinypgp-:mode-menu 'newnym)]
6940 ["sigsend" tinypgp-newnym-req-sigsend
6941 (get 'tinypgp-:mode-menu 'newnym)])
6943 "Configuration and misc"
6944 ["Account expiry status" tinypgp-newnym-account-expiry-warnings t]
6945 ["Configuration template" tinypgp-newnym-config-sendmail-template
6946 (get 'tinypgp-:mode-menu 'newnym)]
6947 ["Create new account" tinypgp-newnym-create
6948 (get 'tinypgp-:mode-menu 'newnym)]
6949 ["Delete account" tinypgp-newnym-delete
6950 (get 'tinypgp-:mode-menu 'newnym)]
6952 ["Get used account list" tinypgp-newnym-get-used-list
6953 (get 'tinypgp-:mode-menu 'newnym)]
6954 ["Get server's PGP key" tinypgp-newnym-get-pgp-key
6955 (get 'tinypgp-:mode-menu 'newnym)])
6959 ["Post as anon" tinypgp-nymserver-post
6960 (get 'tinypgp-:mode-menu 'nymserver)]
6961 ["Finger, account status" tinypgp-nymserver-finger
6962 ));;; Yes; you can finger an anon address ok: anNNN@anon-nymserver.com
6963 ;;; (get 'tinypgp-:mode-menu 'nymserver)
6965 ["Ping, your account status" tinypgp-nymserver-ping
6966 (get 'tinypgp-:mode-menu 'nymserver)]
6967 ["Help, read file" tinypgp-nymserver-help
6968 (get 'tinypgp-:mode-menu 'nymserver)]
6971 "Change account properties"
6972 ["Change account alias" tinypgp-nymserver-newalias
6973 (get 'tinypgp-:mode-menu 'nymserver)]
6974 ["Change nickname" tinypgp-nymserver-nickname
6975 (get 'tinypgp-:mode-menu 'nymserver)]
6976 ["Change .plan" tinypgp-nymserver-newplan
6977 (get 'tinypgp-:mode-menu 'nymserver)]
6978 ["Change .signature" tinypgp-nymserver-newsig
6979 (get 'tinypgp-:mode-menu 'nymserver)]
6980 ["Change to new address" tinypgp-nymserver-newaddress
6981 (get 'tinypgp-:mode-menu 'nymserver)])
6985 ["flag, paranoid" tinypgp-nymserver-paranoid
6986 (get 'tinypgp-:mode-menu 'nymserver)]
6987 ["flag, vacation" tinypgp-nymserver-vacation
6988 (get 'tinypgp-:mode-menu 'nymserver)]
6989 ["flag, no archive" tinypgp-nymserver-noarchive
6990 (get 'tinypgp-:mode-menu 'nymserver)]
6991 ["flag, anNNN/naNNN" tinypgp-nymserver-setnon
6992 (get 'tinypgp-:mode-menu 'nymserver)]
6994 ["PGP key upload " tinypgp-nymserver-pgp-upload
6995 (get 'tinypgp-:mode-menu 'nymserver)]
6996 ["PGP flag, encrypt" tinypgp-nymserver-pgp-encrypt
6997 (get 'tinypgp-:mode-menu 'nymserver)]
6998 ["PGP flag, sign" tinypgp-nymserver-pgp-sign
6999 (get 'tinypgp-:mode-menu 'nymserver)]
7000 ["PGP flag, mixmaster" tinypgp-nymserver-pgp-sendmix
7001 (get 'tinypgp-:mode-menu 'nymserver)])
7005 ["Account create" tinypgp-nymserver-create t]
7006 ["Account remove" tinypgp-nymserver-remove
7007 (get 'tinypgp-:mode-menu 'nymserver)]))
7012 ["Remove last entry" tinypgp-key-cache-remove-entry-last t]
7013 ["Display" tinypgp-key-cache-display t])
7016 "Report and backend service"
7017 ["Select PGP backend" tinypgp-backend-select t]
7018 ["Select PGP backend 2.6.x" tinypgp-backend-select-pgp2 t]
7019 ["Select PGP backend 5.x" tinypgp-backend-select-pgp5 t]
7020 ["Show TinyPgp version" tinypgp-version-message t]
7021 ["Show TinyPgp initial message" tinypgp-initial-message t]
7022 ["Submit bug report" tinypgp-submit-bug-report t]
7024 ["Debug on/off" tinypgp-debug-toggle t]
7025 ["Debug buffer clear" tinypgp-debug-buffer-clear t]
7027 ["Display comint" tinypgp-show-buffer-comint t]
7028 ["Display debug" tinypgp-show-buffer-debug t]
7029 ["Display finger" tinypgp-show-buffer-finger t]
7030 ["Display http" tinypgp-show-buffer-http t]
7031 ["Display shell" tinypgp-show-buffer-shell t]
7032 ["Display tmp" tinypgp-show-buffer-tmp t]))))
7034 ;;; I don't know if average user realizes what this command does...
7035 ;;; ["Generate randseed.bin" t]
7038 ;;{{{ menu: echo, newnym
7040 ;;; ----------------------------------------------------------------------
7042 (defun tinypgp-mode-define-keys-newnym (map n)
7043 ;; Seldom used command in big letter to prevent accidents.
7045 (define-key map (concat n "?") 'tinypgp-newnym-help)
7046 (define-key map (concat n "a") 'tinypgp-newnym-req-acksend)
7047 (define-key map (concat n "b") 'tinypgp-newnym-req-nobcc)
7048 (define-key map (concat n "C") 'tinypgp-newnym-create)
7050 (define-key map (concat n "c")
7051 'tinypgp-newnym-config-sendmail-template)
7053 (define-key map (concat n "D") 'tinypgp-newnym-delete)
7054 (define-key map (concat n "e") 'tinypgp-newnym-req-disable)
7055 (define-key map (concat n "f") 'tinypgp-newnym-req-fingerkey)
7056 (define-key map (concat n "K") 'tinypgp-newnym-get-pgp-key)
7057 (define-key map (concat n "u") 'tinypgp-newnym-get-used-list)
7058 (define-key map (concat n "p") 'tinypgp-newnym-post)
7059 (define-key map (concat n "r") 'tinypgp-newnym-req-cryptrecv)
7060 (define-key map (concat n "s") 'tinypgp-newnym-req-sigsend)
7061 (define-key map (concat n "\t") 'tinypgp-newnym-default-set)
7062 (define-key map (concat n "t") 'tinypgp-newnym-default-toggle)
7063 (define-key map (concat n "x") 'tinypgp-newnym-account-expiry-warnings)
7064 (define-key map (concat n "z") 'tinypgp-newnym-req-fixedsize))
7066 ;;; ----------------------------------------------------------------------
7068 (defcustom tinypgp-:newnym-echo-menu-use-p t
7069 "*Should the 'newnym' commands be accessible from echo-area menu?.
7070 You can set this only once; otherwise you have to reload package."
7072 :group 'tinypgp-nymserver)
7074 ;; Change this mane in the load-hook is need to.
7076 (defconst tinypgp-:newnym-echo-menu
7078 (let* ((srv (get 'tinypgp-:r-newnym-default-account-table 'default-server))
7079 (pfx (if current-prefix-arg "+" ""))
7080 (def (format "%s[%s]" pfx (or srv "Newnym") )))
7081 (tinypgp-backend-set-for-action 'newnym)
7084 %s p)ost c)fg t/ab)oggle h)lp req:a)ck b)cc e)nab f)ing s)ig si(z)e [utx CDK]"
7086 ((?a . ( (call-interactively 'tinypgp-newnym-req-acksend)))
7087 (?C . ( (call-interactively 'tinypgp-newnym-create)))
7088 (?b . ( (call-interactively 'tinypgp-newnym-req-nobcc)))
7089 (?c . ( (call-interactively 'tinypgp-newnym-config-sendmail-template)))
7090 (?D . ( (call-interactively 'tinypgp-newnym-delete)))
7091 (?e . ( (call-interactively 'tinypgp-newnym-req-disable)))
7092 (?f . ( (call-interactively 'tinypgp-newnym-req-fingerkey)))
7093 (?h . ( (tinypgp-newnym-help-verbose current-prefix-arg)))
7094 (?K . ( (call-interactively 'tinypgp-newnym-get-pgp-key)))
7095 (?u . ( (call-interactively 'tinypgp-newnym-get-used-list)))
7096 (?p . ( (call-interactively 'tinypgp-newnym-post)))
7097 (?r . ( (call-interactively 'tinypgp-newnym-req-cryptrecv)))
7098 (?s . ( (call-interactively 'tinypgp-newnym-req-sigsend)))
7099 (?t . (t (call-interactively 'tinypgp-newnym-default-toggle)))
7100 (?\t . ( (call-interactively 'tinypgp-newnym-default-set)))
7101 (?x . ( (tinypgp-newnym-account-expiry-warnings)))
7102 (?z . ( (call-interactively 'tinypgp-newnym-req-fixedsize)))))
7104 Esc or q to exit menu without choosing. Less used commands are in uppercase.
7108 h = Show help file (prefix arg orders help file by mail)
7109 p = convert current message to anon (p)ost
7111 Nym account requests
7113 All these commands send the minus(-) request and request action is
7114 explained to the right. Supply prefix argument if you want to send plus(+)
7117 a = (a)cksend disable automatic acknowledgement
7118 b = no(b)cc receive bcc carbon copies. Needed if you
7119 subscribe to mailing lists.
7120 r = c(r)yptrecv disable encryption to you.
7121 e = disable re-(e)nable account
7122 f = (f)ingerkey disallow people to get your PGP key.
7123 z = fixedsi(z)e do not padd messages to 10K
7124 s = (s)igsend disable automatic pgp signing
7126 Nym account management
7128 t = (t)oggle using default account.
7129 tab = set default server and account
7130 c = prepare (c)onfigure template and enter 'Nym' mode.
7131 You can manage you account in details. See tab key in this mode.
7132 C = (C)reate account
7133 D = (D)elete account
7137 x = Display count of days to account e(x)piration.
7138 u = Get account list ie. (u)sed nym names
7139 K = Get server's PGP (k)ey.")
7142 ;;{{{ menu: echo, nymserver
7144 ;;; ----------------------------------------------------------------------
7146 (defun tinypgp-mode-define-keys-nymserver (map y)
7147 ;; Normal keybindings then. No menu in echo area used.
7149 (define-key map (concat y "p") 'tinypgp-nymserver-post)
7150 (define-key map (concat y "f") 'tinypgp-nymserver-finger)
7151 (define-key map (concat y "i") 'tinypgp-nymserver-ping)
7153 (define-key map (concat y "a") 'tinypgp-nymserver-newalias)
7154 (define-key map (concat y "n") 'tinypgp-nymserver-nickname)
7155 (define-key map (concat y "w") 'tinypgp-nymserver-newpassword)
7157 (define-key map (concat y "o") 'tinypgp-nymserver-paranoid)
7158 (define-key map (concat y "v") 'tinypgp-nymserver-vacation)
7159 (define-key map (concat y "d") 'tinypgp-nymserver-newaddress)
7160 (define-key map (concat y "r") 'tinypgp-nymserver-noarchive)
7161 (define-key map (concat y "l") 'tinypgp-nymserver-newplan)
7162 (define-key map (concat y "g") 'tinypgp-nymserver-newsig)
7163 (define-key map (concat y "t") 'tinypgp-nymserver-setnon)
7165 (define-key map (concat y "k") 'tinypgp-nymserver-pgp-upload)
7166 (define-key map (concat y "e") 'tinypgp-nymserver-pgp-encrypt)
7167 (define-key map (concat y "s") 'tinypgp-nymserver-pgp-sign)
7168 (define-key map (concat y "x") 'tinypgp-nymserver-pgp-sendmix)
7170 (define-key map (concat y "C") 'tinypgp-nymserver-create)
7171 (define-key map (concat y "D") 'tinypgp-nymserver-remove)
7172 (define-key map (concat y "A") 'tinypgp-nymserver-abuse)
7174 (define-key map (concat y "h") 'tinypgp-nymserver-help))
7176 (defcustom tinypgp-:nymserver-echo-menu-use-p t
7177 "*Should the 'nymserver' commands be accessible from echo-area menu?.
7178 You can set this only once; otherwise you have to reload package."
7180 :group 'tinypgp-nymserver)
7182 ;; Change this mane in the load-hook is need to.
7184 (defconst tinypgp-:nymserver-echo-menu
7187 (tinypgp-backend-set-for-action 'nymserv)
7188 "Nymserv p)ost f)ing p(i)ng n)ick si(g) p(l)an PGP.kesx req.drtovwa [hACR]")
7189 ((?p . ( (call-interactively 'tinypgp-nymserver-post)))
7190 (?f . ( (call-interactively 'tinypgp-nymserver-finger)))
7191 (?i . ( (call-interactively 'tinypgp-nymserver-ping)))
7193 (?n . ( (call-interactively 'tinypgp-nymserver-nickname)))
7194 (?v . ( (call-interactively 'tinypgp-nymserver-vacation)))
7195 (?a . ( (call-interactively 'tinypgp-nymserver-newalias)))
7197 (?l . ( (call-interactively 'tinypgp-nymserver-newplan)))
7198 (?g . ( (call-interactively 'tinypgp-nymserver-newsig)))
7199 (?r . ( (call-interactively 'tinypgp-nymserver-noarchive)))
7201 (?y . ( (call-interactively 'tinypgp-nymserver-setnon)))
7202 (?o . ( (call-interactively 'tinypgp-nymserver-paranoid)))
7203 (?d . ( (call-interactively 'tinypgp-nymserver-newaddress)))
7204 (?w . ( (call-interactively 'tinypgp-nymserver-newpassword)))
7206 (?k . ( (call-interactively 'tinypgp-nymserver-pgp-upload)))
7207 (?e . ( (call-interactively 'tinypgp-nymserver-pgp-encrypt)))
7208 (?s . ( (call-interactively 'tinypgp-nymserver-pgp-sign)))
7209 (?x . ( (call-interactively 'tinypgp-nymserver-pgp-sendmix)))
7211 (?A . ( (call-interactively 'tinypgp-nymserver-abuse)))
7212 (?C . ( (call-interactively 'tinypgp-nymserver-create)))
7213 (?D . ( (call-interactively 'tinypgp-nymserver-remove)))
7214 (?h . ( (tinypgp-nymserver-help-verbose current-prefix-arg)))))
7215 "anon.nymserver.com menu.
7216 Esc or q to exit menu without choosing.
7220 p = convert current message to anon (p)ost
7221 f = (f)inger account for configuration information.
7225 n = (n)ickname change request
7226 g = upload new .(s)ignature file
7227 l = upload new .p(l)an file
7229 PGP related requests
7231 k = upload PGP (k)ey to your account
7232 e = (e)ncrypt request
7233 s = (s)igning request
7234 x = mi(x)master request
7238 d = newa(dd)ress request
7239 r = noa(r)chive request
7240 t = se(t)non request
7241 o = paran(o)id request
7242 v = (v)acation request
7243 w = ne(w)password request
7244 a = new(a)lias request. This changes your anNNN to vanity alias.
7248 h = show (h)elp file, With Prefix arg send help request email.
7249 A = Send (a)buse mail
7250 C = (C)reate new account. This command can be sent only once.
7251 D = (D)elete account. This is opposite of create.")
7254 ;;{{{ menu: echo, remail
7256 ;;; ----------------------------------------------------------------------
7258 (defun tinypgp-mode-define-keys-remail (map p)
7259 (define-key map (concat p "b") 'tinypgp-r-reply-block-basic)
7260 (define-key map (concat p "r") 'tinypgp-r-reply-block-insert)
7261 (define-key map (concat p "i") 'tinypgp-r-init)
7262 (define-key map (concat p "u") 'tinypgp-r-update-remailer-list)
7263 (define-key map (concat p "p") 'tinypgp-r-post)
7264 (define-key map (concat p "t") 'tinypgp-r-reply-block-test)
7265 (define-key map (concat p "C") 'tinypgp-r-chain-1)
7266 (define-key map (concat p "c") 'tinypgp-r-chain))
7268 (defcustom tinypgp-:remail-echo-menu-use-p t
7269 "*Should the 'remail' commands be accessible from echo-area menu?.
7270 You can set this only once; otherwise you have to reload package."
7274 (defconst tinypgp-:remail-echo-menu
7277 (tinypgp-backend-set-for-action 'remail)
7278 "remail: p)ost cC)hain b)asic-rb t)est-rb r)b-insert u)pdate i)nit")
7279 ((?b . ( (call-interactively 'tinypgp-r-reply-block-basic)))
7280 (?r . ( (call-interactively 'tinypgp-r-reply-block-insert)))
7281 (?i . ( (call-interactively 'tinypgp-r-init)))
7282 (?u . ( (call-interactively 'tinypgp-r-update-remailer-list)))
7283 (?p . ( (call-interactively 'tinypgp-r-post)))
7284 (?t . ( (call-interactively 'tinypgp-r-reply-block-test)))
7285 (?C . ( (call-interactively 'tinypgp-r-chain-1)))
7286 (?c . ( (call-interactively 'tinypgp-r-chain)))))
7287 "Remail management menu
7289 p convert message to remailer post
7290 c Chain message using predefined paths. Use (p) first
7291 C Chain once manually. Use (p) first
7293 b construct basic reply block
7294 r Insert reply block
7296 i Initialise remailer support
7297 u update remailer list
7298 t test reply blocks")
7302 ;;{{{ menu: echo, buffer
7304 ;;; ----------------------------------------------------------------------
7306 (defun tinypgp-mode-define-keys-buffer (map p)
7307 "Define buffer handling keys. Use P prefix key and assign to MAP."
7308 ;; Buffer management in prefix "b"
7310 (define-key map (concat p "c") 'tinypgp-show-buffer-comint)
7311 (define-key map (concat p "d") 'tinypgp-show-buffer-debug)
7312 (define-key map (concat p "f") 'tinypgp-show-buffer-finger)
7313 (define-key map (concat p "h") 'tinypgp-show-buffer-http)
7314 (define-key map (concat p "s") 'tinypgp-show-buffer-shell)
7315 (define-key map (concat p "t") 'tinypgp-show-buffer-tmp)
7317 (define-key map (concat p "\b") 'tinypgp-debug-buffer-clear)
7318 (define-key map (concat p "\177") 'tinypgp-debug-buffer-clear)
7319 (define-key map (concat p "\C-m") 'tinypgp-show-buffer-debug))
7321 ;;; ----------------------------------------------------------------------
7323 (defcustom tinypgp-:show-buffer-echo-menu-use-p t
7324 "*Should the 'show-buffer' commands be accessible from echo-area menu?.
7325 You can set this only once; otherwise you have to reload package."
7329 (defconst tinypgp-:show-buffer-echo-menu
7331 "buffer: c)ache d)ebug,RET f)ing h)ttp s)hell t)emp DEL)debug clear "
7332 ((?c . ( (tinypgp-key-cache-display)))
7333 (?d . ( (tinypgp-show-buffer-debug)))
7334 (?f . ( (tinypgp-show-buffer-finger)))
7335 (?h . ( (tinypgp-show-buffer-http)))
7336 (?s . ( (tinypgp-show-buffer-shell)))
7337 (?t . ( (tinypgp-show-buffer-tmp)))
7338 (?\b . ( (tinypgp-debug-buffer-clear)))
7339 (?\177 . ( (tinypgp-debug-buffer-clear)))
7340 (?\C-m . ( (tinypgp-show-buffer-debug)))))
7343 c Show key cache buffer
7345 f Show finger buffer
7350 RET Show debug buffer
7351 DEL Clear debug buffer")
7353 ;;; ----------------------------------------------------------------------
7355 (defun tinypgp-mode-define-keys-user (map p)
7356 "Define user keys. Use P prefix key and assign to MAP."
7357 (define-key map (concat p "s") 'tinypgp-user-display)
7358 (define-key map (concat p "\t") 'tinypgp-user-set-current))
7360 (defcustom tinypgp-:user-echo-menu-use-p t
7361 "*Should the 'user' commands be accessible from echo-area menu?.
7362 You can set this only once; otherwise you have to reload package."
7366 (defconst tinypgp-:user-echo-menu
7368 "user: s)how tab)change"
7369 ((?s . ( (call-interactively 'tinypgp-user-display)))
7370 (?\t . ( (call-interactively 'tinypgp-user-set-current)))))
7373 s Show current pgp user
7374 tab Change current pgp user")
7377 ;;{{{ menu: echo, key
7379 ;;; ----------------------------------------------------------------------
7381 (defun tinypgp-mode-define-keys-pubring (map p)
7382 (define-key map (concat p "s") 'tinypgp-pubring-display)
7383 ;; This is little faster key
7384 (define-key map (concat p "\t") 'tinypgp-pubring-set-current))
7386 (defcustom tinypgp-:pubring-echo-menu-use-p t
7387 "*Should the 'pubring' commands be accessible from echo-area menu?.
7388 You can set this only once; otherwise you have to reload package."
7392 (defconst tinypgp-:pubring-echo-menu
7394 "pubring: s)how tab)change"
7395 ((?s . ( (call-interactively 'tinypgp-pubring-display)))
7396 (?\t . ( (call-interactively 'tinypgp-pubring-set-current)))))
7399 s Show current pubring in use
7400 tab Change current pubring")
7403 ;;{{{ menu: echo, key
7405 ;;; ----------------------------------------------------------------------
7407 (defun tinypgp-mode-define-keys-cache (map p)
7408 (define-key map (concat p "r")
7409 'tinypgp-key-cache-remove-entry-last)
7410 (define-key map (concat p "s") 'tinypgp-key-cache-display))
7412 (defcustom tinypgp-:cache-echo-menu-use-p t
7413 "*Should the 'pubring' commands be accessible from echo-area menu?.
7414 You can set this only once; otherwise you have to reload package."
7418 (defconst tinypgp-:cache-echo-menu
7420 "pubring: s)how tab)change"
7421 ((?r . ( (call-interactively 'tinypgp-key-cache-remove-entry-last)))
7422 (?s . ( (call-interactively 'tinypgp-key-cache-display)))))
7425 r remove entry from cache.
7430 ;;{{{ menu: echo, debug
7432 ;;; ----------------------------------------------------------------------
7434 (defun tinypgp-mode-define-keys-debug (map p)
7435 (define-key map (concat p "d") 'tinypgp-debug-toggle)
7436 (define-key map (concat p "c") 'tinypgp-debug-buffer-clear)
7437 (define-key map (concat p "s") 'tinypgp-submit-bug-report)
7438 (define-key map (concat p "v") 'tinypgp-version-message)
7439 (define-key map (concat p "i") 'tinypgp-initial-message)
7440 (define-key map (concat p "\e") 'tinypgp-submit-bug-report))
7442 (defcustom tinypgp-:debug-echo-menu-use-p t
7443 "*Should the 'debug' commands be accessible from echo-area menu?.
7444 You can set this only once; otherwise you have to reload package."
7448 (defconst tinypgp-:debug-echo-menu
7450 "debug: d)toggle c)lear s)submit report v)ersion msg i)nit msg"
7451 ((?d . ( (call-interactively 'tinypgp-debug-toggle)))
7452 (?c . ( (call-interactively 'tinypgp-debug-buffer-clear)))
7453 (?s . ( (call-interactively 'tinypgp-submit-bug-report)))
7454 (?v . ( (call-interactively 'tinypgp-version-message)))
7455 (?i . ( (call-interactively 'tinypgp-initial-message)))))
7458 c Clear debug buffer
7461 v Show version message
7462 i Show initial startup message")
7465 ;;{{{ menu: echo, region
7467 ;;; ----------------------------------------------------------------------
7469 (defun tinypgp-mode-define-keys-region (map p)
7470 (define-key map (concat p "s") 'tinypgp-sign-region)
7471 (define-key map (concat p "S") 'tinypgp-sign-region-base64)
7472 (define-key map (concat p "D") 'tinypgp-sign-region-detached)
7473 (define-key map (concat p "e") 'tinypgp-encrypt-region)
7474 (define-key map (concat p "t") 'tinypgp-encrypt-region-sign)
7475 (define-key map (concat p "d") 'tinypgp-decrypt-region)
7476 (define-key map (concat p "v") 'tinypgp-verify-region)
7477 (define-key map (concat p "c") 'tinypgp-crypt-region))
7479 (defcustom tinypgp-:region-echo-menu-use-p t
7480 "*Should the 'region' commands be accessible from echo-area menu?.
7481 You can set this only once; otherwise you have to reload package."
7485 (defconst tinypgp-:region-echo-menu
7487 "region: sSD)sign,base64,detach e)ncrypt t)1pass d)ecrypt v)erify c)rypt "
7488 ((?s . ( (call-interactively 'tinypgp-sign-region)))
7489 (?S . ( (call-interactively 'tinypgp-sign-region-base64)))
7490 (?D . ( (call-interactively 'tinypgp-sign-region-detached)))
7491 (?e . ( (call-interactively 'tinypgp-encrypt-region)))
7492 (?t . ( (call-interactively 'tinypgp-encrypt-region-sign)))
7493 (?d . ( (call-interactively 'tinypgp-decrypt-region)))
7494 (?v . ( (call-interactively 'tinypgp-verify-region)))
7495 (?c . ( (call-interactively 'tinypgp-crypt-region)))))
7499 S Sign with base64 armor
7502 t encrypt and sign on 1pass
7509 ;;{{{ menu: echo, keyring
7511 ;;; ----------------------------------------------------------------------
7513 (defun tinypgp-mode-define-keys-key (map p)
7514 ;; #todo key generate
7515 ;; A (define-key map (concat p "g") 'tinypgp-key-generate)
7516 ;; - "ki" is closer to keyboard than default pgp "kv".
7518 (define-key map (concat p "i") 'tinypgp-key-info-at-point-show)
7519 (define-key map (concat p "I") 'tinypgp-key-info-insert)
7520 (define-key map (concat p "v") 'tinypgp-key-info-insert)
7522 (define-key map (concat p "a") 'tinypgp-key-add-region-batch)
7523 (define-key map (concat p "A")
7524 'tinypgp-key-add-region-interactive)
7525 (define-key map (concat p "x") 'tinypgp-key-extract-to-point)
7526 (define-key map (concat p "r") 'tinypgp-key-delete-region))
7528 (defcustom tinypgp-:key-echo-menu-use-p t
7529 "*Should the 'key' commands be accessible from echo-area menu?.
7530 You can set this only once; otherwise you have to reload package."
7534 (defconst tinypgp-:key-echo-menu
7536 "key: i)nfo show vI)nsert a)dd batch A)add interactive x)tract r)emove"
7537 ((?i . ( (call-interactively 'tinypgp-key-info-at-point-show)))
7538 (?I . ( (call-interactively 'tinypgp-key-info-insert)))
7539 (?v . ( (call-interactively 'tinypgp-key-info-insert)))
7540 (?a . ( (call-interactively 'tinypgp-key-add-region-batch)))
7541 (?A . ( (call-interactively 'tinypgp-key-add-region-interactive)))
7542 (?x . ( (call-interactively 'tinypgp-key-extract-to-point)))
7543 (?r . ( (call-interactively 'tinypgp-key-delete-region)))))
7544 "Key management menu
7546 i Show keys matching string at point
7547 I Insert key info mathing string to point
7548 v ...same... (synonym)
7549 a add keys in region to pubring
7550 A add keys in region to pubring (interactive)
7551 x Extract key from keyring to point
7552 r removed selected keys in region from keyring
7556 ;;{{{ menu: echo, modes
7558 ;;; ----------------------------------------------------------------------
7560 (defun tinypgp-mode-define-keys-mode (map p)
7561 (define-key map (concat p "!") 'tinypgp-auto-action-toggle)
7562 (define-key map (concat p "c") 'tinypgp-secring-crypt-mode-toggle)
7564 (define-key map (concat p "e")
7565 'tinypgp-email-substitution-toggle)
7567 (define-key map (concat p "h") 'tinypgp-xpgp-header-mode-toggle)
7568 (define-key map (concat p "H")
7569 'tinypgp-header-sign-mode-toggle)
7571 (define-key map (concat p "s") 'tinypgp-sign-mail-auto-mode))
7573 (defcustom tinypgp-:mode-echo-menu-use-p t
7574 "*Should the 'mode' commands be accessible from echo-area menu?.
7575 You can set this only once; otherwise you have to reload package."
7579 (defconst tinypgp-:mode-echo-menu
7581 "mode: !)action c)rypt secring e)mail h)x-pgp H)eader sign s)ign"
7582 ((?! . ( (call-interactively 'tinypgp-auto-action-toggle)))
7583 (?c . ( (call-interactively 'tinypgp-secring-crypt-mode-toggle)))
7584 (?e . ( (call-interactively 'tinypgp-email-substitution-toggle)))
7585 (?h . ( (call-interactively 'tinypgp-xpgp-header-mode-toggle)))
7586 (?H . ( (call-interactively 'tinypgp-header-sign-mode-toggle)))
7587 (?s . ( (call-interactively 'tinypgp-sign-mail-auto-mode)))))
7590 ! Toggle auto action: enable, disable
7591 c Toggle secring crypt mode
7592 e Toggle email subtitution mode
7593 f Toggle fcc encrypt mode
7594 h Toggle header based x-pgp signing mode
7595 H Toggle including part of the headers for signing
7596 s Toggle auto signing mode of outgoing mail")
7599 ;;{{{ menu: echo, key
7601 ;;; ----------------------------------------------------------------------
7603 (defun tinypgp-mode-define-keys-extra (map p)
7605 (define-key map (concat p "a") 'tinypgp-auto-action-verbose)
7607 (define-key map (concat p "b") 'tinypgp-backend-select)
7608 (define-key map (concat p "B") 'tinypgp-secring-backup)
7610 (define-key map (concat p "D") 'tinypgp-delete-processes)
7612 (define-key map (concat p "E")
7613 'tinypgp-key-id-conversion-check-verbose)
7615 (define-key map (concat p "e") 'tinypgp-encrypt-info)
7617 (define-key map (concat p "h") 'tinypgp-header-list-show)
7618 (define-key map (concat p "i")
7619 'tinypgp-pgp-stream-forward-study)
7621 (define-key map (concat p "f") 'tinypgp-show-last-finger-error)
7623 (define-key map (concat p "k")
7624 'tinypgp-keysrv-send-email-command)
7626 (define-key map (concat p "l") 'tinypgp-sign-loose-info)
7628 (define-key map (concat p "p")
7629 'tinypgp-sendmail-key-not-in-plan)
7631 (define-key map (concat p "w") 'tinypgp-password-wipe-buffer)
7633 (define-key map (concat p "x") 'tinypgp-password-expire-now)
7634 (define-key map (concat p "X") 'tinypgp-secring-crypt-expire-password))
7636 (defcustom tinypgp-:extra-echo-menu-use-p t
7637 "*Should the 'extra' commands be accessible from echo-area menu?.
7638 You can set this only once; otherwise you have to reload package."
7642 (defconst tinypgp-:extra-echo-menu
7645 extra: aeh)info f)ing iE)pgp kp)email l)oose b)backend B)up wDxX)pire >dC "
7647 '(?a . ( (call-interactively 'tinypgp-auto-action-verbose)))
7648 '(?b . ( (call-interactively 'tinypgp-backend-select)))
7649 '(?B . ( (call-interactively 'tinypgp-secring-backup)))
7650 '(?D . ( (call-interactively 'tinypgp-delete-processes)))
7651 '(?e . ( (call-interactively 'tinypgp-key-id-conversion-check-verbose)))
7652 '(?E . ( (call-interactively 'tinypgp-encrypt-info)))
7653 '(?h . ( (call-interactively 'tinypgp-header-list-show)))
7654 '(?i . ( (call-interactively 'tinypgp-pgp-stream-forward-study)))
7655 '(?f . ( (call-interactively 'tinypgp-show-last-finger-error)))
7656 '(?k . ( (call-interactively 'tinypgp-keysrv-send-email-command)))
7657 '(?l . ( (call-interactively 'tinypgp-sign-loose-info)))
7658 '(?p . ( (call-interactively 'tinypgp-sendmail-key-not-in-plan)))
7659 '(?w . ( (call-interactively 'tinypgp-password-wipe-buffer)))
7660 '(?x . ( (call-interactively 'tinypgp-password-expire-now)))
7661 '(?X . ( (call-interactively 'tinypgp-secring-crypt-expire-password)))
7663 (cons ?d 'tinypgp-:debug-echo-menu)
7664 (cons ?C 'tinypgp-:cache-echo-menu)))
7669 a Show auto action that would trigger this mail
7670 e Show what email conversion would apply to To address
7671 h Show what headers would be signed
7672 f Show last finger error in echo area
7676 E Study encrypted message and show whom it's encrypted to
7677 i Study pgp stream forward and show info (type pgp version etc.)
7681 k Send command to keyserver
7682 p Send notice that user's key was not in .plan when fingered.
7686 l Loose signing information
7687 b Select backend> pgp 2.6.x or pgp 5.x
7688 B Backup secring in encrypted format
7692 d Delete all running PGP processes. Eg. Pgp 5.x may be hung in your
7693 emacs. Use this command to get rip of those zombies. See process
7694 list with command \\[list-processes]
7695 w wipe passwords from buffer
7696 x Expire pass phrases
7697 X Expire encrypted secring password.")
7701 ;;{{{ menu: define keys
7703 ;;; ----------------------------------------------------------------------
7705 (defun tinypgp-mode-define-keys ()
7707 (let* ((map tinypgp-:mode-map)
7708 (p tinypgp-:mode-prefix-key)
7709 (r tinypgp-:mode-prefix-key-remailer)
7710 (y tinypgp-:mode-prefix-key-nymserver)
7711 (n tinypgp-:mode-prefix-key-newnym))
7713 (if tinypgp-:region-echo-menu-use-p
7714 (define-key map (concat p "r")
7715 (ti::definteractive (ti::menu-menu 'tinypgp-:region-echo-menu arg)))
7716 (tinypgp-mode-define-keys-region map (concat p "r")))
7718 ;; ................................................. user, pubring ...
7720 (if tinypgp-:user-echo-menu-use-p
7721 (define-key map (concat p "u")
7722 (ti::definteractive (ti::menu-menu 'tinypgp-:user-echo-menu arg)))
7723 (tinypgp-mode-define-keys-user map (concat p "u")))
7725 (if tinypgp-:pubring-echo-menu-use-p
7726 (define-key map (concat p "p")
7727 (ti::definteractive (ti::menu-menu 'tinypgp-:pubring-echo-menu arg)))
7728 (tinypgp-mode-define-keys-pubring map (concat p "p")))
7730 ;; ....................................................... keyring ...
7732 (if tinypgp-:key-echo-menu-use-p
7733 (define-key map (concat p "k")
7734 (ti::definteractive (ti::menu-menu 'tinypgp-:key-echo-menu arg)))
7735 (tinypgp-mode-define-keys-key map (concat p "k")))
7737 ;; ........................................................ buffer ...
7739 (if tinypgp-:show-buffer-echo-menu-use-p
7740 (define-key map (concat p "b")
7741 (ti::definteractive (ti::menu-menu 'tinypgp-:show-buffer-echo-menu arg)))
7742 (tinypgp-mode-define-keys-buffer map (concat p "b")))
7744 ;; ......................................................... extra ...
7746 (if tinypgp-:extra-echo-menu-use-p
7747 (define-key map (concat p "x")
7748 (ti::definteractive (ti::menu-menu 'tinypgp-:extra-echo-menu arg)))
7749 (tinypgp-mode-define-keys-extra map (concat p "x")))
7751 (unless tinypgp-:debug-echo-menu-use-p
7752 (tinypgp-mode-define-keys-debug map (concat p "xd")))
7754 (unless tinypgp-:debug-echo-menu-use-p
7755 (tinypgp-mode-define-keys-cache map (concat p "xC")))
7757 ;; .......................................................... mode ...
7759 (if tinypgp-:mode-echo-menu-use-p
7760 (define-key map (concat p "m")
7761 (ti::definteractive (ti::menu-menu 'tinypgp-:mode-echo-menu arg)))
7762 (tinypgp-mode-define-keys-mode map (concat p "m")))
7764 ;; ...................................................... remailer ...
7766 (if tinypgp-:remail-echo-menu-use-p
7768 (ti::definteractive (ti::menu-menu 'tinypgp-:remail-echo-menu arg)))
7769 (tinypgp-mode-define-keys-remail map r))
7771 ;; ..................................................... nymserver ...
7773 (if tinypgp-:nymserver-echo-menu-use-p
7776 (ti::menu-menu 'tinypgp-:nymserver-echo-menu arg)))
7777 (tinypgp-mode-define-keys-nymserver map y))
7779 ;; ........................................................ newnym ...
7781 (if tinypgp-:newnym-echo-menu-use-p
7783 (ti::definteractive (ti::menu-menu 'tinypgp-:newnym-echo-menu arg)))
7784 (tinypgp-mode-define-keys-nymserver map n))
7786 ;; ....................................................... regular ...
7789 (concat p (ti::string-right p 1)) 'tinypgp-next-action-mail)
7791 (define-key map (concat p "?") 'tinypgp-mode-describe)
7793 (define-key map (concat p "a") 'tinypgp-header-move-to-body)
7794 (define-key map (concat p "s") 'tinypgp-sign-mail)
7795 (define-key map (concat p "S") 'tinypgp-sign-mail-base64)
7796 (define-key map (concat p "D") 'tinypgp-sign-mail-detached)
7798 (define-key map (concat p "e") 'tinypgp-encrypt-mail)
7799 (define-key map (concat p "t") 'tinypgp-encrypt-mail-sign)
7801 ;; There no particular reason why "q" for mime.
7802 ;; I chose it because, Q char is obscure enough to
7803 ;; remind that in 1998-03 the PGP/MIME is still new.
7805 (define-key map (concat p "q") 'tinypgp-sign-mail-mime)
7806 (define-key map (concat p "Q") 'tinypgp-encrypt-mail-mime)
7808 (define-key map (concat p "d") 'tinypgp-decrypt-mail)
7809 (define-key map (concat p "v") 'tinypgp-verify-mail)
7810 (define-key map (concat p "V")
7811 'tinypgp-verify-detached-signature)
7813 (define-key map (concat p "c") 'tinypgp-crypt-mail)
7814 (define-key map (concat p "i") 'tinypgp-sign-base64-insert-file)
7816 (define-key map (concat p "h") 'tinypgp-xpgp-header-toggle)
7817 (define-key map (concat p "g") 'tinypgp-hide-show-toggle)
7819 (define-key map (concat p "R") 'tinypgp-view-register)
7820 (define-key map (concat p "F") 'tinypgp-key-find-by-finger)
7822 (define-key map (concat p "G")
7823 'tinypgp-key-find-by-guess)
7825 (define-key map (concat p "E") 'tinypgp-key-find-by-email)
7827 (define-key map (concat p "K")
7828 'tinypgp-key-find-by-http-guess)
7830 (define-key map (concat p "2") 'tinypgp-backend-select-pgp2)
7831 (define-key map (concat p "5") 'tinypgp-backend-select-pgp5)
7833 (define-key map (concat p "\C-m") 'tinypgp-key-find-by-guess)))
7836 ;;{{{ mode: key mode
7838 ;;; ----------------------------------------------------------------------
7840 (defun tinypgp-key-mode-define-menu ()
7843 tinypgp-:key-mode-menu (if (ti::xemacs-p) nil tinypgp-:key-mode-map)
7844 "TinyPgp Key management menu"
7846 tinypgp-:key-mode-menu-name)))
7847 ;;; ["Mail Sign" tinypgp-sign-mail t]
7849 ;;; ----------------------------------------------------------------------
7851 (defun tinypgp-key-mode-define-keys ()
7853 (let* ((p tinypgp-:key-mode-prefix-key)
7854 (map tinypgp-:key-mode-map))
7855 (define-key map (concat p "a") 'tinypgp-key-add-region-batch)))
7858 ;;{{{ mode: summary mode
7860 ;;; --------------------------------------------------------- &summary ---
7862 (defun tinypgp-summary-mode-define-menu ()
7865 tinypgp-:summary-mode-menu (if (ti::xemacs-p) nil tinypgp-:summary-mode-map)
7866 "TinyPgp Mail Summary management menu"
7868 tinypgp-:summary-mode-menu-name
7869 ["Verify" tinypgp-summary-mode-verify t]
7870 ["Decrypt" tinypgp-summary-mode-decrypt t]
7871 ["Next action" tinypgp-summary-mode-next-action t]
7872 ["Describe mode" tinypgp-summary-mode-describe t]
7877 ["Wash expire pass phrases/files" tinypgp-password-expire-now t]
7878 ["Wash expire secring password"
7879 tinypgp-secring-crypt-expire-password t]
7881 ["Info Display last finger error" tinypgp-show-last-finger-error t]
7882 ["Info View pgp register" tinypgp-view-register t]
7884 ["Send email: .plan has no PGP key" tinypgp-sendmail-key-not-in-plan t]
7885 ["Send email: keyserver cmd" tinypgp-keysrv-send-email-command t])
7889 ["Remove last entry" tinypgp-key-cache-remove-entry-last t]
7890 ["Display" tinypgp-key-cache-display t])
7894 ["Submit bug report" tinypgp-submit-bug-report t]
7895 ["Debug on/off" tinypgp-debug-toggle t]
7896 ["Debug buffer clear" tinypgp-debug-buffer-clear t]
7898 ["Display comint" tinypgp-show-buffer-comint t]
7899 ["Display debug" tinypgp-show-buffer-debug t]
7900 ["Display finger" tinypgp-show-buffer-finger t]
7901 ["Display http" tinypgp-show-buffer-http t]
7902 ["Display shell" tinypgp-show-buffer-shell t]
7903 ["Display tmp" tinypgp-show-buffer-tmp t]))))
7905 ;;; ----------------------------------------------------------------------
7907 (defun tinypgp-summary-mode-define-keys ()
7909 (let* ((p tinypgp-:summary-mode-prefix-key)
7910 (map tinypgp-:summary-mode-map))
7912 (tinypgp-mode-define-keys-buffer map p)
7913 (tinypgp-mode-define-keys-user map p)
7916 (concat p (ti::string-right p 1)) 'tinypgp-summary-mode-next-action)
7918 (define-key map (concat p "?") 'tinypgp-summary-mode-describe)
7919 (define-key map (concat p "d") 'tinypgp-summary-mode-decrypt)
7920 (define-key map (concat p "v") 'tinypgp-summary-mode-verify)))
7923 ;;{{{ code: Mode functions
7925 (eval (ti::macrof-minor-mode-viper-attach "tinypgp-mode-" 'tinypgp-mode))
7927 ;;; ----------------------------------------------------------------------
7930 (ti::macrof-minor-mode
7934 \\{tinypgp-:mode-map}
7936 tinypgp-install-modes ;3
7940 tinypgp-:mode-prefix-key ;5
7941 tinypgp-:mode-menu ;6
7948 (if (null tinypgp-:pubring-now)
7949 (setq tinypgp-:pubring-now
7950 (tinypgp-expand-file-name
7951 (nth 1 (car (tinypgp-pubring-table))))))
7953 (if (not (file-exists-p tinypgp-:pubring-now))
7954 (error "TinyPgp: Can't init mode, pubring not found '%s'"
7955 tinypgp-:pubring-now))
7957 (if (not (stringp tinypgp-:user-now))
7958 (error "TinyPgp: Can't init mode, user is not defined '%s'"
7960 (tinypgpd "tinypgp-mode" arg)
7961 (tinypgp-update-modeline)))
7963 (defun turn-on-tinypgp-mode ()
7967 (defun turn-off-tinypgp-mode ()
7971 ;;; ----------------------------------------------------------------------
7973 (defun turn-on-tinypgp-mode-maybe ()
7974 "Turn on `tinypgp-mode' only if PGP tags are found from buffer.
7975 This function is by default installed into `find-file-hooks'."
7976 (when (and (null tinypgp-mode)
7978 (turn-on-tinypgp-mode)))
7980 ;;; ----------------------------------------------------------------------
7982 (defun tinypgp-mode-describe ()
7985 (describe-function 'tinypgp-mode))
7987 ;;; .................................................... &pgp-key-mode ...
7989 ;;; ----------------------------------------------------------------------
7991 (ti::macrof-minor-mode
7993 "PGP key handling minor mode. You should extract the the key information
7994 to some buffer first before turning on this mode.
7995 Eg. with \\[tinypgp-key-info-at-point-show]
7998 \\{tinypgp-:key-mode-map}
8000 tinypgp-install-modes
8002 tinypgp-:key-mode-name ;5
8004 tinypgp-:key-mode-prefix-key
8005 tinypgp-:key-mode-menu ;7
8008 "TinyPgp Key handling"
8009 tinypgp-:key-mode-hook ;10
8012 (if tinypgp-key-mode
8013 (tinypgp-update-modeline))))
8015 ;;; ----------------------------------------------------------------------
8017 (defun tinypgp-key-mode-describe ()
8020 (describe-function 'tinypgp-key-mode))
8022 ;;; .................................................... &pgp-sum-mode ...
8024 ;;; ----------------------------------------------------------------------
8026 (ti::macrof-minor-mode
8027 tinypgp-summary-mode
8028 "PGP summary minor mode. This function can only be turned on in VM
8029 RMAIL and GNUS summary buffer. Any PGP action called there is reflected
8030 on the current message selected.
8033 \\{tinypgp-:summary-mode-map}
8035 tinypgp-install-modes
8036 tinypgp-summary-mode
8037 tinypgp-:summary-mode-name
8039 tinypgp-:summary-mode-prefix-key
8040 tinypgp-:summary-mode-menu
8043 "TinyPgp Mail Summary"
8044 tinypgp-:summary-mode-hook
8047 (when tinypgp-summary-mode
8048 (unless (memq major-mode
8049 '(rmail-summary-mode
8053 (setq tinypgp-summary-mode nil)
8054 (error "You can use this mode only in Mail summary buffers."))
8056 ;; This modeline update is a problem only in RMAIL-summary buffer.
8057 ;; We cannot use rmail-summary-mode-hook, because turning mode on
8058 ;; there does no good (summary buffer is not shown yet)
8060 ;; See advised function rmail-new-summary which calls us.
8062 (tinypgp-update-modeline))))
8064 (defun turn-on-tinypgp-summary-mode ()
8065 "Summary mode." (tinypgp-summary-mode 1))
8067 (defun turn-off-tinypgp-summary-mode ()
8068 "Summary mode." (tinypgp-summary-mode 0))
8070 ;;; ----------------------------------------------------------------------
8072 (defun tinypgp-summary-mode-describe ()
8075 (describe-function 'tinypgp-summary-mode))
8077 ;;; ----------------------------------------------------------------------
8079 (defun tinypgp-summary-mode-verify (&optional arg)
8080 "Verify current article with ARG.
8084 In GNUS Summary buffer, where the *Article* is guessed to be a newsgroup
8085 post, the prefix arg meaning has been reversed. When you verify
8086 newsgroup article, the content of the article is not replaced, as it
8087 would anywhere else."
8088 (interactive "P") (tinypgp-summary-action 'verify arg 'verb))
8090 (defun tinypgp-summary-mode-decrypt (&optional arg)
8091 "Decrypt current article with ARG."
8092 (interactive "P") (tinypgp-summary-action 'decrypt arg 'verb))
8094 (defun tinypgp-summary-mode-next-action (&optional arg)
8095 "Guess next action and pass ARG."
8096 (interactive "P") (tinypgp-summary-action 'next-action arg 'verb))
8098 ;;; ----------------------------------------------------------------------
8100 (defun tinypgp-summary-action-1 (action func arg verb)
8101 "See source code for `tinypgp-summary-action' for ACTION FUNC ARG VERB."
8103 (pop-to-buffer (current-buffer))
8105 ((eq action 'verify) (funcall func arg 'verb))
8106 ((eq action 'next-action) (call-interactively func))
8107 ((eq action 'decrypt) (tinypgp-decrypt-mail-verbose (quote arg))))))
8109 ;;; ----------------------------------------------------------------------
8111 (defun tinypgp-summary-action (action-sym &optional arg verb)
8112 "Do ACTION-SYM in summary buffer. ARG is passed to called function. VERB."
8113 (let* ((fid "tinypgp-summary-action: ")
8114 (win (get-buffer-window (current-buffer)))
8115 (list '(verify decrypt next-action))
8118 (if (not (memq action-sym list))
8119 (error "TinyPgp: Unregognized/Not supported summary action."))
8121 (setq str (format "tinypgp-%s-mail" (symbol-name action-sym)))
8123 (if (null (setq func (intern-soft str)))
8124 (error "TinyPgp: Function not found %s" str))
8126 (tinypgpd fid major-mode action-sym func)
8129 ((eq major-mode 'rmail-summary-mode)
8130 (ti::mail-rmail-macro
8131 (tinypgp-summary-action-1 action-sym func arg verb)))
8133 ((eq major-mode 'vm-summary-mode)
8135 (tinypgp-summary-action-1 action-sym func arg verb)))
8137 ((eq major-mode 'gnus-summary-mode)
8138 (ti::mail-gnus-macro
8139 ;; In newsgroup post the user doesn't want to "open"
8140 ;; the message when he verifies it. Reverse the ARG meaning
8141 (when (and (eq action-sym 'verify) (ti::mail-news-buffer-p))
8142 (ti::bool-toggle arg))
8143 (tinypgpd fid action-sym "ARG" arg "NEWS" (ti::mail-news-buffer-p))
8144 (tinypgp-summary-action-1 action-sym func arg verb)))
8146 ((eq major-mode 'mh-show-mode)
8148 (tinypgp-summary-action-1 action-sym func arg verb)))
8151 (error "TinyPgp: I Can't do anything in this major mode.")))
8152 (if (window-live-p win) ;Back to summary
8153 (select-window win))))
8157 ;;{{{ code: defadvice
8159 ;;; ....................................................... &defadvice ...
8161 (defadvice rmail-new-summary (after tinypgp act)
8163 For some reason this couldn't be done from 19.28's`rmail-summary-mode-hook'."
8164 (tinypgp-summary-mode))
8166 ;;; (ad-unadvise 'vm-edit-message)
8168 (defadvice vm-edit-message (after tinypgp dis)
8169 "If Edit is called interactively, call `turn-on-tinypgp-mode'.
8170 We can't do this in `vm-edit-message-hoo' because the hook function
8171 doesn't know if the function were called interactively or not."
8172 (if (and (interactive-p)
8173 (null tinypgp-mode))
8174 (turn-on-tinypgp-mode)))
8178 ;;{{{ Special: sending email
8180 ;;; ........................................................ &sendmail ...
8182 ;;; ----------------------------------------------------------------------
8184 (defun tinypgp-sendmail-key-not-in-plan (email)
8185 "Send small mail to EMAIL and ask him to add his PGP key to ~/.plan.
8187 When you finger someone for his pgp key, consider this before you send
8188 notice to person. (check the content of finger buffer)
8190 o Finger finds the .plan file and the contents seems valid, there is login
8191 name and directory information and soon. This would indicate that
8192 it is ok to send notice to person.
8197 ;; someone may think this harrashement
8199 "Are you sure you want to send .plan notice? Think twice..." )
8201 "You did check the content of the finger results: was it ok otw? ")
8203 (read-from-minibuffer
8205 (ignore-errors (ti::mail-get-field "to" nil 'nil-mode)))))
8206 (if (not (string-match "@"))
8209 (tinypgp-sendmail email 'pk-finger-none)
8211 (message "Email sent to: %s" email)))
8213 ;;; ----------------------------------------------------------------------
8215 (defun tinypgp-sendmail (email mode &optional arg1 arg2 arg3)
8216 "Send email notice to EMAIL address according to MODE and ARG1 ARG2 ARG3."
8219 "\nThis is message from TinyPgp.el %s\n\n"
8220 (tinypgp-version-number)))
8223 " %s, Notification concerning your PGP."
8227 ((eq mode 'pk-no-full-format)
8231 "\tWe fingered address %s to get your public key\n\t"
8232 "but it was not presented in full format of pgp -fakx.\n\t"
8233 "Would you please insert all test starting from\n\t"
8234 "'Key for user ID:' line from the -fakx output. \n\t"
8235 "That would offer access to your other information\n\t"
8236 "that may be needed. \nt"
8238 "Please note that the -kv format is not the same as -fakx\n"
8242 ((eq mode 'pk-finger-none)
8247 "We could finger address %s but there was no PGP \n\t"
8248 "Public key available. Would you kindly run \n\t"
8249 "'pgp -fakx' on you keyId and put all\n\t"
8250 "lines after 'Key for user ID:' to you $HOME/.plan file.\n\n\t"
8251 "Thank you. Please excuse this message if you don't have\n"
8255 (error "TinyPgp: Unknown mode")))
8257 (ti::mail-sendmail-macro email subject 'send
8263 ;;; ............................................................ &bbdb ...
8265 (defcustom tinypgp-:bbdb-field 'pgp-mail
8266 "*Field to use in BBDB to store PGP preferences.
8267 Entry in table `tinypgp-:auto-action-table' overrides BBDB definition.
8269 Field can have values:
8272 'sign-Keyid' Sign with KeyId
8273 'xpgp' Use X-pgp when signing.
8274 'enccrypt' Encrypt message by looking at To field. If you want to encrypt
8275 using some other value, like 0xFFFFFF hex key id, see
8276 variable `tinypgp-:email-substitution-table'
8277 'mime-tm' use PGP/MIME with package TM
8278 '1pass' Use 1 pass encrypt and sign. The message is signed with
8279 active pgp user's key
8280 '1pass-keyId' ..same but sign by using KeyId
8282 You can't use `sign' and `encrypt' with `1pass', which has highest
8287 pgp-mail: sign ;; Sign by pgp user
8288 pgp-mail: sign mime-tm ;; PGP/MIME sign with TM package
8290 pgp-mail: 1pass ;; encryt and sign"
8294 ;;; ----------------------------------------------------------------------
8296 (defun tinypgp-bbdb-1 (name address field)
8297 "Look up user NAME and ADDRESS in BBDB and return FIELD"
8298 (let* ((record (bbdb-search-simple name address)))
8300 (bbdb-record-getprop record field))))
8302 ;;; ----------------------------------------------------------------------
8304 (defun tinypgp-bbdb-id (&optional email)
8305 "Return BBDB `pgp-id' field matching EMAIL or To-field address."
8307 (when (featurep 'bbdb)
8308 (let* ((fid "tinypgp-bbdb-id:")
8314 (tinypgp-bbdb-1 "" email key)
8315 (setq address (mail-extract-address-components
8316 (or (mail-fetch-field "To" nil t) "")))
8317 (when (nth 1 address)
8318 (tinypgp-bbdb-1 (or (nth 0 address) "") (nth 1 address) key))))
8319 (tinypgpd fid 'ARG email 'address address 'RET ret)
8322 ;;; ----------------------------------------------------------------------
8324 (defun tinypgp-bbdb-entry ()
8325 "Return bbdb auto action entry in format `tinypgp-:auto-action-table'."
8326 (when (featurep 'bbdb)
8327 (let* ((fid "tinypgp-bbdb-entry:")
8328 (to-field (mail-fetch-field "To" nil t))
8329 (address (mail-extract-address-components (or to-field "")))
8330 elt sign enc mime-mua xpgp)
8331 (tinypgpd fid to-field address)
8333 (when (and (nth 1 address)
8334 (setq elt (tinypgp-bbdb-1 (car address) (nth 1 address)
8335 tinypgp-:bbdb-field)))
8337 (if (string-match "mime" elt)
8338 (setq mime-mua 'mime))
8341 ((string-match "sign-\\([^ \t]+\\)" elt)
8342 (setq sign (match-string 1 elt)))
8343 ((string-match "sign" elt)
8344 (setq sign tinypgp-:user-now)))
8346 (if (string-match "xpgp" elt)
8349 (setq enc (string-match "encrypt" elt))
8351 (when (string-match "1pass" elt)
8352 (setq sign (make-symbol tinypgp-:user-now))
8355 (if (and mime-mua sign)
8356 (setq sign (make-symbol sign)))
8358 ;; '(EVAL-OR-REGEXP [SIGN-KEY-ID] [ENCRYPT]
8359 ;; [MIME-MUA] [XPGP] [KEYRING])
8363 sign enc mime-mua xpgp)))))
8366 ;;{{{ special: Mode specific actions
8368 ;;; ................................................... &mode-specific ...
8370 ;;; ----------------------------------------------------------------------
8371 ;;; #todo: tinypgp-mail-do-fcc breaks in VM
8373 (defun tinypgp-mail-do-fcc (&optional cmd user msg string)
8374 "Do FCC before the message is encrypted and remove FCC field.
8375 You don't want sendmail.el to FCC message which was encrypted
8376 with the other user's public key.
8378 This function Supports MUAs:
8380 Sendmail Fcc -- mail-mode
8381 Gnus Gcc -- message-mode
8388 (let ((fid "tinypgp-mail-do-fcc: ")
8392 ;;#todo VM FCC must be handled differently ?
8393 ;;#todo Gnus 5 mail fcc ?
8395 (tinypgpd fid "in: " cmd user msg string major-mode)
8397 (setq field-fcc (mail-fetch-field "fcc")
8398 field-gcc (mail-fetch-field "gcc"))
8400 (when (and (memq major-mode '(mail-mode message-mode))
8401 (memq cmd '(encrypt encrypt-sign)))
8403 (setq hmax (ti::mail-hmax))
8405 (tinypgpd fid 'fcc field-fcc 'gcc field-gcc
8406 'buffer (current-buffer)
8408 'point-max (point-max))
8410 (when (and field-gcc (featurep 'gnus))
8411 (gnus-inews-do-gcc))
8414 ((ti::xemacs-p) ;needs MARKER
8417 (setq hmax (point-marker)))
8418 (mail-do-fcc hmax) ;Header end
8419 (setq hmax nil)) ;kill marker
8421 (t ;XE19.14 and Emacs needs POINT
8422 (mail-do-fcc (ti::mail-hmax))))
8424 (tinypgp-hash 'fcc 'put 'fcc field-fcc)
8425 (tinypgp-hash 'gcc 'put 'gcc field-gcc)
8427 ;; Message saving happened in another buffer, remove these
8428 ;; fields from this original buffer.
8430 (while (not (ti::nil-p (mail-fetch-field "fcc")))
8431 (ti::mail-kill-field "^FCC"))
8433 (while (not (ti::nil-p (mail-fetch-field "gcc")))
8434 (ti::mail-kill-field "^GCC")))))
8436 ;;; ----------------------------------------------------------------------
8438 (defun tinypgp-mode-specific-control-before
8439 (cmd &optional user msg string)
8440 "Turn on possible edit mode while we do some PGP action.
8441 This function is called prior the PGP action takes effect in current
8442 region or buffer. Eg. in RMAIL we have to turn on the edit mode in
8443 order to modify the message content.
8447 The content of these function call parameter depends on the
8448 calling CMD which can be 'sign 'encrypt 'decrypt 'verify.
8449 You have to look at the source code to see what is passed in each case.
8450 CMD OPTIONAL USER MSG STRING
8454 The buffer pointer is recorded to hash table under property
8455 'mode-specific and value 'buffer. This is name of the current buffer
8456 where the original message is.
8458 When edit mode is turned on, the buffer may now be different and
8459 the buffer pointer is recorded under property 'mode-specific and value
8464 `tinypgp-:verify-before-hook' ;; contain this function
8465 `tinypgp-cmd-macro' ;; calls this function
8466 `tinypgp-mode-specific-control-after' ;; 'the other side of the coin'"
8467 (let ((fid "tinypgp-mode-specific-control-before: "))
8469 (tinypgpd fid "CMD" cmd user msg "BUFFER" (current-buffer) major-mode)
8471 (tinypgp-mail-do-fcc cmd user msg string)
8473 ;; When "after" function runs it checks if this flag is non-nil
8474 ;; and strores the contents of the "clone" buffer there.
8476 (tinypgp-hash 'mode-specific 'put 'register nil 'global)
8478 ;; We have to record the initial buffer, so that the AFTER
8479 ;; hook can restore the state in correct buffer. The package
8480 ;; may die anywhere in the code and the buffer pointer certainly
8481 ;; isn't pointing to the right place any moreon error.
8483 (tinypgp-hash 'mode-specific 'put 'buffer (buffer-name) 'global)
8484 (tinypgp-hash 'mode-specific 'put 'major-mode major-mode 'global)
8485 (tinypgp-hash 'vm 'put 'control nil 'global)
8487 ;; - For some unknown reason the VM window configurations
8488 ;; is mixed when we open edit mode and close it afterwards,
8489 ;; we must save window configuration now.
8490 ;; - We save this every time, but we only use it in VM
8492 (tinypgp-hash 'mode-specific 'put 'wcfg
8493 (current-window-configuration)
8496 (tinypgp-hash 'mode-specific 'put 'frame (selected-frame) 'global)
8497 (tinypgp-hash 'mode-specific 'put 'window (selected-window) 'global)
8498 (tinypgp-hash 'mode-specific 'put 'read-only buffer-read-only 'global)
8500 (when (featurep 'vm)
8501 (tinypgp-hash 'vm 'put 'vm-frame-per-edit vm-frame-per-edit 'global))
8503 (tinypgp-hash 'mode-specific 'put 'buffer (buffer-name) 'global)
8505 ;; ....................................................... secring ...
8506 (when (and tinypgp-:secring-crypt-mode
8507 (not (memq cmd '(verify))))
8508 (tinypgp-secring-use))
8510 ;; ......................................................... modes ...
8512 ;; We have to quit TM so that underlying mode underneath is
8515 ;; But in Gnus, this wouldn't have any effect, because TM is permanently
8516 ;; on. See ESC-t which runs `gnus-summary-toggle-mime'.
8518 (when (eq major-mode 'mime/viewer-mode) ;TM preview buffer
8520 ((and (featurep 'gnus)
8521 (string= (buffer-name)
8522 (symbol-value 'gnus-article-buffer)))
8523 nil) ;Entering article edit quits mime.
8525 ;;; (setq buffer-read-only nil)
8526 ;; in RMAIL this works
8527 (mime-viewer/quit))))
8530 ((and (featurep 'gnus)
8531 (or (string= (buffer-name) (symbol-value 'gnus-article-buffer))
8532 (eq major-mode 'gnus-article-mode)))
8533 (when (and buffer-read-only
8534 (not (eq 'ok (ignore-errors
8535 (gnus-summary-edit-article) 'ok))))
8536 ;; Eg. NNTP backend doesn't allow editing buffers.
8537 (message (substitute-command-keys "\
8538 Gnus backend doesn't support edit. Use \\[tinypgp-view-register]"))
8539 (tinypgp-hash 'mode-specific 'put 'register t 'global)
8540 (set-buffer (tinypgp-clone-buffer)))
8542 ;; Old Gnus versions have a bug, they give *Article* buffer
8543 ;; for editing, which is not good. The buffer may have been
8544 ;; formatted so that there is gnus buttons in the middle of the PGP
8546 ;; noRr110XVahfo/3MaLL2PGlJ/h8rOdZkJCPCQ1OO8BKcXg3NQWTb+RpqSbSRnbEq
8548 ;; win0apLYccO+tqhhzK3CIiDbgBGfQLNU9ju+nMOOm1VUfF2A/phMoQg6ucYrXFxk
8550 ;; We must edit the `gnus-original-article-buffer', which contains
8551 ;; the message "as is".
8553 ;; I submitted gnus bug report on this, but Lars didn't consider
8554 ;; it as a bug: User is expect to do C-u g to view raw article.
8556 (if (not (buffer-live-p
8557 (get-buffer (symbol-value 'gnus-original-article-buffer))))
8558 ;; If the original article weren't found, try anyway in
8559 ;; this *Article* buffer. It may even succeed if there
8560 ;; is no gnus buttons in the PGP block.
8562 (message "TinyPgp: Wish me luck, I couldn't find original article")
8564 ;; Ok, found buffer, so play safe
8566 (delete-region (point-min) (point-max))
8567 (insert-buffer (symbol-value 'gnus-original-article-buffer))))
8569 ((memq major-mode '(rmail-mode))
8570 (rmail-edit-current-message))
8572 ((memq major-mode '(vm-mode))
8574 ;; - VM opens another frame immediately if you
8575 ;; put message in edit mode (that happend when you decrypt mail)
8576 ;; - We don't want it to do that; Set this locally to nil
8578 (setq vm-frame-per-edit nil)
8580 (tinypgp-hash 'vm 'put 'control 'edit 'global)))
8582 ;; Expose any hidden text
8584 (set-text-properties (point-min) (point-max) nil)
8585 (ti::overlay-remove-region (point-min) (point-max))
8587 (tinypgp-hash 'mode-specific 'put 'buffer-edit (buffer-name) 'global)
8588 (tinypgpd fid major-mode "BUFFER-EDIT" (current-buffer))
8591 ;;; ----------------------------------------------------------------------
8593 (defun tinypgp-mode-specific-label (cmd &optional buffer)
8594 "Add mail-agent labels according to CMD. Work buffer is BUFFER."
8595 (let* ((fid "tinypgp-mode-specific-label")
8597 (tbl tinypgp-:label-table)
8598 (v+ (nth 0 (nth 1 (assq 'v tbl))))
8599 (v- (nth 1 (nth 1 (assq 'v tbl))))
8600 (si (nth 1 (assq 's tbl)))
8601 (en (nth 1 (assq 'e tbl)))
8602 (de (nth 1 (assq 'd tbl)))
8603 (pgp (nth 1 (assq 'pgp tbl)))
8605 (with-current-buffer (or buffer (current-buffer))
8608 ;; ...................................................... rmail ...
8610 ((memq major-mode '(rmail-mode rmail-edit-mode))
8614 (rmail-kill-label v+)
8615 (rmail-kill-label v-)
8616 (when (not (ti::nil-p pgp)) (rmail-add-label pgp))
8617 (when (not (ti::nil-p si)) (rmail-add-label si)))
8620 (rmail-kill-label en)
8621 (when (not (ti::nil-p pgp)) (rmail-add-label pgp))
8622 (rmail-add-label de)
8624 ;; The message may have beeen encrypted and signed (one pass),
8625 ;; force checking verify too.
8630 (rmail-kill-label de)
8631 (when (not (ti::nil-p pgp)) (rmail-add-label pgp))
8632 (rmail-add-label en))
8634 ((eq cmd 'encrypt-sign)
8635 (rmail-kill-label de)
8636 (when (not (ti::nil-p pgp)) (rmail-add-label pgp))
8637 (rmail-add-label en)
8638 (rmail-add-label si)))
8640 (when (eq cmd 'verify)
8641 ;; This is special, the parameter call order is 'beg end RET'
8643 (rmail-add-label "pgp")
8644 (setq stat (or (tinypgp-binary-get-result-verify-status) ""))
8646 ((string-match "good.*signature" stat)
8647 (rmail-kill-label si)
8648 (rmail-kill-label v-)
8649 (rmail-add-label v+))
8650 ((string-match "bad.*signature" stat)
8651 (rmail-kill-label si)
8652 (rmail-kill-label v+)
8653 (rmail-add-label v-)))))
8655 ;; ......................................................... vm ...
8657 ((or (memq major-mode '(vm-mode vm-edit-mode))
8658 (string-match "edit.*note " (buffer-name)))
8659 (tinypgpd fid "LABELING" cmd (current-buffer))
8663 (vm-delete-message-labels v+ 1)
8664 (vm-delete-message-labels v- 1)
8665 (vm-add-message-labels si 1)
8666 (when (not (ti::nil-p pgp)) (vm-add-message-labels pgp 1)))
8669 (vm-delete-message-labels en 1)
8670 (vm-add-message-labels de 1)
8671 (when (not (ti::nil-p pgp)) (vm-add-message-labels pgp 1))
8675 (vm-delete-message-labels de 1)
8676 (vm-add-message-labels en 1)
8677 (when (not (ti::nil-p pgp)) (vm-add-message-labels pgp 1)))
8679 ((eq cmd 'encrypt-sign)
8680 (vm-delete-message-labels de 1)
8681 (vm-add-message-labels si 1)
8682 (vm-add-message-labels en 1)
8683 (when (not (ti::nil-p pgp)) (vm-add-message-labels pgp 1))))
8685 (when (eq cmd 'verify)
8686 (when (not (ti::nil-p pgp)) (vm-add-message-labels pgp 1))
8687 (setq stat (or (tinypgp-binary-get-result-verify-status) ""))
8689 ((string-match "good.*signature" stat)
8690 (vm-delete-message-labels si 1)
8691 (vm-delete-message-labels v- 1)
8692 (vm-add-message-labels v+ 1))
8693 ((string-match "bad.*signature" stat)
8694 (vm-delete-message-labels si 1)
8695 (vm-delete-message-labels v+ 1)
8696 (vm-add-message-labels v- 1)
8697 (when (not (ti::nil-p pgp))
8698 (vm-add-message-labels pgp 1))))))))))
8700 ;;; ----------------------------------------------------------------------
8702 (defun tinypgp-mode-specific-control-after
8703 (cmd &optional user msg string)
8704 "See `tinypgp-mode-specific-control-before' for CMD USER MSG STRING."
8705 (let* ((fid "tinypgp-mode-specific-control-after: ")
8707 ;; We have to set this to nil; otherwise TM goes nuts
8708 ;; when it calls tm-rmail/preview-message
8709 ;; #todo: investigate
8711 rmail-show-message-hook
8714 (tinypgp-hash 'mode-specific 'get 'buffer nil 'global))
8716 (tinypgp-hash 'mode-specific 'get 'buffer-edit nil 'global))
8720 (when (tinypgp-hash 'mode-specific 'get 'register nil 'global)
8721 (with-current-buffer tinypgp-:buffer-tmp-article
8722 (ti::mail-hmax 'move)
8725 (buffer-substring (point) (point-max)))))
8727 (if rmail-show-message-hook ;; ByteComp silencer; no-op
8728 (setq rmail-show-message-hook nil))
8730 (tinypgpd fid cmd user "BUFFER" buffer "B-edit" buffer-edit major-mode
8731 msg string (buffer-name))
8733 ;; ....................................................... secring ...
8735 (when tinypgp-:secring-crypt-mode
8736 (tinypgp-secring-kill-maybe))
8738 ;; .......................................................... mode ...
8739 ;; The "before" hook must have been called otherwise, there must be
8740 ;; some error somewhere or exist some situation I haven't thought of.
8742 (with-current-buffer (or buffer-edit
8744 (tinypgpd fid "**CONFLICT; no buffer")
8745 (ti::read-char-safe-until
8747 Internal error in AFTER HOOK; send bug report + debug immediately."))
8750 ((memq major-mode '(rmail-mode rmail-edit-mode))
8751 ;; ..................................................... rmail ...
8753 (if (eq major-mode 'rmail-edit-mode)
8755 (tinypgp-mode-specific-label cmd))
8757 ;; ....................................................... gnus ...
8758 ((eq major-mode 'gnus-article-edit-mode)
8759 (gnus-article-edit-done))
8761 ((memq major-mode '(gnus-article-mode
8763 (setq buffer-read-only ;Restore this value
8764 (tinypgp-hash 'mode-specific 'get 'read-only nil 'global)))
8766 ;; ......................................................... vm ...
8767 ((or (memq major-mode '(vm-mode vm-edit-mode))
8768 ;; XEmacs 19.14 sources say...
8770 ;; In vm-edit.el :: vm-edit-message
8771 ;; It says (funcall (or vm-edit-message-mode 'text-mode)),
8772 ;; where vm-vars.el:1506:(defvar vm-edit-message-mode 'text-mode
8774 ;; --> VM does editing in text mode? Glup; that makes hard
8775 ;; to detect its edit buffer.
8777 (string-match "edit.*note " (buffer-name)))
8779 (tinypgpd fid "VM ENTRY" major-mode (current-buffer) (buffer-name))
8781 (setq restore-cfg 'vm) ;Yes; we need to restore Win cfg
8785 (tinypgp-hash 'vm 'put 'vm-frame-per-edit vm-frame-per-edit 'global))
8787 ;; Only close edit mode if we opened it. If user was inside
8788 ;; edit buffer, we don't close it here.
8790 (when (and (tinypgp-hash 'vm 'get 'control nil 'global)
8791 (or (eq major-mode 'vm-edit-mode)
8792 (string-match "edit.*note " (buffer-name))))
8793 (vm-edit-message-end))
8794 (tinypgp-mode-specific-label cmd))))
8798 (tinypgp-hash 'mode-specific 'get 'wcfg nil 'global))
8800 (tinypgp-hash 'mode-specific 'get 'frame nil 'global))
8802 (tinypgp-hash 'mode-specific 'get 'window nil 'global)))
8803 (set-window-configuration wcfg)
8804 (select-frame frame)
8805 (select-window window)))
8807 (tinypgp-hash 'mode-specific 'put 'buffer nil) ;Clear this
8808 ;; hook's return value
8815 ;;; .......................................................... &remail ...
8816 ;;; -r- refers to remailing
8817 ;;; -r-h refers to remailer headers
8819 ;;; ----------------------------------------------------------------------
8821 (defsubst tinypgp-r-subject-cookie ()
8822 "Return random subject cookie."
8823 (nth (1- (rand1 (length tinypgp-:r-subject-table)))
8824 tinypgp-:r-subject-table))
8826 ;;; ----------------------------------------------------------------------
8828 (defsubst tinypgp-r-elt-email2elt (email)
8829 "Return remailer entry when EMAIL is known."
8830 (ti::list-find tinypgp-:r-levien-table email
8833 (string= arg (nth 1 elt))))))
8835 ;;; ----------------------------------------------------------------------
8837 (defsubst tinypgp-r-elt-remailer (remailer)
8838 "Return remailer elt when REMAILER is known."
8839 ;; We have the alias name, find the real email address
8840 (or (assoc remailer tinypgp-:r-host-table)
8841 (error "No such remailer %s" remailer)))
8843 ;;; ----------------------------------------------------------------------
8845 (defsubst tinypgp-r-type (alias &optional email)
8846 "Return post type for remailer. ALIAS and EMAIL are mutually exclusive."
8848 (ti::mail-pgpr-reply-type (nth 2 (tinypgp-r-elt-email2elt email))))
8849 (ti::mail-pgpr-reply-type (nth 2 (assoc alias tinypgp-:r-levien-table))))
8851 ;;; ----------------------------------------------------------------------
8853 (put 'tinypgp-r-server-macro 'lisp-indent-function 2)
8854 (defmacro tinypgp-r-server-macro (server account &rest body)
8855 "Find SERVER and do body or signal error.
8859 SERVER remailer server (alias name)
8860 ACCOUNT remailer ACCOUNT@some.remailer.net
8861 Can also be nil, in that case the `email' is not constructed.
8862 (gains little speed)
8863 BODY lisp form to do if server exists.
8865 Defined variables inside BODY
8867 `info' Full Levien list entry for server
8868 `email' Constructed according to ACCOUNT."
8870 (let* ((info (or (assoc (, server) tinypgp-:r-levien-table)
8871 (error "Server is unknown %s" (, server))))
8874 (setq email (tinypgp-r-format-email-address (, account) info)))
8876 ;; If these varibles are not used in the macro BODY,
8877 ;; then byteCompiler nags. Make it quiet.
8879 (if (null email) (setq email nil))
8880 (if (null info) (setq info nil))
8884 ;;; ----------------------------------------------------------------------
8886 (defsubst tinypgp-r-post-p (elt)
8887 "Check if this remailer ELT can be used for posting."
8888 (or (string-match "cut.* hash.* pgp.* post" (nth 2 elt))
8890 TinyPgp: not enough properties %s '%s'" (nth 0 elt) (nth 2 elt))))
8892 ;;; ----------------------------------------------------------------------
8894 (defsubst tinypgp-r-init-maybe ()
8895 "Call initialise function is needed."
8896 (tinypgp-backend-set-for-action 'remail)
8897 (or (tinypgp-hash 'remail 'get 'init nil 'global)
8900 ;;; ----------------------------------------------------------------------
8902 (defun tinypgp-r-init (&optional force)
8903 "Initialise remailer support. Set up all necessary variables etc.
8904 If `tinypgp-:r-levien-table' is non-nil, then this function does nothing.
8906 FORCE tells to discard old values and build all from scratch.
8907 You usually do this if you have updated your remailer list.
8908 FORCE is set to t if you call this function interactively.
8911 `tinypgp-:r-init-hook' is run after initialise sequences have been completed."
8912 (interactive (list 'force)) ;inteactive call always forces init
8914 (let ((file tinypgp-:r-list-file)
8915 (clist tinypgp-:r-control-list)
8917 (tinypgp-backend-set-for-action 'remail)
8919 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... ... . check ...
8921 (if (not (stringp tinypgp-:r-mail2news-remailer)) ;has default
8922 (error "TinyPgp: Please set Usenet post remailer tinypgp-:r-mail2news-remailer."))
8924 (if (not (stringp tinypgp-:r-user-mail-address)) ;has default
8925 (error "TinyPgp: Please set tinypgp-:r-user-mail-address"))
8927 (when (not (and (stringp tinypgp-:r-list-file)
8928 (file-exists-p tinypgp-:r-list-file)))
8929 (error "TinyPgp: Hm, no tinypgp-:r-list-file please see manual.")
8932 ;; - not a good idea. Person may not have access to ftp or
8933 ;; the ftp location does not exist any more.
8935 (message "TinyPgp: Hm, no tinypgp-:r-list-file; fetching it by finger..")
8937 ;; Notice the 'no-init parameter. It would otw loop back to us.
8938 (tinypgp-r-update-remailer-list 'verb 'no-init))
8940 ;; It is important that you have new remailer file, print
8941 ;; warning regularly if the file is old
8943 (when (and tinypgp-:r-list-file
8945 (setq val (tinypgp-hash 'remail 'get 'file-warning))
8946 (if (not (integerp val))
8949 (tinypgp-hash 'remail 'put 'file-warning val)
8950 (eq 0 (% val 5)))) ;every 5th call
8951 (tinypgp-hash 'remail 'put 'file-warning 0)
8952 (tinypgp-r-file-old-warning))
8954 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... ... do init ...
8956 ;; If this doesn't exist, init all
8958 (when (or force (null tinypgp-:r-levien-table))
8959 (when (or (not (stringp file))
8960 (not (file-exists-p file)))
8962 (substitute-command-keys
8964 "TinyPgp: Please set variable tinypgp-:r-list-file and call"
8965 "\\[tinypgp-r-update-remailer-list]"))))
8969 (setq tinypgp-:r-levien-table (tinypgp-r-get-list "." nil file clist))
8970 (tinypgpd "tinypgp-r-init: " tinypgp-:r-levien-table)
8972 (setq tinypgp-:r-host-table ;only cpunk and some properties
8973 (tinypgp-r-get-list nil tinypgp-:r-levien-table))
8975 (if (null tinypgp-:r-host-table)
8977 "TinyPgp: Can't find good remailers from '%s'. Consult maintainer."
8978 tinypgp-:r-list-file))
8980 (setq tinypgp-:r-reply-block-cache nil) ;Build from scratch
8982 (tinypgp-hash 'remail 'put 'init (or force 'done) 'global)
8983 (if tinypgp-:r-init-hook (run-hooks 'tinypgp-:r-init-hook))
8986 (message "TinyPgp: Remailer support initialised.")))))
8988 ;;; ----------------------------------------------------------------------
8990 (defun tinypgp-r-file-old-warning (&optional file days-old fmt)
8991 "Print warning if file is too old.
8994 FILE Defaults to `tinypgp-:r-list-file'
8995 DAYS-OLD Defaults to 24 (3 weeks).
8996 FMT Message format. First arg is %s file and second %d how old file."
9000 (setq file tinypgp-:r-list-file)
9001 (error "No tinypgp-:r-list-file set."))
9004 (setq days-old (* 3 7)))
9005 (setq days (ti::file-days-old file))
9007 ;; over 3 weeks old remailer list...too old
9009 (when (> days days-old)
9013 (or fmt "'%s' is approx %d days old, which is too much.")
9017 ;;; ----------------------------------------------------------------------
9019 (defun tinypgp-r-get-list (&optional re list file control-list)
9020 "Get remailer list matching RE.
9023 RE what properties to grep. The properties are sorted
9024 and defaults to \"cpunk.* hash.* pgp\". These features are
9025 considered minimum features from remailer.
9027 FILE file from where to read the Levien list. LIST must be nil.
9028 CONTROL-LIST See `ti::mail-pgpr-parse-levien-list'.
9031 `tinypgp-:r-get-list-hook' is run after the Levien file is read into
9033 (let* ((fid "tinypgp-r-get-list:")
9035 (setq re (or re "cpunk.* hash.* pgp"))
9039 ;; Read remailer list from file and parse it
9042 (not (file-exists-p file)))
9043 (error "TinyPgp: Can't read remailer file file '%s'" file))
9045 (with-current-buffer (tinypgp-ti::temp-buffer)
9046 (insert-file-contents file)
9047 (run-hooks 'tinypgp-:r-get-list-hook)
9048 (tinypgp-r-file-old-warning)
9051 (unless (setq list (ti::mail-pgpr-parse-levien-list
9053 (tinypgpd fid (buffer-string))
9054 (pop-to-buffer (current-buffer))
9056 TinyPgp: Cannot parse this buffer: not in levien format. %s " file))))
9059 (if (string-match re (nth 2 elt))
9064 ;;; ----------------------------------------------------------------------
9066 (defun tinypgp-r-mail-mode-init ()
9067 "Turn off all interfering minor modes from remailer mail buffer."
9069 (setq s 'post-command-hook)
9070 (make-local-hook s) ;19.30+
9071 (remove-hook s 'timi-post-command) ;disable tinymail.el
9073 ;; What should we remove from this hook ?
9075 (setq s 'post-command-idle-hook)
9076 (when (boundp s) (make-local-hook s))
9078 (setq s 'mime/editor-mode-flag) ;tm.el
9079 (when (boundp s) (set s nil))))
9081 ;;; ----------------------------------------------------------------------
9083 (defun tinypgp-r-post-before-default ()
9084 "Disable/exit known minor modes/features."
9085 (ti::mail-mime-turn-off-mode)
9086 (if (featurep 'tinymail)
9087 (timi-mail 'disable)))
9089 ;;; ----------------------------------------------------------------------
9091 (defun tinypgp-r-latent-time-random (remailer str)
9092 "Add 'r' to the time if REMAILER supports it. If STR is nil, do nothing."
9095 ;; The remailers are not checked yet.
9097 (if (not (char= (aref str (1- (length str))) ?r))
9098 (setq str (concat str "r"))))
9102 ;;{{{ remail: reply block
9104 ;;; ................................................... &r-reply-block ...
9106 ;;; ----------------------------------------------------------------------
9108 (defun tinypgp-r-reply-block-read (remailer)
9109 "Read reply block for the REMAILER.
9110 Don't use this function, use `tinypgp-r-reply-block-cache' instead.
9117 (let ((elt (assoc remailer tinypgp-:r-reply-block-table))
9127 "TinyPgp: No Reply block defined for remailer '%s' "
9128 "in tinypgp-:r-reply-block-table")
9131 (setq file (nth 1 elt)
9132 buffer (or (find-buffer-visiting file)
9133 (if (file-exists-p file)
9135 ;; pure find avoigs calling hooks/modes
9136 ;; when file is loaded.
9138 (ti::find-file-literally file)
9139 (error "TinyPgp: No reply block file %s" file))))
9140 (with-current-buffer buffer
9143 ;; Make sure it will not be modified.
9145 (setq buffer-read-only t)
9146 ;;; (rename-buffer (concat " " file))
9148 (unless (setq reg (ti::mail-pgp-block-area 'any))
9149 (pop-to-buffer buffer)
9150 (error "TinyPgp: Can't find reply block region?"))
9151 (setq beg (point-min) end (cdr reg)))
9153 (list buffer beg end))))
9155 ;;; ----------------------------------------------------------------------
9157 (defun tinypgp-r-reply-block-cache (mode &optional arg1)
9158 "Reply block cache management according to MODE and ARG1.
9162 'get ARG1 = remailer alias; return reply block.
9163 'put ARG1 = `tinypgp-:r-reply-block-cache' element
9164 'del ARG1 = remailer alias"
9165 (let ((table tinypgp-:r-reply-block-table)
9171 (or (setq elt (assoc arg1 table))
9172 (error "TinyPgp: %s not defined in tinypgp-:r-reply-block-table '%s'"
9175 ;; Have we read it already?
9176 (setq buffer (find-buffer-visiting (nth 1 elt)))
9177 (or (setq elt (assq buffer tinypgp-:r-reply-block-cache))
9178 ;; No, load it from file then
9180 (and (setq elt (tinypgp-r-reply-block-read arg1))
9181 (setq old (assq (car elt) tinypgp-:r-reply-block-cache))
9182 (setq tinypgp-:r-reply-block-cache
9183 (delq old tinypgp-:r-reply-block-cache)))
9184 (push elt tinypgp-:r-reply-block-cache))
9186 ;; Remove non-existing buffers -- keep the list up to date
9188 (dolist (elt tinypgp-:r-reply-block-cache)
9189 (if (buffer-live-p (get-buffer (car elt)))
9190 (setq tinypgp-:r-reply-block-cache
9191 (delq elt tinypgp-:r-reply-block-cache))))
9196 (and (setq elt (assoc arg1 table))
9197 (setq buffer (get-buffer
9198 (file-name-nondirectory
9200 (setq elt (assq buffer tinypgp-:r-reply-block-cache))
9201 (setq tinypgp-:r-reply-block-cache
9202 (delq elt tinypgp-:r-reply-block-cache)))
9203 tinypgp-:r-reply-block-cache)
9206 (push arg1 tinypgp-:r-reply-block-cache)
9209 ;;; ----------------------------------------------------------------------
9211 (defun tinypgp-r-reply-block-insert (remailer)
9212 "Insert REMAILER's reply block."
9213 (interactive (list (tinypgp-ask-reply-block-remailer)))
9214 (let* ((elt (tinypgp-r-reply-block-cache 'get remailer)))
9216 (error "TinyPgp: Invalid return value.")
9217 (insert-buffer-substring (nth 0 elt) (nth 1 elt) (nth 2 elt)))))
9219 ;;; ----------------------------------------------------------------------
9221 (defun tinypgp-r-reply-block-header (remailer latent key anon-to)
9222 "Return reply block headers of remailer.
9226 REMAILER string or symbol or list, The remailer used.
9227 If list, then the REMAILER is remailer-elt from
9228 `tinypgp-:r-levien-table'
9229 LATENT latent time specification. This is not be used if
9230 remailer does not support it.
9231 KEY The conventional crypt password
9232 ANON-TO Where to send the reply block (return address)."
9233 (if (symbolp remailer) (setq remailer (symbol-name remailer)))
9234 (let* ((properties (cond
9235 ((ti::listp remailer) remailer)
9236 ((tinypgp-r-elt-remailer remailer))))
9237 ;;; (email (nth 1 properties))
9238 (rtype (ti::mail-pgpr-reply-type (nth 2 properties)))
9239 ;; What kind of reply block: With/out latent ?
9241 (btype (nth 2 properties)))
9243 (if (null (string-match "latent" btype))
9244 (setq latent nil) ;Not supported
9245 (setq latent (tinypgp-r-latent-time-random remailer latent))))
9248 (if (null (string-match "ek" btype))
9250 ;; The Reply string type "cpunk, eric..."
9251 (ti::mail-pgpr-block nil rtype anon-to key latent)))
9254 ;;{{{ remail: reply-block: interactive
9256 ;;; ................................................... &reply-block-i ...
9258 (defun tinypgp-r-reply-block-test (&optional no-confirm)
9259 "Send every reply block listed in `tinypgp-:r-reply-block-table'.
9260 NO-CONFIRM bypasses asking.
9261 If you don't receive mail back, there are two possibilities:
9263 o your reply block was not constructed correctly."
9265 (tinypgp-r-init-maybe)
9266 (let* ((fid "tinypgp-r-reply-block-test: ")
9270 (dolist (elt tinypgp-:r-reply-block-table)
9271 (setq remailer (nth 0 elt))
9272 (setq email (nth 1 (assoc remailer tinypgp-:r-levien-table)))
9274 (tinypgpd fid remailer email)
9278 (ti::read-char-safe-until
9280 "[%s] Does not exist any more, delete reply block. [press]"
9283 (when (or no-confirm
9284 (y-or-n-p (format "Send reply block to %s " remailer)))
9286 (ti::mail-sendmail-macro email remailer 'send
9287 (ti::mail-kill-field
9291 (ti::date-standard-date)))
9292 ;;; (pop-to-buffer (current-buffer))
9293 ;; (insert (ti::mail-pgpr-block 'epgp "cpunk" ) "\n")
9294 (tinypgp-r-reply-block-insert remailer)))))
9295 ;;; (ti::pmin) (ti::d! "testing-rblock")
9298 (message "Sent %d test reply block%s."
9299 i (if (eq i 1) "" "s"))))))
9301 ;;; ----------------------------------------------------------------------
9303 (defun tinypgp-r-reply-block-basic
9304 (remailer-elt &optional latent key anon-to final verb)
9305 "Contruct most basic reply block.
9307 The created encrypted reply block will contain following
9310 Request-Remailing-To: <`tinypgp-:r-user-mail-address'>
9311 Encrypt-Key: <key you gave>
9312 Latent-Time: <latent time you gave>
9316 You must be in empty [mail] buffer. When this function finishes, you
9317 should _encrypt_ the mail body.
9321 REMAILER-ELT Remailer table entry
9323 KEY crypt key, no spaces
9324 ANON-TO send-to@some.com
9325 FINAL flag, if this is final block, include
9326 \"**\" to the end. (See remailer faqs)
9327 And kill any extra headers.
9329 VERB Verbose messages.
9331 Interactive call note:
9333 LATENT can be passed by prefix arg. Each \\[universal-argument] adds 30 minutes, so
9334 3 times \\[universal-argument] is same as +1:30.
9335 Numeric argument gives straigh hours, so M - x 2 means +2:00. Latent time
9336 is not always supported by selected remailer and it is ignored if remailer
9339 ANON-TO is `tinypgp-:r-user-mail-address'.
9341 FINAL is always set to t"
9345 (unless (ti::mail-body-empty-p)
9346 (if (y-or-n-p "Fresh buffer needed, empty this buffer? ")
9348 (ti::mail-text-start 'move) (delete-region (point) (point-max)))
9349 (error "TinyPgp: Buffer must be emptied first")))
9351 (ti::list-merge-elements
9352 (tinypgp-ask-remail-args)
9353 tinypgp-:r-user-mail-address
9355 ;; ... ... ... ... ... ... ... ... ... ... ... ... . interactive end . .
9358 (tinypgp-r-init-maybe)
9360 (unless (ti::mail-body-empty-p)
9361 (error "TinyPgp: Buffer must be emptied first"))
9363 (tinypgp-r-chain-1 remailer-elt latent key anon-to final)
9365 (if tinypgp-:r-reply-block-basic-hook
9366 (run-hooks 'tinypgp-:r-reply-block-basic-hook))
9369 ;;; (message "If you encrypt this, you should leave '**' outside."))
9374 ;;{{{ remail: interactive
9376 ;;; ................................................... &r-interactive ...
9378 ;;; ----------------------------------------------------------------------
9380 (defun tinypgp-r-chain-1 (remailer-elt &optional latent key anon-to final)
9381 "Encrypt mail to next remailer.
9384 REMAILER-ELT remailer elt from `tinypgp-:r-levien-table'
9385 LATENT latent time e.g. 0:00r (not used if...)
9386 KEY Encrypt key (not used if remailer does not support it)
9387 ANON-TO send-to@somewhere.com
9388 FINAL flag, prefix arg, if this is final block, include
9389 \"**\" to the end. (See remailer faqs)
9392 email remailer address"
9394 (ti::list-merge-elements
9395 (tinypgp-ask-remail-args)
9396 (read-from-minibuffer
9398 (mail-fetch-field "To"))))
9399 (tinypgp-r-init-maybe)
9400 (let* (tinypgp-:xpgp-signing-mode ;Do not use X-Pgp
9401 (properties remailer-elt)
9402 (email (nth 1 properties))
9404 ;; The Reply string type "cpunk, eric..."
9406 (rtype (ti::mail-pgpr-reply-type (nth 2 properties)))
9408 (mail (ti::mail-mail-p))
9411 (or tinypgp-:r-mode-indication-flag
9412 (setq tinypgp-:r-mode-indication-flag 'basic-1))
9414 (if (and key (string-match "[ \t\n]" key))
9415 (error "TinyPgp: Key may not contains spaces '%s'" key))
9417 ;; ........................................... destination address ...
9419 (ti::mail-text-start 'move)
9421 (setq str (tinypgp-r-reply-block-header remailer-elt latent key anon-to))
9424 (tinypgp-encrypt-mail email)
9426 ;; ................................................ remail address ...
9428 (ti::mail-text-start 'move)
9430 ;; The outer block encrypt key is disabled for now because
9431 ;; it causes double encryptinn. When you receive the mail,
9432 ;; then you have to decrypt it twice...not convenient.
9434 ;; The Reply Blocks EK should be enough. User can add the
9435 ;; extra Field if he wants it.
9437 (setq str (ti::mail-pgpr-block nil rtype email nil latent))
9440 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... ... . final ...
9443 (ti::mail-pgpr-close)
9446 (ti::mail-kill-field "^To" (concat " " email) )
9448 ;; sysadm in your site probably isn't interested in subjects
9449 ;; like this one. We don't want to draw his attention
9451 (ti::mail-kill-field "^Subject" (tinypgp-r-subject-cookie))
9452 (ti::mail-kill-field "^Fcc")
9453 (ti::mail-kill-field "^Gcc") ;GNUS 5
9454 (ti::mail-kill-field "^Reply-to")))
9458 ;;; ----------------------------------------------------------------------
9460 (defun tinypgp-r-chain (chain &optional verb)
9461 "Decrypt current message according to remailer CHAIN. VERB.
9462 Important, before you call this function:
9463 1. You have called \\[tinypgp-r-post] or \\[tinypgp-newnym-post] to convert
9464 the message into remail post format first.
9465 2. You must have encrypted the message.
9467 Only after these, the additonal chain layers are feasible."
9470 (or tinypgp-:r-chain
9471 (error "TinyPgp: tinypgp-:r-chain is empty"))
9474 "Select remailer chain: "
9475 tinypgp-:r-chain nil 'match nil 'tinypgp-:history-r-chain))))
9483 (or (setq chain (assoc chain tinypgp-:r-chain))
9484 (error "TinyPgp: No such choice in tinypgp-:r-chain"))
9486 (setq chain (nth 1 chain) list chain)
9488 (unless (or (vectorp chain)
9489 (vectorp (setq list (eval chain))))
9490 (error "TinyPgp: %s evaluated to %s, which is not vector." chain list))
9492 (or (setq list (append list nil)) ;Convert to list :-)
9493 (error "TinyPgp: Vector list was empty?"))
9495 ;; I can't do automatic encryption, because I have no of
9496 ;; knowing if user had called C-c / . p to convert the message
9497 ;; to post format. It would be disaster to encrypt non-post message
9499 (or (ti::mail-pgp-encrypted-p)
9501 TinyPgp: The message must have been encrypted to mail2news gateway."))
9503 (dolist (elt list) ;; #todo: Can't use dolist beacause tests FINAL
9504 (setq remailer (nth 0 elt)
9507 remailer-elt (tinypgp-r-elt-remailer remailer)
9508 final (null (cdr list)) ;No more remailers
9509 anon-to (mail-fetch-field "to"))
9511 (error "TinyPgp: To address is empty, can't use Anon-to"))
9512 (tinypgp-r-chain-1 remailer-elt latent key anon-to final))
9514 ;; Let's do fast check and turn off auto-action
9516 (when (and verb (tinypgp-auto-action-on-modeline-p))
9517 (tinypgp-hash 'auto-action 'put 'user-mode nil))))
9519 ;;; ----------------------------------------------------------------------
9521 (defun tinypgp-r-update-remailer-list (&optional verb no-auto-init)
9522 "Finger remailer list maintainer and get updated list.
9523 VERB allows verbose messages. NO-AUTO-INIT suppresses call to
9524 `tinypgp-r-init' after file update."
9526 (let ((file tinypgp-:r-list-file)
9527 (email tinypgp-:r-list-finger)
9528 (buffer (tinypgp-ti::temp-buffer))
9532 (setq ret (ti::process-finger email nil nil buffer verb))
9534 ((not (bufferp ret))
9535 (setq tinypgp-:last-network-error ret)
9536 (error "TinyPgp: finger Failed: %s" ret))
9538 (ti::file-delete-safe file)
9539 (with-current-buffer ret (write-region (point-min) (point-max) file))
9541 (message "TinyPgp: remailer list [%s] updated." file))
9542 (call-interactively 'tinypgp-r-init)))))
9544 ;;; ----------------------------------------------------------------------
9546 (defun tinypgp-r-post (&optional type)
9547 "Anonymize message. See TYPE from `tinypgp-r-post-usenet'."
9551 (setq type 'remail))
9552 (tinypgp-r-init-maybe)
9553 (run-hooks 'tinypgp-:r-post-before-hook)
9554 (if (ti::mail-news-buffer-p)
9555 (tinypgp-r-post-usenet type)
9556 (call-interactively 'tinypgp-r-post-regular))
9557 (run-hooks 'tinypgp-:r-post-after-hook)))
9559 ;;; ----------------------------------------------------------------------
9561 (defun tinypgp-r-post-regular
9562 (remailer &optional insert-reply-block remailer-elt)
9563 "Normal mail to: send as anonymous post. Bulk mail is not permitted.
9564 This means that any BCC or FCC field generates error.
9566 The Prefix arg inserts to the message a reply block, so that person
9567 can answer to the mail if he sends the message back to remailer.
9571 `post-command-hook' and possible `post-command-idle-hook' are
9572 bound locally to current buffer and set to nil,
9573 so that nothing special happens when you compose and send this mail.
9577 REMAILER remailer alias name
9578 INSERT-REPLY-BLOCK prefix arg, if non-nil, insert remailer reply block
9579 REMAILER-ELT the remailer entry from table `tinypgp-:r-host-table'"
9583 (setq remailer (tinypgp-ask-remailer))
9584 (setq remailer-elt (tinypgp-r-elt-remailer remailer))
9585 (list remailer current-prefix-arg remailer-elt)))
9586 (let* (tinypgp-:xpgp-signing-mode ;Do not use X-Pgp
9587 (var-list '(post-command-hook
9588 post-command-idle-hook))
9589 (hlist (delete 'newsgroups (ti::mail-required-headers)))
9590 (hlist (push 'to hlist))
9591 (to (ti::mail-get-field "TO" nil 'nil-mode))
9593 (reply-msg "To reply to this message, send it to some remailer.")
9594 (properties (or remailer-elt
9595 (assoc remailer tinypgp-:r-levien-table)
9596 (error "TinyPgp: No remailer [%s]" remailer)))
9597 (email (nth 1 properties))
9599 ;; The Reply string type "cpunk, eric..."
9601 (rtype (ti::mail-pgpr-reply-type (nth 2 properties)))
9609 (if (or (mail-fetch-field "CC")
9610 (mail-fetch-field "BCC"))
9611 (error "TinyPgp: sorry, bulk CC or BCC mail is not permitted."))
9614 (error "TinyPgp: No TO field filled."))
9616 (tinypgp-r-init-maybe)
9617 (setq str (ti::mail-pgpr-block nil rtype to))
9619 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... . headers . .
9620 ;; Get rid of headers that may reveal your identity
9622 (ti::mail-kill-non-rfc-fields hlist)
9624 (if (setq hash-headers (tinypgp-header-move-to-body 'move-to-body 'no-ins))
9625 (setq header-block (mapconcat 'concat hash-headers ""))
9626 (setq header-block ""))
9628 ;; ... ... ... ... ... ... ... ... ... ... ... ... . doing message ...
9630 (ti::mail-kill-field "to" email)
9631 (setq point (ti::mail-text-start))
9632 (setq message (buffer-substring point (point-max)))
9633 (delete-region point (point-max))
9639 "##\n" header-block "\n")
9641 (when insert-reply-block
9642 (tinypgp-r-reply-block-insert remailer))
9644 (when (and insert-reply-block reply-msg)
9645 (insert reply-msg "\n" ))
9646 (insert message "\n--\n")
9648 ;; Make sure there is nothing that interferes sending.
9649 ;; make them first local; then set them to nil
9651 (dolist (sym var-list)
9653 (make-local-hook sym)
9656 ;;; ----------------------------------------------------------------------
9659 (defun tinypgp-r-post-usenet-body-convert
9660 (groups email &optional rb rtype rblk)
9661 "Convert body text into Remail post.
9662 Supposes that you have already reformatted the buffer.
9666 GROUPS list of newsgroups where to post.
9667 EMAIL the mail2news gateway email address
9668 RB if string, insert reply block of remailer given.
9669 RTYPE Remailer reply type, e.g. 'cpunk'
9672 (let* ((reply-msg "To reply to this message, send it to some remailer.")
9678 ;; ... ... ... ... ... ... ... ... ... ... ... ... doing blocks . .
9680 (setq point (ti::mail-text-start)
9681 message (buffer-substring point (point-max)))
9682 (delete-region point (point-max))
9684 (dolist (grp groups)
9685 (setq str (ti::mail-pgpr-block nil rtype grp)
9686 block (concat str "\n##\n" rblk "\n"))
9690 (tinypgp-r-reply-block-insert rb)
9692 (insert reply-msg "\n" ))
9693 (insert message "\n--\n"))))
9695 ;;; ----------------------------------------------------------------------
9697 (defun tinypgp-r-post-usenet (type &optional rb)
9698 "Usenet message: Convert current message into anonymous remailer post.
9699 Call error if buffer is not a newsgroup post.
9703 TYPE type of conversion: 'newnym or 'remail
9704 RB Insert reply block of remailer RB, so that user can aswer to you
9705 directly by using this replay block.
9709 '(remailer-email-addr (newsgroup newsgroup ..))
9713 `tinypgp-:r-mail2news-remailer'"
9714 (let* (post-command-hook
9729 (setq tinypgp-:r-mode-indication-flag 'post)
9731 ;; Why these if statemnts? Because the byteCompiler sees that
9732 ;; I have introduced hooks in let*, but I never use them!
9733 ;; This fools bytecompiler to believe they are used and it
9734 ;; doesn't give any warnings any more
9736 (if post-command-hook (setq post-command-hook nil)) ;ByteComp silencer
9737 (if mail-setup-hook (setq mail-setup-hook nil))
9738 (if mail-mode-hook (setq mail-mode-hook nil))
9740 ;; This does exist between 19.30 - 19.33; but then it was made obsolete
9741 ;; This trick gives clean byteCompilation and no warnings
9743 (setq sym 'post-command-idle-hook)
9746 (make-local-hook sym)
9749 (setq group-fld (mail-fetch-field "Newsgroups"))
9751 (when (and t ;Enabled now
9752 (ti::nil-p group-fld))
9753 (error "TinyPgp: No newsgroups? Buffer must contain a news message."))
9755 (run-hooks 'tinypgp-:r-post-before-hook)
9757 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... variables . .
9758 ;; Read needed variables
9760 (if (or (null (setq phost (eval tinypgp-:r-mail2news-remailer)))
9761 (null (setq phost-elt (assoc phost tinypgp-:r-levien-table))))
9762 (error "TinyPgp: tinypgp-:r-mail2news-remailer '%s' %s"
9763 tinypgp-:r-mail2news-remailer phost))
9765 (tinypgp-r-post-p phost-elt) ;Calls error is not capable enough
9766 (setq phost-email (nth 1 phost-elt)
9767 phost-prop (nth 2 phost-elt)
9768 rtype (ti::mail-pgpr-reply-type phost-prop))
9770 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... . headers . .
9771 ;; Get rid of headers that may reveal your identity
9772 ;; Don't kill in-reply to because it is used in newsgroup postings.
9774 (tinypgp-header-kill)
9776 ;; Save all headers because they are inserted into body
9778 (if (setq hash-headers (tinypgp-header-move-to-body 'move-to-body 'no-ins))
9779 (setq header-block (mapconcat 'concat hash-headers ""))
9780 (setq header-block ""))
9782 ;; The remaier doesn't need this field
9784 (ti::mail-kill-field "in-reply-to")
9785 (ti::mail-kill-field "newsgroups")
9787 (if (string-match "," group-fld)
9788 (setq group-list (split-string group-fld "[,\t\n ]+"))
9789 (setq group-list (list group-fld)))
9791 ;; ... ... ... ... ... ... ... ... ... ... ... ... doing blocks . .
9793 ;;; (setq point (ti::mail-text-start)
9794 ;;; message (buffer-substring point (point-max)))
9795 ;;; (delete-region point (point-max))
9800 (tinypgp-r-post-usenet-body-convert
9801 group-list phost rb rtype header-block)))
9803 (ti::pmin) (insert "To: " phost-email "\n") ;Set destination
9805 (mail-mode) ;This is not a news message any more.
9806 (unless tinypgp-mode (tinypgp-mode 1))
9808 (list phost-email group-list)))
9814 ;;; ........................................................ &r-newnym ...
9816 ;;; ----------------------------------------------------------------------
9818 (defsubst tinypgp-newnym-read-word ()
9819 "Read newnym configuration command word."
9822 (when (char= (char-syntax (following-char)) ?\ ) ;Sitting on whitespace
9824 (when (setq word (ti::buffer-read-space-word))
9825 (ti::string-match "[^-+=]+" 0 word)))))
9827 ;;; ----------------------------------------------------------------------
9829 (defsubst tinypgp-newnym-list (&optional mode force)
9830 "Return ELTS for all 'newnym'.
9831 Normally once the list has been generated; it is stored to hash.
9835 MODE nil = return full configuration list
9836 'alias = return alias name list
9837 FORCE reread Levien table content and update hash.
9840 `tinypgp-:r-levien-table'"
9841 (let* ((list (tinypgp-hash 'remail 'get 'newnym)))
9842 (tinypgp-r-init-maybe)
9843 (when (or force (null list))
9844 (or tinypgp-:r-levien-table
9845 (error "TinyPgp: Levien list is nil."))
9847 (setq list (tinypgp-r-get-list "newnym" tinypgp-:r-levien-table))
9848 (tinypgp-hash 'remail 'put 'newnym list)
9849 (tinypgp-hash 'remail 'put 'newnym-alias (mapcar 'car list)))
9850 (cond ;No other choices yet
9852 (setq list (tinypgp-hash 'remail 'get 'newnym-alias))))
9855 ;;; ----------------------------------------------------------------------
9857 (defsubst tinypgp-r-format-email-address (account remailer-entry)
9858 "Return address that has ACCOUNT@site.com derived from REMAILER-ENTRY.
9859 The remailer-entry is one of the entries in `tinypgp-:r-levien-table'"
9861 (let* ((email (nth 1 remailer-entry)))
9862 (if (null (string-match "^[^@]+" email))
9863 (error "TinyPgp Internal error. Call \\[tinypgp-r-init] or maintainer."))
9864 ;; Set address to "help@..."
9866 (ti::replace-match 0 account email)))
9868 ;;; ----------------------------------------------------------------------
9870 (defsubst tinypgp-newnym-ask-server (&optional prompt)
9871 "Ask newnym server name with completion and PROMPT."
9872 (tinypgp-r-init-maybe)
9873 (or (get 'tinypgp-:r-newnym-default-account-table 'default-server)
9875 (or "Newnym account domain: " prompt)
9876 (ti::list-to-assoc-menu (tinypgp-newnym-list 'alias))
9880 ;;; ----------------------------------------------------------------------
9882 (defun tinypgp-newnym-file-stamp-name (server account)
9883 "Return Stamp file name according to SERVER and ACCOUNT."
9884 (concat tinypgp-:r-newnym-stamp-file-prefix
9885 (ti::string-mangle (concat server account))))
9887 ;;; ----------------------------------------------------------------------
9889 (defun tinypgp-newnym-file-stamp (server account)
9890 "Stamp Newnym file with with SERVER and ACCOUNT."
9891 (let* ((file (tinypgp-newnym-file-stamp-name server account)))
9892 (if (and (file-exists-p file)
9893 (not (file-writable-p file)))
9894 (set-file-modes file (ti::file-mode-make-writable (file-modes file))))
9895 (ti::file-touch file)
9896 (ti::file-mode-protect file)))
9898 ;;; ----------------------------------------------------------------------
9900 (defun tinypgp-newnym-account-expiry-warnings ()
9901 "Print possible account expiry warnings.
9903 `tinypgp-:r-newnym-default-account-table'"
9905 (let* ((limit 100) ;It's actually 120, but we use 100
9910 (dolist (elt tinypgp-:r-newnym-default-account-table)
9912 (setq server (nth 1 elt)
9914 file (tinypgp-newnym-file-stamp-name server account))
9916 ;;; (setq F file S server A account)
9917 ;;; (ti::d! (file-exists-p file) account server file)
9920 ((null (file-exists-p file))
9921 (message "TinyPgp Warning: No stamp file for %s %s, Creating..."
9924 (tinypgp-newnym-file-stamp server account))
9926 (setq days (ti::file-days-old file)
9927 ret (format "%s %s: %d" ret account (- limit days)))
9928 (when (> days limit)
9930 "Tinypgp Newnym stamp is %d days old, account may expire: %s %s"
9938 ;;; ----------------------------------------------------------------------
9940 (defsubst tinypgp-newnym-ask-account ()
9941 "Ask newnym Account name."
9942 (tinypgp-r-init-maybe)
9946 (or (get 'tinypgp-:r-newnym-default-account-table 'default-account)
9949 (read-from-minibuffer
9950 "Nym account login name: "
9952 'tinypgp-:history-newnym-account
9953 (error "TinyPgp: Empty not accepted.")
9957 ;;; ----------------------------------------------------------------------
9959 (defun tinypgp-newnym-ask-srv-acc (&optional confirm-msg)
9960 "Ask '(server account) with optional CONFIRM-MSG."
9961 (tinypgp-r-init-maybe)
9965 (or (y-or-n-p confirm-msg)
9967 (setq srv (tinypgp-newnym-ask-server))
9968 (setq acc (tinypgp-newnym-ask-account))
9971 ;;; ----------------------------------------------------------------------
9973 (defun tinypgp-newnym-ask-srv-acc-arg (&optional confirm-msg)
9974 "Ask '(server account prefix_arg) with CONFIRM-MSG."
9975 (tinypgp-r-init-maybe)
9977 (or (y-or-n-p confirm-msg)
9980 (tinypgp-newnym-ask-server)
9981 (tinypgp-newnym-ask-account)
9982 current-prefix-arg))
9984 ;;; ----------------------------------------------------------------------
9986 (defsubst tinypgp-r-sendmail-create-buffer (name &optional subject)
9987 "Create mail buffer. The old buffer is killed.
9989 NAME buffre name. Kill eny existing buffer with NAME without query.
9990 SUBJECT Message subject."
9991 (ti::kill-buffer-safe name)
9992 (with-current-buffer (tinypgp-ti::temp-buffer 'mail "NONE" (or subject ""))
9993 (rename-buffer name)
9994 (buffer-enable-undo)
9995 (setq tinypgp-:r-mode-indication-flag 'newnym)
9996 (tinypgpd "tinypgp-r-sendmail-create-buffer" name (current-buffer))
9999 ;;; ----------------------------------------------------------------------
10002 (defun tinypgp-newnym-sendmail-fmacro-1 (func doc account subject msg)
10003 "Use `tinypgp-newnym-sendmail-fmacro' instead.
10004 See FUNC DOC ACCOUNT SUBJECT MSG there."
10005 (let* ((sym (intern (symbol-name (` (, func))))))
10007 (defun (, sym) (alias &optional verb)
10009 (interactive (list (tinypgp-newnym-ask-server)))
10011 (tinypgp-r-init-maybe)
10012 (tinypgp-r-server-macro alias (, account)
10013 (ti::mail-sendmail-macro email (, subject) 'send (insert "empty"))
10015 (message "'%s' request sent to %s, wait for answer."
10016 (, msg) email))))))))
10018 ;;; ----------------------------------------------------------------------
10020 (put 'tinypgp-newnym-sendmail-fmacro 'lisp-indent-function 0)
10021 (defmacro tinypgp-newnym-sendmail-fmacro (func doc account subject msg)
10022 "Create interactive function that sends mail to remailer.
10025 FUNC Created function name
10026 DOC Function's doc string
10027 ACCOUNT the account name where to send email request
10028 SUBJECT Subject for email
10029 MSG Notification message to interactive user e.g. 'create'."
10030 (` (, (tinypgp-newnym-sendmail-fmacro-1
10031 func doc account subject msg ))))
10034 ;;{{{ newnym: keys; menus
10036 ;;; ................................................... &newnym-mode ...
10038 (defun tinypgp-newnym-mode-define-menu ()
10041 tinypgp-:newnym-mode-menu (if (ti::xemacs-p)
10043 tinypgp-:newnym-mode-map)
10044 "TinyPgp Newnym management menu"
10046 tinypgp-:newnym-mode-menu-name
10047 ["Nym-Commands: Electric tab" tinypgp-newnym-mode-electric-tab t]
10048 ["Nym-Commands: Go to." tinypgp-newnym-mode-nym-commands-goto t]
10049 ["Reply-Block: Add" tinypgp-newnym-mode-reply-block t]
10050 ["Reply-Block: Kill" tinypgp-newnym-mode-reply-block-kill t]
10051 ["Public-key: Add" tinypgp-newnym-mode-public-key t]
10052 ["Public-key: Kill" tinypgp-newnym-mode-public-key-kill t]
10053 ["Mode description" tinypgp-newnym-mode-describe t]
10056 ;;; ----------------------------------------------------------------------
10058 (defun tinypgp-newnym-mode-define-keys ()
10060 (let* ((p tinypgp-:newnym-mode-prefix-key)
10061 (map tinypgp-:newnym-mode-map))
10062 (define-key map "\t" 'tinypgp-newnym-mode-electric-tab)
10063 (define-key map (concat p "\t") 'tinypgp-newnym-mode-nym-commands-goto)
10064 (define-key map (concat p "p") 'tinypgp-newnym-mode-public-key)
10065 (define-key map (concat p "P") 'tinypgp-newnym-mode-public-key-kill)
10066 (define-key map (concat p "r") 'tinypgp-newnym-mode-reply-block)
10067 (define-key map (concat p "R") 'tinypgp-newnym-mode-reply-block-kill)
10068 (define-key map (concat p "?") 'tinypgp-newnym-mode-describe)))
10071 ;;{{{ newnym: Mode functions
10073 ;;; ----------------------------------------------------------------------
10076 (ti::macrof-minor-mode
10077 tinypgp-newnym-mode ;1
10078 "Newnym account management help mode.
10079 You turn this mode on in mail buffer and it helps you to
10080 compose message to nym account. The most interesting command probably
10081 is `tinypgp-newnym-mode-electric-tab'; which works as follows
10083 If cursor is anywhere else that at the line Nym-Commands:, then the
10084 original tab function is called.
10086 Nym-Commands: create +acksend +fin +
10088 | | | | complete all commands
10089 | | | complete command 'fin'
10090 | | Show default setting or example (previous word)
10092 | Show command help and advance to '*'.
10093 If the cursor is over word Nym-Commands:, then advance forward to first
10096 In hooks you should use functions
10098 `turn-on-tinypgp-newnym-mode'
10099 `turn-off-tinypgp-newnym-mode'
10102 \\{tinypgp-:newnym-mode-map}
10104 tinypgp-install-modes ;3
10105 tinypgp-newnym-mode ;4
10106 tinypgp-:newnym-mode-name
10108 tinypgp-:newnym-mode-prefix-key ;5
10109 tinypgp-:newnym-mode-menu ;6
10112 "Newnym acocunt handling" ;8
10113 tinypgp-:newnym-mode-hook ;
10116 (tinypgp-update-modeline)))
10118 (defun turn-on-tinypgp-newnym-mode ()
10120 (tinypgp-newnym-mode 1))
10122 (defun turn-off-tinypgp-newnym-mode ()
10124 (tinypgp-newnym-mode 0))
10126 ;;; .............................................. &newnym-interactive ...
10128 ;;; ----------------------------------------------------------------------
10130 (defun tinypgp-newnym-mode-describe ()
10133 (describe-function 'tinypgp-newnym-mode))
10135 ;;; ----------------------------------------------------------------------
10137 (defun tinypgp-newnym-mode-electric-tab ()
10138 "Compose newnym commands if cursor is on field Nym-Commands.
10139 Otherwise call original mode's tab key. See description of this command
10140 from `tinypgp-newnym-mode'."
10142 (let* ((tbl tinypgp-:newnym-cmd-table)
10147 (save-excursion (beginning-of-line) (looking-at "Nym-Commands:")))
10148 ;; Turn mode off and call original tab key.
10150 (let* (tinypgp-newnym-mode)
10151 (call-interactively (key-binding "\t"))))
10153 (setq word (tinypgp-newnym-read-word))
10156 ;; ................................................... beg line ...
10157 ((and (not (ti::nil-p word))
10158 ;; the "-" terminates word; because it is [+-] option,
10159 ;; that's why we have to test separate words.
10160 (member word '("Nym" "Commands:")))
10161 (skip-chars-forward "^ \t\n")
10162 (skip-chars-forward " \t"))
10163 ;; ............................................... complete all ...
10164 ((and (ti::nil-p word) ;User wrote [+-] and wants to complete
10165 (ti::char-in-list-case (preceding-char) '(?+ ?-)))
10166 (setq word (completing-read "Insert Command: " tbl))
10167 (if (not (ti::nil-p word))
10170 ;; ............................................... example show ...
10171 ((and (not (ti::nil-p word))
10172 (setq elt (assoc word tbl)) ;Full match
10173 ;; after word that is full match; on whitespace
10174 (ti::char-in-list-case (following-char) '(?\ ?\t ?\n)))
10175 (message (nth 2 elt)))
10177 ;; ........................................... full match; help ...
10178 ((and (not (ti::nil-p word))
10179 (setq elt (assoc word tbl))) ;Full match
10180 (message (nth 1 elt))
10181 (skip-chars-forward "^ \t\n"))
10183 ;; ........................................... partial complete ...
10184 ((and (not (ti::nil-p word)) ;Partial
10185 (setq elt (all-completions word tbl)))
10187 ((eq 1 (length elt)) ;one match
10188 (skip-chars-forward "^ \t\n")
10189 (delete-backward-char (length word))
10190 (insert (car elt)))
10191 (t ;many completions
10192 (message (ti::list-to-string elt)))))
10194 ;; .............................................. nothing works ...
10196 ;; User is sitting on whitespace and nothing is nearby
10197 ;; "Nym-Commands: "
10198 (message "Write [+-] before options. Complete with TAB.")))))))
10200 ;;; ----------------------------------------------------------------------
10202 (defun tinypgp-newnym-mode-nym-commands-goto ()
10203 "Goto Nym-Commands: forward or add that field if it does not exist."
10205 (let* ((fld "Nym-Commands: ")
10206 (point (if (re-search-forward fld nil t)
10208 (save-excursion ;Wrap
10210 (if (re-search-forward fld nil t)
10214 ;; No such field; add one. Put after From field.
10221 (ti::mail-text-start 'move)
10223 ((re-search-forward "From:") (forward-line 1))
10224 ((re-search-forward "Config:") (forward-line 1)))
10226 (backward-char 1))))
10228 ;;; ----------------------------------------------------------------------
10230 (defun tinypgp-newnym-mode-public-key-kill ()
10231 "Kill Public-Key field."
10233 (tinypgp-newnym-mode-public-key nil 'kill))
10235 ;;; ----------------------------------------------------------------------
10237 (defun tinypgp-newnym-mode-public-key (key-id &optional kill)
10238 "Insert Public-Key field and PGP key block to the end.
10239 If there already exist Public-Key tag, then insert pgp key block after it
10240 by possibly deleting old pgp key block.
10243 KEY-ID key-id matching public key
10244 KILL if non-nil prefix arg, kill the public key block"
10246 (let* ((default (save-excursion
10247 (ti::mail-text-start 'move)
10248 ;; find the From command field and suggest
10249 ;; inserting pgp key-id amtching it
10251 (ti::mail-get-field "From" 'any)))
10253 (unless current-prefix-arg ;Don't ask if arg given
10256 (read-from-minibuffer "Insert pgp key matching key-id: "
10257 (if (not (ti::nil-p default))
10258 (ti::string-remove-whitespace default))))
10259 (if (ti::nil-p ret)
10260 (error "TinyPgp: Empty not accepted.")))
10262 (list ret current-prefix-arg)))
10263 (let* ((fld "Public-Key:")
10265 (ti::save-with-marker-macro
10266 (ti::mail-text-start 'move)
10267 (setq stat (re-search-forward fld nil t))
10271 (ti::buffer-kill-line))
10277 (insert fld "\n"))))
10279 (ti::mail-pgp-block-area-kill-forward 'pkey 'move)
10282 (tinypgp-key-extract-to-point key-id 'raw)))))
10284 ;;; ----------------------------------------------------------------------
10286 (defun tinypgp-newnym-mode-reply-block-kill (&optional insert remailer)
10287 "Kill Reply-Block or INSERT (or replace with) matching REMAILER."
10289 (let* ((fld "Reply-Block:")
10291 (ti::save-with-marker-macro
10292 (ti::mail-text-start 'move)
10293 (setq stat (re-search-forward fld nil t))
10296 ((and insert (null stat))
10301 (save-excursion ;Previous reply block?
10302 (forward-line 1) ;Peek next line
10303 (looking-at "::\n")))
10305 (delete-region (point) (point-max)))
10306 ((and (null insert) stat)
10307 (ti::buffer-kill-line)
10308 (if (looking-at "::\n")
10309 (delete-region (point) (point-max)))))
10312 (tinypgp-r-reply-block-insert remailer)))))
10314 ;;; ----------------------------------------------------------------------
10316 (defun tinypgp-newnym-mode-reply-block (remailer &optional verb)
10317 "Insert Reply-Block field and REMAILER block to the end.
10318 If there already exist Reply-Block tag, then insert block after it
10319 by possibly deleting old block.
10322 REMAILER The reply block must have been created beforehand and
10323 it must be included in `tinypgp-:r-reply-block-table'
10324 VERB Verbose messages."
10325 (interactive (list (tinypgp-ask-reply-block-remailer)))
10327 (tinypgp-newnym-mode-reply-block-kill 'insert remailer)
10329 (message "Tinypgp: '%s' reply block inserted" remailer)))
10332 ;;{{{ newnym: misc, interactive(delete; create; toggle)
10334 ;;; ............................................ &r-newnym-interactive ...
10336 ;;; ----------------------------------------------------------------------
10338 (defun tinypgp-newnym-default-set (completion-name)
10339 "Set default newnym server and account according to COMPLETION-NAME.
10340 The name must be found from table `tinypgp-:r-newnym-default-account-table'."
10343 (if (null tinypgp-:r-newnym-default-account-table)
10344 (error "TinyPgp: tinypgp-:r-newnym-default-account-table not defined.")
10346 "Default Newnym selection: "
10347 tinypgp-:r-newnym-default-account-table
10350 (let* ((sym 'tinypgp-:r-newnym-default-account-table)
10351 (elt (assoc completion-name (symbol-value sym))))
10353 (put sym 'default-completion completion-name)
10354 (put sym 'default-server (nth 1 elt))
10355 (put sym 'original-server (nth 1 elt))
10356 (put sym 'default-account (nth 2 elt))
10357 (put sym 'original-account (nth 2 elt))
10358 (if (interactive-p)
10359 (message "TinyPgp: Default newnym server and account now: %s %s"
10360 (nth 1 elt) (nth 2 elt) ))
10361 (tinypgp-update-modeline)
10364 ;;; ----------------------------------------------------------------------
10366 (defun tinypgp-newnym-default-toggle (&optional arg verb)
10367 "Toggle setting and resetting default newnym account.
10368 Set and restore variable's `tinypgp-:r-newnym-default-account-table' properties
10369 'default-server and 'default-account.
10371 ARG behaves like mode arg.
10374 0 set values to nil
10376 9 Force re-reading values now. You have to call this if you chnage the
10377 contents of the values during session manually.
10379 VERB allows verbose messages."
10382 (if (null tinypgp-:r-newnym-default-account-table)
10383 (error "TinyPgp: tinypgp-:r-newnym-default-account-table not defined."))
10385 (let* ((sym 'tinypgp-:r-newnym-default-account-table)
10386 (srv (get sym 'default-server))
10387 (acc (get sym 'default-account))
10391 ;; Not recorded? Record original value
10393 (when (or force (null (get sym 'original-server)))
10394 (put sym 'original-server srv))
10396 (when (or force (null (get sym 'original-account)))
10397 (put sym 'original-account acc))
10401 (setq msg (format "Default newnym parameters updated: %s %s"
10404 ((memq arg '(0 -1))
10405 (put sym 'default-server nil)
10406 (put sym 'default-account nil)
10407 (setq msg (format "Default newnym parameters off.")))
10412 (put sym 'default-server nil)
10413 (put sym 'default-account nil))
10415 (put sym 'default-server (get sym 'original-server))
10416 (put sym 'default-account (get sym 'original-account))))
10417 (setq msg (format "Default newnym server and account now: %s %s"
10418 (or (get sym 'original-server) "nil")
10419 (or (get sym 'original-account) "nil")))))
10421 (tinypgp-update-modeline)
10426 ;;; ----------------------------------------------------------------------
10428 (tinypgp-newnym-sendmail-fmacro
10429 tinypgp-newnym-get-pgp-key
10430 "Get PGP key via email from remailer."
10431 "remailer-key" "Send PGP key" "PGP key get")
10433 (tinypgp-newnym-sendmail-fmacro
10434 tinypgp-newnym-get-used-list
10435 "Get list of used 'newnym' account names."
10436 "list" "Send used account list" "Used")
10438 ;;; ----------------------------------------------------------------------
10440 (defun tinypgp-newnym-help-verbose (&optional arg)
10441 "Call `tinypgp-nymserver-help' as interactive would with ARG."
10442 (let* ((a (tinypgp-newnym-help-i-args arg)))
10443 (tinypgp-newnym-help (nth 0 a) (nth 1 a))))
10445 ;;; ----------------------------------------------------------------------
10447 (defun tinypgp-newnym-help-i-args (&optional arg)
10448 "Ask arrgs for `tinypgp-newnym-help'. ARG is prefix arg."
10449 (let* ((list (tinypgp-newnym-list)))
10450 (when (or (not (stringp tinypgp-:r-newnym-help-file))
10451 (null (file-exists-p tinypgp-:r-newnym-help-file))
10452 current-prefix-arg)
10455 TinyPgp: No 'newnym' type remailers in `tinypgp-:r-levien-table'."))
10459 (tinypgp-newnym-ask-server "Send help request to newnym: ")))))
10461 ;;; ----------------------------------------------------------------------
10463 (defun tinypgp-newnym-help (&optional mail-req nym-alias-name verb)
10464 "Print newnym remailer help or send the help request via mail.
10467 MAIL-REQ send mail request [current-prefix-arg]
10468 NYM-ALIAS-NAME from where to ask the help file.
10469 VERB verbose messages"
10470 (interactive (tinypgp-newnym-help-i-args current-prefix-arg))
10471 (let* ((file tinypgp-:r-newnym-help-file)
10472 (elt (if nym-alias-name
10473 (assoc nym-alias-name tinypgp-:r-levien-table)))
10479 (error "TinyPgp: Cannot find ELT for '%s'" nym-alias-name))
10481 ;; Set address to "help@..."
10482 (setq email (nth 1 elt))
10484 (if (null (string-match "^[^@]+" email))
10485 (error "TinyPgp Internal error. Call \\[tinypgp-r-init]"))
10487 (setq email (ti::replace-match 0 "help" email))
10489 (ti::mail-sendmail-macro email "help" 'send (insert "help\n"))
10492 "Email request sent to '%s'.%s"
10495 "Update tinypgp-:r-newnym-help-file when you get answer."))))
10498 (file-exists-p file))
10499 (pop-to-buffer (find-file-noselect file)))
10502 (error "TinyPgp: Don't know what to do. %s %s "
10503 mail-req nym-alias-name)))))
10505 ;;; ----------------------------------------------------------------------
10507 (defun tinypgp-newnym-config-insert
10508 (server nym-name &optional command pgp-key remailer)
10509 "Insert Config request to mail buffer. Mail body is supposed to be empty.
10513 SERVER newnym server alias name, like 'weasel'
10514 NYM-NAME account name i the newnym server
10515 COMMAND commands to send
10516 PGP-KEY PGP key block.
10517 if 'string' insert as is
10518 if buffer pointer, insert buffer contents
10519 if symbol; call pgp to find key from keyrings matching symbol.
10521 REMAILER Reply block
10522 if 'string', then insert as is
10523 if buffer pointer, then insert buffer content.
10524 if symbol, it must be remailer alias name to use for
10525 reply block. The remailer reply block is then
10526 inserted from file pointed by `tinypgp-:r-reply-block-table'."
10529 (tinypgp-newnym-ask-server)
10530 (read-from-minibuffer "Nym account name: ")))
10531 (tinypgp-r-init-maybe)
10532 (let* ((fid "tinypgp-newnym-config-insert:")
10535 (tinypgpd fid "in:" server nym-name command pgp-key remailer)
10536 ;; ... ... ... ... ... ... ... ... ... ... ... ... compose request ...
10537 (tinypgp-r-server-macro server "config"
10539 (ti::mail-kill-field "^To:" email)
10540 (ti::mail-text-start 'move)
10544 "From: " (or nym-name "") "\n"
10545 "Nym-Commands: " (or command "") "\n")
10548 (insert "Public-Key:\n")
10550 ((bufferp pgp-key) (insert-buffer pgp-key))
10551 ((stringp pgp-key) (insert pgp-key))
10554 (tinypgp-key-extract-to-point (symbol-name pgp-key) 'raw)
10555 ;; check that PGP public key definition contains <> email
10558 (with-current-buffer tinypgp-:buffer-tmp-shell
10559 (setq list (ti::mail-email-find-region))
10560 (when (or (null list)
10562 (replace-regexp-in-string ".*@" "" email 0)
10563 ;; Take first email from key-id
10566 (pop-to-buffer (current-buffer))
10568 TinyPgp: no email found from pgp key?"))))))
10569 (pop-to-buffer (current-buffer))
10570 (error "TinyPgp: PGP user ID '%s' does not refer to domain '%s'"
10573 ((error "TinyPgp: Oops, wrong argument..."))))
10576 (insert "Reply-Block:\n")
10578 ((bufferp remailer) (insert-buffer remailer))
10579 ((stringp remailer) (insert remailer))
10580 ((symbolp remailer)
10581 (tinypgp-r-reply-block-insert (symbol-name remailer)))
10582 ((error "TinyPgp: Oops, wrong argument...")))
10586 ;;; ----------------------------------------------------------------------
10588 (defun tinypgp-newnym-config-sendmail-template (server account &optional verb)
10589 "Create mail buffer and inset newnym' configuration template.
10592 SERVER newnym server
10593 ACCOUNT login account
10594 VERB verbose, show buffer. Interactive call sets this.
10600 (tinypgp-newnym-ask-server)
10601 (tinypgp-newnym-ask-account)))
10602 (tinypgp-r-init-maybe)
10605 (with-current-buffer (setq buffer
10606 (tinypgp-r-sendmail-create-buffer
10607 tinypgp-:buffer-newnym
10609 (tinypgp-newnym-config-insert server account)
10610 (turn-on-tinypgp-mode)
10611 (turn-on-tinypgp-newnym-mode)
10612 (tinypgp-newnym-mode-nym-commands-goto))
10614 (switch-to-buffer buffer))
10617 ;;; ----------------------------------------------------------------------
10619 (defun tinypgpg-newnym-account-request
10620 (server account cmd &optional pgp-key remailer send)
10621 "Set up all necessary things to send command to newnym server account.
10625 SERVER newnym server alias
10626 ACCOUNT newnym account name
10627 CMD Nym-Comands's field content
10629 PGP-KEY If t, then inser pgp-key matching ACCOUNT
10631 It symbol but not t, Email address string which
10632 matches the key-id from PGP key -- that key is sent to newnym.
10634 REMAILER Use this remailer's reply block. You must have created this
10635 beforehand with `tinypgp-r-reply-block-basic' and stored
10636 it to file pointed by `tinypgp-:r-reply-block-table'.
10637 SEND if non-nil, encrypt and send the message.
10640 mail buffer pointer if SEND is nil"
10641 (let* ((fid "tinypgpg-newnym-account-request: ")
10644 (tinypgpd fid "ARGS" server account (current-buffer))
10645 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... mail buffer ...
10646 (tinypgp-r-server-macro server account
10647 (ti::mail-sendmail-pure-env-macro
10648 (setq buffer (tinypgp-r-sendmail-create-buffer
10649 tinypgp-:buffer-newnym
10650 "Account request"))
10651 ;; The window excursion is needed so that nothing fancy happens
10652 ;; when we send mail. User doesn't want his windows changed
10654 (save-window-excursion
10656 (set-buffer buffer)
10657 (tinypgpd fid server account email info)
10659 (setq pgp-key (make-symbol email)))
10661 (tinypgp-newnym-config-insert server account cmd pgp-key remailer)
10665 (make-local-variable 'tinypgp-:auto-action-table)
10666 (setq tinypgp-:auto-action-table nil)
10667 (ti::mail-sendmail-reset-send-hooks)
10669 (tinypgp-save-state-macro
10670 (setq tinypgp-:user-now email)
10671 (tinypgp-password-set (format "Newnym Encrypt password: "))
10672 (setq to (mail-fetch-field "to"))
10673 (tinypgp-encrypt-mail (ti::string-remove-whitespace to) nil))
10674 (mail-send-and-exit nil))))))))
10676 ;;; ----------------------------------------------------------------------
10678 (defun tinypgp-newnym-delete (server account &optional verb)
10679 "Send to newbyn SERVER a ACCOUNT delete request. VERB."
10681 (tinypgp-newnym-ask-srv-acc
10682 "Are you sure you want to send DELETE request? "))
10684 (tinypgp-r-init-maybe)
10686 (tinypgpg-newnym-account-request server account "delete" nil nil))
10687 (if verb (message "Newnym Delete request sent.")))
10689 ;;; ----------------------------------------------------------------------
10691 (defun tinypgp-newnym-create-i-args ()
10692 "Ask arguments to `tinypgp-newnym-create'."
10693 (let* ((site (get 'tinypgp-:r-newnym-default-account-table 'default-server))
10698 (tinypgp-r-init-maybe)
10699 (message "You should check free Nym login names first...ok?")
10702 (setq srv-account (tinypgp-newnym-ask-srv-acc))
10707 (read-from-minibuffer
10709 "[%s] Create Nym Login: "
10716 (read-from-minibuffer
10718 "[%s] Describe Nym login name: "
10720 (error "TinyPgp: Empty not accepted."))
10723 (tinypgp-ask-reply-block-remailer
10725 "[%s] Select Reply block of remailer: "
10728 (list (nth 0 srv-account)
10733 ;;; ----------------------------------------------------------------------
10735 (defun tinypgp-newnym-create (server account desc remailer &optional verb)
10736 "Send to newbyn SERVER a ACCOUNT delete request.
10740 Before you call this function, make sure you have created new key
10741 with 'pgp -kg' and that its key-id line contain email address
10742 <yournym@remail.domain.com>
10746 SERVER newnym server (alias) name
10747 ACCOUNT account name in newnym
10748 DESC account description
10749 REMAILER remailer's reply block to submit to newnym server.
10750 VERB Verbose messages. Shows the buffer and turns on
10751 `tinypgp-mode' and `tinypgp-newnym-mode`."
10754 (tinypgpd "tinypgp-newnym-create: INTERACTIVE")
10759 Do have created the ncessary PGP keys for newnym account? (see manual)")
10760 ;; Umph; again some impatient user selected this choice without readin
10761 ;; the newnym documentation....
10762 (error "TinyPgp: Please read the newnym remailer manual first."))
10763 (tinypgp-newnym-create-i-args)))
10764 (tinypgpd "tinypgp-newnym-create: in" server account desc remailer verb)
10765 (tinypgp-r-init-maybe)
10768 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... mail buffer ...
10769 (with-current-buffer (tinypgpg-newnym-account-request
10771 (format "create +acksend +fingerkey name=\"%s\"" desc)
10773 (make-symbol remailer))
10776 (turn-on-tinypgp-mode)
10777 (switch-to-buffer (current-buffer)) ;Now visible to user
10778 (ti::mail-text-start 'move)
10780 (turn-on-tinypgp-newnym-mode)
10781 (ti::mail-mime-turn-off-mode)
10782 (tinypgp-email-substitution-toggle 0) ;; Config request
10783 ;;; (tinypgp-auto-action-toggle 0) ;; No auto action here by default
10785 ;; We havae to "account", bwecause 1pass needs to be signed
10786 ;; with the "account" key. Store the active pgp user information
10787 ;; to local variables, so that we can restore the user in mail send
10791 (make-local-variable 'tinypgp-pgp-user-original)
10792 (make-local-variable 'tinypgp-pgp-user-now)
10794 (defconst tinypgp-pgp-user-original tinypgp-:user-now)
10795 (defconst tinypgp-pgp-user-now account)
10796 (setq tinypgp-:user-now account)
10798 ;; Warn about this change, because user may kill the buffer
10799 ;; and the active pgp user still stays "nym" login.
10801 (message "Active PGP user changed to: %s" account) (sleep-for 1.5)
10803 (ti::read-char-safe-until
10804 (substitute-command-keys
10806 "Check all; do 1pass Encrypt-Sign with NymKey: "
10807 "\\[tinypgp-encrypt-mail-sign] [press to continue]")))))))
10809 ;;; ----------------------------------------------------------------------
10811 (defun tinypgp-newnym-post (&optional server account verb)
10812 "Convert current message into Nym post ueing SERVER and ACCOUNT. VERB.
10813 The message can be newsgroup post or regular email."
10816 (tinypgp-r-init-maybe)
10818 (tinypgp-newnym-ask-server)
10819 (tinypgp-newnym-ask-account))))
10820 (tinypgp-r-init-maybe)
10821 (let* ((subj (mail-fetch-field "Subject"))
10822 (news (ti::mail-news-buffer-p))
10829 (tinypgp-r-server-macro server "send"
10832 (setq ret (tinypgp-r-post-usenet 'newnym))
10833 (ti::mail-kill-field "To")
10834 (ti::mail-kill-field "Subject")
10835 (ti::mail-kill-field "From")
10836 ;; Rest of the headers without "To" field.
10838 (setq hdr (buffer-substring (point-min) (ti::mail-hmax)))
10840 ;; Now send to newnym server
10843 (insert "To: " email "\n"
10844 "Subject: message\n")
10846 (ti::mail-text-start 'move)
10847 (insert "From: " account "\n"
10848 "To: " (or (eval tinypgp-:r-newnym-mail2news-address)
10849 (error "TinyPgp: no newnym mail2news gateway?"))
10851 "subject: " subj "\n")
10854 (insert "Newsgroups: " (ti::list-to-string (nth 1 ret)) "\n\n")
10855 (ti::mail-kill-field-in-body '("fcc" "gcc")))
10857 (setq to (mail-fetch-field "to"))
10858 (tinypgp-header-kill)
10859 ;; Save all headers because they are inserted into body
10861 (if (setq hash-headers
10862 (tinypgp-header-move-to-body 'move-to-body 'no-ins))
10863 (setq hdr-blk (mapconcat 'concat hash-headers "")))
10864 (ti::mail-kill-field "To" email)
10865 (ti::pmin) (insert "To: " email "\n")
10867 (ti::mail-text-start 'move)
10868 (insert "From: " account "\n"
10872 (unless tinypgp-newnym-mode (turn-on-tinypgp-newnym-mode))
10873 ;; (tinypgp-auto-action-update-modeline)
10875 (substitute-command-keys
10877 "Nym-Commands can be set per message basis, press "
10878 "\\[tinypgp-newnym-mode-nym-commands-goto] and "
10879 "\\[tinypgp-newnym-mode-electric-tab]"))))))
10882 ;;{{{ newnym: interactive requests
10884 ;;; ------------------------------------------------------ &newnym-req ---
10887 (defun tinypgp-newnym-req-fmacro-1 (func req)
10888 "Use `tinypgp-newnym-req-fmacro' instead. See FUNC REQ there."
10889 (let* ((sym (intern (symbol-name (` (, func))))))
10891 (defun (, sym) (server account &optional plus verb)
10892 "Send to newnym SERVER ACCOUNT an minus(default) or PLUS request. VERB."
10893 (interactive (tinypgp-newnym-ask-srv-acc-arg))
10895 (setq plus (concat (if plus "+" "-") (, req)))
10896 (tinypgpg-newnym-account-request
10897 server account plus nil nil 'send)
10898 (tinypgp-newnym-file-stamp server account)
10900 (message "[%s] Newnym request sent: %s" server plus)
10901 ;; If mouse pressed, don't wipe message immediately
10902 (sleep-for 1)))))))
10904 ;;; ----------------------------------------------------------------------
10906 (put 'tinypgp-newnym-req-fmacro 'lisp-indent-function 0)
10907 (defmacro tinypgp-newnym-req-fmacro (func req)
10908 "Create interactive function that sends newnym request.
10911 FUNC Created function name
10912 REQ request to send; without +- option at front."
10913 (` (, (tinypgp-newnym-req-fmacro-1 func req))))
10915 ;;; ----------------------------------------------------------------------
10916 ;;; We have to tell the autoloads by hand; because the functions are
10917 ;;; created by separate macro.
10919 ;;;###autoload (autoload 'tinypgp-newnym-req-acksend "tinypgp" "" t)
10920 ;;;###autoload (autoload 'tinypgp-newnym-req-sigsend "tinypgp" "" t)
10921 ;;;###autoload (autoload 'tinypgp-newnym-req-cryptrecv "tinypgp" "" t)
10922 ;;;###autoload (autoload 'tinypgp-newnym-req-fixedsize "tinypgp" "" t)
10923 ;;;###autoload (autoload 'tinypgp-newnym-req-disable "tinypgp" "" t)
10924 ;;;###autoload (autoload 'tinypgp-newnym-req-fingerkey "tinypgp" "" t)
10925 ;;;###autoload (autoload 'tinypgp-newnym-req-nobcc "tinypgp" "" t)
10927 (tinypgp-newnym-req-fmacro tinypgp-newnym-req-acksend "acksend")
10928 (tinypgp-newnym-req-fmacro tinypgp-newnym-req-sigsend "sigsend")
10929 (tinypgp-newnym-req-fmacro tinypgp-newnym-req-cryptrecv "cryptrecv")
10930 (tinypgp-newnym-req-fmacro tinypgp-newnym-req-fixedsize "fixedsize")
10931 (tinypgp-newnym-req-fmacro tinypgp-newnym-req-disable "disable")
10932 (tinypgp-newnym-req-fmacro tinypgp-newnym-req-fingerkey "fingerkey")
10933 (tinypgp-newnym-req-fmacro tinypgp-newnym-req-nobcc "nobcc")
10937 ;;{{{ Nymserver: misc
10939 ;;; .................................................. &nymserver-misc ...
10940 ;;; anon.nymserver.com successor of anon.penet.fi
10942 ;;; ----------------------------------------------------------------------
10944 (defun tinypgp-nymserver-mail-p (&optional alias)
10945 "Check if there is Anon X-headers in the buffers. ALIAS."
10946 (setq alias (car (car tinypgp-:nymserver-table)))
10948 (ti::re-search-check "^X-Anon-Password\\|^X-Anon-To")
10949 (ti::re-search-check (format "^To:.*%s" alias))))
10951 ;;; ----------------------------------------------------------------------
10953 (defsubst tinypgp-nymserver-service-elt (alias)
10954 "Return service entries or call error is no such ALIAS."
10955 (or (assoc alias tinypgp-:nymserver-table)
10956 (error "TinyPgp: No server alias '%s'" alias)))
10958 ;;; ----------------------------------------------------------------------
10960 (defsubst tinypgp-nymserver-mailto (alias)
10961 "Return address where user can send mail so that it gets anynymized. ALIAS."
10962 (or (nth 3 (assoc alias tinypgp-:nymserver-table))
10963 (error "TinyPgp: No post email address")))
10965 ;;; ----------------------------------------------------------------------
10967 (defsubst tinypgp-nymserver-address (string alias)
10968 "Return nymserver email address prepended with STRING as account name. ALIAS.
10971 STRING@NYMSERVER-ADDRESS"
10976 (nth 2 (assoc alias tinypgp-:nymserver-table)))))
10978 ;;; ----------------------------------------------------------------------
10980 (defun tinypgp-nymserver-ask (&optional msg)
10981 "Ask server alias name with MSG."
10982 (if nil ;disabled now
10984 (or msg "Use pent server: ")
10985 (ti::list-to-assoc-menu (mapcar 'car tinypgp-:nymserver-table))
10988 ;; 1997-02-13 Jari aalto
10989 ;; - We don't support other nymserver accounts currently
10991 (car (car tinypgp-:nymserver-table))))
10993 ;;; ----------------------------------------------------------------------
10995 (defun tinypgp-nymserver-password (alias)
10996 "Return password or nil for ALIAS."
10997 (let* ((elt (assoc alias tinypgp-:nymserver-account-table))
10998 (pass (nth 2 elt)))
11001 ;;; ----------------------------------------------------------------------
11003 (defun tinypgp-nymserver-sendmail (action alias &optional verb arg1 arg2)
11004 "Send ACTION mail to nymserver ALIAS.
11005 Mail will be encrypted if `tinypgp-:nymserver-request-encrypt' is non-nil.
11006 See variables documentation for more detailed usage.
11009 ACTION ALIAS VERB ARG1 ARG2
11012 following variables are bound to nil to prevent any interference when
11013 sending mail commands.
11015 `mail-archive-file-name'
11016 `mail-default-headers'
11019 (let* ((elt (assoc alias tinypgp-:nymserver-account-table))
11020 (account (or (nth 1 elt)
11021 (error "TinyPgp: No account")))
11022 (pass (or (nth 2 elt)
11023 (error "TinyPgp: No account password")))
11024 (my-from (nth 4 elt))
11026 (fld1 "X-Anon-Password: ")
11027 (fld2 "X-Anon-Subject: ")
11028 (encrypt tinypgp-:nymserver-request-encrypt)
11030 ;; Make sure email substitution mode is on when we send
11031 ;; mail to anon server. User may have forgotten it off
11033 (tinypgp-:read-email-after-hook
11034 (or (get 'tinypgp-:read-email-after-hook 'original)
11036 ;; if the above fails, that means that the 'original
11037 ;; property is not used yet and not available.
11039 tinypgp-:read-email-after-hook))
11041 (email (tinypgp-nymserver-address (symbol-name action) alias))
11042 (enc-key (car (tinypgp-key-id-conversion email)))
11046 (tinypgpd "tinypgp-nymserver-sendmail in: " action alias verb arg1 arg2)
11048 (save-window-excursion
11050 ((memq action '(finger ping remove help abuse))
11051 (ti::mail-sendmail-macro email "None" 'send
11052 (insert fld2 (or arg1 "No subject data") "\n")
11054 ;; This field will confuse Nymserver server. Remove it
11056 (ti::mail-kill-field "Reply-To")
11057 (if my-from (ti::mail-add-field "From" my-from "To"))
11059 (if encrypt (tinypgp-encrypt-mail-find-keyring enc-key))))
11060 ;;; (pop-to-buffer (current-buffer)) (ti::d! 101)
11062 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. upload pgp key . .
11063 ((eq action 'newpgp)
11064 (unless arg1 ;Nor a remove request?
11065 (with-current-buffer (setq buffer (tinypgp-ti::temp-buffer 'finger))
11067 (tinypgp-key-extract-to-point account)
11070 (if (re-search-forward "matching keys found" nil t)
11071 (error "TinyPgp: [%s' didn't match exactly." arg1))))
11073 (ti::mail-sendmail-macro email "No subject" 'send
11074 (if my-from (ti::mail-add-field "From" my-from "To"))
11076 (insert fld1 pass "\n")
11078 ;;; (pop-to-buffer (current-buffer)) (ti::d! 10)
11080 (if (string= "remove" arg1)
11081 (insert fld2 "remove" "\n")
11082 (insert-buffer buffer))
11085 (tinypgp-encrypt-mail-find-keyring enc-key))))
11087 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. plan and sig . .
11088 ((memq action '(newplan newsig))
11089 (ti::mail-sendmail-macro email "No subject" 'send
11090 (insert fld1 pass "\n")
11092 (ti::mail-kill-field "Reply-To")
11093 (if my-from (ti::mail-add-field "From" my-from "To"))
11095 (if (string= "remove" arg1)
11096 (insert fld2 "remove" "\n")
11097 (insert-file arg1))
11100 (tinypgp-encrypt-mail-find-keyring enc-key))))
11102 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. flags . .
11103 ((memq action '(paranoid newalias nick
11104 newpassword vacation noarchive
11106 pgpencrypt pgpsign sendmix))
11107 (setq subject (or arg1 "No subject")) ;this is the new alias name
11108 (ti::mail-sendmail-macro email "No subject" 'send
11109 (insert fld1 pass "\n"
11112 (ti::mail-kill-field "Reply-To")
11113 (if my-from (ti::mail-add-field "From" my-from "To"))
11115 ;;; (pop-to-buffer (current-buffer)) (ti::d! 10)
11116 (if encrypt (tinypgp-encrypt-mail-find-keyring enc-key))))
11117 ;;; (pop-to-buffer (current-buffer)) (ti::d! 10)
11119 (error "TinyPgp: unknown action '%s'" action)))
11120 (if verb (message "Nymserver: %s request sent."
11121 (capitalize (symbol-name action)))))))
11123 ;;; ----------------------------------------------------------------------
11125 (defun tinypgp-nymserver-create-1 (email)
11126 "Send EMAIL to create account."
11128 (ti::read-char-safe-until
11129 "[press] Store received account info into tinypgp-:nymserver-account-table.")
11130 (ti::mail-sendmail-macro email "No subject" 'send))
11133 ;;{{{ Nymserver: interactive
11135 ;;; ----------------------------------------------------------------------
11137 (defun tinypgp-nymserver-post (alias &optional verb)
11138 "Convert message so that it can be posted to through nymserver. ALIAS VERB."
11142 (tinypgp-nymserver-i-enable)
11143 (tinypgp-nymserver-ask))))
11145 (let* ((srv (tinypgp-nymserver-service-elt alias))
11146 (mailto (or (nth 3 srv)
11147 (error "TinyPgp: No server mailto address.")))
11148 (grp-limit (nth 4 srv))
11150 (elt (or (assoc alias tinypgp-:nymserver-account-table)
11151 (error "TinyPgp: Unknown server %s" alias)))
11152 ;;; (email (or (nth 1 elt)
11153 ;;; (error "No account email")))
11155 (pass (or (nth 2 elt)
11156 (error "TinyPgp: No account password")))
11158 (my-from (nth 4 elt))
11160 (fld1 "X-Anon-Password: ")
11161 (fld2 "X-Anon-To: ")
11162 (fld3 "X-Anon-Name: ")
11163 (fld4 "X-Anon-Subject: ")
11164 ;;; (fld-ref "X-Anon-references: ") references
11171 (unless (ti::mail-mail-p)
11172 (error "TinyPgp: This is not email buffer."))
11174 (setq to (mail-fetch-field "to")
11175 subject (mail-fetch-field "subject")
11176 hlist (delete 'newsgroups (ti::mail-required-headers)))
11178 (when (ti::nil-p subject)
11179 (error "TinyPgp: No subject. Aborted"))
11181 (ti::save-with-marker-macro
11182 (ti::mail-text-start 'move)
11183 (if (looking-at "X-Anon")
11185 (message "Already in anon post format."))
11188 ((not (ti::nil-p to)) ;regular email message
11190 ;; tinymail.el / we have to add 2 spaces to the beginning of field
11191 ;; so that CC tracking goes off.
11193 (ti::mail-kill-field "to" (concat " " mailto))
11194 (if my-from (ti::mail-add-field "From" my-from "To"))
11196 (insert fld1 pass "\n"
11198 (if name (concat fld3 name "\n") "")
11201 (tinypgp-update-modeline))
11203 ((not (ti::nil-p (setq grp (mail-fetch-field "newsgroups"))))
11205 (> (count-char-in-string ?, grp) grp-limit))
11207 TinyPgp: Too many newsgroups, only %d allowed" grp-limit))
11209 ;;; (setq references (mail-fetch-field "references"))
11210 (push 'in-reply-to hlist )
11211 (ti::mail-kill-non-rfc-fields hlist)
11213 (ti::mail-add-field "To" mailto)
11215 ;; it may be possible that this field is there already,
11218 (ti::mail-kill-field "^From:")
11219 (ti::mail-add-field "From" my-from "To"))
11221 (ti::mail-text-start 'move)
11222 (insert fld1 pass "\n"
11224 (if name (concat fld3 name "\n") "")
11227 (tinypgp-update-modeline))
11232 TinyPgp: Don't know what to do: To or Newsgroup field empty."))))
11233 (ti::mail-kill-field "subject" " None")
11235 ;; Add 'cutmarks' so that all the rest of the text are
11243 (run-hooks 'tinypgp-:nymserver-post-hook)))
11245 ;;; ----------------------------------------------------------------------
11247 (defun tinypgp-nymserver-send ()
11248 "Handle sending mail addressed to Nymserver.
11249 This function is called after C -c C -c to sned the mail.
11250 If there are no multiple recipients, this function does nothing
11255 (let* ((fid "tinypgp-nymserver-send: ")
11256 (email "anon@anon.nymserver.com")
11257 (to (mail-fetch-field "to"))
11258 (cc (mail-fetch-field "cc"))
11259 (fcc (mail-fetch-field "fcc"))
11260 (subject (mail-fetch-field "subject"))
11264 (ti::mail-email-from-string to)
11265 (if cc (ti::mail-email-from-string cc)))))
11267 (enc-key (car (tinypgp-key-id-conversion email)))
11268 (encrypt tinypgp-:nymserver-request-encrypt)
11270 (len (length elist))
11277 ;; - Nymserver doesn't accept CC or many addresses in To field,
11278 ;; it can only have one X-anon-To destination.
11279 ;; - What we do here is, that we copy the message and send it
11280 ;; individually to each destination
11281 ;; - We need confirmation for this
11283 (when (or (> len 1)
11284 ;; If there is CC, then automatically suppose multiple
11285 ;; recipients. The To field is already in X-Anon-To
11286 ;; So this CC makes at least 2 recipients.
11289 (tinypgpd fid subject to cc fcc elist)
11291 ;; The X-Anon-To is inside PGP envelope, we can't use this message
11292 ;; body to CC it to others.
11294 (if (ti::mail-pgp-encrypted-p 'double-check)
11296 TinyPgp: You have CC in Nymserver mail. Can't process encrypted message."))
11301 "CC %d: You have multiple anon recipients, are you sure? "
11305 (buffer-substring (ti::mail-text-start) (point-max)))
11306 (dolist (elt elist)
11307 (ti::mail-sendmail-macro email "None" send-flag
11308 (insert message-body)
11309 (pop-to-buffer (current-buffer))
11311 (re-search-forward "X-Anon-To:\\(.*\\)")
11312 (ti::replace-match 1 (concat " " elt))
11313 (pop-to-buffer (current-buffer))
11314 ;;; (incf i) (message "Sending-quick %d/%d %s" i len elt)
11316 (tinypgp-encrypt-mail-find-keyring enc-key))))
11317 (ti::read-char-safe-until
11318 "[press]Anon CC copies sent, now sending this mail buffer.")
11319 (ti::mail-kill-field "cc")
11321 (tinypgp-encrypt-mail-find-keyring enc-key))
11325 ;;; ----------------------------------------------------------------------
11327 (defun tinypgp-nymserver-create (alias)
11328 "Send account create request. ALIAS."
11329 (interactive (list (tinypgp-nymserver-ask)))
11330 (let ((srv (tinypgp-nymserver-service-elt alias)))
11332 "Are you absolutely sure you want to send 'create' request ")
11333 (funcall (nth 1 srv) (nth 1 srv)))))
11335 ;;; ----------------------------------------------------------------------
11337 (defun tinypgp-nymserver-remove (alias)
11338 "Remove your anonymous account. ALIAS."
11342 (tinypgp-nymserver-i-enable)
11343 (tinypgp-nymserver-ask))))
11345 "Are you absolutely sure you want to terminate anonymous account ")
11346 (tinypgp-nymserver-sendmail 'remove alias (interactive-p))))
11348 ;;; ----------------------------------------------------------------------
11349 ;;; Hm. This function does not have paramaeter 'alias'.
11350 ;;; So it's not general purpose for other accounts
11351 ;;; #todo: Should rethink it sometime.
11353 (defun tinypgp-nymserver-finger (account)
11354 "Finger account's email address for its configuration.
11355 If ACCOUNT is in format vanity.an@site or vanity.na@site.com, it is converted
11356 into vanity@site.com before sending finger request."
11359 ;;; (tinypgp-nymserver-i-enable)
11360 (let* ((elt (assoc (tinypgp-nymserver-ask)
11361 tinypgp-:nymserver-account-table))
11363 (ti::mail-email-from-string
11364 (or (mail-fetch-field "from") ""))))
11365 (account (nth 1 elt))
11367 (ti::list-to-assoc-menu (list account)))))
11368 ;; If user has reveived mail from anNNN@anon.nymserver.com
11369 ;; Then we offer to finger that account too
11371 (when (and from (string-match "an[0-9]@\\|\\.[an][na]@" from))
11372 (setq list (ti::list-to-assoc-menu
11374 (list from account)
11376 (setq account from))
11380 "Finger nymserver account [give email address]: "
11386 ;; Use may press <empty> RET in completing-read
11388 (if (not (string-match "@" account))
11389 (error "TinyPgp: Need email address."))
11391 ;; silent converion to 'an' format
11393 (setq account (ti::mail-nymserver-email-convert account))
11395 (tinypgp-nymserver-sendmail
11396 'finger (tinypgp-nymserver-ask) (interactive-p) account))
11398 ;;; ----------------------------------------------------------------------
11400 (defun tinypgp-nymserver-abuse (alias)
11401 "Send ABUSE request. ALIAS."
11402 (interactive (list (tinypgp-nymserver-ask)))
11403 (let* ((buffer "*mail-nymserver-abuse*"))
11404 (ti::kill-buffer-safe buffer)
11405 (when (y-or-n-p "Nymserver: Are you sure you want to report ABUSE? ")
11406 (ti::mail-sendmail-macro
11407 (tinypgp-nymserver-address "abuse" alias)
11410 (rename-buffer buffer)
11411 (pop-to-buffer (current-buffer))
11412 (message "Write message and possibly encrypt it.")))))
11414 ;;; ----------------------------------------------------------------------
11416 (defun tinypgp-nymserver-ping (alias)
11417 "Send Ping request. ALIAS.
11418 In order to send ping, you have to be sending
11419 mail FROM AN ACCOUNT WHERE YOU SENT the create command. You can't send ping
11420 from any other location."
11423 (tinypgp-nymserver-i-enable)
11424 (list (tinypgp-nymserver-ask))))
11425 (tinypgp-nymserver-sendmail 'ping alias (interactive-p)))
11427 ;;; ----------------------------------------------------------------------
11429 (defun tinypgp-nymserver-paranoid (alias)
11430 "Toggle paranoid setting. ALIAS."
11433 (tinypgp-nymserver-i-enable)
11434 (list (tinypgp-nymserver-ask))))
11435 (tinypgp-nymserver-sendmail 'paranoid alias (interactive-p)))
11437 ;;; ----------------------------------------------------------------------
11439 (defun tinypgp-nymserver-vacation (alias)
11440 "Toggle vacation setting. ALIAS."
11443 (tinypgp-nymserver-i-enable)
11444 (list (tinypgp-nymserver-ask))))
11445 (tinypgp-nymserver-sendmail 'vacation alias (interactive-p)))
11447 ;;; ----------------------------------------------------------------------
11449 (defun tinypgp-nymserver-noarchive (alias)
11450 "Toggle USENET achive setting. ALIAS."
11453 (tinypgp-nymserver-i-enable)
11454 (list (tinypgp-nymserver-ask))))
11455 (tinypgp-nymserver-sendmail 'noarchive alias (interactive-p)))
11457 ;;; ----------------------------------------------------------------------
11459 (defun tinypgp-nymserver-setnon (alias)
11460 "Toggle anNNN/naNNN mode when you get private mail. ALIAS."
11463 (tinypgp-nymserver-i-enable)
11464 (list (tinypgp-nymserver-ask))))
11465 (tinypgp-nymserver-sendmail 'setnon alias (interactive-p)))
11467 ;;; ----------------------------------------------------------------------
11469 (defun tinypgp-nymserver-newplan (alias file)
11470 "ALIAS. Upload plan FILE. If file is 'remove' then remove plan."
11473 (tinypgp-nymserver-i-enable)
11475 (tinypgp-nymserver-ask)
11476 (if (y-or-n-p "y = upload .plan, n = remove plan" )
11477 (call-interactively
11478 '(lambda (arg) (interactive "fNymserver plan file: ") arg))
11480 (tinypgp-nymserver-sendmail 'newplan alias (interactive-p) file))
11482 ;;; ----------------------------------------------------------------------
11484 (defun tinypgp-nymserver-newsig (alias file)
11485 "ALIAS. Upload signature FILE. If file is 'remove' then remove signature."
11488 (tinypgp-nymserver-i-enable)
11490 (tinypgp-nymserver-ask)
11491 (if (y-or-n-p "y = upload .signature, n = remove plan" )
11492 (call-interactively
11493 '(lambda (arg) (interactive "fNymserver signature file: ") arg))
11495 (tinypgp-nymserver-sendmail 'newsig alias (interactive-p) file))
11497 ;;; ----------------------------------------------------------------------
11499 (defun tinypgp-nymserver-newaddress (alias new)
11500 "ALIAS. Change your mailbox address.
11501 You must be mailing from the NEW ADDRESS currently."
11504 (tinypgp-nymserver-i-enable)
11506 (tinypgp-nymserver-ask)
11507 (read-from-minibuffer
11508 "[You must be in NEW site now] Your old address: "))))
11509 (if (ti::nil-p new) ;User may have pressed ENTER...
11510 (error "TinyPgp: No address."))
11511 (tinypgp-nymserver-sendmail 'newaddress alias (interactive-p) new))
11513 ;;; ----------------------------------------------------------------------
11515 (defun tinypgp-nymserver-newalias (alias name)
11516 "ALIAS NAME. Change you anNNN@ account to NEWALIAS@."
11519 (tinypgp-nymserver-i-enable)
11521 (tinypgp-nymserver-ask)
11522 (read-from-minibuffer
11523 "newalias request; vanity alias [word]: "))))
11524 (if (or (< (length name) 3)
11525 (> (length name) 15))
11526 (error "TinyPgp: Invalid string size [3-15]; %s has %d characters."
11527 name (length name)))
11528 (tinypgp-nymserver-sendmail 'newalias alias (interactive-p) name))
11530 ;;; ----------------------------------------------------------------------
11532 (defun tinypgp-nymserver-nickname (alias name)
11533 "ALIAS. Change you nick NAME that appears in anon post From field."
11536 (tinypgp-nymserver-i-enable)
11538 (tinypgp-nymserver-ask)
11539 (read-from-minibuffer "Nickname [string or word 'remove']: "))))
11540 (tinypgp-nymserver-sendmail 'nick alias (interactive-p) name))
11542 ;;; ----------------------------------------------------------------------
11544 (defun tinypgp-nymserver-newpassword (alias password)
11545 "ALIAS. Change your PASSWORD."
11548 (tinypgp-nymserver-i-enable)
11550 (tinypgp-nymserver-ask)
11551 (ti::compat-read-password "New nymserver password: "))))
11552 (tinypgp-nymserver-sendmail 'newpassword alias nil password)
11553 (ti::read-char-safe-until
11554 "Update your password _now_ to tinypgp-:nymserver-account-table"))
11556 ;;; ----------------------------------------------------------------------
11558 (defun tinypgp-nymserver-pgp-upload (alias &optional remove)
11559 "ALIAS. Upload or REMOVE pgp key. Before you call this commaand note:
11561 o You must have created the PGP public key for your Nymserver account.
11562 o You must have defined the `tinypgp-:nymserver-account-table'; the key
11563 uploaded must have the email address.
11564 o If you change your vanity name, remember to start all over(New key,
11568 (tinypgp-nymserver-i-enable)
11570 (tinypgp-nymserver-ask)
11572 "Y = upload your PGP key to Anon account [N = remove] ")))))
11573 (tinypgp-nymserver-sendmail 'newpgp alias (interactive-p) remove))
11575 ;;; ----------------------------------------------------------------------
11577 (defun tinypgp-nymserver-pgp-encrypt (alias)
11578 "Toggle receiving PGP encryped mail. ALIAS.
11579 You have to upload PGP key first with \\[tinypgp-nymserver-pgp-upload]"
11582 (tinypgp-nymserver-i-enable)
11583 (list (tinypgp-nymserver-ask))))
11584 (tinypgp-nymserver-sendmail 'pgpencrypt alias (interactive-p)))
11586 ;;; ----------------------------------------------------------------------
11588 (defun tinypgp-nymserver-pgp-sign (alias)
11589 "Turn on/off PGP siging. ALIAS."
11592 (tinypgp-nymserver-i-enable)
11593 (list (tinypgp-nymserver-ask))))
11594 (tinypgp-nymserver-sendmail 'pgpsign alias (interactive-p)))
11596 ;;; ----------------------------------------------------------------------
11598 (defun tinypgp-nymserver-pgp-sendmix (alias)
11599 "Turn on/off Mixmaster support. ALIAS."
11602 (tinypgp-nymserver-i-enable)
11603 (list (tinypgp-nymserver-ask))))
11604 (tinypgp-nymserver-sendmail 'sendmix alias (interactive-p)))
11606 ;;; ----------------------------------------------------------------------
11608 (defun tinypgp-nymserver-help-i-args (arg)
11609 "Ask args for `tinypgp-nymserver-help' using ARG."
11611 (tinypgp-nymserver-ask)
11614 ;;; ----------------------------------------------------------------------
11616 (defun tinypgp-nymserver-help-verbose (&optional arg)
11617 "Call `tinypgp-nymserver-help' as interactive would with ARG."
11618 (let* ((a (tinypgp-nymserver-help-i-args arg)))
11619 (tinypgp-nymserver-help (nth 0 a) (nth 1 a))))
11621 ;;; ----------------------------------------------------------------------
11623 (defun tinypgp-nymserver-help (alias &optional mail-req verb)
11624 "Print help or send the help request via mail.
11627 ALIAS ,from where to ask the help file.
11628 MAIL-REQ ,send mail request [current-prefix-arg]
11629 VERB ,verbose messages"
11630 (interactive (tinypgp-nymserver-help-i-args current-prefix-arg))
11631 (let* ((elt (assoc alias tinypgp-:nymserver-account-table))
11632 (file (or (nth 5 elt) "_#_#")))
11636 (tinypgp-nymserver-sendmail 'help alias verb))
11639 ((file-exists-p file)
11640 (pop-to-buffer (find-file-noselect file)))
11642 ((not (file-exists-p file))
11643 (error "TinyPgp: File not exists %s" file))
11646 (message "No HELP file defied in tinypgp-:nymserver-account-table")
11648 (message " You get the help file, when you create account.")))))))
11654 ;;; ........................................................... &r-ask ...
11656 ;;; ----------------------------------------------------------------------
11658 (defun tinypgp-ask-reply-block-remailer (&optional msg)
11659 "Ask which remailer's reply block to use. Return remailer.
11661 `tinypgp-:r-reply-block-tab.le'"
11662 (or tinypgp-:r-reply-block-table
11663 (error "TinyPgp tinypgp-:r-reply-block-table is empty."))
11665 (or msg "Select Reply block of remailer: ")
11666 (ti::list-to-assoc-menu (mapcar 'car tinypgp-:r-reply-block-table))
11670 ;;; ----------------------------------------------------------------------
11672 (defun tinypgp-ask-remailer (&optional msg)
11673 "Select REMAILER with optional MSG."
11675 (tinypgp-r-init-maybe)
11677 (ti::list-to-assoc-menu
11678 (mapcar 'car tinypgp-:r-host-table)))
11679 (error "TinyPgp Internal error, tinypgp-:r-host-table is nil."))
11681 (or msg "Select remailer: ")
11685 'tinypgp-:r-history)))
11687 ;;; ----------------------------------------------------------------------
11689 (defun tinypgp-ask-email-keyserver (&optional msg)
11690 "Ask which email keyserver to use using MSG."
11691 (tinypgp-alias2name
11693 (or msg "Email key server: ")
11694 (ti::list-to-assoc-menu (mapcar 'car tinypgp-:keyserver-mail-table))
11697 (car (car tinypgp-:keyserver-mail-table)))
11698 tinypgp-:keyserver-mail-table))
11700 ;;; ----------------------------------------------------------------------
11702 (defun tinypgp-ask-http-keyserver ()
11703 "Ask which http keyserver to use. Return keyserver elt."
11710 (ti::list-to-assoc-menu (mapcar 'car tinypgp-:keyserver-http-table))
11712 (or (tinypgp-hash 'keyserver 'get 'used nil 'global) ;; last used
11713 (car (car tinypgp-:keyserver-http-table))) ;; or first in list
11714 'tinypgp-:history-http-keyserver)
11715 tinypgp-:keyserver-http-table))
11717 ;; Remember the last used keyserver
11719 (tinypgp-hash 'keyserver 'put 'used (car-safe elt) 'global)
11720 (tinypgp-hash 'keyserver 'put 'elt elt 'global)
11723 ;;; ----------------------------------------------------------------------
11725 (defun tinypgp-ask-remail-args (&optional msg)
11726 "Ask remail arguments for REMAILER with crypt key ask MSG.
11728 '(remailer-elt latent key)"
11734 (setq remailer (tinypgp-ask-remailer))
11735 (setq remailer-elt (tinypgp-r-elt-remailer remailer))
11737 (if (string-match "ek" (nth 2 remailer-elt)) ;Supports this ?
11740 key (read-from-minibuffer
11741 "Use crypt key: ")))
11744 (if (string-match "latent" (nth 2 remailer-elt))
11748 latent (read-from-minibuffer
11749 "Latent time e.g. +0:00r [empty = no latent]: ")))
11752 (setq latent (ti::string-remove-whitespace latent))
11753 (or (string-match "^\\+[0-9]:[0-9][0-9]r?$" latent)
11754 (error "TinyPgp: Invalid latent time format '%s'" latent)))))
11755 (list remailer-elt latent key)))
11757 ;;; ----------------------------------------------------------------------
11759 (defun tinypgp-i-args-decrypt ()
11760 "Ask suitable decrypt password and return decrypt type.
11761 This function tries to determine if it should ask conventional password of
11762 pgp password by looking at the pgp stream.
11765 string decrypt-type"
11766 (let* ((fid "tinypgp-i-args-decrypt: ")
11767 (c-point (ti::mail-pgp-encrypted-p))
11768 (tlist (ti::list-to-assoc-menu '("pgp" "base64" "conventional")))
11771 (tinypgpd fid c-point)
11774 ;; couldn't find "Encrypted: PGP" tag, ask type then
11777 (and tinypgp-:pgp-encrypted-p-function
11778 (funcall tinypgp-:pgp-encrypted-p-function)))
11780 ;; See if the type was set to sensible value. Ask from
11781 ;; user if it wasn't
11783 (if (or (not (stringp type))
11784 (not (assoc type tlist)))
11785 (setq type (completing-read
11786 "Decrypt type: " tlist nil 'match "pgp"))))
11789 ((string= type "conventional")
11790 (setq var-sym type)
11791 (ti::vector-table-get tinypgp-:hash-password var-sym 'allocate)
11792 (ti::vector-table-property
11793 tinypgp-:hash-password var-sym 'password nil 'force)
11794 (tinypgp-password-set nil 'conventional))
11796 ((string= type "pgp")
11797 (tinypgp-save-state-macro
11798 (tinypgp-user-change-macro
11799 ;; Now We are right user to ask the PGP pass phrase
11801 (tinypgp-ask-pass-phrase-decrypt)))))
11805 ;;{{{ PGP entry i-macros
11807 ;;; ........................................................ &i-macros ...
11808 ;;; functions that are normally used in (interactive) spec.
11811 ;;; ----------------------------------------------------------------------
11813 (defun tinypgp-i-args-read-email
11814 (&optional barf-if-not-email-buffer prompt history-sym)
11815 "Read email addresses from buffer or ask from use with completion.
11819 BARF-IF-NOT-EMAIL-BUFFER as name says
11820 PROMPT display this string
11821 HISTORY-SYM use this history"
11822 (let* ((fid "tinypgp-i-args-read-email:")
11828 (tinypgpd fid "in: " barf-if-not-email-buffer prompt)
11830 (if (and barf-if-not-email-buffer
11831 (not (ti::mail-mail-p)))
11832 (error "TinyPgp: This is not an mail buffer."))
11834 (or tinypgp-:pgp-email-list-completions ;make sure this exist
11835 (tinypgp-update-mail-abbrevs))
11838 ((and (string-match "news\\|message\\|mail" (symbol-name major-mode))
11840 (mail-fetch-field "To")))) ;Just check this
11842 (setq to-field (ti::mail-get-all-email-addresses
11844 tinypgp-:pgp-email-abbrev-list))
11846 (tinypgpd fid "cond1: to-field" to-field)
11848 ;; Slim down "Mr. ABC <abc@com>" --> "abc@com"
11854 (ti::string-remove-whitespace
11855 (ti::remove-properties (tinypgp-email-or-string x)))))
11858 (setq ret to-field)
11860 ;; Confirm only if there is multiple recipients
11861 ;; 07.03.97 I have disbled the confimation with 'and'.
11863 (if (> (length to-field) 1)
11866 (ti::read-char-safe-until
11867 (format "%d email recipients found. Press to continue."
11868 (length to-field))))
11869 ;; See if point in on line that has email
11874 (car-safe (ti::mail-email-from-string
11875 (ti::remove-properties (ti::read-current-line)))))
11876 (push tmp to-field)
11879 "You were on email line, use it? [empty=skip]: "
11880 (ti::list-to-assoc-menu to-field) nil nil
11883 (if (not (ti::nil-p tmp))
11888 (ti::string-remove-whitespace
11889 (or (ti::mail-get-field "Request-Remailing-To" 'any)
11890 (ti::mail-get-field "Anon-To" 'any)
11891 tinypgp-:user-now)))
11893 (tinypgpd fid "cond t: ")
11897 (or prompt "User: ")
11898 tinypgp-:pgp-email-list-completions
11902 'tinypgp-:history-email)))
11903 (setq ret (tinypgp-email-or-string ret))
11905 (setq ret (ti::string-remove-whitespace ret)))))
11907 (tinypgpd fid "hook call: " ret)
11909 (setq ret (tinypgp-key-id-conversion ret))
11911 (tinypgpd fid "RET: " ret)
11915 ;;; ----------------------------------------------------------------------
11917 (defun tinypgp-i-args-pass-phrase (&optional msg)
11918 "The MSG defaults to asking signing pass phrase."
11919 (tinypgp-password-set
11921 (or tinypgp-:user-now
11922 (error "TinyPgp Internal error: current pgp user unknown."))
11924 "Sign pass phrase: "))))
11926 ;;; ----------------------------------------------------------------------
11928 (defun tinypgp-ask-pass-phrase-decrypt ()
11929 "See `tinypgp-i-args-pass-phrase'."
11930 (tinypgp-i-args-pass-phrase "Decrypt pass phrase: "))
11932 ;;; ----------------------------------------------------------------------
11934 (defun tinypgp-i-args-reg-email (&optional prompt barf-not-mail-buffer)
11935 "Read region + String. PROMPT BARF-NOT-MAIL-BUFFER."
11936 (ti::i-macro-region-body
11937 (tinypgp-i-args-read-email barf-not-mail-buffer)))
11940 ;;{{{ PGP entry command macros, email,exe
11942 ;;; ----------------------------------------------------------------------
11944 (put 'tinypgp-cmd-macro-email 'lisp-indent-function 1)
11945 (defmacro tinypgp-cmd-macro-email (message &rest body)
11946 "(MESSAGE &rest BODY). Select email body or whole buffer.
11948 You must locally define variable `beg' `end' in let statement
11949 before using this macro."
11952 ((or (ti::mail-text-start)
11954 ;; The region is defined beforehand, now.
11956 (setq beg (point-min) end (point-max))
11958 (format "Not a mail buffer, %s whole buffer? "
11959 (or (, message) "Use")))))
11962 ;;; ----------------------------------------------------------------------
11964 (put 'tinypgp-cmd-macro 'lisp-indent-function 3)
11965 (defmacro tinypgp-cmd-macro
11966 (cmd user password &optional msg reg options mode-specific &rest body)
11967 "Common command macro for all PGP commands.
11968 Macro, used to contruct user command. CMD and USER must be
11969 variables. You must bound 'beg' and 'end' variables before calling this
11974 (cmd user password &optional msg reg options &rest body mode-specific)
11978 CMD USER PASSWORD parameters. CMD is symbol for logical command
11980 MSG message shown to user before initiating command
11982 REG non-nil = put results to register instead
11983 of replacing the region with pgp output.
11985 OPTIONS extra switched that are added to the pgp command.
11987 MODE-SPECIFIC If non-nil, Do not run mode specific actions.
11989 BODY code to execute when real pgp command is known.
11990 If there is no body, then execute the command
11991 that is found from table.
11993 Body must assign the result of command to
11994 macro variable 'ReS'
11996 The default command executed in macro is, where
11997 Rcmd is the real shell command. However the
11998 command can still contains macros that start
12001 (tinypgp-binary-do-command-region Rcmd beg end msg (, reg))
12004 `tinypgp-before-do-cmd-region-hook'
12005 `tinypgp-after-do-cmd-region-hook'"
12007 (let* ((FiD "tinypgp-cmd-macro: ")
12008 (Rcmd (tinypgp-binary-get-cmd (, cmd) (, options))) ;Real command
12009 (enter-buffer (current-buffer))
12010 (msg (if (or verb (interactive-p))
12017 ;; VM: edit mode changes the current buffer
12018 ;; Gnus: sometimes we must clone the buffer (nntp doesn't allow edit)
12020 (unless (, mode-specific)
12021 (tinypgp-mode-specific-control-before
12022 (, cmd) (, user) msg (, reg)))
12024 (tinypgpd FiD "in:" enter-buffer
12028 "pass" (, password)
12031 "MODE-SPEC" (, mode-specific))
12033 (setq edit-buffer (current-buffer))
12034 (tinypgpd FiD "EDIT-BUFFER" major-mode edit-buffer)
12036 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . setting markers ..
12038 ((eq (, cmd) 'decrypt)
12039 (setq ReS (save-excursion (ti::pmin) (ti::mail-pgp-block-area 'msg)))
12041 ;; This checks "encrypted: PGP" tag.
12042 (ti::mail-pgp-encrypted-p)
12043 ;; Nope, there was none, use this.
12047 (setq beg-mark (point-marker))
12048 (goto-char (cdr ReS)) (setq end-mark (point-marker))
12049 (tinypgpd FiD "DECRYPT marks" beg-mark end-mark)
12052 ;; If user hasn't set END variable, we suppose
12053 ;; rest of the buffer. It is important that END variable
12054 ;; gets set here when MAIL message is handled, because
12055 ;; only now the message is trimmed and whitespaces
12059 (setq end (point-max)))
12062 (setq beg (if (ti::mail-mail-p)
12063 (ti::mail-text-start)
12066 ;; We use markers, because hook is called and it
12067 ;; may change the buffer content. The area must still be
12068 ;; available for us after changes.
12071 (goto-char beg) (setq beg-mark (point-marker))
12072 (goto-char end) (setq end-mark (point-marker)))))
12074 (tinypgpd FiD "BEG END" beg end "MARKER-BEGIN" beg-mark end-mark
12076 (tinypgpd FiD (buffer-substring beg-mark end-mark))
12078 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . user funcall ..
12080 (if tinypgp-:cmd-macro-before-hook
12081 (run-hook-with-args-until-success 'tinypgp-:cmd-macro-before-hook
12082 (, cmd) (, user) msg (, reg)))
12084 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. checking markers ..
12086 (if (or (null (setq beg (marker-position beg-mark)))
12087 (null (setq end (marker-position end-mark)))
12088 (eq beg end)) ;This is error too.
12090 TinyPgp: tinypgp-:cmd-macro-before-hook modified text too much."))
12092 (setq beg-mark nil end-mark nil) ;kill the markers
12094 (if ReS (setq ReS nil)) ;NoOp XE ByteComp silencer
12096 (if (null (, user))
12097 (setq (, user) (user-login-name)))
12099 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . make command ..
12101 (setq Rcmd (tinypgp-cmd-compose Rcmd (, user) ))
12103 (tinypgpd FiD "vars:" "USER" (, user)
12104 "CUR-BUF" (current-buffer) beg end
12106 "BODY-NIL" (equal 'nil (quote (, body))))
12108 ;;; (ti::d! "Doing COMMAND" beg end (current-buffer))
12110 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . DO ACTION ..
12111 ;; Check if BODY is omitted
12114 ((equal 'nil (quote (, body)))
12117 (if (or (tinypgp-backend-pgp2-p)
12118 (tinypgp-backend-gpg-p))
12119 (tinypgp-binary-do-command-region
12123 (tinypgp-hash 'mode-specific 'get 'buffer-edit nil 'global)
12126 (tinypgp-binary-do-command-region-with-expect
12129 (tinypgp-hash 'mode-specific 'get 'buffer-edit nil 'global)
12136 (tinypgp-binary-header-field-fix (, cmd) 'force)
12138 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. results ..
12141 (when (, reg) ;Save results
12144 (tinypgp-binary-get-result-as-string ReS)))
12146 (tinypgpd FiD "cmd-macro done. calling mode specific...")
12148 (if tinypgp-:cmd-macro-after-hook
12149 (run-hook-with-args-until-success 'tinypgp-:cmd-macro-after-hook
12150 (, cmd) (, user) msg (, reg)))
12152 (tinypgpd "cmd-macro out:")
12156 ;;{{{ PGP exe command compose
12158 ;;; ................................................. &command-compose ...
12160 ;;; ----------------------------------------------------------------------
12162 (defun tinypgp-cmd-compose (cmd user &optional password args)
12163 "Compose PGP command.
12167 CMD list of strings which may contain #TAGS
12168 '(binary base-command-set options)
12172 (let* ((cat (if (eq (tinypgp-backend-type) 'win32)
12175 (binary-type (tinypgp-backend-type))
12179 (setq cmd (format "%s %s" (nth 1 cmd) (or (nth 2 cmd) "")))
12181 ;; Decide where to put the binary itself. Is there a token #bin
12182 ;; where to put it?
12185 ((string-match "#bin" cmd)
12186 (setq cmd (ti::replace-match 0 binary cmd)))
12188 (setq cmd (concat binary " " cmd))))
12190 (if tinypgp-:pgp-command-compose-function
12191 (setq cmd (funcall tinypgp-:pgp-command-compose-function cmd)))
12193 (tinypgpd "[cmd-compose] in: USER"
12194 tinypgp-:user-now "PRING" tinypgp-:pubring-now)
12196 (tinypgpd "[cmd-compose] in: cmd"
12197 cmd "USER" user "PASS" password )
12199 (unless (stringp tinypgp-:pubring-now)
12200 (error "TinyPgp: no current pubring? tinypgp-:pubring-now"))
12202 (unless (file-exists-p tinypgp-:pubring-now)
12203 (error "TinyPgp: %s (tinypgp-:pubring-now) does not exist."))
12205 (tinypgpd "[cmd-compose] in2: global user, pring"
12206 tinypgp-:user-now tinypgp-:pubring-now )
12208 (unless (stringp tinypgp-:user-now) ;; make sure this variable exists
12209 (error "TinyPgp: user is unknown."))
12211 (when (string-match "#PUBRING" cmd)
12212 (setq cmd (ti::replace-match
12214 (concat "+pubring="
12215 (tinypgp-expand-file-name
12216 tinypgp-:pubring-now binary-type)
12220 (when (string-match "#PGP-USER" cmd)
12221 (setq cmd (ti::replace-match
12224 ;; Always treat this as list
12225 (ti::list-to-string (ti::list-make tinypgp-:user-now))
12230 (string-match "#USER" cmd))
12232 ;; With PGP 2: -u "user"
12233 ;; With pgp 5: -u user
12235 (setq tmp (if (or (tinypgp-backend-pgp2-p)
12236 (tinypgp-backend-gpg-p))
12239 (setq cmd (ti::replace-match
12240 0 (concat "-u " tmp
12241 ;; Always treat this as list
12242 (ti::list-to-string (ti::list-make user ))
12246 (when (string-match "#OUT-FILE" cmd)
12247 (setq cmd (ti::replace-match
12250 (tinypgp-expand-file-name
12251 tinypgp-:file-output binary-type)
12256 (string-match "#MUSER" cmd))
12258 ((tinypgp-backend-pgp2-p)
12259 (let ((type (save-match-data (tinypgp-binary-get-version 'symbol))))
12261 ((eq type 'international)
12267 (tinypgp-expand-file-name
12268 tinypgp-:file-user-list binary-type)
12271 (t ;doesn't know -@ switch
12277 (tinypgp-expand-file-name
12278 tinypgp-:file-user-list binary-type))
12280 (tinypgp-file-control 'users-write user)))
12284 (setq tmp (concat tmp " -r " elt)))
12286 (setq cmd (ti::replace-match 0 tmp cmd))
12287 (tinypgpd "[cmd-compose] #MUSER" user cmd))))
12289 ;; ........................................................... other ...
12290 ;; These are called from tinypgp-binary-do-command-region when parameters
12291 ;; are better known.
12293 (when (and args (string-match "#PIPE" cmd))
12294 ;; REST ARGS 1 = pipe file
12296 (setq cmd (ti::replace-match
12299 (tinypgp-expand-file-name
12301 tinypgp-:file-source)
12306 (when (string-match "#SOURCE-FILE" cmd)
12307 (let ((file (or (nth 0 args)
12308 tinypgp-:file-source)))
12311 (setq cmd (ti::replace-match
12314 (tinypgp-expand-file-name file binary-type)
12318 ;; .......................................................... password ...
12320 (when (string-match "#password" cmd)
12321 (when (ti::nil-p password)
12322 (setq password (tinypgp-password-get)))
12324 (when (null password)
12326 "TinyPgp Internal error: Command composing failed. No passwd."))
12328 (when (tinypgp-backend-gpg-p)
12329 (setq cmd (ti::replace-match
12331 (concat "\"" password "\" | ") cmd)))
12333 (when (tinypgp-backend-pgp2-p)
12334 (if (or nil ;Enabled now!
12335 (null tinypgp-:password-protection))
12336 (setq cmd (ti::replace-match
12338 (concat "-z\"" password "\" ") cmd))
12340 (setq cmd (ti::replace-match 0 nil cmd))
12341 (tinypgp-file-control 'password-write password)
12343 ;; PGP gets the password from file descriptor 3. This way
12344 ;; 'ps' listing doesn't show the password like it does
12347 (setq cmd (format (concat "PGPPASSFD=3; export PGPPASSFD; "
12348 " #PIPE %s 3< %s ")
12350 (tinypgp-expand-file-name
12351 tinypgp-:file-password binary-type))))))
12353 (tinypgpd "[cmd-compose] out: "
12354 cmd tinypgp-:pgp-command-compose-function )
12359 ;;{{{ PGP exe result, general, macros, error
12361 ;;; ........................................................ &pgp-core ...
12363 ;;; ----------------------------------------------------------------------
12365 (defun tinypgp-binary-header-field-set (field value)
12366 "Set FIELD with VALUE in PGP Signature header."
12368 (when (or (re-search-backward (ti::mail-pgp-signature-begin-line) nil t)
12369 (re-search-backward (ti::mail-pgp-msg-begin-line) nil t))
12370 (tinypgpd "tinypgp-binary-header-field-set: " field value)
12372 ((re-search-forward field nil t)
12373 (delete-region (point) (line-end-position))
12376 ((re-search-forward "^[ \t]*$") ;Must exist
12377 (insert field " " value "\n")))))
12379 ;;; ----------------------------------------------------------------------
12381 (defun tinypgp-binary-header-field-fix (command &optional force)
12382 "Change PGP headers for COMMAND. Optionally FORCE in spite of backend.
12383 In Windows NT not all the command line options cannot passed
12384 with the call, so we patch resulte manually."
12385 (when (and (or force
12387 (not (tinypgp-backend-pgp2-p)))
12388 (ti::re-search-check (ti::mail-pgp-signature-begin-line)))
12391 (get 'tinypgp-:pgp-binary-interactive-option 'comment)))
12392 (when (eq command 'sign)
12393 ;; (tinypgp-binary-header-field-set "Charset:" tinypgp-:pgp-binary-charset)
12395 (tinypgp-binary-header-field-set "Comment:" comment)))))))
12397 ;;; ----------------------------------------------------------------------
12399 (put 'tinypgp-excute-in-tmp 'lisp-indent-function 2)
12400 (defmacro tinypgp-excute-in-tmp (beg end &rest body)
12401 "Copy region BEG END from current buffer and execute BODY.
12402 Uses buffer `tinypgp-:buffer-tmp-shell'."
12404 (let* ((ob (current-buffer))
12405 (tmp (tinypgp-ti::temp-buffer 'shell)))
12406 (with-current-buffer tmp
12407 (insert-buffer-substring ob (, beg) (, end))
12408 (tinypgp-x-headers-deinstall)
12411 ;;; ----------------------------------------------------------------------
12413 (defsubst tinypgp-binary1-command-table (cmd)
12414 "Return right command table"
12416 ((eq 'pgp2 (tinypgp-backend-now))
12417 (assq cmd tinypgp-:pgp-command-table))
12418 ((eq 'gpg (tinypgp-backend-now))
12419 (assq cmd tinypgp-:gpg-command-table))
12421 (assq cmd tinypgp-:pgp-command-table5))))
12423 ;;; ----------------------------------------------------------------------
12424 ;;; http://www.pgpi.org/products/pgp/versions/freeware/
12425 ;;; => Unix => PGP 2.6.3i => Download PGP 2.6.3i
12426 ;;; => Download PGP 2.6.3i source code
12428 ;;; Win32/Cygwin compile command:
12431 ;;; gzip -dc pgp263is.tar.gz | tar -xvf
12432 ;;; tar -xvf pgp263ii.tar
12434 ;;; make -f makefile CFLAGS='-DUNIX -DPORTABLE' CC=gcc linux
12436 (defun tinypgp-binary-path-set (&optional verb)
12437 "Define backend properties in variable `tinypgp-:pgp-binary'.
12439 This function stores the executable paths in variable
12440 `tinypgp-:pgp-binary'."
12442 (let ((fid "tinypgp-binary-path-set: ")
12443 (list '("pgpk" "pgpv" "pgpe" "pgps"))
12444 (ext (if (ti::win32-p)
12447 (cygwin-root (ti::win32-cygwin-p))
12448 (search (delete "." exec-path))
12458 (dolist (sym '(pgp-set
12464 pgpk pgpv pgpo pgpe))
12465 (put 'tinypgp-:pgp-binary sym nil))
12467 ;; ......................................................... 2.6.x ...
12470 ((setq path (ti::file-get-load-path (concat "pgp" ext) search 'all))
12471 (dolist (bin (ti::list-make path))
12473 ;; Is this really 2.6.x? The PGP 5.x kit may contain binary
12476 (setq str (ti::mail-pgp-exe-version-string bin))
12477 (tinypgpd fid "Verifying 2.6" bin str)
12479 (when (stringp str)
12481 ((string-match "2\\.6" str)
12482 (put 'tinypgp-:pgp-binary 'pgp bin)
12483 (put 'tinypgp-:pgp-binary 'pgp-backends '(pgp2))
12485 ;; It is impossible to say if the pgp.exe is Cygwin
12486 ;; compiled or pure DOS version, because "pgp -h" gives
12487 ;; identical message.
12489 ;; The cygwin status is needed, because it affects
12490 ;; how file names are passed.
12492 ;; It is supposed that "cygwin version" WILL reside under
12493 ;; Cygwin hierarchy. This test fails if user uses
12494 ;; mount points that refer to external disks
12496 (let* ((cygwin-p (and cygwin-root
12498 (ti::file-path-to-unix cygwin-root)
12499 (ti::file-path-to-unix bin))))
12500 (type (if (and (ti::win32-p)
12504 (put 'tinypgp-:pgp-binary 'pgp2-type type))
12507 (message "TinyPgp: `pgp' found but that's not 2.6 version"))))))
12510 (message "Tinypgp: Hm, no pgp 2.x binary found.")
12513 ;; ........................................................... GPG ...
12516 ((setq path (ti::file-get-load-path (concat "gpg" ext) search 'all))
12517 (dolist (bin (ti::list-make path))
12519 (setq str (ti::mail-pgp-exe-version-string bin))
12520 (tinypgpd fid "Verifying GPG 1.x" bin str)
12522 (when (stringp str)
12524 ((string-match "1\\." str)
12525 (put 'tinypgp-:pgp-binary 'gpg bin)
12526 (put 'tinypgp-:pgp-binary
12528 (append '(gpg) (tinypgp-backend-list)))
12530 ;; It is impossible to say if the gpg.exe is Cygwin
12531 ;; compiled or pure DOS version, because "pgp -h" gives
12532 ;; identical message.
12534 (let* ((cygwin-p (and cygwin-root
12536 (ti::file-path-to-unix cygwin-root)
12537 (ti::file-path-to-unix bin))))
12538 (type (if (and (ti::win32-p)
12542 (put 'tinypgp-:pgp-binary 'gpg-type type))
12545 (message "TinyPgp: `gpg' found but that's not 1.x version"))))))
12548 (message "Tinypgp: Hm, no gpg 1.x binary found.")
12551 ;; ........................................................... 5.x ...
12554 (setq exe (concat bin ext)
12555 path (ti::file-get-load-path exe search 'all))
12559 (message "TinyPgp: Can't find PGP[56] executable %s:%s" exe search))
12560 (tinypgpd fid "Verifying 5.x FAILED" exe path))
12562 (dolist (binary (ti::list-make path))
12564 ;; #todo: what should be done to multiple occurrances of BIN?
12566 (tinypgpd fid "Verifying 5.x" binary)
12568 (put 'tinypgp-:pgp-binary (intern bin) binary)))))
12570 ;; if all pgp 5.x executables were found; then installation went okay
12573 (setq list (tinypgp-backend-list))
12574 (add-to-list 'list 'pgp5)
12575 (put 'tinypgp-:pgp-binary 'pgp-backends list))
12581 "pgp-set" (tinypgp-backend-list)
12582 "pgp" (get 'tinypgp-:pgp-binary 'pgp)
12583 "pgpk" (get 'tinypgp-:pgp-binary 'pgpk))
12586 (message "Tinypgp: found %s"
12588 (and (tinypgp-backend-list)
12590 (function (lambda (elt) (symbol-name elt)))
12591 (tinypgp-backend-list)
12595 (tinypgp-backend-list)))
12597 ;;; ----------------------------------------------------------------------
12599 (defun tinypgp-backend-select (backend &optional verb)
12600 "Select BACKEND 'pgp2 or 'pgp5 executables for use. VERB."
12602 (let* ((list (mapcar
12608 (tinypgp-backend-list)))
12610 (setq ret (completing-read "Select pgp: " list nil 'match))
12611 (list (cdr (assoc ret list)))))
12613 (let* ((fid "tinypgp-backend-select: ")
12619 ;; Check that arg is part of known list
12620 (unless (member backend (tinypgp-backend-list))
12623 TinyPgp: Feature %s is not configured or available: Call tinypgp-binary-path-set"
12626 (put 'tinypgp-:pgp-binary 'pgp-now backend)
12628 (setq secring (tinypgp-secring-file))
12629 (unless (file-exists-p secring)
12631 TinyPgp: Secring %s does not exist. See tinypgp-:file-secring %s" secring))
12633 (setq pubring (tinypgp-pubring-default))
12634 (unless (file-exists-p pubring)
12637 TinyPgp: Can't find pubring %s. Check tinypgp-:pubring-table for backend %s"
12641 (setq tinypgp-:pubring-now pubring)
12643 ;; Each time backend is changed, the cache must be updated and
12645 (tinypgp-key-cache-remove-entry-last)
12646 (setq tinypgp-:key-cache nil)
12647 (tinypgp-key-cache-save 'load)
12649 (tinypgpd fid backend pubring secring)
12650 (tinypgp-update-modeline)
12653 (message "Tinypgp: backend %s" (symbol-name backend)))
12657 ;;; ----------------------------------------------------------------------
12659 (defun tinypgp-variable-state-control (&optional restore)
12660 "Save or RESTORE variables. Used when changing backends."
12661 (let* ((opt (get 'tinypgp-:pgp-binary-interactive-option 'original)))
12662 ;; PGP 5.x doesn't know +comment option.
12666 (setq tinypgp-:pgp-binary-interactive-option opt))
12668 (put 'tinypgp-:pgp-binary-interactive-option 'original
12669 tinypgp-:pgp-binary-interactive-option)
12670 (setq tinypgp-:pgp-binary-interactive-option nil)))))
12672 ;;; ----------------------------------------------------------------------
12674 (defun tinypgp-backend-select-pgp2 ()
12675 "Select pgp 2.6.x backend"
12677 (tinypgp-variable-state-control 'restore)
12678 (tinypgp-backend-select 'pgp2 (interactive-p)))
12680 ;;; ----------------------------------------------------------------------
12682 (defun tinypgp-backend-select-pgp5 ()
12683 "Select pgp 5.x backend"
12685 (tinypgp-variable-state-control)
12686 (tinypgp-backend-select 'pgp5 (interactive-p)))
12688 ;;; ----------------------------------------------------------------------
12690 (defun tinypgp-backend-select-auto ()
12691 "Select pgp 2 if it exists else use pgp 5. Otherwise flag error."
12692 (let* ((list (get 'tinypgp-:pgp-binary 'pgp-backends)))
12695 (tinypgp-backend-select-pgp2))
12697 (tinypgp-backend-select-pgp5))
12700 Check PATH for pgp executable(s): maybe tinypgp-binary-path-set failed.")))))
12702 ;;; ----------------------------------------------------------------------
12704 (defun tinypgp-backend-set-for-action (action &rest args)
12705 "Select right backend for ACTION.
12706 Action may be 'remail 'newnym 'nymserv or 'pgp
12707 Die if can't select right backend."
12708 (when (memq action '(remail newnym nymserv))
12709 (unless (tinypgp-backend-pgp2-p)
12710 (unless (tinypgp-backend-exist-pgp2)
12711 (error "Pgp 2 not available for Action %s" action))
12712 (tinypgp-backend-select-pgp2))))
12714 ;;; ----------------------------------------------------------------------
12716 (defun tinypgp-binary1 (cmd)
12717 "Return right pgp executable for COMMAND type 'encrypt ...."
12723 ((tinypgp-backend-pgp2-p)
12724 (get 'tinypgp-:pgp-binary 'pgp))
12726 ((tinypgp-backend-gpg-p)
12727 (get 'tinypgp-:pgp-binary 'gpg))
12729 ((eq 'pgp5 (tinypgp-backend-now))
12733 (get 'tinypgp-:pgp-binary 'pgps))
12735 ((memq cmd '(encrypt
12739 (get 'tinypgp-:pgp-binary 'pgpe))
12741 ((memq cmd '(decrypt
12743 (get 'tinypgp-:pgp-binary 'pgpv))
12746 (get 'tinypgp-:pgp-binary 'pgpv))
12748 ((string-match "key" (symbol-name cmd))
12749 (get 'tinypgp-:pgp-binary 'pgpk))))))
12751 (if (or (not (stringp ret))
12752 (not (file-exists-p ret)))
12753 (error "Install failure: Please run tinypgp-binary-path-set (%s)" cmd))
12755 ;; In WinNT the maximum command length is 255, so we can't
12756 ;; afford to use absolute path here. (It would have been faster)
12760 (file-name-nondirectory ret)
12763 ;;; ----------------------------------------------------------------------
12765 (defun tinypgp-binary-get-cmd (cmd &optional options)
12766 "Return pgp shell command according to logical CMD with appended OPTIONS."
12767 (let* ((exe (tinypgp-binary1 cmd))
12768 (elt (tinypgp-binary1-command-table cmd)))
12770 (error "PGP exe command error: No logical command in table '%s'" cmd)
12776 ;;; ----------------------------------------------------------------------
12778 (defmacro tinypgp-binary-result-data-win32 (beg end)
12779 "Set result of PGP2 in WindowsNt shell buffer.
12780 In unix the output is printed so that 1)stderr 2)results
12781 but in Windows NT it could be printed in reverse order.
12783 We check here if the data is put to the beginning of the buffer,
12784 before the PGP logo.
12786 Variables BEG and END are modified if data starts from `point-min'."
12789 ;; 1) If variables are both nil
12790 ;; 2) they are equal
12792 (when (or (not (and (, beg) (, end)))
12793 (eq (, beg) (, end)))
12796 ;; No configuration file found.
12797 ;;
\aPretty Good Privacy(tm) 2.6.3ia -
12799 (when (and (re-search-forward
12802 "^No configuration file found.$\\|"
12803 "\C-g?Pretty Good Privacy(tm)")
12805 (prog1 t (beginning-of-line))
12806 (not (eq (point) (point-min))))
12807 (setq beg (point-min) end (point))))))))
12809 ;;; ----------------------------------------------------------------------
12811 (put 'tinypgp-binary-get-result-re1-macro 'lisp-indent-function 1)
12812 (defmacro tinypgp-binary-get-result-re1-macro (options &rest body)
12813 "If case-sensitive REGEXP match, execute BODY.
12814 The OPTIONS is a list containing an alist of options:
12816 '((regexp REGEXP) - Search REGEXP
12817 (loop [t|nil])) - if LOOP is t, run while loop for REGEXP"
12819 (with-current-buffer tinypgp-:buffer-tmp-shell
12820 (let (case-fold-search ;Case sensitive matching
12821 (re (nth 1 (assq 'regexp (, options))))
12822 (loop (nth 1 (assq 'loop (, options)))))
12824 (when (re-search-forward re nil t)
12826 (while (re-search-forward re nil t)))
12827 (tinypgpd "exe-get-result-re1-macro:" (match-string 0) )
12830 ;;; ----------------------------------------------------------------------
12832 (defsubst tinypgp-binary-insert-command-log (&optional point cmd)
12833 "Insert last command log into POINT[current point] or insert CMD."
12834 (if point (goto-char point))
12838 (prin1-to-string cmd)
12839 (prin1-to-string tinypgp-:last-pgp-exe-command)))
12841 (insert "\n\nTinyPgp report, last command and parameters:\n\n"
12843 "explicit-shell-file-name: "
12844 (or explicit-shell-file-name "<>") "\n"
12846 "shell-file-name : " (or shell-file-name "<>") "\n"
12847 "command length : " (int-to-string (length cmd)) "\n\n"
12854 ;;{{{ PGP exe result get,check
12856 ;;; ----------------------------------------------------------------------
12858 (defun tinypgp-binary-check-error (&optional ignore-output-error cmd buffer)
12859 "Return non-nil, if the PGP output is not valid.
12863 IGNORE-OUTPUT-ERROR this skips checking the output: --- TAGS
12865 BUFFER Where the pgp output is
12868 `tinypgp-:error' stored error message"
12869 (let ( ;; the re-ok does not produce re-block, but it's still valid
12870 ;; pgp answer, not an error condition.
12872 (fid "tinypgp-binary-check-error:" )
12874 "Good signature \\(from\\|made\\)"
12875 "\\|Bad signature from"
12876 "\\|Pass phrase +\\(is\\|appears\\) +good"
12878 (re-block "-----BEGIN.*PGP")
12879 (re tinypgp-:pgp-binary-error-regexp)
12880 case-fold-search) ;; Case is important here !!
12883 (setq buffer tinypgp-:buffer-tmp-shell))
12885 (setq tinypgp-:error nil)
12887 ;; - See if buffer DOES not contain ok sign, then GO AND
12888 ;; check error. Once I have message where
12889 ;; "You do not have the secret" was written in message body.
12890 ;; and that was not an error condition.
12892 (with-current-buffer buffer
12893 (unless (and (ti::re-search-check
12894 "^Pass phrase is good. Just a moment[.][.]+")
12896 ;; Funny; The previous message is ouputted, but
12897 ;; if one pass encryption&sign fails; this is message
12898 ;; will be seen. Make3 sure we don't see it.
12900 ;; Including "pgp-lst"...
12901 ;; Pass phrase is good. Just a moment....
12902 ;; ^GKey matching userid 'a@b.if' not found
12903 ;; in file '/aa7bb/ring-all.pgp'
12905 ;; ^GCannot find the public key matching userid 'a@b.if'
12906 ;; This user will not be able to decrypt this message.
12907 ;; ^GEncryption error
12909 (null (ti::re-search-check "Encryption error$")))
12910 (tinypgp-binary-get-result-re1-macro (list (list 'regexp re))
12911 (tinypgpd fid "MB" (match-beginning 0) "ME" (match-end 0)
12913 (tinypgp-highlight 'match 0 nil tinypgp-:face-error nil
12914 (match-beginning 0)
12916 (setq tinypgp-:error (ti::remove-properties (ti::read-current-line)))
12917 (tinypgp-binary-insert-command-log (point-max) cmd))))
12919 (unless ignore-output-error
12920 (with-current-buffer buffer
12921 (when (and (null tinypgp-:error) ;Not already set?
12922 (not (ti::re-search-check re-ok 0 '(point-min)))
12923 (not (ti::re-search-check re-block 0 '(point-min))))
12924 (setq tinypgp-:error "Internal error. No output from PGP.")
12925 (tinypgp-binary-insert-command-log (point-max) cmd))))
12927 ;; If this was encryption and it failed, then remove entry from
12931 (tinypgp-key-cache-remove-entry tinypgp-:error))
12933 (tinypgpd fid "RET" tinypgp-:error )
12937 ;;; ----------------------------------------------------------------------
12939 (defun tinypgp-binary-get-result (&optional buffer)
12940 "Return the result of PGP output from BUFFER or `tinypgp-:buffer-tmp-shell'.
12941 Look for markers -----BEGIN PGP, -----END PGP.
12944 (let* ((re1 "[.]*\\(-----BEGIN.*PGP\\)")
12945 (re2 "^-----END.*PGP")
12948 (with-current-buffer (or buffer tinypgp-:buffer-tmp-shell)
12950 (when (re-search-forward re1 nil t)
12951 (setq beg (match-beginning 1))
12953 (when (re-search-backward re2 nil t)
12954 (setq ret (list (current-buffer) beg (line-end-position))))))
12955 (tinypgpd "exe-get-result ret: " ret )
12958 ;;; ----------------------------------------------------------------------
12960 (defun tinypgp-binary-get-result-decrypt (&optional buffer)
12961 "Read BUFFER after decrypt and sign (international version).
12963 Return position of result in buffer.
12967 ;; Note how international version spits string "pass phrase",
12968 ;; and US version doesn't
12969 ;; +++++++++++++++++++++++++++
12971 ;; International version - not for use in the USA. Does not useRSAREF.
12972 ;; Current time: 1997/05/19 12:10 GMT
12973 ;; Pass phrase is good. Just a moment....-----BEGIN PGP SIGNED
12976 ;; Export of this software may be restricted by the U.S. government.
12977 ;; Current time: 1997/05/16 20:40 GMT
12978 ;; Pass phrase is good.
12979 ;; Key for user ID: xxxxk
12980 ;; 768-bit key, Key ID xxxx
12983 ;; Just a moment....-----BEGIN PGP SIGNED MESSAGE-----
12985 ;; note: When you call command -seatf; encrypt and sign in one pass,
12986 ;; the output is bit different.
12987 ;; +++++++++++++++++++++++++++
12989 ;; International version - not for use in the USA. Does not use RSAREF.
12990 ;; Current time: 1997/06/26 20:29 GMT
12992 ;; Including "/users/jaalto/.pgp/pgp-lst"...
12993 ;; Pass phrase is good. Just a moment....
12994 ;; Key for user ID: Foo <foo@example.com>
12995 ;; 512-bit key, key ID 47141D35, created 1996/06/03
12996 ;; Also known as: Jari Aalto, Finland <ssjaaa@uta.fi>
12997 ;; .-----BEGIN PGP MESSAGE-----
12998 ;; Version: 2.6.3ia
12999 ;; Comment: Processed by Emacs TinyPgp.el 1.222
13001 ;; hEwDwLrt1UcUHTUBAgCFBDvkHJ7dEffIGiqyPi2WtdOPwWQ+Duw6/be/7FjJYEUV
13003 (tinypgp-binary-get-result-re1-macro ; -seatf
13004 '((regexp "Pass phrase is good. Just a moment[.]+"))
13005 (when (and (save-excursion
13007 (looking-at ".*Key for user ID:"))
13008 (re-search-forward (ti::mail-pgp-msg-begin-line) nil t))
13011 ret (list (current-buffer) (match-beginning 0) (point-max)))))
13014 (tinypgp-binary-get-result-re1-macro
13019 "Pass phrase is good. Just a moment[.]+"
13020 ;; #todo: warning handling in decrypting
13022 "\\|WARNING: Can't find.*can't check signature integrity.*\n")))
13025 ret (list (current-buffer) (point) (point-max)))))
13028 ;; This is from conventional decrypt
13029 (tinypgp-binary-get-result-re1-macro
13030 '((regexp "Pass phrase appears good\\. \\."))
13033 ret (list (current-buffer) (point) (point-max)))))
13035 ;; gpg: encrypted with 1024-bit ELG-E key, ID E7114155, created 2002-01-15
13036 ;; "foo <foo@some.com>"
13037 ;; <THE MESSAGE FOLLOWS>
13040 ;; This is from conventional decrypt
13041 (tinypgp-binary-get-result-re1-macro
13042 '((regexp "^gpg: encrypted with.*[\r\n\]+.*[\r\n\][\r\n\]?"))
13045 ret (list (current-buffer) (point) (point-max)))))
13047 ;; GPG is different. It will not give any indication if
13048 ;; Pass phrase was good. It simply decrypted the message and
13049 ;; possibly gave warnings:
13050 ;; gpg: Please note that you don't have secure memory on this system
13051 ;; gpg: Warning: unsafe permissions on file "~/.gnupg/options"
13052 ;; gpg: Warning: unsafe permissions on file "~/.gnupg/random_seed"
13053 ;; gpg: Warning: unsafe permissions on file "~/.gnupg/secring.gpg"
13054 ;; gpg: Warning: unsafe permissions on file "~/.gnupg/pubring.gpg"
13055 ;; <THE MESSAGE FOLLOWS>
13058 ;; This is from conventional decrypt
13059 (tinypgp-binary-get-result-re1-macro
13060 '((regexp "^gpg: Warning:.*[\r\n]")
13064 ret (list (current-buffer) (point) (point-max)))))
13066 (tinypgpd "exe-get-result-decrypt ret: " tmp ret )
13069 ;;; ----------------------------------------------------------------------
13071 (defun tinypgp-binary-get-result-encrypt-info (&optional buffer)
13072 "Return pointer to block 'This message can only be read by:'"
13073 (with-current-buffer (or buffer tinypgp-:buffer-tmp-shell)
13075 (when (re-search-forward
13076 "This message can only be read by:" nil t)
13077 (beginning-of-line)
13078 (let* ((beg (point)))
13079 (or (re-search-forward "^[ \t]*$" nil t) (ti::pmax))
13080 (beginning-of-line)
13081 (list (current-buffer) beg (point))))))
13083 ;;; ----------------------------------------------------------------------
13085 ;;; This message can only be read by:
13086 ;;; keyID: EFDB16AD
13087 ;;; foo <foo@some.com>
13089 (defun tinypgp-binary-get-result-encrypt-info-list (&optional pointer)
13090 "Return list of users in 'This message can only be read by:'.
13091 POINTER is region where to read the results: (buffer beg end)"
13095 (setq pointer (tinypgp-binary-get-result-encrypt-info)))
13097 (with-current-buffer (car pointer)
13098 (goto-char (nth 1 pointer))
13100 (while (or (looking-at ".*keyID: +\\(.*\\)")
13101 (looking-at "^ +\\(.*\\)"))
13102 (push (ti::remove-properties (match-string 1)) list)
13103 (forward-line 1))))
13106 ;;; ----------------------------------------------------------------------
13108 (defun tinypgp-binary-get-result-verify-status (&optional buffer)
13109 "Return result STRING after verify from BUFFER."
13110 (tinypgp-binary-get-result-re1-macro
13114 (concat "Good signature \\(from\\|made\\)"
13116 ;; This warning is preceeded by lines:
13117 ;; File has signature. Public key is required to check...
13118 ;; Key matching expected Key ID 1CEB1F55 not found
13120 "\\|WARNING: Can't find the right public"
13121 "\\|Bad signature from"
13122 "\\|Key matching.*not found")))
13123 (if (or (tinypgp-backend-pgp2-p)
13124 (tinypgp-backend-gpg-p))
13125 (ti::read-current-line)
13128 (let* ((case-fold-search t)
13129 (id (ti::buffer-match ".*key +id +\\([0-9A-Z]+\\)" 1))
13133 (ti::mail-email-find-region
13135 (progn (forward-line 5) (point))))
13136 (format "Good signature from %s%s"
13137 (if id (format " %s " id) "")
13139 (ti::list-to-string list)
13142 ;;; ----------------------------------------------------------------------
13144 (defun tinypgp-binary-get-result-using-function (function &optional buffer)
13145 "Call FUNCTION with arg BUFFER and return result in string format.
13146 Function is the one that returns `pointer' object, like
13147 `tinypgp-binary-get-result-verify'"
13148 (let* ((pointer (funcall function buffer)))
13150 (inline (tinypgp-binary-get-result-as-string pointer)))))
13152 ;;; ----------------------------------------------------------------------
13154 (defun tinypgp-binary-insert-pointer-data (pointer &optional beg)
13155 "Read POINTER '(buffer beg end) and insert data to point.
13157 pointer '(BUFFER BEG END)
13158 beg flag, keep poin in beginnning instead of end of inserted data.
13160 (if (not (eq 3 (length pointer)))
13161 (error "Invalid pointer")
13162 (let ((point (point)))
13163 (insert-buffer-substring (car pointer) (nth 1 pointer) (nth 2 pointer))
13165 (goto-char point)))))
13167 ;;; ----------------------------------------------------------------------
13169 (defun tinypgp-binary-get-result-as-string (pointer)
13170 "Read string from POINTER '(buffer beg end)."
13171 (with-current-buffer (car pointer)
13172 (buffer-substring (nth 1 pointer) (nth 2 pointer))))
13174 ;;; ----------------------------------------------------------------------
13175 ;;; File has signature. Public key is required to check signature.
13177 ;;; Good signature from user "XXX xxx <xxx@example.com>
13178 ;;; Signature made 1998/03/04 08:22 GMT using 512-bit key, key ID 47141D35
13179 ;;; PGP-DATA-FOLLOWS
13181 (defun tinypgp-binary-get-result-verify (&optional buffer)
13182 "Return result after verify from BUFFER. '(buffer beg end)."
13183 (let ((fid "tinypgp-binary-get-result-verify")
13187 (tinypgp-binary-get-result-re1-macro
13191 (concat "Good signature \\(from\\|made\\)"
13193 ;; This warning is preceeded by lines:
13194 ;; File has signature. Public key is required to check...
13195 ;; Key matching expected Key ID 1CEB1F55 not found
13197 "\\|WARNING: Can't find the right public")))
13198 (re-search-forward "Signature made" nil t)
13200 (if (or (tinypgp-backend-pgp2-p)
13201 (tinypgp-backend-gpg-p)
13203 (goto-char (tinypgp-hash 'expect 'get 'point nil 'global)))
13208 (if (or (tinypgp-backend-pgp2-p)
13209 (tinypgp-backend-gpg-p))
13210 (tinypgp-binary-result-data-win32 beg end))
13212 ;; Sometimes PGP says this:
13214 ;; Looking for next packet in '/users/jaalto/junk/pgptemp.$00'...
13216 ;; File has signature. Public key is required to check signature.
13218 ;; File '/users/jaalto/junk/pgptemp.$01' has signature, but with no text.
13220 (when (re-search-forward "Looking for next packet in '" nil t)
13221 (beginning-of-line)
13222 (setq end (point)))
13224 (setq ret (list (current-buffer) beg end)))
13226 (tinypgpd fid "POINTER" ret)
13229 ;;; ----------------------------------------------------------------------
13231 (defun tinypgp-binary-get-result-base64 (&optional buffer)
13232 "Get contents after the 'Signature made 1996/11 ...' from BUFFER.
13234 pointer '(buffer beg end)"
13236 (tinypgp-binary-get-result-re1-macro
13237 '((regexp "^Good signature from"))
13238 ;; Good signature from user
13239 ;; Signature made 1996/11/07
13243 (setq ret (list (current-buffer) (point) (point-max))))
13246 ;;; ----------------------------------------------------------------------
13248 (defun tinypgp-binary-get-result-key-add (&optional buffer)
13249 "Return result of key adding from BUFFER."
13254 ((tinypgp-binary-get-result-re1-macro
13259 "you need a newer version of PGP"
13260 "\\|Bad ASCII armor"
13261 "\\|^No +keys found\\|.*added.*\\|ERROR: Bkad ASCII armor.*"
13262 "\\|.*error\\|No new keys or signatures")))
13263 (setq ret (ti::read-current-line))))
13264 ((with-current-buffer tinypgp-:buffer-tmp-shell
13266 (setq list (ti::buffer-grep-lines "new key(s)")))
13267 (setq ret (format "%d New keys added." (length list)))))
13271 ;;; ----------------------------------------------------------------------
13273 (defun tinypgp-binary-get-result-key-sign (&optional buffer)
13274 "Return result of key signing from BUFFER."
13278 ((tinypgp-binary-get-result-re1-macro
13283 "^No +keys found\\|ERROR\\|.*error"
13284 "\\|Key is already signed by")))
13285 (setq ret (ti::read-current-line)))))
13288 ;;; ----------------------------------------------------------------------
13290 (defun tinypgp-binary-get-result-key-remove (&optional buffer)
13291 "Return result of key remove from BUFFER."
13294 ((tinypgp-binary-get-result-re1-macro
13299 ;; PGP can't remove key if it asks this
13301 ;; Key has more than one user ID.
13302 ;; Do you want to remove the whole key (y/N)? << WAITS HERE
13304 "^Key has more than one user ID"
13305 "\\|Keyring remove error")))
13306 (setq ret (ti::read-current-line)))))
13309 ;;; ----------------------------------------------------------------------
13311 (defun tinypgp-binary-exit-code-ok-p (number)
13312 "Check if exit code NUMBER is ok."
13313 (if (and (tinypgp-backend-pgp2-p)
13314 (memq number '(0 1)))
13318 ;;; ----------------------------------------------------------------------
13320 (defun tinypgp-binary-exit-status-entry (number)
13321 "Check PGP's exit code NUMBER and return appropriate error message."
13322 (let* ((table tinypgp-:pgp-binary-exit-code-table)
13325 ((tinypgp-backend-pgp2-p)
13326 (setq elt (cdr (assq 'pgp2 table)))))
13327 ;; (unless elt (error "Unknown PGP executable."))
13328 (assq number elt)))
13330 ;;; ----------------------------------------------------------------------
13332 (defun tinypgp-binary-handle-result (&optional status)
13333 "Show `tinypgp-:buffer-tmp-shell' buffer if error, otherwise return result.
13334 STATUS is Shell processes exit code.
13337 '(buffer beg end) or call error"
13338 (tinypgpd "tinypgp-binary-handle-result: in" status)
13339 (let* ((fid "tinypgp-binary-handle-result")
13340 (action (tinypgp-hash 'action 'get 'now nil 'global))
13341 (elt (if status (tinypgp-binary-exit-status-entry status)))
13342 ;;; (sym (if elt (nth 1 elt)))
13343 ;;; (re (if elt (nth 2 elt)))
13344 (ok (if status (tinypgp-binary-exit-code-ok-p status)))
13348 (tinypgpd fid "Status" status "OK" ok )
13350 ;; There is one case where pgp return 0 status(ok): encrypt with
13351 ;; multiple keys, but some key is not found from keyring.
13352 ;; --> I'd say this is fatal error
13354 ;; That's why we always check the verbal results in spite of STATUS
13356 (setq error (tinypgp-binary-check-error))
13360 ;; verifying the message also unpacks
13361 ;; encrypted message if sig was good
13363 (tinypgp-binary-get-result-verify)
13365 (tinypgp-binary-get-result)
13366 (and (string-match "decrypt" (symbol-name action))
13367 (tinypgp-binary-get-result-decrypt)))))
13381 (tinypgp-error (or error "No PGP output or error; huh?"))))))
13386 ;;; ----------------------------------------------------------------------
13388 (defun tinypgp-binary-command-region-fix (cmd pointer)
13389 "If the CMD failed when PGP asked random bits, fix it. POINTER is PGP data."
13390 (tinypgpd "tinypgp-binary-command-region-fix in:" pointer )
13391 (with-current-buffer (car pointer)
13392 (when (ti::re-search-check
13393 "We need to generate \\([0-9]+\\)" 0 '(point-min))
13394 (tinypgpd "tinypgp-binary-command-region-fix done:" pointer "\n")
13395 (tinypgp-error "randseed.bin must be generated."))))
13397 ;;; ----------------------------------------------------------------------
13399 (defsubst tinypgp-send (string)
13400 "Send STRING to open expect process."
13401 (expect-send (concat string (if (ti::win32-p) "\r" "\n"))))
13403 ;;; ---------------------------------------------------------- &engine ---
13405 (defun tinypgp-binary-do-command-region-with-expect
13406 (cmd beg end o-buffer &optional msg ret-ptr)
13407 "Execute shell CMD on region BEG END with USER.
13411 CMD str, full PGP command.
13412 BEG int, region beg to feed to PGP
13413 END int, region end to feed to PGP
13414 O-BUFFER bfr, original buffer where BEG END are
13416 RET-PTR flag, instead of replacing previous content return pointer
13420 REGION END REPLACED point at beg, if ret-ptr = nil
13421 POINTER '(buffer beg end) if ret-ptr = non-nil"
13422 (let* ((fid "tinypgp-binary-do-command-region-with-expect: ")
13423 (binary-process-input t)
13424 (out-p (string-match "-o\\|#OUT" cmd))
13425 (orig-buffer (current-buffer))
13438 (if (null binary-process-input) ;quiet ByteCompiler
13439 (setq binary-process-input nil))
13441 (tinypgp-hash 'expect 'put 'process nil 'global)
13443 (tinypgp-do-shell-env
13444 (tinypgp-excute-in-tmp beg end ;results in temp buffer
13449 (tinypgp-file-control 'all-kill)
13452 (tinypgp-file-control 'source-write)
13455 ((string-match "#PIPE" cmd)
13456 (setq cmd (tinypgp-cmd-compose cmd nil nil '(nil))))
13457 ((string-match "#SOURCE-FILE" cmd)
13458 (setq cmd (tinypgp-cmd-compose cmd nil nil '(nil)))))
13460 ;; If this command requires password, it contains marker #password
13461 ;; --> get the password from cache or ask from user.
13463 (when (string-match "#password" cmd)
13464 (setq cmd (ti::replace-match 0 nil cmd) ;; Delete tag from command
13465 pass (tinypgp-password-get)))
13467 ;; The command is given as plain string. Explode it to individual
13468 ;; arguments "pgp -s +batchmode=1" --> '("pgpg" "-s" "+batchmode=1")
13470 (setq split (split-string cmd "[ ]+")
13471 bin-name (nth 0 split)
13473 out-buffer (current-buffer))
13475 (setq tinypgp-:last-pgp-exe-command cmd)
13477 (tinypgpd fid "in:"
13479 "CURRENT" (current-buffer)
13482 "min-max" (point-min) (point-max)
13491 (setq expect-start (point-max)
13500 (with-expect process
13502 (unless (ti::win32-p) ;; Unix is slower than NT, add delay
13507 ;; Error! Unable to load string ENTER_PASSPHRASE
13509 ("Enter pass phrase:\\|ENTER_PASSPHRASE"
13510 (tinypgpd "Expect: triggered password prompt, sending it...")
13511 (unless (stringp pass)
13512 (delete-process process)
13513 (tinypgp-error "Internal error. No pass phrase available."))
13514 (sit-for 0.3) ;Small delay so that PGP is ready
13515 (tinypgp-send pass)
13518 ("Error: Bad pass phrase."
13519 (interrupt-process process)
13520 (setq pgp-error 'bad-pass-phrase))
13522 ("Enter pass phrase:"
13523 (interrupt-process process)
13524 (setq pgp-error 'bad-pass-ohrase))
13526 ("Cannot decrypt message. It can only be decrypted by:"
13527 (interrupt-process process)
13528 (setq pgp-error 'cannot-decrypt)))))
13530 ;; WRN: WARNING: The above key is not trusted to belong to:
13531 ;; WRN: Mr. Foo <foo.site.com>
13532 ;; QRY: Do you want to use the key with this name? [y/N]
13536 ("Do you want to use the key with this name"
13537 (tinypgpd "Expect: Use this kay ok...")
13538 (tinypgp-send "y"))))
13543 (delete-process process))
13546 (tinypgpd "Expect: timeout")
13547 (delete-process process)
13549 (substitute-command-keys
13551 "Expect: timeout occurred: send bug report "
13552 "\\[tinypgp-submit-bug-report]"))))
13556 ;; Killing killed process won't hurt. Make sure the
13557 ;; Expect-cond didn't fall through.
13559 (delete-process process)
13561 ;; ......................................... read results ...
13565 (tinypgpd "Expect: Terminated on error" pgp-error)
13567 (format "Expect error %s" (symbol-name pgp-error))))
13571 (setq point (point)))
13574 (tinypgpd "Expect: reading input"
13577 tinypgp-:file-output)
13579 ;; Expect may move us out of the buffer
13581 (unless (eq (current-buffer) out-buffer)
13582 (if (buffer-live-p (get-buffer out-buffer))
13583 (set-buffer out-buffer)
13584 (error "Expect: Can't insert data: buffer has changed")))
13586 ;; point is nil if there was no output file in
13587 ;; this command, so the eq test will work in those
13590 (if (eq (point) point)
13591 (tinypgp-error "Expect: no output from PGP"))
13594 (setq point (point))
13596 (if (file-exists-p tinypgp-:file-output)
13597 (insert-file-contents tinypgp-:file-output)
13598 (if (buffer-live-p (get-buffer out-buffer))
13599 (pop-to-buffer out-buffer)
13600 (error "No expected output-file %s "
13601 tinypgp-:file-output))))) ;; end of cond
13603 ;; ...................................... handle results ...
13605 (tinypgp-hash 'expect 'put 'point point 'global)
13607 ;; Remove possible ^M chars
13609 (ti::buffer-lf-to-crlf 'dos2Unix 'doReadOnly)
13610 (setq pointer (list (current-buffer) point (point-max)))
13612 (tinypgpd "Expect: pointer" pointer)
13614 (when (eq point (point-max))
13615 (tinypgp-error "No output from pgp"))
13617 (tinypgp-file-control 'source-kill)))))
13619 (unless (eq (current-buffer) orig-buffer) ;Restore buffer we left
13620 (set-buffer orig-buffer))
13624 (setq ret pointer))
13627 (delete-region beg end)
13628 (insert-buffer-substring
13629 (car pointer) (nth 1 pointer) (nth 2 pointer))
13634 ;;; ---------------------------------------------------------- &engine ---
13636 (defun tinypgp-binary-do-command-region
13637 (cmd beg end o-buffer &optional msg ret-ptr)
13638 "Execute shell CMD on region BEG END with USER.
13642 CMD string, full PGP command.
13643 BEG integer, region beg to feed to PGP
13644 END integer, region end to feed to PGP
13645 O-BUFFER buffer, original buffer where BEG END are
13646 MSG string, message
13647 RET-PTR flag, instead of replacing previous content return pointer
13651 REGION END REPLACED point at beg, if ret-ptr = nil
13652 POINTER '(buffer beg end) if ret-ptr = non-nil
13656 `tinypgp-:pgp-sh-exe'
13657 `tinypgp-:last-pgp-exe-command'
13658 `tinypgp-:file-output'
13659 `tinypgp-:file-source'"
13660 (let* ((fid "tinypgp-binary-do-command-region: ")
13661 (action (tinypgp-hash 'action 'get 'now nil 'global))
13663 (final-newline "\n")
13664 (binary-process-input t)
13666 ret pointer pointer-orig)
13668 (if (null binary-process-input) ;quiet ByteCompiler
13669 (setq binary-process-input nil))
13671 (tinypgp-do-shell-env
13676 (tinypgpd fid "in:" (current-buffer)
13677 beg end "min-max" (point-min) (point-max)
13682 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... loop start ...
13683 (while loop ;If we should repeat the task?
13685 (tinypgpd fid "loop-beg" loop (current-buffer) cmd "\n")
13687 (tinypgp-excute-in-tmp beg end ;results in temp buffer
13689 ;;; (pop-to-buffer (current-buffer)) (ti::d! "DOING PGP")
13691 (setq pointer-orig (list (current-buffer) (point-min) (point-max)))
13694 (tinypgp-file-control 'source-write)
13696 ;; PGP: Cannot use INPUT file as a parameter to pgp, but
13697 ;; we must feed the file through pipe to pgp. Fix some
13700 (when (tinypgp-backend-pgp2-p)
13702 ((string-match "#PIPE" cmd)
13703 (setq cmd (tinypgp-cmd-compose cmd nil nil '(nil))))
13704 ((string-match "#SOURCE-FILE" cmd)
13705 (setq cmd (ti::replace-match 0 nil cmd))
13706 (setq cmd (concat " #PIPE " cmd))
13707 (setq cmd (tinypgp-cmd-compose cmd nil nil '(nil))))
13709 (setq cmd (concat " #PIPE " cmd))
13710 (setq cmd (tinypgp-cmd-compose cmd nil nil '(nil))))))
13712 (tinypgpd fid "last-cmd:" (current-buffer) cmd )
13714 (setq tinypgp-:last-pgp-exe-command cmd)
13716 (if tinypgp-:do-command-region-before-hook
13717 (run-hook-with-args-until-success
13718 'tinypgp-:do-command-region-before-hook
13723 ;; ............................................. save command ...
13725 (when nil ;; only t if development version
13727 (let ((file "~/.tinypgp-cmd"))
13729 (write-region (point-min) (point-max) file)
13730 (ti::file-mode-protect file))))
13732 ;; .............................................. run command ...
13734 (ti::file-delete-safe tinypgp-:file-output)
13737 (shell-command cmd (current-buffer)))
13739 ;; If there is output file (which was not sent stdout),
13740 ;; then read it. This happens with GPG, which is unable to send
13741 ;; to stdout, if stdin is used for password.
13743 (when (file-exists-p tinypgp-:file-output)
13745 (tinypgpd fid "READING OUTPUT FILE" tinypgp-:file-output)
13746 (insert-file-contents-literally tinypgp-:file-output))
13748 (tinypgpd fid "SHELL-STATUS" status)
13750 (if tinypgp-:do-command-region-after-hook
13751 (run-hook-with-args-until-success
13752 'tinypgp-:do-command-region-after-hook
13755 ;; sometimes PGP need new randseed file, this generates it
13756 ;; and runs the command again.
13758 ;; WinNT: If PGP tries to ask for ranadseed, it hangs whole emacs.
13760 (when (and t ;enable for now..
13761 (not (ti::win32-p))
13762 (tinypgp-binary-command-region-fix cmd pointer-orig))
13765 ;; Arggh, When decrypting message in WinNT with 2.6.x The output
13766 ;; is not correct: there is extra "..." at the end of DATA.
13768 ;; Pass phase is good. Just a moment...DATA-DATA
13771 (when (ti::win32-p)
13773 (if (not (eq 0 (skip-chars-backward ".")))
13774 (delete-region (point) (line-end-position))))
13776 ;; Remove possible ^M chars
13777 (ti::buffer-lf-to-crlf 'dos2Unix 'force)))
13779 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... .. loop end ...
13781 ;;; (tinypgp-binary-insert-command-log)
13782 ;;; (pop-to-buffer (car pointer-orig)) (ti::d! 1234)
13784 (setq pointer (tinypgp-binary-handle-result status))
13786 ;; We kill these only after the results have been examined,
13787 ;; because user may want to check the contents if error happend.
13789 (tinypgp-file-control 'password-kill) ;Remove password file
13790 ;; (tinypgp-file-control 'source-kill)
13792 ;; For some reason PGP does not output final newline
13793 ;; after its TAGS. Check this and add it, otherwise replacing
13794 ;; the buffer content doesn't go right.
13797 (with-current-buffer (car pointer)
13798 (when (string= "---"
13800 (nth 1 pointer) (+ 3 (nth 1 pointer))))
13801 (goto-char (nth 2 pointer))
13802 (insert final-newline)
13804 (list (current-buffer)
13806 (1+ (nth 2 pointer)))))))
13809 (setq ret pointer))
13812 (delete-region beg end)
13813 (insert-buffer-substring
13814 (car pointer) (nth 1 pointer) (nth 2 pointer))
13820 ;;{{{ PGP public key 'find by'
13822 ;;; ..................................................... &pgp-key-get ...
13824 ;;; ----------------------------------------------------------------------
13826 (defun tinypgp-finger-discard-by-regexp (string-or-list)
13827 "Discards some email addresses from STRING-OR-LIST.
13828 See variable `tinypgp-:finger-discard-email-hook'"
13830 (tinypgpd "[tinypgp-:finger-discard-email-hook] in:"
13831 tinypgp-:finger-discard-by-regexp "#" string-or-list )
13833 (when string-or-list
13834 (if (not (stringp tinypgp-:finger-discard-by-regexp))
13835 (setq ret string-or-list)
13836 (dolist (x (ti::list-make string-or-list))
13837 (if (string-match tinypgp-:finger-discard-by-regexp x)
13838 (tinypgpd "[tinypgp-:finger-discard-email-hook doing]:" x )
13842 ;;; ----------------------------------------------------------------------
13844 (defun tinypgp-key-network-spawn (mode &optional arg1 arg2 verb)
13845 "Get key by fingering EMAIL.
13846 Examine the returned information and ask user help if there is more than
13852 ARG1 ARG2 if 'finger then arg1 is email
13853 if 'http then arg1 is host, arg2 is command
13854 VERB flag, verbose messages.
13858 string if only one public key
13859 (string) internal finger error string
13863 `tinypgp-:buffer-tmp-shell' ,results of finger
13864 `tinypgp-:last-network-error' ,if error happened."
13865 (let ((fid "tinypgp-key-network-spawn:")
13866 (buffer (tinypgp-ti::temp-buffer 'finger))
13867 (email arg1) ;if command is finger
13874 (tinypgpd fid "in:" mode arg1 arg2 verb)
13876 (setq tinypgp-:last-network-error nil)
13880 (setq stat (ti::process-finger email nil nil buffer verb)))
13882 (error "Wrong mode '%s' " mode)))
13886 (setq tinypgp-:last-network-error stat)
13887 (setq ret (list stat)))
13890 (ti::mail-pgp-trim-buffer) ;Remove garbage around keys.
13893 (ti::mail-pgpk-public-get-region nil nil buffer))
13895 (ti::mail-pgpk-public-get-region nil nil buffer 'relax)))
13900 ;; I don't think people undertand this mail very well,
13901 ;; they only know how to do -kxa and -kv, not -fkxa
13905 ;;; "Public key found, but not in full -fakx format "
13906 ;;; "Send email notice? "))
13907 ;;; (tinypgp-sendmail email 'pk-no-full-format))
13909 (setq len (length data))
13912 ((and (eq 1 len) ;only 1 public key found
13915 ;; P-key block must not me empty
13916 (setq ret (nth 1 (car data))))))
13920 (ti::read-char-safe-until
13921 "finger ok, but no Public key in his ~/.plan file.[press]")
13926 ;;; (ti::d! "FSTAT" stat (length data))
13927 (error "Multiple keys not implemented yet.")))))
13929 (tinypgpd fid email ret )
13932 ;;; ----------------------------------------------------------------------
13934 (defun tinypgp-key-finger-guess-email ()
13935 "Check Whole buffer for PGP email address.
13939 (let* ((set "[^ \t\n<=\"';:]+")
13940 (email-re (concat "\\(" set "@" set "\\)"))
13941 ;; finger ssjaaa@uta.fi | pgp -fka for pgp key
13943 (kaf-re "[ \t]*|[ \t]*pgp[ \t]+-\\(fka\\|kaf\\|afk\\|fak\\)")
13952 buffer-read-only ;Incoming message RMAIL
13955 ;; access-type=Finger; Address=foo@site.com;
13957 (setq list (tinypgp-xpgp-get-info))
13958 (setq email (assoc "address" list))))
13962 ;; If's faster first look for simple regexp, and match
13963 ;; it against complex regexp
13965 (re-search-forward kaf-re nil t)
13966 (setq line (ti::read-current-line))
13967 (string-match (concat email-re kaf-re) line)
13968 (setq email (ti::remove-properties (match-string 1 line)))))
13974 "public.*key.*@\\|@.*public.*key"
13976 ;; |Boudewijn Visser|E-mail:visser@ph.tn.tudelft.nl |finger for |
13977 ;; |University of Technology |PGP-key |
13979 "\\|@.*finger\\|finger.*@"
13981 ;; steve*windsong.demon.co.uk (for which PGP is preferred)
13983 "\\|@.*pgp.*prefered\\|pgp.*prefered.*@")
13985 (setq line (ti::read-current-line))
13986 (string-match email-re line)
13987 (setq email (ti::remove-properties (match-string 1 line)))))))
13989 (tinypgpd "tinypgp-key-finger-guess-email out:" email )
13993 ;;; ----------------------------------------------------------------------
13995 (defun tinypgp-key-finger-add (email &optional no-ask)
13996 "Ask where to store the public key for EMAIL; optionally NO-ASK.
14001 (let ((finger-buffer tinypgp-:buffer-tmp-finger)
14005 ;; Put into temporary keyring ... #todo
14006 (error "Not supported no-ask"))
14009 (tinypgp-pubring-alias2file
14010 (tinypgp-pubring-complete
14012 "%s: Store the public key to pubring[empty=cancel]: "
14013 (or (car-safe (ti::mail-email-from-string email))
14014 (ti::string-left email 20))))))
14015 (if (ti::nil-p ans)
14017 ;; #todo, should add the key to keyring.
14019 (with-current-buffer finger-buffer
14020 ;; (tinypgp-key-add-region-interactive)
14021 (tinypgp-key-add-region-batch (point-min) (point-max)))
14022 ;;; (ti::d! "Cacheing finger>>" ans)
14024 (tinypgp-key-cache 'put email ans))))
14027 ;;; ----------------------------------------------------------------------
14029 (defun tinypgp-key-find-by-finger-verbose (email-list)
14030 "EMAIL-LIST. See `tinypgp-key-find-by-finger'."
14031 (tinypgp-key-find-by-finger email-list nil 'verb))
14033 ;;; ----------------------------------------------------------------------
14035 (defun tinypgp-key-find-by-finger (&optional email-list no-ask verb)
14036 "Find a PGP key using finger.
14038 The exact references searched are like:
14040 finger foo@site.com for pgp public key
14041 finger foo@site.com | pgp -fka
14044 If finger fails then user is offered a list of all email
14045 addresses and each one selected is fingered.
14048 EMAIL-LIST ,if this is given, then do not search
14049 current buffer for email addresses.
14050 All entries that do not contain @ are filtered out.
14051 This can be string list or single string
14052 NO-ASK ,store all fingered keys without asking
14053 to current keyring.
14054 VERB ,enable verbose messages
14057 string ,pgp publick key block
14060 (tinypgpd "tinypgp-key-find-by-finger in:")
14069 ;; ... ... ... ... ... ... ... ... ... ... ... exact match search ...
14072 (setq list (ti::list-make email-list))
14074 ;; ... ... ... ... ... ... ... ... ... ... ... .. list not given . .
14075 (setq email (tinypgp-key-finger-guess-email)
14076 email (tinypgp-email-discard-default list)
14077 email (tinypgp-finger-email-filter email))
14079 (if (ti::listp email)
14080 (setq email (car email)))
14082 (when email ;Try adding the exact match
14083 (setq ret (tinypgp-key-network-spawn 'finger email nil verb)))
14086 (setq ret (tinypgp-key-finger-add email))
14088 (tinypgp-email-find-region
14090 ;; For large buffers, look only the start
14091 ;; of buffer. The point-min offset is
14092 ;; needed because buffer may be narrowed (RMAIL)
14094 (if (> (point-max) (+ (point-min) 1000))
14095 (+ (point-min) 1000)
14098 (if (and list tinypgp-:finger-discard-email-hook)
14099 (setq list (run-hook-with-args-until-success
14100 'tinypgp-:finger-discard-email-hook list)))
14103 (setq list (tinypgp-email-discard-default list))
14104 (setq email (car-safe list)))
14106 ;; ... ... ... ... ... ... ... ... ... ... ... ... . loop-finger . .
14108 (not (stringp ret))
14109 (not (ti::nil-p email)))
14111 (when (null no-ask)
14115 (format "%sFinger [e(x)it, !, empty=skip]: "
14116 (if (> (length list) 1)
14117 (format "%d: " (length list)) ""))
14118 (ti::list-to-assoc-menu list) nil nil email))
14132 (setq email ans))))
14134 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... results ...
14136 (when (not (ti::nil-p email))
14137 (setq stat (tinypgp-key-network-spawn 'finger email nil t))
14140 ((and (ti::listp stat) verb)
14141 (message (format "[press]Finger internal error: %s" (car stat)))
14148 (message "Fingered PGP key found."))))
14150 (setq list (delete email list)))
14152 ;; ................................................ go to next ...
14153 (unless ret ;not found yet?
14155 (setq list (delete email list)))
14156 (setq email (car list)
14160 (tinypgp-key-finger-add email no-ask))
14162 (tinypgpd "tinypgp-key-find-by-finger out:" ret )
14166 ;;; ----------------------------------------------------------------------
14168 (defun tinypgp-key-http-study-buffer (&optional buffer)
14169 "Search public key from HTTP keyserver request result BUFFER."
14171 (tinypgpd "tinypgp-key-http-study-buffer in: " buffer (current-buffer))
14172 (with-current-buffer buffer
14173 (ti::mail-pgp-trim-buffer))))
14175 ;;; ----------------------------------------------------------------------
14177 (defun tinypgp-key-find-by-http-url-verbose (&rest args) ;Called from hook
14178 "Call `tinypgp-key-find-by-http-url' interactively."
14179 (call-interactively 'tinypgp-key-find-by-http-url))
14181 ;;; ----------------------------------------------------------------------
14183 (defun tinypgp-key-find-by-http-url (url &optional verb)
14184 "Send http request and try to read key from URL page. VERB.
14186 Interactive call note:
14188 This function searches only X-Pgp field for possible key location
14189 pointer in format Access-type=URL; URL=http://me.org/~me/pgp.html"
14191 (list (tinypgp-xpgp-key-address
14193 "(http) X-Pgp information is not present.")))
14195 (let* ((fid "tinypgp-key-find-by-http-url: ")
14196 (buffer (tinypgp-ti::temp-buffer 'http))
14197 (obuffer (current-buffer))
14198 (win-count (length (ti::window-list)))
14203 (tinypgpd fid "URL" url "VERB" verb)
14205 (when (stringp url)
14206 (setq stat (ti::process-http-request url nil nil buffer verb)))
14208 (tinypgpd fid "STAT" stat buffer)
14213 (message "Http internal error: %s" stat)
14217 ((bufferp (setq stat (car stat)))
14218 (pop-to-buffer stat)
14223 ((ti::mail-pgp-public-key-p (point-min))
14225 (call-interactively 'tinypgp-key-add-region-batch)
14226 (tinypgp-key-add-region-batch (point-min) (point-max))))))
14228 ;; See tinypgp-key-add-region-batch documentation
14230 (setq ret tinypgp-:return-value)
14232 ;; If user had only 1 window visible, make this 'new' buffer
14233 ;; small. But if he had more windows, don't shrink the
14234 ;; just shown buffer (it shocks if your window settings are
14237 (when (eq win-count 1)
14238 (shrink-window-if-larger-than-buffer))
14240 ;; Keep cursor in the original buffer
14242 (pop-to-buffer obuffer)
14245 (message "Http request didn't find public key."))))) ;cond end
14248 ;;; ----------------------------------------------------------------------
14250 (defun tinypgp-key-find-by-http-keyserver-i-args (&optional string)
14251 "Ask args for function `tinypgp-key-find-by-http-keyserver'.
14252 If STRING is already know then do not ask for it.
14256 (let* ((fid "tinypgp-key-find-by-http-keyserver: ")
14257 (dummy (tinypgpd fid "in: "))
14259 (to-field (if buffer-read-only ;; RMAIL VM
14260 (mail-fetch-field "from")
14261 (mail-fetch-field "to"))) ;; mail buffer
14263 (line-end-position (or (ti::mail-hmax) (point-max)))
14265 (elist (tinypgp-email-find-region
14268 ;; Search up till character limit 3000
14269 (if (> line-end-position (+ (point-min) 3000))
14270 (+ (point-min)3000) line-end-position)))
14271 (key-id (tinypgp-key-id-find))
14276 (if dummy (setq dummy t)) ;No-op, byte-comp silencer.
14278 (tinypgpd fid to-field key-id elist
14279 (current-buffer) (point-min) line-end-position)
14282 (setq to-field (car (ti::mail-email-from-string to-field))))
14284 (if (setq elt (tinypgp-ask-http-keyserver))
14285 (setq srv (nth 0 elt)
14287 (error "Internal.")) ;should not happen
14289 (if key-id ;Add this to completion list too
14290 (push key-id elist))
14295 "Search string, no spaces: "
14296 (ti::list-to-assoc-menu elist) nil nil
14299 (ti::remove-properties
14300 (or to-field (ti::buffer-read-space-word))))
14301 'tinypgp-:history-http-keyserver-string)))
14302 (list srv cmd string)))
14304 ;;; ----------------------------------------------------------------------
14306 (defun tinypgp-key-find-by-http-keyserver-verbose (string)
14307 "See `tinypgp-key-find-by-http-keyserver'. STRING."
14308 (let ((a (tinypgp-key-find-by-http-keyserver-i-args string)))
14309 (tinypgp-key-find-by-http-keyserver (nth 0 a) (nth 1 a) string 'verb)))
14311 ;;; ----------------------------------------------------------------------
14313 (defun tinypgp-key-find-by-http-keyserver
14314 (server command string &optional verb)
14315 "Send http request to keyserver to get a key.
14319 All email addresses are read from `point-min' to end of
14320 current line where your cursor sits. The default search string
14321 offered is read from the To field but you can delete the prompt
14322 and enter other found email addresses via Tab completion.
14326 Please understand that waiting for a HTTP response may be painfully
14327 slow many times. If you can, prefer the finger and instruct
14328 poeople to include their publick key information in the
14329 $HOME/.plan file in full -fkax format.
14334 COMMAND command to run in server
14335 STRING the search string without spaces. If this parameter is nil
14336 or contains spaces, thi function returns immediately.
14337 VERB Verbose messages.
14341 keyring If htttp call succeeded and key was inserted to some keyring
14342 nil no keys added or found"
14343 (interactive (tinypgp-key-find-by-http-keyserver-i-args))
14344 (tinypgpd "tinypgp-key-find-by-http-keyserver in: " string )
14346 (unless (ti::nil-p string)
14347 (let* ((cmd (format (concat "http://%s" command) server string)))
14349 (tinypgpd "tinypgp-key-find-by-http-keyserver cmd: " cmd)
14350 (tinypgp-key-find-by-http-url cmd verb))))
14352 ;;; ----------------------------------------------------------------------
14354 (defun tinypgp-key-find-by-http-guess ()
14355 "Select X-pgp URL if it exists or suggest keyserver search.
14356 This function is stricly for interactive use."
14358 (let* ((url (tinypgp-xpgp-key-address 'http))
14362 (setq tried (y-or-n-p "X-Pgp key url found; obey it ")))
14363 (setq ret (tinypgp-key-find-by-http-url url 'verb)))
14368 (message "No luck, Inform person about possible defective X-URL")
14371 (setq ret (call-interactively 'tinypgp-key-find-by-http-keyserver)))))
14374 ;;; ----------------------------------------------------------------------
14376 (defun tinypgp-key-find-by-email (email-srv string)
14377 "Send email to nearest Public key mail service to get the Key.
14378 Notice that this sends _mail_ and doesn't return any values.
14380 This function should not be put into any key find nook, but
14381 called by user with clear intention to find key as last resort.
14384 EMAIL-SRV full string placed in To: field where to send the
14386 STRING what to request from the server normally
14387 \"FirstName Surname\""
14391 (setq srv (tinypgp-ask-email-keyserver))
14394 (read-from-minibuffer "Search string [firstname surname]: "))
14395 (list srv string)))
14397 ;; ... ... ... ... ... ... ... ... ... ... ... ... .. function start . .
14400 (if (or (ti::nil-p email-srv)
14402 (not (string-match "@" email-srv)))
14403 (error "Invalid arguments."))
14405 (setq cmd (format "GET %s" string))
14407 (ti::mail-sendmail-macro email-srv cmd 'send
14408 (insert cmd "\n"))))
14410 ;;; ----------------------------------------------------------------------
14411 ;;; - We don't make this a macro! It could be installed into hooks...
14413 (defun tinypgp-key-find-by-cache (string &optional who)
14414 "Check cache for STRING.
14417 STRING string to find
14418 WHO who calls this function (for debug purposes)
14423 (tinypgpd "tinypgp-key-find-by-cache: " string who)
14424 (if (stringp string)
14425 (tinypgp-key-cache 'get string)))
14427 ;;; ----------------------------------------------------------------------
14429 (defsubst tinypgp-key-cache-update (&optional user)
14430 "Update cache with current USER/pubring parameters."
14431 (setq user (or user tinypgp-:user-now))
14433 (tinypgpd "tinypgp-key-cache-update: " user tinypgp-:pubring-now )
14435 ;; The USER must at least contain 3 character, it's no use to
14436 ;; cache 2 character user, because that may be a bug in program
14438 (if (> (length user) 2)
14439 (tinypgp-key-cache 'put user tinypgp-:pubring-now)
14440 (error "TinyPgp: cache update internal error %s" user)))
14442 ;;; ----------------------------------------------------------------------
14444 (defun tinypgp-key-find-by-keyrings-1 (string-or-list)
14445 "Search all keyrings and cache.
14448 STRING-OR-LIST string or list of search strings, first one found
14452 (string . keyring) STRING is the one in string-or-list that was found
14455 (let* ((tinypgp-:pubring-now tinypgp-:pubring-now)
14456 (fid "tinypgp-key-find-by-keyrings-1:")
14461 (tinypgpd fid "in:" string-or-list)
14462 (setq string-or-list (ti::list-make string-or-list))
14464 (dolist (search-string string-or-list) ;; #todo: Can't use dolist/2 loop
14465 (setq list (tinypgp-pubring-list))
14467 (tinypgp-save-state-macro
14468 (with-current-buffer (tinypgp-ti::temp-buffer 'shell)
14469 (dolist (kring list) ;; #todo: Can't use dolist/2 loop
14470 (if (not (file-exists-p kring))
14472 Check tinypgp-:pubring-table/Config error, no exist '%s'" kring))
14474 (setq tinypgp-:pubring-now kring) ;Search this
14476 (when (tinypgp-key-info-insert search-string)
14477 ;; That's it, stop the loop by setting list to nil
14478 (setq ret (cons search-string kring)
14479 string-or-list nil ;Stop loop 1
14480 list nil) ;Stop loop 2
14481 (tinypgp-key-cache 'put search-string kring))))))
14482 (tinypgpd fid "out:" search-string kring ret)
14485 ;;; ----------------------------------------------------------------------
14487 (defun tinypgp-key-find-by-keyrings-verbose (string)
14488 "See `tinypgp-key-find-by-keyrings'. STRING."
14489 (tinypgp-key-find-by-keyrings string 'verb))
14491 (defun tinypgp-key-find-by-keyrings (string &optional verb)
14492 "Try all available keyrings and try to find the public key.
14493 If pubring file searched does not exist, signal error.
14497 STRING ,search string
14498 VERB ,if non-nil, then ask for search string if STRING search fails.
14502 This function caches the pubring and string information
14503 The cache is always looked first, before doing any outside search.
14507 `tinypgp-:return-value' and property 'find-by-keyrings
14509 If you call this function with argument VERB
14510 user can change the search STRING. if the user's string is found
14511 from the keyrings then the original STRING is changed. The
14512 property has value nil if STRING is original or
14513 it has the user's input value if that match was found.
14515 You need the information if you try to encrypt with key
14516 xxx@foo.site.com and user changes it to 'doodle'. Then if
14517 'doodle' is found, you should use that for encryption and not
14518 the original xxx@foo.site.com
14522 string public keyring
14524 (let ((fid "tinypgp-key-find-by-keyrings:")
14528 (tinypgpd "tinypgp-key-find-by-keyrings in:" string )
14529 (put 'tinypgp-:return-value 'find-by-keyrings nil)
14531 (while (and loop (null ret))
14532 (setq loop nil) ;User sets this 't' if retry
14534 (or (setq ret (tinypgp-key-find-by-keyrings-1 string))
14539 Hm, Consider using tinypgp-email-substitution-add in tinypgp rc file: TO hdr")
14546 "[%s] No keyring, try another string? : "
14548 (ti::list-to-assoc-menu (tinypgp-email-make-choices string))))
14549 (if (ti::nil-p string) ;RET pressed --> ""
14552 (tinypgpd fid "RETRY" string)
14553 (setq ret (tinypgp-key-find-by-keyrings-1 string)))))))
14555 ;; tinypgp-key-find-by-keyrings-1 return cons cell
14557 (when (ti::listp ret)
14558 (put 'tinypgp-:return-value 'find-by-keyrings (car ret))
14559 (setq ret (cdr ret)))
14561 ;;; (ti::d! "fbk" (get 'tinypgp-:return-value 'find-by-keyrings))
14562 (tinypgpd "tinypgp-key-find-by-keyrings out:" string ret )
14565 ;;; ----------------------------------------------------------------------
14567 (defun tinypgp-key-find-by-guess (string &optional verb)
14568 "Try to determine where to get the Public key-id STRING.
14569 For best results, the STRING should be in 0xFFFFF format to
14570 uniquely match single person. Second best choice is full email address.
14571 VERB activates verbose messages.
14573 The order of search depends on the variable:
14575 `tinypgp-:find-by-guess-hook'
14577 Which is list of functions."
14580 (ti::string-remove-whitespace
14581 (read-from-minibuffer
14583 (ti::string-remove-whitespace
14584 (or (ti::mail-get-field "from" nil 'null-mode)
14585 (ti::mail-get-field "to" nil 'null-mode)))))))
14586 (let* ((fid "tinypgp-key-find-by-guess:")
14589 (if (ti::nil-p string) (error "Invalid arg"))
14591 ;; Is there substitution for this ?
14593 (setq ret (car-safe (tinypgp-key-id-conversion string)))
14594 (tinypgpd fid "in: STRING" string "key-subst" ret verb)
14596 (if ret (setq string ret))
14598 (tinypgpd fid "RUN HOOKS" tinypgp-:find-by-guess-hook)
14600 (setq ret (run-hook-with-args-until-success
14601 'tinypgp-:find-by-guess-hook string))
14603 (if ret (tinypgp-key-cache 'put string ret))
14608 ;; maybe the previous call cached they KEY whose indicator "k"
14609 ;; is not shown in modeline. Show "k" now
14611 (tinypgp-update-modeline)
14612 (message "TinyPgp Guess found: [%s] keyring %s"
14614 (file-name-nondirectory ret)))
14616 (message "TinyPgp Guess failure: (maybe converted) %s" string))))
14620 ;;{{{ PGP key management
14622 ;;; ......................................................... &pgp-key ...
14624 ;;; ----------------------------------------------------------------------
14626 (defun tinypgp-key-ring-at-point (&optional alias)
14627 "See if there is keyring by looking backward.
14628 First empty line terminates search. Eg.
14630 Key ring: '/users/jaalto/.pgp/pubring.pgp', looking for
14631 user ID \"foo@site.com\".
14632 Type Bits/KeyID Date User ID
14633 pub 1024/20378F71 1995/08/19 Mr. foo <foo@site.com>
14636 ALIAS ,flag, return keyring alias name"
14640 ;; move away from empty line
14642 (if (looking-at "^[ \t]*$")
14645 (while (and (not (bobp))
14646 (not (looking-at "^[ \t]*$"))
14648 (if (looking-at ".*Key ring:[ \t]+'\\([^']+\\)")
14649 (setq ret (match-string 1)))
14650 (forward-line -1)))
14653 (setq ret (tinypgp-pubring-file2alias ret)))
14657 ;;; ----------------------------------------------------------------------
14659 (defsubst tinypgp-key-trust-ask (&optional id)
14660 "Ask trust parameter. If user gives empty line, 'undefined' is returned.
14664 (format "%s%strust parameter? " (or id "") (if id " " ""))
14665 (ti::list-to-assoc-menu
14666 '("undefined" "untrusted" "marginal" "complete"))
14669 (if (ti::nil-p ans)
14673 ;;; ----------------------------------------------------------------------
14675 (defun tinypgp-key-info-insert-current-user ()
14676 "Insert current user's key information to point.
14677 The current pubring is set temporarily to first
14678 entry in `tinypgp-pubring-table'."
14679 (tinypgp-save-state-macro
14680 (setq tinypgp-:pubring-now (nth 1 (car (tinypgp-pubring-table))))
14681 (tinypgp-key-info-insert tinypgp-:user-now 'verb)))
14683 ;;; ----------------------------------------------------------------------
14685 (defun tinypgp-key-info-insert (string &optional verb)
14686 "Run pgp -kvc to get key information matching the STRING.
14687 Insert the content to current point. VERB allows verbose messages.
14690 `tinypgp-:buffer-tmp-shell'
14693 t something inserted
14694 nil error condition"
14697 (read-from-minibuffer
14698 (format "insert key matching [pubring: '%s']: "
14699 (or (tinypgp-pubring-file2alias tinypgp-:pubring-now)
14702 (barf-if-buffer-read-only)
14703 (tinypgpd "tinypgp-key-info-insert in: " string verb )
14705 (let* ((bcmd (tinypgp-binary-get-cmd 'key-info)) ;;base command
14706 (cmd (tinypgp-cmd-compose bcmd nil nil '(nil)))
14707 (fid "tinypgp-key-info-insert: ")
14715 ((and (string-match "[ \t]" string) (ti::win32-p))
14716 (error "STRING must not contain whitespace in WInNT"))
14718 (setq string (format "\"%s\"" string))))
14720 (tinypgp-do-shell-env
14721 (with-current-buffer (setq buffer (tinypgp-ti::temp-buffer 'shell))
14722 (setq shell-cmd (format "%s %s" cmd string))
14723 (tinypgpd fid "run: " shell-cmd)
14724 (shell-command shell-cmd buffer)
14725 ;; (pop-to-buffer (current-buffer)) (ti::d! "::key" string)
14729 ((re-search-forward "0 matching keys found\\." nil t)
14731 (message "0 matching keys found.")))
14736 (insert-buffer buffer))
14738 (tinypgpd fid "out: " ret )
14742 ;;; ----------------------------------------------------------------------
14744 (defun tinypgp-key-info-at-point-show (string &optional pubring-list)
14745 "Find match using STRING from current keyring or PUBRING-LIST.
14746 When called interactively, read space-separated-word
14747 under point and find matches from current keyring and
14748 show them in temporary buffer."
14752 (read-from-minibuffer
14753 "Display key info matching: "
14754 (if (null (setq str (ti::buffer-read-word "-0-9a-zA-Z@.")))
14756 ;; If underlying word is Key-id 12345678, then
14757 ;; prepend 0x to it because that is only valid search string
14759 (if (and (eq (length str) 8)
14760 (string-match "^[0-9A-Z]+$" str))
14762 (ti::string-left str 35)))
14765 'tinypgp-:history-key-info))
14766 (list str (tinypgp-pubring-list))))
14768 (let ((tmp (tinypgp-ti::temp-buffer 'show)))
14769 (if (not (stringp string))
14770 (error "Arg error")
14772 (with-current-buffer tmp
14773 (tinypgp-save-state-macro
14774 (dolist (elt pubring-list)
14775 (setq tinypgp-:pubring-now elt)
14777 (insert "\n" elt ":")
14779 (beginning-of-line)
14780 (if (looking-at "^.*/\\(.*:\\)")
14781 (tinypgp-highlight 'match 1))
14782 (end-of-line) (insert "\n")
14784 (tinypgp-key-info-insert string)
14786 (pop-to-buffer tmp)
14789 ;;; ----------------------------------------------------------------------
14791 (defun tinypgp-key-add-region-batch (beg end &optional noerr verb)
14792 "Add all public keys in region to active keyring.
14793 The region is handled by PGP directly. No checkings are done here.
14798 NOERR if nil, then signal error if PGP reports error.
14799 VERB allow verbose messages
14803 The region is cecked for public key. If none exist offer using
14807 `tinypgp-:return-value' pubring where the key was inserted
14812 nil no keys were added"
14816 (ti::compat-activate-region) ;Make sure user sees region
14817 ;; Check this before going further
14818 (if (null (ti::mail-pgp-public-key-p (point-min)))
14819 (error "No public key area in buffer"))
14820 (ti::i-macro-region-ask
14821 "No region selected, use whole buffer for key insert? ")))
14823 (tinypgpd "tinypgp-key-add-region-batch in: pring"
14824 tinypgp-:pubring-now (current-buffer) )
14826 (let* ((tinypgp-:pubring-now tinypgp-:pubring-now) ;make local copy
14827 (logical-cmd 'key-add)
14828 (bcmd (tinypgp-binary-get-cmd logical-cmd)) ;;base command
14829 (copy (tinypgp-ti::temp-buffer))
14830 (buffer (tinypgp-ti::temp-buffer 'shell))
14837 (tinypgpd "tinypgp-key-add-region-batch in:"
14838 (current-buffer) beg end bcmd cmd )
14840 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . verbose part ..
14841 ;; Many times there may be old region active and user doesn't
14842 ;; realize that,. Do little check first...
14845 (when (and (not (ti::narrow-safe beg end
14846 (ti::mail-pgp-public-key-p (point-min))))
14849 "Can't find public key block in region.. "
14850 "Use full buffer [C-g to abort]")))
14851 (setq beg (point-min) end (point-max)))
14853 (if (setq pring (tinypgp-pubring-ask))
14854 (setq tinypgp-:pubring-now pring)))
14856 ;; Only now can we compose the command: pubring is known or
14859 (setq tinypgp-:return-value tinypgp-:pubring-now)
14860 (setq cmd (tinypgp-cmd-compose bcmd nil nil '(nil)))
14862 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. do it ..
14863 (tinypgp-do-shell-env
14864 (save-window-excursion
14865 (append-to-buffer copy beg end)
14866 (append-to-buffer buffer beg end)
14867 (with-current-buffer buffer
14868 ;;; (pop-to-buffer (current-buffer)) (ti::d! 12345)
14869 ;; Remove spaces: "intended PGP key", but only if there is
14870 ;; only one key. Ignore "chop" if there is multiple keys.
14873 (while (re-search-forward (ti::mail-pgp-pkey-begin-line) nil t) (incf i))
14874 (if (eq 1 i) (ti::mail-pgp-chop-region (point-min) (point-max)))
14876 ;; If there is error situation, the "after" hook runs.
14877 (tinypgp-mode-specific-control-before logical-cmd)
14879 (shell-command-on-region ;This shows the buffer, gawk!
14880 (point-min) (point-max) (format "%s " cmd) buffer))))
14882 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. results ..
14883 (setq ret (tinypgp-binary-get-result-key-add))
14884 (when (and verb ret)
14885 (message "Key add note: %s" ret))
14887 (when (and (stringp ret)
14888 (string-match "error" ret))
14891 (tinypgp-error ret)))
14893 (when (and (stringp ret)
14894 (string-match "No keys found" ret))
14899 ;;; ----------------------------------------------------------------------
14901 (defun tinypgp-key-add-region-interactive (beg end)
14902 "Parse BEG END and ask if key should be added to the active keyring."
14903 (interactive (ti::i-macro-region-ask))
14904 (tinypgpd "tinypgp-key-add-region-interactive in: pring"
14905 tinypgp-:pubring-now (current-buffer) beg end )
14906 (let ((data (ti::mail-pgpk-public-get-region
14907 nil nil tinypgp-:buffer-tmp-shell))
14908 (verb (interactive-p))
14913 (tinypgp-unfinished-function)
14918 "'Key for user ID:' tags not found to signify public key blocks.")))
14921 (setq id (nth 0 elt) pkey (nth 1 elt))
14924 (ti::read-char-safe
14925 (format "Public key empty: %s" (or id "<id not known>"))))
14927 ((y-or-n-p (format"Add: %s" id))
14928 ;;; (setq trust (tinypgp-key-trust-ask id))
14929 (with-current-buffer (tinypgp-ti::temp-buffer)
14931 (tinypgp-key-add-region-batch (point-min) (point-max))
14932 (error "#todo trust not set."))))))
14934 )));;; ----------------------------------------------------------------------
14935 ;;; Called by TM.el
14937 (defun tinypgp-key-extract-to-point-current-user ()
14938 "Extract `tinypgp-:user-now' key to current point."
14939 (tinypgp-key-extract-to-point tinypgp-:user-now))
14941 ;;; ----------------------------------------------------------------------
14943 (defun tinypgp-key-extract-to-point (string &optional raw noerr)
14944 "Insert public key matching STRING to current point.
14948 If Pgp extracts file to some temporary file, that file will be deleted
14949 automatically, because the key will be available from emacs buffer.
14950 This prevents temporary files accumulating in your tmp directory.
14951 Also the line that containbs sentence
14953 Key extracted to file '/users/xxx/junk/pgptemp.$07'.
14955 is removed from the shell output buffer before yanking.
14959 `tinypgp-:buffer-tmp-shell'
14963 STRING string to search
14964 RAW only insert the PGP block
14965 NOERR if non-nil no error is signalled is string is not found,
14966 also the output is _not_ inserted to the current point,
14975 (read-from-minibuffer "Insert public key matching: " tinypgp-:user-now)
14976 current-prefix-arg))
14978 (barf-if-buffer-read-only)
14979 (tinypgpd "tinypgp-key-extract-to-point in: pring" tinypgp-:pubring-now )
14980 (let* ((fid "tinypgp-key-extract-to-point:")
14981 (bcmd (tinypgp-binary-get-cmd 'key-extract))
14982 (out (tinypgp-ti::temp-buffer 'shell))
14988 (tinypgpd fid "in:" (current-buffer) string noerr )
14990 (unless (setq kring (tinypgp-key-find-by-keyrings string))
14991 (error "No PGP key for '%s'" string))
14993 (tinypgpd fid "cmd,out,kring" cmd out kring )
14995 (tinypgp-save-state-macro
14996 (setq tinypgp-:pubring-now kring)
14997 (setq cmd (tinypgp-cmd-compose bcmd nil nil '(nil)))
14998 (setq cmd (format "%s '%s'" cmd string)))
15000 (tinypgp-do-shell-env (shell-command cmd out))
15002 (with-current-buffer out
15004 (when (and (null (setq ret (ti::mail-pgp-pkey-read raw 'kill-file)))
15006 ;; Remove cache entry, maybe user has moved the key
15007 ;; to another keyring?
15009 (tinypgp-key-cache-remove-entry string)
15010 (pop-to-buffer out)
15012 PGP error; Maybe cache has old keyring information? Check cache.")))
15018 (tinypgpd fid "out:" ret )
15022 ;;; ----------------------------------------------------------------------
15024 (defun tinypgp-key-delete-region (beg end &optional mode plist verb)
15025 "Remove all keys from keyring that are found from region.
15026 The picked key items are:
15027 o all email addresses
15028 o All regular pgp key lines \"pub 512/47141D35 1996/06/03 ...\"
15030 In interactive or verb mode, all removed KeyId's used are marked
15031 with overlays after command completes. Overlays have property '(owner tinypgp)
15035 MODE nil = key id 0x based deletion
15036 1 or 'email = key id email based deletion
15037 2 or 'any = both methods used.
15038 PLIST list of pubring filenames to touch.
15040 all public keyring are stepped through;
15041 permission to use the pubring is asked from user.
15043 If this list oi nil, active pubring is used
15044 VERB Enable verbose asking/message mode.
15046 If VERB is non-nil, error is generated if it happens. if VERB is nil,
15047 then the possible error string is returned."
15049 (let* ((plist (list tinypgp-:pubring-now))
15050 (kring (or (tinypgp-key-ring-at-point 'alias)
15051 (tinypgp-pubring-file2alias tinypgp-:pubring-now)))
15054 (if (not (region-active-p))
15055 (error "Region not selected.")
15056 (setq reg (ti::i-macro-region-ask)))
15060 (tinypgp-pubring-complete
15063 "%sDel keys from all prings or one ring? "
15066 ((eq 1 current-prefix-arg) "@: ")
15067 ((eq 2 current-prefix-arg) "0x@: ")
15068 ((eq nil current-prefix-arg) "0x: ")
15070 (error "No such prefix arg mode"))))
15073 (if (not (ti::nil-p ans))
15074 (setq plist (list (tinypgp-pubring-alias2file ans)))
15075 (setq plist (tinypgp-pubring-list)))
15078 (nth 0 reg) (nth 1 reg)
15082 (tinypgpd "tinypgp-key-delete-region in: " beg end mode plist verb )
15083 (let* ((buffer-orig (current-buffer))
15084 (BCMD (tinypgp-binary-get-cmd 'key-delete)) ;base command
15090 list1 list2 email-list keyid-list
15096 ;; #todo: use comint to delete keys ?
15098 ;;; (error "PGP can't use batch mode...needs new implementation.")
15100 (tinypgpd "tinypgp-key-delete-region in: BCMD " BCMD)
15101 (if (null plist) ;Set default value
15102 (setq plist tinypgp-:pubring-now))
15104 (setq plist (ti::list-make plist)) ;make sure it is list
15108 "TinyPgp: are you sure about this (region right)? ")))
15109 (error "Aborted."))
15111 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... ... narrow ...
15112 ;; We narrow so that highlighting finds right matches
15114 (ti::narrow-safe beg end
15115 (tinypgp-run-in-tmp-buffer nil
15116 (cond ;Gather key-ids first
15117 ((memq mode '(nil 2 any))
15119 (ti::mail-pgpk-id-0x-lines-in-region (point-min) (point-max))))
15120 ((memq mode '(1 email))
15121 (setq email-list (tinypgp-email-find-region (point-min) (point-max))))
15123 (error "Unknown mode %s" mode))))
15125 (and verb (tinypgp-highlight 'delete-all))
15127 (tinypgp-do-shell-env
15128 (tinypgp-save-state-macro
15129 (setq buffer (tinypgp-ti::temp-buffer)
15130 buffer-shell (tinypgp-ti::temp-buffer 'shell))
15131 (with-current-buffer buffer
15132 (dolist (pring plist)
15134 (setq tinypgp-:pubring-now pring)
15135 (setq list1 email-list list2 keyid-list)
15137 (tinypgpd "email-list" list1 "keyid-list" list2)
15139 ;; ... ... ... ... ... ... ... ... ... ... ... . user-ask ..
15141 (not (string= "!" (or permission ""))))
15143 (read-from-minibuffer
15147 "[ret=ok, !=all, s=skip]: ")
15148 (file-name-nondirectory pring)))))
15150 ;; ... ... ... ... ... ... ... ... ... ... user-response ..
15152 (member permission '("!" ""))
15155 (setq elt nil elt2 nil)
15156 (setq bcmd (tinypgp-cmd-compose BCMD nil nil '(nil)))
15157 ;; ... ... ... ... ... ... ... ... ... ... ... .. email ..
15159 (setq elt (pop list1))
15161 (setq cmd (format "%s '%s'" bcmd elt))
15162 (shell-command cmd buffer-shell)
15163 (tinypgpd "tinypgp-key-delete-region shell: " cmd )
15164 (incf delete-count)
15166 ;; "Key not found in keyring"
15167 ;; But that's no error and we don't report it.
15169 (setq err1 (tinypgp-binary-check-error 'ignore-output cmd))
15170 (when (and verb err1) (tinypgp-error err1))))
15172 ;; ... ... ... ... ... ... ... ... ... ... ... ... . 0x ..
15174 (setq elt2 (pop list2))
15175 (when (stringp elt2)
15176 (setq cmd (format "%s '0x%s'" bcmd elt2))
15177 (shell-command cmd buffer-shell)
15178 (incf delete-count)
15179 (tinypgpd "tinypgp-key-delete-region shell: " cmd )
15180 (setq err1 (tinypgp-binary-check-error 'ignore-output cmd))
15181 (when (and verb err2) (tinypgp-error err2))))
15183 (tinypgpd "tinypgp-key-delete-region do: " pring
15184 elt elt2 err1 err2 )
15186 ;; Highlight the line so that user sees it was processed.
15188 (if (and verb (or elt elt2))
15189 (with-current-buffer buffer-orig
15190 (if elt (tinypgp-highlight elt))
15191 (if elt2 (tinypgp-highlight elt2 nil nil 'region))))))))
15193 )) ;; ... ... ... ... ... ... ... ... ... ... ... ... ... ... message ...
15194 (when (and verb (null err))
15196 ((zerop delete-count)
15197 (message "TinyPgp: Hm. It appears that no keys were found to delete."))
15199 (message "TinyPgp: Deleted keys have been marked with color. [%d]"
15203 (setq err (tinypgp-binary-get-result-key-remove buffer-shell)))
15204 (pop-to-buffer buffer-shell)
15205 (error "TinyPgp: Key remove problem; remove manually "))
15209 ;;; ----------------------------------------------------------------------
15211 (defun tinypgp-key-sign-1 (your-keyid her-keyid &optional noerr)
15212 "Sign key-id to current pubring.
15215 YOUR-KEYID HER-KEYID NOERR"
15216 (tinypgpd "tinypgp-key-sign-1 in: " your-keyid her-keyid noerr )
15217 (let* ((BCMD (tinypgp-binary-get-cmd 'key-sign)) ;base command
15218 (bcmd (tinypgp-cmd-compose BCMD nil nil '(nil)))
15219 (buffer-shell (tinypgp-ti::temp-buffer 'shell))
15222 (tinypgp-unfinished-function)
15223 (setq cmd (format "%s %s" bcmd your-keyid her-keyid))
15224 (error "#todo") (ti::d! (ti::string-right cmd 50))
15225 (shell-command cmd buffer-shell)
15227 ;; #todo: check results of signing
15229 (if (setq stat (tinypgp-binary-get-result-key-sign))
15232 ;;; ----------------------------------------------------------------------
15234 (defun tinypgp-key-sign-0x-forward (&optional verb)
15235 "Sign current 0x key forward. VERB.
15236 The lines must contain valid key info entry extracted from pubring."
15241 (tinypgpd "tinypgp-key-sign-0x-forward in:")
15244 (when (and (ti::mail-pgp-re-search 'kpub)
15245 (setq keyid (match-string 1)))
15246 (setq line (buffer-substring (match-end 0) (line-end-position)))
15248 (if (or (null verb)
15251 (format "Sign key %s , %s: " line keyid ))))
15252 (tinypgp-save-state-macro
15253 (tinypgp-user-in-use-confirm
15254 (tinypgp-key-sign-1 tinypgp-:user-now keyid)))))))
15256 ;;; ----------------------------------------------------------------------
15258 (defun tinypgp-key-mode-set-trust (mode)
15259 "Set the trust MODE on current key/email in the line or point."
15263 ((eq mode 'undefined))
15264 ((eq mode 'untrusted))
15265 ((eq mode 'marginal))
15266 ((eq mode 'complete)))))
15269 ;;{{{ PGP main code
15271 ;;; ............................................................. &pgp ...
15273 ;;; ----------------------------------------------------------------------
15275 (defun tinypgp-delete-processes (&optional verb)
15276 "Kill all PGP processes found from `process-list'. VERB."
15280 (dolist (elt (process-list))
15281 (when (string-match "pgp" (prin1-to-string elt))
15283 (delete-process elt)))
15285 (message "TinyPgp: %d processes deleted" count))
15287 ;; Return t if processes were deleted.
15288 (not (eq count 0))))
15290 ;;; ----------------------------------------------------------------------
15292 (defun tinypgp-signature-user-info ()
15293 "Return User's X-Pgp information.
15296 `tinypgp-:xpgp-user-info'
15301 (let ((ret (if (stringp tinypgp-:xpgp-user-info)
15302 tinypgp-:xpgp-user-info
15303 (eval tinypgp-:xpgp-user-info))))
15304 (if (ti::nil-p ret)
15308 ;;; ----------------------------------------------------------------------
15310 (defun tinypgp-signature-move-to-header (&optional just-delete no-cnv)
15311 "Move Normal PGP signature to email headers.
15312 If there is no PGP signature info, do nothing.
15313 Works for read-only buffers too.
15315 You can call this function only after you have composed the
15316 message and attached the normal PGP signature.
15319 JUST-DELETE delete Normal PGP signature: do not move.
15320 NO-CNV Do not convert '- -' to '-' when deleting old signature."
15321 (tinypgpd "tinypgp-signature-move-to-header in:" just-delete)
15322 (let* (buffer-read-only
15323 (fid "tinypgp-signature-move-to-header:")
15324 (hlist tinypgp-:header-sign-smf-info)
15325 (psig "X-Pgp-Signed")
15337 (when (and (null just-delete)
15338 (setq data ;only if there is PGP
15340 (ti::pmin) (ti::mail-pgp-signature-normal-info))))
15341 (setq hdr-smf (if hlist
15346 (nth 1 tinypgp-:header-sign-smf-info)
15350 (tinypgpd fid "DATA" data
15351 "HDR-SMF" hdr-smf tinypgp-:header-sign-smf-info)
15352 ;; moving signature in buffer is not really a modification
15354 (with-buffer-modified
15355 (ti::save-with-marker-macro
15356 (setq info-list (nth 1 data)
15357 sig-list (nth 2 data))
15359 ;;; (setq I info-list S sig-list)
15362 (tinypgpd fid "INFO-LIST" info-list "SIG-LIST" sig-list)
15364 (unless just-delete
15365 (setq user-info (tinypgp-signature-user-info))
15367 (dolist (elt info-list)
15368 ;; For each PGP id, we just use that ID as
15369 ;; additional header name.
15371 (when (string-match "\\(.*\\):[ \t]+\\(.*\\)" elt)
15372 (setq fld (match-string 1 elt)
15373 str (match-string 2 elt))
15375 (if (string-match "Version\\|Charset" fld)
15376 (setq sig-fld (format "%s%s=%s; "
15380 (setq sig-fld (format "%sSignature=\n" sig-fld))
15382 (dolist (elt sig-list)
15383 ;; Last one Must have terminating colon
15385 (if (null (cdr sig-list))
15386 (setq sig-fld (format "%s \"%s\";\n" sig-fld elt))
15387 (setq sig-fld (format "%s \"%s\"\n" sig-fld elt))))
15389 (tinypgpd fid "SIG-FLD" sig-fld)
15392 (concat (if user-info (concat user-info "\n " ) " ")
15394 ;; Fit in the same line?
15397 ((< (+ (length hdr-smf) (length sig-fld))
15398 ;; If there is no user info, then
15399 ;; these fields go directly after
15400 ;; X-Pgp-Signed: (value 60)
15402 (if user-info 77 60))
15403 (concat hdr-smf sig-fld "\n "))
15405 ((< (length hdr-smf) 40)
15406 (concat hdr-smf " \n " sig-fld))
15409 (concat "\n " hdr-smf "\n " sig-fld)))
15411 (ti::mail-add-field psig str)))))
15413 ;; We can do this without knowing if there is PGP sig,
15414 ;; The previous statements already got rid of it
15415 ;; Remove the traditional signature.
15417 (ti::mail-pgp-signature-remove nil no-cnv)
15419 (tinypgpd fid "out: hooks" tinypgp-:sig-to-header-hook)
15421 (if tinypgp-:sig-to-header-hook
15422 (run-hook-with-args-until-success 'tinypgp-:sig-to-header-hook))))
15424 ;;; ----------------------------------------------------------------------
15425 ;;; The parameter 'delete' is optional, because
15426 ;;; - we may want to convert Headers to INFO block
15427 ;;; - do something when the block is there
15428 ;;; remove that blocka.
15430 ;;; And we don't have no Moving back to headers.
15432 (defun tinypgp-signature-from-header (&optional just-delete)
15433 "Convert X-Pgp signature to regular PGP signature.
15436 JUST-DELETE do not move but delete header signature info."
15437 (let* ((fid "tinypgp-signature-from-header:" )
15439 (sig-b-line (ti::mail-pgp-re (ti::mail-pgp-signature-begin-line)))
15440 (sig-e-line (tinypgp-cnv (ti::mail-pgp-signed-end-line)))
15450 (tinypgpd fid "in:" "DEL FLAG" just-delete )
15454 ;; Old v2.xx x-pgp standard
15456 (setq sig-list '("^X-Pgp-Charset" "^X-Pgp-Version"
15457 "^X-Pgp-Signed" "^X-Pgp-Comment"))
15458 (dolist (elt sig-list) (ti::mail-kill-field elt))
15459 (ti::mail-pgp-signature-remove))
15461 ((setq data (ti::mail-pgp-signature-header-info))
15462 (tinypgpd fid "X-pgp" data)
15463 (ti::save-with-marker-macro
15464 (ti::mail-pgp-signature-remove 'add)
15465 (setq beg (car (nth 0 data)) ;headers are here
15466 end (cdr (nth 0 data))
15467 info-list (nth 1 data)
15468 sig-list (nth 2 data))
15471 (when (setq hdr-smf (tinypgp-header-sign-make-smf 'xpgp))
15472 (ti::mail-text-start 'move)
15474 (insert (car hdr-smf)))
15475 (re-search-forward sig-b-line)
15478 ;; There must be absolutely nothing after it.
15480 (delete-region (point) (point-max))
15482 (unless just-delete
15483 ;;; (insert sig-b-line "\n")
15484 (dolist (elt info-list)
15485 (setq elt (replace-regexp-in-string (concat "^" pbase) "" elt))
15488 (insert "\n") ;blank line
15489 (dolist (elt sig-list) (insert elt "\n"))
15491 (insert sig-e-line "\n"))
15493 ;;; (ti::d! "DEL" beg end delete)
15496 (delete-region beg end)
15497 ;; v3.xx has only one heder field
15498 (ti::mail-kill-field "^X-Pgp-signed"))
15500 (run-hooks 'tinypgp-:sig-from-header-hook))))))
15502 ;;; ----------------------------------------------------------------------
15504 (defun tinypgp-signature-move-to-header-maybe (&optional verb)
15505 "If current mode is mail or news then move signature to header.
15506 But only if this is not a remailer message.
15509 VERB Verbose messages.
15512 `tinypgp-:xpgp-signing-mode'
15513 `tinypgp-:header-sign-table' ,overrides all"
15514 (tinypgpd "tinypgp-signature-move-to-header-maybe in:")
15516 (let* ((fid "tinypgp-signature-move-to-header-maybe:")
15518 (tinypgp-:xpgp-signing-mode ;take local copy
15519 tinypgp-:xpgp-signing-mode)
15520 (allowed (tinypgp-mail-buffer-p))
15521 (remail (or (ti::mail-pgp-remail-p)
15522 tinypgp-:r-mode-indication-flag))
15524 (do-it tinypgp-:xpgp-signing-mode)
15525 (count (tinypgp-hash 'sign 'get 'sign-remind-counter nil 'global)))
15526 (tinypgpd fid "ALLOWED" allowed "DO" do-it "REMAIL" remail)
15531 (if (setq elt (tinypgp-header-sign-active-list))
15532 (null (nth 2 elt)) ;if this entry is NIL then proceed
15535 (tinypgp-signature-move-to-header nil 'no-cnv)
15538 (unless (integerp count)
15540 (tinypgp-hash 'sign 'put 'sign-remind-counter 0 'global))
15544 ;; Display message every 5th time
15546 (when (eq 0 (% count 5))
15550 "Do not modify buffer, otherwise "
15551 "PGP signature must be generated again.")))
15552 (tinypgp-hash 'sign 'put 'sign-remind-counter count 'global)))
15553 (tinypgpd fid "out:")))
15556 ;;{{{ secring management
15558 ;;; ......................................................... &secring ...
15560 ;;; ----------------------------------------------------------------------
15562 (defun tinypgp-secring-file ()
15563 "Return current backends secring."
15564 (or (cdr (assq (tinypgp-backend-now) tinypgp-:file-secring ))
15565 (error "No secring in tinypgp-:file-secring")))
15567 ;;; ----------------------------------------------------------------------
15569 (defun tinypgp-crypt-command-get (from to password)
15570 "Return 'crypt' command for files FROM TO using PASSWORD."
15571 ;; Store to property so that we don't have to ask it again
15573 (let* ((fid "tinypgp-crypt-command")
15574 (sym 'tinypgp-:pgp-binary)
15576 (unless (setq crypt (get sym 'crypt))
15577 (setq crypt (or (executable-find "crypt")
15578 (error "Can't find 'crypt' on `exec-path'.")))
15579 (put sym 'crypt crypt))
15580 (unless (and (stringp from) (stringp to) (stringp password))
15581 (error "Invalid crypt command parameters."))
15583 (tinypgpd fid crypt from to)
15584 (format "%s %s < %s > %s" crypt password from to)))
15586 ;;; ----------------------------------------------------------------------
15588 (defun tinypgp-crypt-do-with-pgp (from to password &optional comment)
15589 "Use PGP to conventionally crypt file.
15594 TO destination file
15595 PASSWORD crypt password
15596 COMMENT the +comment string. Default is
15597 'FILE is conventionally encrypted.'
15598 Set to \"\" if you don't want comment.
15602 If the FROM file is pgp armored, it will be assumed that it is already
15603 encrypted conventionally and that it should be restored. If the file
15604 has no ascii armor, then it will be crypted.
15606 So, depending on input file, the file is either locked or unlocked.
15607 You don't get double conventional encryption if you specify FROM
15608 as already crypted file."
15609 (let* ((fid "tinypgp-crypt-do-with-pgp")
15610 (buffer (tinypgp-ti::temp-buffer 'shell))
15611 (opt tinypgp-:pgp-command-options)
15612 (pgp-exe (tinypgp-binary1 'crypt))
15614 ;; in case there is error these hooks are called to
15615 ;; restore buffer. But because this function deals with
15616 ;; files; no emacs buffer is involved. Prevent
15617 ;; calling these functions.
15619 tinypgp-:cmd-macro-after-hook
15624 (tinypgpd fid "in:" from to "comment:" comment)
15626 (if (not (file-exists-p from))
15627 (error "no FROM file"))
15629 (if (file-exists-p to)
15632 (or (stringp comment)
15634 (format "Conventionally crypted %s" from)))
15636 ;; We have to know if the file is already crypted to select right
15637 ;; command. We only read part of the file to determine if it has ascii
15640 (with-current-buffer buffer
15641 (insert-file-contents from nil 0 300)
15642 (setq encrypted-p (ti::mail-pgp-re-search 'msg))
15645 (tinypgpd fid "ENCRYPTED stat" encrypted-p)
15647 ;; cat T | pgp +comment="Crypted secring.pgp" -caf -z foo > T.asc
15648 ;; cat T.asc | pgp -f -z foo > T
15653 "%s %s | %s -f -z %s %s +batch > %s "
15654 (if (ti::win32-p) "type " "cat ")
15660 (tinypgpd fid "CRYPT --> regular ."))
15663 "%s %s | %s -caf -z %s %s +batch %s > %s"
15664 (if (ti::win32-p) "type " "cat ")
15670 (if (not (ti::nil-p comment))
15671 (format "+comment=\"%s\"" comment)
15674 (tinypgpd fid "REGULAR --> crypt" cmd)))
15676 (setq tinypgp-:last-pgp-exe-command cmd)
15677 (shell-command cmd buffer)
15678 (when (setq err (tinypgp-binary-check-error 'ignore-output))
15679 (tinypgp-error err)
15682 ;;; ----------------------------------------------------------------------
15684 (defun tinypgp-crypt-do-with-crypt (from to password)
15685 "Crypt FROM source TO destination using PASSWORD using 'crypt'."
15687 ;; Maybe I add something here later.
15688 ;; It's too bad that we can't check if the (de)crypting was done
15689 ;; with right password. The 'crypt' command won't tell success or
15690 ;; failure so be _sure_ you type it right in the prompt.
15692 (tinypgpd "tinypgp-crypt-do-with-crypt" from to)
15693 (shell-command (tinypgp-crypt-command-get from to password)))
15695 ;;; ----------------------------------------------------------------------
15697 (defun tinypgp-crypt-do (from to password)
15698 "Crypt FROM source TO destination using PASSWORD."
15699 (funcall tinypgp-:secring-crypt-function from to password))
15701 ;;; ----------------------------------------------------------------------
15703 (defun tinypgp-ask-secring-password (&optional force)
15704 "Ask secring password. Return old or FORCE asking again."
15705 (let* ((sym 'tinypgp-:hash)
15706 (ret (get sym 'secring-passwd)))
15707 (when (or force (null ret))
15708 (setq ret (ti::compat-read-password "Password for secring: "))
15709 (put sym 'secring-passwd ret))
15712 ;;; ----------------------------------------------------------------------
15714 (defun tinypgp-secring (&optional set)
15715 "Return secring from memory or set secring from current buffer.
15717 'kill Empty secring from memory
15718 non-nil read buffer content into memory as secring
15719 nil return secring from memory."
15723 (get 'tinypgp-:hash 'secring))
15725 (put 'tinypgp-:hash 'secring nil))
15727 (put 'tinypgp-:hash 'secring (buffer-string)))))
15729 ;;; ----------------------------------------------------------------------
15731 (defun tinypgp-secring-use ()
15732 "Make sure we have secring available."
15733 (let* ((fid "tinypgp-secring-use")
15734 (secring (tinypgp-secring-file))
15735 (enc tinypgp-:file-secring-encrypted)
15738 (when (not (file-exists-p secring)) ;Ahem, it's encrypted...
15740 (if (not (file-exists-p enc)) ;Nope, something is very wrong here
15741 (error "Panic, no secring! Pull out your backup..."))
15744 ((and (file-exists-p enc) ;In memory
15746 (tinypgpd fid "Write")
15747 (tinypgp-secring-crypt-read nil 'write))
15748 ((and (file-exists-p enc)
15749 (null (tinypgp-secring))) ;Not in Memory
15750 (tinypgpd fid "read & rrite")
15751 (setq pass (tinypgp-ask-secring-password))
15752 (tinypgp-secring-crypt-read pass)
15753 (tinypgp-secring-crypt-read nil 'write))))))
15755 ;;; ----------------------------------------------------------------------
15756 ;;; Why I dind't use PGP? because I can't control to what file it
15757 ;;; produces the output. It always writes to .pgp or .asc (-a) and
15758 ;;; that not very friendly.
15760 (defun tinypgp-secring-crypt (password &optional decrypt)
15761 "Conventionally encrypt secrig with PASSWORD secring.
15762 This function doesn't use PGP, but calls external 'crypt' command.
15763 If DECRYPT is non-nil, move encrypted secring back.
15765 Caution: Make backup first. This fuction deletes or modifies the
15769 `tinypgp-:file-secring-encrypted'"
15772 (ti::compat-read-password
15773 (format "[%s] Secring password: "
15774 (if current-prefix-arg "decrypt" "encrypt")))
15775 current-prefix-arg))
15776 (let* ((fid "tinypgp-secring-crypt")
15778 tinypgp-:file-secring-encrypted
15779 (tinypgp-secring-file)))
15781 (tinypgp-secring-file)
15782 tinypgp-:file-secring-encrypted)))
15783 (tinypgpd fid "in:" decrypt from to)
15784 (if (not (file-exists-p from))
15785 (error "Fatal condition, no file: %s" from))
15787 ;; If this fails; then we can't execute crypt command that
15788 ;; overwrites file.
15790 (if (file-exists-p to)
15793 (tinypgp-crypt-do from to password)
15795 (if (interactive-p)
15796 (message "Secring %s"
15801 ;;; ----------------------------------------------------------------------
15803 (defun tinypgp-secring-crypt-read (&optional password write force)
15804 "Read encrypted secring, open it, and put to to memory.
15805 If file already exists in memory, do nothing.
15809 PASSWORD password string
15810 WRITE write secring from memory to (tinypgp-secring-file)
15811 FORCE If non-nil force reading encrypted secring to memory"
15812 (let* ((fid "tinypgp-secring-crypt-read")
15813 (secring (tinypgp-secring-file))
15814 (from tinypgp-:file-secring-encrypted)
15815 (to tinypgp-:file-source))
15816 (tinypgpd fid (if write "WRITE" "READ") force)
15819 (if (null (setq from (tinypgp-secring)))
15820 (error "Read secring first to memory."))
15824 (tinypgp-secring 'read-to-memory)
15825 (write-region (point-min) (point-max) secring)))
15827 ;; ........................................................ read ...
15828 (when (or (not (tinypgp-secring))
15830 (unless (file-exists-p from)
15831 (error "There is no encrypted secring."))
15833 (if (file-exists-p to)
15836 (tinypgp-crypt-do from to password)
15842 (insert-file-contents to)
15843 (if (ti::buffer-empty-p)
15844 (error "No results after opening encrypted secring?"))
15845 (tinypgp-secring 'read-to-memory)))
15846 (tinypgp-file-control 'source-kill)))))))
15848 ;;; ----------------------------------------------------------------------
15850 (defun tinypgp-secring-crypt-maybe ()
15851 "Make encrypted secring if it doesn't exist already."
15852 (unless (file-exists-p (tinypgp-secring-file))
15853 (call-interactively 'tinypgp-secring-crypt)))
15855 ;;; ----------------------------------------------------------------------
15857 (defun tinypgp-secring-kill-maybe ()
15858 "Kill secring.pgp if there is encrypted keyring.
15859 `tinypgp-:secring-crypt-mode' must be non-nil too."
15860 (when (and tinypgp-:secring-crypt-mode
15861 (file-exists-p (tinypgp-secring-file)))
15862 (delete-file (tinypgp-secring-file))))
15864 ;;; ----------------------------------------------------------------------
15866 (defun tinypgp-secring-restore-maybe ()
15867 "Restore (tinypgp-secring-file) if there is encrypted keyring.
15868 If there already is (tinypgp-secring-file) then do nothing."
15869 (unless (file-exists-p (tinypgp-secring-file))
15870 ;; - Be sure that there exists encrypted secring in the disk
15871 ;; - We may have the secring in the memory, but nevertheless
15872 ;; I must require that is also in disk.
15874 (when (or (file-exists-p tinypgp-:file-secring-encrypted)
15875 (error "Can't find encrypted scring?"))
15876 (tinypgp-secring-crypt (tinypgp-ask-secring-password) 'restore))))
15878 ;;; ----------------------------------------------------------------------
15880 (defun tinypgp-secring-backup (file password &optional verb)
15881 "Backup (tinypgp-secring-file) in crypted format to FILE with PASSWORD.
15882 Previous FILE is deleted. VERB."
15885 (let* ((default-directory (concat (tinypgp-path ".") "/")))
15887 (read-file-name "Backup secring to: ")
15888 (ti::compat-read-password "Backup password: ")))))
15889 (let* ((from (tinypgp-secring-file)))
15891 (unless (file-exists-p from)
15892 (error "There is no secring to be backed up."))
15893 (if (file-exists-p file) (delete-file file))
15896 (tinypgp-crypt-do from file password)
15897 (if (not (file-exists-p file))
15898 (error "Couldn't make backup."))
15900 (message "TinyPgp: secring backup done.")))))
15902 ;;; ----------------------------------------------------------------------
15904 (defun tinypgp-secring-crypt-mode-detect ()
15905 "Set correct `tinypgp-:secring-crypt-mode'."
15906 (if (and tinypgp-:secring-crypt-mode
15907 (not (file-exists-p tinypgp-:file-secring-encrypted)))
15908 (setq tinypgp-:secring-crypt-mode nil))
15910 ;; If mode is off; then this condition must be true
15911 ;; - there must be secring.pgp
15912 ;; - there must not be secring.enc
15914 (if (null tinypgp-:secring-crypt-mode)
15916 ((file-exists-p tinypgp-:file-secring-encrypted)
15917 (setq tinypgp-:secring-crypt-mode t))
15918 ((or (not (file-exists-p (tinypgp-secring-file) )) ;; .pgp missing
15919 (file-exists-p tinypgp-:file-secring-encrypted)) ;; .enc found
15920 (error "Fatal, no secring.pgp or secring.enc found."))))
15921 tinypgp-:secring-crypt-mode)
15923 ;;; ----------------------------------------------------------------------
15925 (defun tinypgp-secring-crypt-expire-password (&optional verb)
15926 "Reset the secring password so that you can change it. VERB.
15927 The password is set once when you turn on crypt mode
15928 with `tinypgp-secring-crypt-mode-toggle' and it never chages during the
15929 lifetime of program.
15931 However if you want to change the password; you must
15932 o turn off the crypt mode
15933 o call this function
15934 o turn on the crypt mode"
15936 ;;; (or (tinypgp-secring-crypt-mode-detect)
15938 ;;; (substitute-command-keys
15940 ;;;Can't expire secring password: Use \\[tinypgp-secring-crypt-mode-toggle]")))
15943 (let* ((pass (get 'tinypgp-:hash 'secring-passwd)))
15944 (if (stringp pass) (fillarray pass ?\0))
15945 (put 'tinypgp-:hash 'secring-passwd nil)
15947 (message "TinyPgp: Secring Password expired."))))
15949 ;;; ----------------------------------------------------------------------
15951 (defun tinypgp-secring-crypt-mode-toggle (arg &optional verb)
15952 "Toggle using crypted secring.
15956 ARG Mode arg. nil = toggle, 0 = off, 1 = on.
15957 VERB If non-nil, print verbose messages.
15961 Before turning on this mode make backup of your keyring removable media.
15962 Prefer ancrypting that backup too, otherwise you have defeated the
15963 purpose of this mode by letting people to access your secring
15964 in some other readable file. See command \\[tinypgp-secring-backup]
15966 See also \\[tinypgp-secring-crypt-expire-password]
15970 When this mode is enabled. You secring is immediately moved to
15971 conventionally encrypted format if it already isn't crypted.
15972 The ecrypted secring is located at `tinypgp-:file-secring-encrypted'
15973 and (tinypgp-secring-file), `Secring' , is deleted.
15975 When programs needs the secring it temporarily opens the encrypted
15976 secring and write to `Secring'. When the PGP operation
15977 that needed secring is over, the `Secring' is removed.
15979 If you are in multi-user environment, be aware that all your files
15980 are propable taped due to regular backups in the file system.
15981 Thus your PGP keys are available to the sysadm.
15983 And even if your're in single user environment, somebody may sit
15984 down to your computer console and copy the secring.pgp withing
15987 If you're paranoid at all, you keep this mode permanently on by
15988 setting `tinypgp-:secring-crypt-mode' to t.
15992 When you turn on the mode the `Secring' is deleted and
15993 encrypted `tinypgp-:file-secring-encrypted'. When you turn off this
15994 mode reverse happens and `Secring' is restored.
15998 Turning on or off this mode causes a slight delay because
15999 the command to encyprt or decypt the password is called.
16001 While the mode is active, you cannot use all pgp commands
16002 from the shell command prompt because there is no secring.pgp
16003 directly available. Eg. if you want to generate new key, which
16004 modifies secring; you should turn off this mode to temprarily
16005 reveal secring.pgp.
16008 value of `tinypgp-:secring-crypt-mode'"
16010 (let* ((fid "tinypgp-secring-crypt-mode-toggle")
16014 (tinypgpd fid "in:" arg)
16015 (setq old-mode (tinypgp-secring-crypt-mode-detect))
16016 (ti::bool-toggle tinypgp-:secring-crypt-mode arg)
16017 (tinypgpd fid "ARG" arg "MODE" old-mode tinypgp-:secring-crypt-mode verb)
16019 ;; If MODE was ON; and we were called with parameter 1,
16020 ;; then do nothing; because mode hasn't changed.
16022 (when (not (eq old-mode tinypgp-:secring-crypt-mode))
16023 ;; When mode is turned off
16024 ;; o Remove secring from memory, because user may now change it
16027 ;; o Read it from disk to memory. Secring is nor in encrypted
16031 (tinypgp-:secring-crypt-mode
16032 ;; Display messages so that user doesn't get nervous. This
16033 ;; may take 1-3 seconds.
16035 (when verb (message "Secring conversion in progress...2"))
16036 (tinypgp-secring-crypt (tinypgp-ask-secring-password))
16037 (tinypgp-secring-kill-maybe)
16038 (when verb (message "Secring conversion in progress...1"))
16039 (tinypgp-secring-crypt-read (tinypgp-ask-secring-password)))
16041 (when verb (message "Secring conversion in progress..."))
16042 (tinypgp-secring-restore-maybe)
16043 ;; We must delete this
16044 ;; o In many places program checks if this exist; but because
16045 ;; mode is off it should not be used. Safest is to destroy it.
16046 ;; o If user starts adding new secret keys; he turns this mode off
16047 ;; --> he should see just regular secring.pgp and not get confused
16050 (delete-file tinypgp-:file-secring-encrypted)
16051 (tinypgp-secring 'kill))))
16053 (tinypgp-secring-crypt-mode-detect)
16057 (concat "TinyPgp: SECRING encrypt mode: "
16058 (if tinypgp-:secring-crypt-mode
16060 (if (null tinypgp-:secring-crypt-mode)
16062 (file-name-nondirectory
16063 (tinypgp-secring-file))
16066 (tinypgp-update-modeline)
16067 tinypgp-:secring-crypt-mode))
16070 ;;{{{ interactive, guess next action
16072 ;;; .................................................... &guess-action ...
16074 ;;; ----------------------------------------------------------------------
16075 ;;; - If you have used vc.el, then you know why this function ....
16077 (defun tinypgp-next-action-mail (&optional arg)
16078 "Try to guess next action. ARG is passed to called function.
16079 If buffer has auto action active or if function cannot guess what
16080 to do, this command does nothing.
16084 o If buffer is read-only, try to decrypt it. We suppose that the
16085 buffer is used by some mail reader.
16086 o -- Check if there is only one email in TO field. If the
16087 user is cached (you have previously encrypted message to him),
16088 then ask permission to encrypt the message.
16089 -- Sign the message
16091 In some other buffer:
16093 o If not signed, sign.
16094 o If signed, verify and if that reveals inner folders, open them all.
16095 o If encrypted, decrypt. (Mail buffers are ignored, because you can't
16096 decrypt other users encrypted message.)
16100 o Is passed to decrypt command"
16102 (tinypgpd "tinypgp-next-action-mail in:" arg)
16103 (let ((auto-action-pending (and (not buffer-read-only)
16104 (tinypgp-auto-action-p)
16105 (tinypgp-hash 'auto-action 'get 'user-mode)))
16106 (fid "tinypgp-next-action-mail: ")
16111 (tinypgpd fid "auto action:" auto-action-pending )
16114 (auto-action-pending
16115 (message "TinyPgp.el ...note, auto action is pending."))
16118 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... regular ..
16119 ((not (ti::mail-mail-p)) ;not a mail buffer
16120 (tinypgpd fid "non-mail buffer start:")
16123 ((not (ti::mail-pgp-signed-p))
16124 (tinypgpd fid "regular not pgp-signed:")
16125 (tinypgp-sign-region (point-min) (point-max)))
16127 ((ti::mail-pgp-signed-p)
16129 (tinypgpd fid "regular signed:")
16130 (while (or (if (ti::mail-pgp-signed-p) (setq type 'sign))
16131 (if (ti::mail-pgp-p) (setq type 'other)))
16132 (tinypgpd fid "regular; envelope" type)
16136 (tinypgp-verify-region (point-min) (point-max)))
16139 ;; When we verify message...
16140 ;; a) an encrypted message envelope surfaces
16141 ;; b) it was base64 signed -> regular text
16144 (tinypgp-decrypt-region
16145 (point-min) (point-max)
16146 (car (tinypgp-i-args-decrypt)))))))))
16148 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... ... mail ..
16151 (setq to (mail-fetch-field "to"))
16153 (tinypgpd fid "mail: to" to
16154 "see pgp? " (ti::mail-pgp-p)
16155 "multi ,? " (count-char-in-string ?, (or to "")))
16158 ((and (not buffer-read-only)
16159 (not (ti::nil-p to)) ;; Must have TO email
16160 (null (ti::mail-pgp-p)) ;; No PGP yet, okay...
16161 (eq (count-char-in-string ?, to) 0) ;; only one email?
16162 (setq to (car-safe (ti::mail-email-from-string to)))
16163 ;; Have we sent encrypted mail to him?
16165 (setq pring (tinypgp-key-find-by-cache to)))
16166 (tinypgpd fid "mail: 1 encrypt")
16167 (tinypgp-save-state-macro
16168 (setq tinypgp-:pubring-now pring)
16169 (call-interactively 'tinypgp-encrypt-mail)))
16171 ((and (ti::mail-pgp-signed-p)
16172 (ti::mail-pgp-encrypted-p 'double-check))
16173 (tinypgpd fid "mail: verify/decrypt")
16174 (call-interactively 'tinypgp-verify-mail)
16175 (sit-for 1.7) ;let user see "Good signature..."
16176 (tinypgp-decrypt-mail-verbose (quote arg)))
16178 ((and (null buffer-read-only)
16179 (not (ti::mail-pgp-headers-p))
16180 (not (ti::mail-pgp-signed-p)))
16181 (tinypgpd fid "mail: sign")
16182 (call-interactively 'tinypgp-sign-mail))
16184 ((and (ti::mail-pgp-signed-p)
16185 (not (ti::mail-pgp-encrypted-p 'message-tag-too)))
16186 (tinypgpd fid "mail: 3")
16187 (call-interactively 'tinypgp-verify-mail))) ;Cond end
16189 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
16191 ;; Still pgp ? Maybe we should decrypt it ?
16192 ;; But what if this is mail that is meant to be sent to
16193 ;; someone else --> we assume that non-read-only buffer
16194 ;; is mail to someone else
16196 ;; This is looped two times because:
16197 ;; - Nym account sends use [ENCRYPT [conventional CRYPT]] envelope
16198 ;; - Loop1 open CRYPT envelope and the second loop checks
16199 ;; is there was still real encrypted message (by your nym key)
16201 ;; but I don't dare...2 envelopes should suffice.
16203 (while (and buffer-read-only
16204 (not (ti::mail-pgp-signed-p))
16206 (tinypgpd fid "mail: still pgp")
16207 (tinypgp-decrypt-mail-verbose (quote arg)))
16209 (goto-char (ti::mail-text-start))))))))
16210 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... mail end ..
16215 ;;; ......................................................... &signing ...
16217 ;;; ----------------------------------------------------------------------
16219 (defun tinypgp-sign-modify-check ()
16220 "Detect if signed message is modified.
16222 `tinypgp-:sign-data'"
16223 (let* ((mail (ti::mail-mail-p))
16224 (mime (ti::mail-mime-maybe-p)))
16227 (ti::mail-pgp-headers-p)
16228 (tinypgp-sign-data-same-p))
16229 (message "TinyPgp: Body changed, signature invalid; resigning...")
16231 (tinypgp-sign-loose-info)
16232 (call-interactively 'tinypgp-sign-mail))
16234 (tinypgpd "sign-modify-check:" (current-buffer) "MAIL" mail "MIME"
16235 (ti::mail-message-length)
16236 tinypgp-:sign-data)
16237 ;; hook return value
16240 ;;; ----------------------------------------------------------------------
16242 (defun tinypgp-sign-mail-auto-p ()
16243 "Check if auto signing would happen."
16245 (not (ti::mail-pgp-signed-p))
16246 (not (ti::mail-mime-maybe-p))
16247 (null tinypgp-:r-mode-indication-flag)
16248 (or (null tinypgp-:sign-mail-p-function)
16249 (funcall tinypgp-:sign-mail-p-function))))
16251 ;;; ----------------------------------------------------------------------
16253 (defun tinypgp-sign-mail-func ()
16254 "Maybe sign current buffer. This function is called from hooks.
16255 If buffer is already signed or remailer action is in progress,
16259 `tinypgp-:sign-mail-p-function'"
16260 (if (inline (tinypgp-sign-mail-auto-p))
16261 (call-interactively 'tinypgp-sign-mail)))
16263 ;;; ----------------------------------------------------------------------
16264 ;;; on/off function can be used in hooks
16266 (defun tinypgp-sign-mail-auto-mode-on ()
16267 "Turn on automatic signing."
16268 (tinypgp-sign-mail-auto-mode 1))
16270 (defun tinypgp-sign-mail-auto-mode-off ()
16271 "Turn off automatic signing."
16272 (tinypgp-sign-mail-auto-mode 0))
16274 ;;; ----------------------------------------------------------------------
16277 (defun tinypgp-sign-mail-auto-mode (&optional arg)
16278 "Toggle autosigning mode according to ARG.
16285 'push-on Record previous value and turn on auto signing.
16286 'push-off Record previous value and turn off auto signing.
16287 'pop pop previous autosign value.
16290 nil autosigning off
16291 non-nil autosigning on"
16293 (let* ((fid "tinypgp-sign-mail-auto-mode")
16294 (stack (get 'tinypgp-sign-mail-auto-mode 'stack))
16295 (func 'tinypgp-sign-mail-func)
16296 (hooks tinypgp-:mail-send-hook-list)
16297 (now-on-p (tinypgp-sign-mail-auto-mode-on-p))
16302 ;; ......................................................... stack ...
16303 (when (and (not (null arg))
16307 (push now-on-p stack)
16310 ((eq arg 'push-off)
16311 (push now-on-p stack)
16315 (if (not (ti::listp stack))
16316 (error "Nothing to pop from stack.")
16317 (setq arg (car stack))
16318 (setq stack (cdr stack))))
16320 (error "Not known arg")))
16321 (put 'tinypgp-sign-mail-auto-mode 'stack stack))
16323 (tinypgpd fid arg "STACK" stack)
16325 ;; ...................................................... mode arg ...
16331 ((memq arg '(0 -1))
16334 (ti::add-hooks hooks func remove)
16335 (tinypgp-update-modeline)
16337 (if (interactive-p)
16340 "TinyPgp: mail auto signing mode %s"
16341 (if remove "off" "on"))))
16345 ;;; ----------------------------------------------------------------------
16348 (defun tinypgp-sign-loose-info (&optional verb)
16349 "Loose signature info.
16351 VERB Verbose messages."
16353 (let* (tinypgp-:sig-to-header-hook ;must be disabled for now
16354 (allow (tinypgp-mail-buffer-p)))
16357 (ti::mail-pgp-headers-p))
16358 (ti::mail-kill-field "X-Pgp-Signed"))
16359 (ti::save-with-marker-macro
16360 (tinypgp-signature-from-header 'just-delete))
16362 (when (and verb (null allow))
16363 (message "PGP action maybe partially completed...") (sit-for 2))
16365 (run-hooks 'tinypgp-:sign-loose-info-hook)
16367 (message "PGP signing information deleted."))
16370 ;;; ----------------------------------------------------------------------
16371 ;;; - parameters BEG and END _must_ be nil
16374 (defun tinypgp-sign-mail (&optional register user options verb noxpgp)
16375 "Sign message in mail buffer.
16379 REGISTER flag, if non-bil store the signature to register.
16380 This is the prefix arg user passes to program.
16381 This will automatically turn off X-pgp.
16383 VERB allow verbose messages
16384 NOXPGP Prohibit X-Pgp
16388 if VERB is non-nil (set in interactive call), the pubring is
16389 changed if it the information is on the cache."
16392 (tinypgp-hash 'action 'put 'now 'sign 'global)
16393 (tinypgp-hash 'action 'put 'detail 'mail 'global)
16395 (tinypgpd "tinypgp-sign-mail: interactive")
16397 (tinypgp-user-change-macro
16401 (eval tinypgp-:pgp-binary-interactive-option)
16403 current-prefix-arg))))
16405 (barf-if-buffer-read-only)
16406 (tinypgp-i-args-pass-phrase)
16408 (let* ((fid "tinypgp-sign-mail: ")
16409 (tinypgp-:pubring-now tinypgp-:pubring-now)
16410 (signed-p (ti::mail-pgp-signed-conventional-p))
16411 (signed-xpgp-p (ti::mail-pgp-signed-xpgp-p))
16412 (signed-multi-p (ti::mail-pgp-signed-conventional-multi-p))
16413 (mail-p (ti::mail-mail-p))
16414 (write-point (point))
16426 (tinypgp-hash 'action 'put 'now 'sign 'global)
16427 (tinypgp-hash 'action 'put 'detail 'mail 'global)
16429 (tinypgpd fid "signed" signed-p signed-xpgp-p signed-multi-p
16435 ;; Note: It sis very unfortunate that the signature separator
16436 ;; is "-- ". Thazt extra space will be gone below, because we trim
16437 ;; the message before signing it.
16439 ;; To my opinion it's more important to trim the message than
16440 ;; preserve trailing spaces at the end of lines.
16442 (tinypgp-add-signature-if-signing)
16443 (ti::mail-trim-buffer)
16445 (ti::mail-pgp-header-kill-in-body)
16447 ;; Actually; someone else could have signed using X-pgp,
16448 ;; and when we sign the message, the Right Thing would be
16449 ;; - check if X-pgp is ours --> remove it. If not, then convert
16450 ;; it to regular pgp signature.
16451 ;; - add out signing (if there is regular signature, then
16452 ;; do ot use X-pgp)
16454 (when signed-xpgp-p (tinypgp-sign-loose-info))
16457 (goto-char (if mail-p
16458 (ti::mail-text-start)
16460 (setq beg (point)))
16462 (if (or (eq beg (point-max))
16463 (and mail-p ;Check only mail buffer
16465 (goto-char (or beg (point-min)))
16466 ;; there must be text, not just emptly lines
16468 (null (re-search-forward "[^ \t\n]" nil t)))))
16469 (error "Nothing to do, no text found."))
16471 (tinypgp-save-state-macro
16472 ;; Turn this off if buffer is not mail or if there already is signature
16473 (when (or (not mail-p)
16475 (setq tinypgp-:xpgp-signing-mode nil))
16478 (if (null (setq pring (tinypgp-key-find-by-cache tinypgp-:user-now)))
16479 (tinypgp-pubring-in-use-confirm)
16480 (setq tinypgp-:pubring-now pring)))
16482 (tinypgpd fid "PRING NOW" tinypgp-:pubring-now pring)
16484 ;; ... ... ... ... ... ... ... ... ... ... ... ... tmp buffer ...
16486 (tinypgp-mode-specific-control-before 'sign tinypgp-:user-now)
16488 (tinypgp-run-in-tmp-buffer nil
16489 (tinypgp-user-change-macro
16490 (tinypgp-set-session-parameters 'sign)
16492 (goto-char write-point)
16493 (setq buffer (current-buffer)
16494 sign-user tinypgp-:user-now ;Save this value
16495 write-mark (point-marker)
16496 write-line (ti::read-current-line)
16497 write-col (current-column))
16498 ;; ............................................ do signing ...
16499 ;;; (ti::d! "::sign do" tinypgp-:pubring-now)
16500 (tinypgp-cmd-macro-email "sign"
16502 ((and (ti::mail-mail-p)
16503 (setq hdr-smf (tinypgp-header-sign-make-smf)))
16505 (insert (car hdr-smf))))
16507 (tinypgp-cmd-macro 'sign user nil
16508 "Signing..." register options 'no-mode-funcs)
16510 ;; (pop-to-buffer (current-buffer)) (ti::d! "::sign done")
16512 (tinypgp-signature-move-to-header-maybe verb)
16513 (setq write-point (marker-position write-mark)
16516 ;; ........................................... signing end ...
16518 ;;; (tinypgp-mode-specific-control-after 'sign tinypgp-:user-now nil nil nil)
16520 ;; - Copy signed data to original buffer.
16521 ;; - restore original write position: this is tricky because the
16522 ;; buffer has changed: Search line string and goto column OR
16523 ;; got to marker position.
16527 (insert-buffer buffer)
16529 (if (and (not (ti::nil-p write-line)) ; can't search empty line
16530 (search-forward write-line nil 'noerr))
16531 (move-to-column write-col)
16532 ;; This doesn't necessarily succeed to preserve position,
16533 ;; but it's better than nothing.
16535 (goto-char write-point)
16536 ;; If this changes, signing is not valid
16537 (tinypgp-sign-data-set)))
16539 ;; ............................................. verbose message ...
16541 (message "%sSigned with key: %s"
16543 (format "[Result in register %c] " tinypgp-:register)
16550 ;;; ----------------------------------------------------------------------
16552 (defun tinypgp-sign-mail-base64 (&optional register )
16553 "Uuencode message with pgp.
16554 Store output to `tinypgp-:register' if REGISTER is non-nil.
16555 This function turns off clearsig, so that mail is signed, compressed,
16556 and uuencoded in base64."
16559 (barf-if-buffer-read-only)
16561 current-prefix-arg)))
16562 (tinypgp-i-args-pass-phrase "[Base64] Sign pass phrase: ")
16563 (tinypgp-hash 'action 'put 'now 'sign 'global)
16564 (let* ((beg (or (ti::mail-text-start) (point-min)))
16567 (error "TinyPgp: sign mase64, There is no text in message body."))
16568 (tinypgp-sign-region-base64 beg end register nil (interactive-p))))
16570 ;;; ----------------------------------------------------------------------
16572 (defun tinypgp-sign-base64-insert-file (file &optional options)
16573 "Insert uuencoded FILE into point using OPTIONS.
16574 This function inserts the given file into point and turns
16575 off clearsig, so that the file is signed, compressed, and uuencoded
16578 It is encouraged that insert big files with this function
16579 to the buffer when you're going to send them via email."
16580 (interactive "*f[base64 sign] Insert file: ")
16581 (let ((buffer (tinypgp-ti::temp-buffer 'finger)) ;This is free for us.
16584 (barf-if-buffer-read-only)
16585 (tinypgp-hash 'action 'put 'now 'sign 'global)
16586 ;; Hm. This should be interactive part...
16588 (tinypgp-i-args-pass-phrase)
16590 ;; Insert file leaves point before the file, but we need to know
16591 ;; where it ends...
16593 (with-current-buffer buffer
16594 (insert-file-contents file)
16597 (setq size (/ (buffer-size) 1000)) ;in kilos
16601 "Base64 signed. File: %s uncompresses to approx. %s"
16602 (file-name-nondirectory file)
16604 (if (eq 0 size) ;Hm. very small file
16605 (format "%dbytex" (buffer-size))
16606 (format "%dK" size)))))
16608 ;; In Unix we pass the option directly to pgp.
16609 ;; This way UNDO can undo whole PGP response at once
16611 (when (and comment (not (ti::win32-p)))
16612 (setq options (format "+comment=\"%s\"" comment)))
16614 (tinypgp-sign-region-base64 (point-min) (point-max) nil options)
16616 ;; But in Windows we have to manually patch the genrated output.
16617 ;; You have to ress twice UNDO to get original text
16620 (or (not (tinypgp-backend-pgp2-p))
16622 (tinypgp-binary-header-field-set "Comment:" comment))
16625 (run-hook-with-args-until-success
16626 'tinypgp-:insert-file-sign-base64-hook
16628 (insert-buffer buffer)
16629 ;; It may be big file, don't leave into emacs
16630 (ti::erase-buffer buffer)))
16632 ;;; ----------------------------------------------------------------------
16634 (defun tinypgp-sign-region-base64
16635 (beg end &optional register options verb )
16636 "Sign as base64 (uuencode).
16641 REGISTER if non-nil; then store contents to `tinypgp-:register'
16642 OPTIONS option string passed to pgp.
16643 VERB Verbose messages.
16645 This function turns off clearsig, so that region is signed,
16646 compressed, and uuencoded in base64."
16649 (barf-if-buffer-read-only)
16651 (region-beginning) (region-end)
16652 current-prefix-arg)))
16654 (barf-if-buffer-read-only)
16655 (tinypgp-i-args-pass-phrase "Region Sign base64 pass phrase:" )
16657 (tinypgp-hash 'action 'put 'now 'sign 'global)
16658 (tinypgp-hash 'action 'put 'detail 'base64 'global)
16660 (let* ((orig-opt options)
16664 "run signature verify to to dearmor to clear text. ")))
16666 (when (and (null orig-opt) (not (ti::win32-p)))
16667 (setq options (format "+comment=\"%s\"" comment)))
16669 ;; Add user options to the end
16671 (setq options (concat "+clearsig=off " options))
16672 (tinypgp-sign-region beg end verb options nil register )
16674 (when (and (null orig-opt) (ti::win32-p))
16675 (tinypgp-binary-header-field-set "Comment:" comment)))
16677 (if (and verb register)
16679 (substitute-command-keys
16682 "Results in register `%c'. View it with "
16683 "\\[tinypgp-view-register]")
16684 tinypgp-:register)))))
16686 ;;; ----------------------------------------------------------------------
16688 (defun tinypgp-sign-mail-mime ()
16689 "Sign buffer as PGP/MIME using SEMI or TM.
16690 Function activates mime mode if needed."
16693 (unless (ti::re-search-check mail-header-separator)
16694 (error "Tinypgp: MPGP/MIME Must have mail buffer."))
16696 (tinypgpd "tinypgp-sign-mail-mime: MIME-P" (ti::mail-mime-feature-p))
16698 (when (ti::mail-mime-feature-p)
16699 (ti::mail-mime-turn-on-mode))
16701 (unless (ti::mail-mime-sign-region)
16702 (error "Can't sign PGP/MIME. TM or SEMI is not active."))
16704 (ti::mail-mime-turn-off-mode))
16706 ;;; ----------------------------------------------------------------------
16708 (defun tinypgp-sign-mail-detached ()
16709 "Create detached signature to register `tinypgp-:register' using PASSWORD."
16711 (tinypgp-i-args-pass-phrase "Detach sign password: ")
16712 (let* ((beg (ti::mail-text-start))
16715 (error "TinyPgp: sign detached, There is no text in message body."))
16716 (tinypgp-sign-region-detached beg end (interactive-p))))
16718 ;;; ----------------------------------------------------------------------
16720 (defun tinypgp-sign-region-detached
16721 (beg end &optional verb options noerr)
16722 "Put detached signature to register `tinypgp-:register'.
16727 VERB verbose messages
16728 OPTIONS additional option string for PGP
16729 NOERR do not call error
16732 If verb is non-nil, correct keyring containing the key is
16733 first set according to `tinypgp-:user-now' before signing."
16736 (if (null (region-active-p))
16737 (error "region not active"))
16744 (let* ((fid "tinypgp-sign-region-detached:"))
16746 (tinypgp-i-args-pass-phrase "Region detach sign pass phrase: ")
16747 (tinypgpd fid "in:" beg end verb options noerr)
16749 (tinypgp-hash 'action 'put 'now 'sign 'global)
16750 (tinypgp-hash 'action 'put 'detail 'detach 'global)
16752 ;; This is an ugly hack, but the previous SIGN options are replaced
16753 ;; with the new ones. User options are added before -bfast.
16755 (setq options (format "%s %s" (or (eval options) "")
16756 (if (tinypgp-backend-pgp2-p)
16760 (set-register tinypgp-:register nil) ;Clear it
16762 (tinypgp-sign-region beg end verb options nil 'register 'as-is)
16765 (message "Detached signature in register '%s'"
16766 (char-to-string tinypgp-:register)))))
16768 ;;; ----------------------------------------------------------------------
16771 (defun tinypgp-sign-region
16772 (beg end &optional verb options noerr register as-is)
16777 BEG END ints, region
16778 VERB flag, verbose messages
16779 OPTIONS string, flags to add to the real pgp command.
16780 NOERR flag, return nil or t only
16781 REGISTER flag, save results to register
16782 AS-IS flag, if non-nil. no buffer modification is done.
16783 Normally would delete whitespaces at the end of lines.
16787 (barf-if-buffer-read-only)
16788 (if (null (region-active-p))
16789 (error "region not active"))
16796 current-prefix-arg)))
16798 (let ((fid "tinypgp-sign-region:")
16800 (barf-if-buffer-read-only)
16801 (tinypgp-i-args-pass-phrase "Sign region pass phrase:")
16803 (tinypgp-hash 'action 'put 'now 'sign 'global)
16804 (tinypgp-hash 'action 'put 'detail 'region 'global)
16807 (ti::buffer-trim-blanks beg end)) ;EOL whitespace strip
16809 (tinypgpd fid "in:" beg end verb options)
16811 (tinypgp-save-state-macro
16812 (tinypgp-user-change-macro
16815 (tinypgp-set-pgp-env-macro tinypgp-:user-now 'verb
16816 (tinypgp-cmd-macro 'sign tinypgp-:user-now nil
16817 "Signing..." register options))
16822 (tinypgp-set-pgp-env-macro tinypgp-:user-now 'verb
16823 (tinypgp-cmd-macro 'sign tinypgp-:user-now nil
16824 "Signing..." register options))
16828 (tinypgp-key-cache-update)
16829 (tinypgp-sign-data-set))
16834 ;;{{{ interactive, verifying
16836 ;;; ....................................................... &verifying ...
16838 ;;; ----------------------------------------------------------------------
16840 (defun tinypgp-verify-maybe-fetch-key (status-string)
16841 "If verify fails, asks if we should try to fetch key.
16844 STATUS-STRING ,the result of verify
16847 t ,if key fetch tried.
16849 (let* ((fid "tinypgp-verify-maybe-fetch-key:")
16850 (tinypgp-:find-by-guess-hook (copy-list tinypgp-:find-by-guess-hook))
16852 ;; We already tried these methods, there is finger
16854 (setq tinypgp-:find-by-guess-hook
16856 'tinypgp-key-find-by-cache
16858 'tinypgp-key-find-by-keyrings-verbose
16859 tinypgp-:find-by-guess-hook)))
16862 (ti::string-match "ID \\([^ \t]+\\) not found"
16865 ;; Key matching expected Key ID C4AF0331 not found in file
16866 ;; '/home/xxx/.pgp/pubring.pgp'.
16868 (tinypgpd fid "status" status-string key-id)
16871 (format "Can't verify: fetch key for %s ? "
16873 (tinypgp-key-find-by-guess key-id)
16876 ;;; ----------------------------------------------------------------------
16878 (defun tinypgp-verify-region (beg end &optional no-replace verb)
16879 "Verify message in region.
16881 If signature is good and there is some PGP message inside it,
16882 say encrypted to you, then message is replaced
16883 with the output of PGP. In short: message is unpacked.
16885 If there is no PGP, this function does nothing.
16889 BEG END region which is feed to PGP. If both are nil, then whole
16892 NO-REPLACE If non-nil prefix argument, the result is put into
16893 register instead. RBEG and REND are replace position beg
16894 and end points. They default to BEG and END. These
16895 arguments are useful if you feed whole buffer to PGP but
16896 want the replace tho happen only in cerating region.
16897 VERB Verbose messages
16900 `tinypgp-:verify-before-hook'
16901 `tinypgp-:verify-after-hook'"
16903 (tinypgpd "tinypgp-verify-region in:" no-replace verb)
16905 (let* ((cmd (tinypgp-binary-get-cmd 'verify))
16906 (fid "tinypgp-verify-region: ")
16907 (sig-holder (ignore-errors
16909 (ti::mail-email-from-string
16910 (mail-fetch-field "from")))
16911 ;; Maybe this is mail message that user has
16912 ;; just signed and he want to varify it himself
16913 tinypgp-:user-now)))
16925 (tinypgp-hash 'action 'put 'now 'verify 'global)
16926 (tinypgp-hash 'action 'put 'no-replace no-replace 'global)
16929 "Verifying signature..."
16932 (if (null (ti::mail-pgp-p))
16933 (if verb (message "No PGP tags found."))
16935 (run-hook-with-args-until-success
16936 'tinypgp-:verify-before-hook 'verify beg end)
16938 ;; Because we have our own hooks, we can use the
16939 ;; command macro, because if we'd call it see what happens:
16942 ;; macro (macro-B-hook macro-E-hook)
16945 ;; The macro-E-hook would e.g. cease rmail-edit-mode
16946 ;; already. That's why we don't use the macro here at all.
16948 (tinypgpd fid "verb sig-holder" verb sig-holder "BEG" beg end )
16950 (tinypgp-save-state-macro
16951 (when (and verb sig-holder)
16952 (if (or (setq pring (tinypgp-key-find-by-keyrings
16953 (tinypgp-key-id-conversion sig-holder)))
16954 ;; Hmmm, User's email weren't found, find HEX key-id
16955 ;; from base64 signature them. This is slower way
16957 (and (setq info (ti::mail-pgp-stream-forward-and-study t))
16960 (ti::mail-pgp-stream-data-elt
16963 (tinypgp-key-find-by-keyrings
16964 (tinypgp-key-id-conversion sig-holder)))
16966 Need From addr -- key-id conversion: use `tinypgp-email-substitution-add'")
16968 (setq tinypgp-:pubring-now pring)
16969 (tinypgpd fid "--Can't find key-id from keyrings")
16974 (format "Can't find %s from keyrings, call pgp anyway?"
16976 (setq stat (format "ID %s not found" sig-holder)))))
16978 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . action ..
16980 (tinypgpd fid "DO-IT" cmd beg end (current-buffer))
16981 (setq cmd (tinypgp-cmd-compose cmd nil))
16982 (if (or (tinypgp-backend-pgp2-p)
16983 (tinypgp-backend-gpg-p))
16984 (setq ret (tinypgp-binary-do-command-region
16985 cmd beg end (current-buffer) msg 'string))
16986 (setq ret (tinypgp-binary-do-command-region-with-expect
16987 cmd beg end (current-buffer) msg 'string))))
16991 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. result . .
16993 ;; Was it encrypted + signed message? The result removes
16994 ;; the signature around the region
16999 (setq ret "Good signature. Results unpacked to register.")))
17002 ((save-excursion ;Normal PGP signing
17003 (ti::mail-hmax 'move)
17006 (ti::mail-pgp-block-area 'signed)
17007 ;; Base64 signed then
17008 (ti::mail-pgp-block-area 'msg)))))
17009 ((and (ti::mail-pgp-headers-p) ;X-Pgp signed message?
17011 (ti::mail-text-start 'move)
17013 ;; Message is not yet verified if this is found
17015 (not (re-search-forward "^--+BEGIN.*PGP" nil t))))
17016 (setq region (cons (ti::mail-text-start) (point-max))))
17019 Cannot find PGP signature. Already verified or signature hidden?")))
17021 (tinypgpd "REGION" region (current-buffer))
17023 (delete-region (car region) (cdr region))
17024 (goto-char (car region) )
17025 (tinypgp-binary-insert-pointer-data ret 'beg)
17028 (tinypgp-binary-get-result-using-function
17029 'tinypgp-binary-get-result-verify))
17031 ;;; (setq stat (or (tinypgp-binary-get-result-verify-status) ""))
17032 (when (and (null no-replace) (ti::mail-pgp-headers-p))
17033 ;; We must remove the X-Pgp too.
17035 (tinypgp-signature-from-header 'just-remove-all))))
17037 (run-hook-with-args-until-success
17038 'tinypgp-:verify-after-hook 'verify beg end ret)
17040 (setq stat (or stat
17041 (tinypgp-binary-get-result-verify-status)
17044 ((and verb (tinypgp-verify-maybe-fetch-key stat))
17045 nil) ;Nothing more to do
17047 (setq msg (or (tinypgp-binary-get-result-verify-status)
17048 "<unknown verify status>"))
17049 (if (fboundp tinypgp-:verify-message-function)
17050 (funcall tinypgp-:verify-message-function msg)
17052 (tinypgpd fid "out: " ret "stat" stat)
17056 ;;; ----------------------------------------------------------------------
17058 (defun tinypgp-verify-detached-signature (file key-id &optional pring verb)
17059 "Verify detached signature in current buffer against file on disk.
17064 KEY-ID If this string has '@' e.g. 'mister foo <qf@site.com>'
17065 the key-id is automatically shortened to 'qf@site.com'.
17066 PRING If nil; all pubrings are searched to contain key-id and if none
17067 found, funtion calls error. The found keyring is used to call
17068 pgp with option +pubring
17069 VERB Verbose messages.
17074 nil verify successfull.
17077 `tinypgp-:buffer-tmp-shell' pgp response"
17080 (let* ((data (ti::mail-pgp-stream-forward-and-study 'search 'any))
17082 (key-id (and (eq type 'signed)
17083 (ti::mail-pgp-stream-data-elt data 'key-id))))
17084 (if (not (stringp key-id))
17085 (error "Can't find key id from PGP stream?")
17086 (setq key-id (concat "0x" key-id)))
17089 (read-file-name "Verify detach signed file: " nil nil t)
17091 (let* ((fid "tinypgp-verify-detached-signature:")
17096 (tinypgp-hash 'action 'put 'now 'verify 'global)
17097 (if (and (string-match "@" key-id)
17098 (setq email (car-safe (ti::mail-email-from-string key-id))))
17099 (setq key-id email))
17101 (tinypgpd fid "in:" file key-id "OPT" pring verb)
17103 (setq file (tinypgp-expand-file-name file))
17104 ;; First we have to know in what pubring the key is in, because
17105 ;; PGP needs pubring when it checks the key.
17108 (or (setq pring (tinypgp-key-find-by-cache key-id))
17109 (setq pring (tinypgp-key-find-by-keyrings key-id)))
17110 (error "Can't find '%s' from any pubring." key-id))
17111 (tinypgpd fid "pring" pring)
17113 (setq out (tinypgp-ti::temp-buffer 'shell))
17114 (save-excursion (ti::pmin) (tinypgp-file-control 'source-write))
17116 ;; call-process-region
17117 ;; START END PROGRAM
17118 ;; &optional DELETE DESTINATION DISPLAY
17121 ;; % pgp sig-file original-file
17125 (call-process-region (point-min) (point-max) "pgp"
17129 (not 'constant-display)
17131 tinypgp-:file-source
17133 (format "+pubring=%s" pring)))
17134 (tinypgp-file-control 'source-kill)
17136 ;;; (pop-to-buffer (current-buffer)) (ti::d! orig-file pring)
17137 ;;; (pop-to-buffer out)
17140 (message (or (tinypgp-binary-get-result-verify-status)
17141 (and (pop-to-buffer out)
17142 "<unknown verify results>"))))
17144 ;; Convert 0(pgp ok) to nil(lisp ok) return code
17150 ;;; ----------------------------------------------------------------------
17151 ;;; - parameters BEG and end _must_ be nil
17153 (defun tinypgp-verify-mail (&optional no-replace verb)
17154 "Verify message in mail buffer. See `tinypgp-verify-region' for more details.
17157 NO-REPLACE flag, store results to `tinypgp-:register'
17158 VERB flag, display verbose messages"
17160 (let ((fid "tinypgp-verify-mail:")
17165 (tinypgp-hash 'action 'put 'now 'verify 'global)
17166 (tinypgp-hash 'action 'put 'no-replace no-replace 'global)
17168 (tinypgpd fid "in:" no-replace verb)
17170 (when (tinypgp-hidden-p)
17171 (tinypgp-hide 'show)
17174 (tinypgp-verify-region
17175 nil nil ;it is not a good idea to pass region
17179 (setq stat (or (tinypgp-binary-get-result-verify-status)
17181 (when (and (null no-replace)
17182 (ti::mail-pgp-headers-p)
17183 (not (string-match "bad\\|not found" stat)))
17184 ;; We must remove the X-Pgp signed fields, if the status was ok
17186 (tinypgp-signature-from-header 'just-delete))
17192 ;;{{{ interactive, encrypting
17194 ;;; .......................................................... &encypt ...
17196 (defun tinypgp-encrypt-add-remailer-tag ()
17197 "Add' Encrypted: PGP' remailer tag to the point in mail mode buffers."
17198 (if (ti::mail-mail-mode-p)
17199 (insert "::\nEncrypted: PGP\n\n")))
17201 ;;; ----------------------------------------------------------------------
17203 (defun tinypgp-encrypt-allowed-check ()
17204 "In certains situations it is not allowed to encrypt the mail message.
17205 Check those cases and call error."
17208 ((and (tinypgp-nymserver-mail-p)
17209 (or (string-match "," (or (mail-fetch-field "To") ""))
17210 (mail-fetch-field "CC")))
17212 Impossible to encrypt Nymserver mail to multiple recipients.")))))
17214 ;;; ----------------------------------------------------------------------
17216 (defun tinypgp-encrypt-by-cache (string func &rest args)
17217 "If the STRING is found from cache, encrypt with FUNC and ARGS.
17222 (tinypgpd "tinypgp-encrypt-by-cache: " string func args )
17223 (let* ((pring (tinypgp-key-find-by-cache string)))
17224 ;; # todo: not tested
17226 (tinypgp-save-state-macro
17227 (setq tinypgp-:pubring-now pring)
17231 ;;; ----------------------------------------------------------------------
17233 (defun tinypgp-encrypt-mail-mime ()
17234 "Sign buffer as PGP/MIME using SEMI or TM."
17237 (unless (ti::re-search-check mail-header-separator)
17238 (error "Tinypgp: PGP/MIME needs mail buffer."))
17240 (tinypgpd "tinypgp-encrypt-mail-mime: MIME-P" (ti::mail-mime-feature-p))
17242 (when (ti::mail-mime-feature-p)
17243 (ti::mail-mime-turn-on-mode))
17245 (unless (or (not (ti::mail-mime-feature-p))
17246 (ti::mail-mime-encrypt-region))
17247 (error "Can't encrypt PGP/MIME. TM or SEMI is not active."))
17248 (ti::mail-mime-turn-off-mode))
17250 ;;; ----------------------------------------------------------------------
17252 (defun tinypgp-encrypt-mail-verbose (&optional arg)
17253 "Call `tinypgp-encrypt-mail' like user would with ARG."
17256 (tinypgp-encrypt-mail
17257 (,@ (tinypgp-encrypt-mail-i-args arg nil 'bquote))))))
17259 ;;; ----------------------------------------------------------------------
17261 (defun tinypgp-encrypt-mail-find-keyring (single &optional sign-pwd)
17262 "Find keyring for SINGLE key-id and encrypt and optionally use SIGN-PWD."
17263 (tinypgp-encrypt-mail single nil sign-pwd nil 'verb))
17265 ;;; ----------------------------------------------------------------------
17266 ;;; - parameters BEG and end _must_ be nil
17269 (defun tinypgp-encrypt-mail-sign
17270 (single-or-list &optional no-replace sign-pwd options verb noerr)
17271 "See `tinypgp-encrypt-mail'. Raise parameter 'sign'.
17272 SINGLE-OR-LIST NO-REPLACE SIGN-PWD OPTIONS VERB NOERR."
17273 (interactive (tinypgp-encrypt-mail-i-args
17277 (tinypgp-encrypt-mail
17278 single-or-list no-replace sign-pwd options verb noerr))
17280 ;;; ----------------------------------------------------------------------
17282 (defun tinypgp-encrypt-mail-i-args (&optional arg pwd bquote)
17283 "Read args for `tinypgp-encrypt-mail'.
17286 PWD If non-nil, ask password
17287 BQUOTE If you call this function in macro which uses ,@ you must
17288 set this flag to non-nil"
17289 (tinypgpd "tinypgp-encrypt-mail-i-args")
17293 ;; We need to protect this list or else Backquote
17294 ;; tries to call first element as a function
17296 (quote (tinypgp-i-args-read-email nil "Encrypt to: "))
17297 (tinypgp-i-args-read-email nil "Encrypt to: "))
17298 (or arg current-prefix-arg)
17300 (if (null tinypgp-:r-mode-indication-flag)
17301 (eval tinypgp-:pgp-binary-interactive-option))))
17303 ;;; ----------------------------------------------------------------------
17304 ;;; - parameters BEG and end _must_ be nil
17307 (defun tinypgp-encrypt-mail
17308 (single-or-list &optional no-replace sign-flag options verb noerr)
17309 "Encrypt mail buffer.
17313 SINGLE-OR-LIST List of key-ids. Interactive call reads To,CC,BCC.
17314 NO-REPLACE prefix arg, store result to `tinypgp-:register'.
17315 SIGN-FLAG if non-nil, sign at the same time as you encrypt.
17316 OPTIONS Additional pgp option string.
17317 VERB If non-nil, verbose messages.
17318 NOERR If non-nil, do not call error.
17320 Function call note:
17323 In case the EMAIL address you're sending doesn't have entry in your
17324 keyring, but you know that person has a PGP public key, then
17325 please remove the email address prior calling this function and
17326 it will prompt you a string to match for USER.
17328 If this function is called interactively, it tries to set right
17329 pubring by querying cache and other keyrings (user prompted)
17330 Also the `tinypgp-:pgp-binary-interactive-option' is suppressed if
17331 `tinypgp-:r-mode-indication-flag' is non-nil
17333 Normally the To field's address is read and used for encryption.
17334 However, if you are _on_ line that has email address in format
17335 <foo@site.com> then your are asked if you want to use this email
17336 instead. You can complete between this and To address.
17338 [when called as lisp function]
17339 Be sure to take precaution when passing OPTIONS if the message is
17340 sent to remailer. Any extra keyword, like 'Comment:'
17341 may reveal your identity.
17343 SINGLE-OR-LIST is not processed with `tinypgp-key-id-conversion'.
17344 You should call it manually if you want to respect user's
17345 substitution definitions.
17348 If there are multiple recipiens in the To, CC, BCC field the
17349 last keyring in the `tinypgp-pubring-table' is used when doing the
17354 single-or-list list of email addresses or KEY ID's
17355 no-replace flag, do not replace area with encryption
17356 options string, extra options passed to pgp exe
17357 verb flag, allow printing messages."
17358 (interactive (tinypgp-encrypt-mail-i-args current-prefix-arg))
17359 (let* ((fid "tinypgp-encrypt-mail:")
17360 (beg-text (ti::mail-text-start))
17366 (tinypgp-hash 'action 'put 'now 'encrypt 'global)
17367 (tinypgp-hash 'action 'put 'detail nil 'global)
17368 (tinypgp-hash 'action 'put 'no-replace no-replace 'global)
17370 (tinypgp-encrypt-allowed-check)
17372 (put 'tinypgp-:return-value 'find-by-keyrings nil) ;reset
17374 (tinypgpd "tinypgp-encrypt-mail in: "
17376 "no-rep" no-replace
17380 "BEG" beg (point-max))
17382 (unless single-or-list
17383 (error "single-or-list is empty"))
17385 (if (eq beg-text (point-max))
17386 (error "Nothing to do, no text found."))
17388 (setq single-or-list (tinypgp-user-list single-or-list))
17390 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. do it . .
17391 (setq single-or-list (ti::list-make single-or-list))
17393 (tinypgp-cmd-macro-email "Encrypt"
17394 (tinypgp-set-pgp-env-macro single-or-list 'verb
17396 ;; See the tinypgp-key-find-by-keyrings function.
17397 ;; Effective encrypt key may have changed
17399 (when (setq elt (get 'tinypgp-:return-value 'find-by-keyrings))
17400 (tinypgpd "tinypgp-encrypt-mail: KEY CHANGED " elt )
17401 (setq single-or-list (ti::list-make elt)))
17403 ;; Beacuse the Encrypt and signing is done
17404 ;; in 'One pass' both keys must be in same pubring.
17407 (tinypgpd fid "1pass: PUBRING CHANGED TO BIG")
17408 (tinypgp-hash 'action 'put '1pass nil 'global)
17409 (tinypgp-pubring-set-big))
17411 ;; single-or-list will be changed if it is nil.
17412 ;; --> user login name
17415 (if sign-flag 'encrypt-sign 'encrypt)
17418 "Encrypting...." no-replace options)
17420 ;; If all went ok, then we update cache, user XXX in in pubring YYY
17421 ;; All users must be in same pubring otherwise the previous command
17424 (dolist (elt single-or-list)
17425 (when (stringp elt)
17426 (tinypgp-key-cache 'put elt tinypgp-:pubring-now)))))
17428 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . results . .
17430 (when (and (null no-replace)
17431 (null buffer-read-only)
17432 tinypgp-:encrypt-after-function)
17433 (if (ti::mail-mail-p)
17434 (goto-char (ti::mail-text-start)) ;ignore other buffers
17437 (ti::save-with-marker-macro
17438 (funcall tinypgp-:encrypt-after-function)))
17442 "%d: Encrypted to %s %s"
17443 (length single-or-list)
17444 (ti::list-to-string single-or-list)
17445 (if (null sign-flag) ""
17446 (format "and signed [%s]" tinypgp-:user-now)))
17447 ;; Make sure this is seen
17450 ;;; ----------------------------------------------------------------------
17452 (defun tinypgp-encrypt-region-i-args (&optional pwd)
17453 "Ask arguments for `tinypgp-encrypt-region-i-args' possibly also asking PWD."
17454 (ti::list-merge-elements
17455 (tinypgp-i-args-reg-email "Encrypt to: ")
17457 (if pwd (tinypgp-password-set
17458 (format "[%s] Sign password: " tinypgp-:user-now)))
17459 (if (null tinypgp-:r-mode-indication-flag)
17460 (eval tinypgp-:pgp-binary-interactive-option))))
17462 ;;; ----------------------------------------------------------------------
17465 (defun tinypgp-encrypt-region-sign
17466 (beg end user &optional no-replace sign-pwd options verb)
17467 "Same as `tinypgp-encrypt-region' but raise 'sign' parameter.
17468 BEG END USER NO-REPLACE SIGN-PWD OPTIONS VERB"
17469 (interactive (tinypgp-encrypt-region-i-args 'pwd))
17471 (tinypgp-encrypt-region
17472 beg end user no-replace sign-pwd options verb))
17474 ;;; ----------------------------------------------------------------------
17477 (defun tinypgp-encrypt-region
17478 (beg end user &optional no-replace sign-pwd options verb)
17484 USER key-id (possibly email) or list of keyIds.
17485 NO-REPLACE prefix arg, store results to `tinypgp-:register'
17486 SIGN-PWD if non-nil string, Sign at the same time as you encrypt.
17487 OPTIONS Additional option string for PGP.
17488 VERB If non-nil, Verbose messages."
17489 (interactive (tinypgp-encrypt-region-i-args))
17490 (tinypgpd "tinypgp-encrypt-region in:"
17491 beg end user "replace" no-replace options verb)
17494 (tinypgp-encrypt-allowed-check)
17495 (tinypgp-password-set (format "[%s] Encrypt password: " tinypgp-:user-now))
17497 (tinypgp-hash 'action 'put 'now 'encrypt 'global)
17498 (tinypgp-hash 'action 'put 'no-replace no-replace 'global)
17500 (setq user (tinypgp-user-list user))
17502 (tinypgp-set-pgp-env-macro user 'verb
17504 (if sign-pwd 'encrypt-sign 'encrypt )
17507 "Encrypting...." no-replace options))
17509 ;; If all went ok, then we update cache, use XXX in in pubring YYY
17510 (tinypgp-key-cache-update (car (ti::list-make user))))
17512 ;;; ----------------------------------------------------------------------
17514 (defun tinypgp-encrypt-info (&optional register verb)
17515 "Check encrypted message and who can read it.
17516 If Flag REGISTER is non-nil store results to `tinypgp-:register'. VERB."
17518 (let* ((user tinypgp-:user-primary)
17525 (ignore-errors ;We know this generates error.
17526 (tinypgp-set-pgp-env-macro user 'verb
17531 "Checking encrypt users...." 'no-replace (not 'options))))
17532 (setq ptr (tinypgp-binary-get-result-encrypt-info))
17537 "TinyPgp: Can't find list of encrypt users. Maybe not encrypted."))
17539 (with-current-buffer (car ptr)
17540 (set-register tinypgp-:register
17541 (buffer-substring (nth 1 ptr) (nth 2 ptr))))
17543 (message "Encrypt info in register '%s'"
17544 (char-to-string tinypgp-:register))))
17546 (setq list (tinypgp-binary-get-result-encrypt-info-list ptr)
17547 str (ti::list-to-string list ","))
17549 (if (< (length str) 75)
17550 (message "Encrypt: %s" str)
17551 ;; Hm, Doesn't fit in echo area, so display in another window
17552 (tinypgp-ti::temp-buffer 'show)
17553 (display-buffer tinypgp-:buffer-tmp-show)
17554 (with-current-buffer (car ptr)
17555 (append-to-buffer tinypgp-:buffer-tmp-show
17556 (nth 1 ptr) (nth 2 ptr))))))))
17559 ;;{{{ interactive, decrypting
17561 ;;; .......................................................... &decypt ...
17563 ;;; ----------------------------------------------------------------------
17565 (defun tinypgp-decrypt-signed-base64
17566 (beg end user &optional no-replace verb)
17567 "Decrypt conventinally signed but base64 coded text.
17572 USER key-id string (possibly email)
17573 NO-REPLACE store results to `tinypgp-:register'
17574 VERB Verbose messages."
17575 (let* ((fid "tinypgp-decrypt-signed-base64: ")
17581 (tinypgp-hash 'action 'put 'now 'decrypt 'global)
17582 (setq file-out (ti::mail-pgp-comment-file-p beg))
17584 (tinypgpd fid "in:" beg end user no-replace verb)
17590 "Base64 block save contents to file: "
17591 nil (concat default-directory file-out) nil file-out))
17593 ((ti::nil-p file-write)
17594 (setq file-write nil))
17596 ((not (file-exists-p (file-name-directory file-write)))
17597 (error "No such directory %s" file-write))
17599 ((file-exists-p file-write)
17600 (if (y-or-n-p "File exists, overwrite?")
17601 (delete-file file-write)
17602 (error "Abort.")))))
17605 (setq no-replace t))
17607 (tinypgp-cmd-macro 'decrypt-base64 user nil "Decrypting..." no-replace)
17609 ;; The result of PGP is not delimited by any
17610 ;; --- TAG, so we cannot request replace now, but read the contents
17613 (with-current-buffer tinypgp-:buffer-tmp-shell
17614 (setq pointer (tinypgp-binary-get-result-base64))
17615 (unless pointer (tinypgp-error "No output from PGP.")))
17619 (with-current-buffer (tinypgp-ti::temp-buffer)
17620 (tinypgp-binary-insert-pointer-data pointer)
17621 (write-region (point-min) (point-max) file-write)
17623 (message "Wrote %s" file-write))
17625 (set-register tinypgp-:register
17626 (tinypgp-binary-get-result-as-string pointer)))
17628 (delete-region beg end)
17629 (tinypgp-binary-insert-pointer-data pointer)))))
17631 ;;; ----------------------------------------------------------------------
17633 (defun tinypgp-decrypt-arg-function (arg)
17634 "See how we should interpret the passed prefix ARG.
17635 If buffer is read-only, then assume, that it may be MAIL buffer
17636 or the like and honor the variable `tinypgp-:decrypt-arg-interpretation'
17638 If buffer is not read-only. return ARG as is."
17639 (if (not buffer-read-only) ;regular buffer
17642 ;; This may be MAIL buffer, because it is read only,
17643 ;; see how user want the arg to be intepreted.
17645 (if (null tinypgp-:decrypt-arg-interpretation)
17647 (if arg ;reverse sense
17649 tinypgp-:decrypt-arg-interpretation))))
17651 ;;; ----------------------------------------------------------------------
17653 (defun tinypgp-decrypt-mail-verbose (&optional prefix-arg)
17654 "Call `tinypgp-decrypt-mail' like user would with PREFIX-ARG."
17655 ;; Loonks cryptic? Not really, because i-args returns a
17656 ;; list and tinypgp-decrypt-mail needs individual args,
17657 ;; we use eval + backquote to construct command that
17658 ;; turns list into individual args before
17659 ;; it calls tinypgp-decrypt-mail.
17661 ;; Got it? No? Then you must learn backquote syntax first.
17664 (` (tinypgp-decrypt-mail
17665 (,@ (tinypgp-decrypt-mail-i-args prefix-arg))))))
17667 ;;; ----------------------------------------------------------------------
17669 (defun tinypgp-decrypt-mail-i-args (&optional arg)
17670 "Ask args to function `tinypgp-decrypt-mail'.
17671 ARG passed can be `current-prefix-arg' if that is known."
17672 (tinypgpd "tinypgp-decrypt-mail-i-args: ")
17673 (tinypgp-hash 'action 'put 'now 'decrypt 'global)
17675 (if (null (ti::mail-pgp-p))
17676 (error "Nothing to do. No pgp found."))
17679 (funcall tinypgp-:pgp-decrypt-arg-function arg)
17680 (tinypgp-i-args-decrypt)
17684 ;;; ----------------------------------------------------------------------
17687 (defun tinypgp-decrypt-mail (&optional no-replace type verb)
17688 "Decrypt mail buffer.
17689 The PGP data in the buffer is detected by reading the CTB bits:
17690 see pgpformat.doc in pgp documentation.
17694 NO-REPLACE flag, prefix arg instructs to show the cotent in
17695 separate buffer. See refrerence note too.
17696 If this is 'preview and verb argument is nil-nil,
17697 then automatically show content is different buffer.
17699 TYPE nil or \"pgp\" --> PGP encrypted
17700 \"base64\" --> base64 signed and
17701 \"conventional\" --> encrypted with conventional key.
17707 `tinypgp-:pgp-encrypted-p-function'
17708 `tinypgp-:decrypt-arg-interpretation' for interactive calls
17709 `tinypgp-:pgp-decrypt-arg-function' for interactive calls
17710 `tinypgp-:user-identity-table'"
17712 (interactive (tinypgp-decrypt-mail-i-args current-prefix-arg))
17713 (tinypgpd "tinypgp-decrypt-mail in:" no-replace type verb)
17715 (let* ((fid "tinypgp-decrypt-mail:")
17716 (region (save-excursion (ti::pmin) (ti::mail-pgp-block-area 'msg)))
17717 (beg (car-safe region))
17718 (end (cdr-safe region))
17719 (buffer (current-buffer))
17724 (tinypgp-hash 'action 'put 'now 'decrypt 'global)
17725 (tinypgp-hash 'action 'put 'type type 'global)
17726 (tinypgp-hash 'action 'put 'no-replace no-replace 'global)
17729 (error "No PGP encrypt block found."))
17731 (tinypgp-save-state-macro
17732 (tinypgpd fid "user" tinypgp-:user-now)
17734 ;; ... ... ... ... ... ... ... ... ... ... ... normally encrypted ...
17737 ((member type '("conventional" "pgp"))
17738 (tinypgp-save-state-macro
17739 (tinypgp-user-change-macro
17740 (tinypgp-cmd-macro-email "Decrypt"
17741 (tinypgp-decrypt-region beg end no-replace type verb)))))
17743 ;; ... ... ... ... ... ... ... ... ... ... ... ... ... ... base64 ..
17745 ((member type '("base64"))
17748 (setq buffer (tinypgp-ti::temp-buffer))
17749 (append-to-buffer buffer beg end))
17751 (with-current-buffer buffer
17753 ;; There may be several blocks, open them all.
17754 ;; This is the first one.
17756 (tinypgp-decrypt-signed-base64 beg end nil no-replace)
17757 (while (and (setq region
17760 (ti::mail-pgp-block-area 'msg)))
17761 (setq beg (car region) end (cdr region)))
17762 (tinypgp-decrypt-signed-base64 beg end nil no-replace))))
17764 (error "Unkown decrypt type '%s'" type))))
17766 (goto-char (ti::mail-text-start))
17768 ;; The message may have been encrypted and signed (one pass).
17772 (setq stat (tinypgp-binary-get-result-verify-status)))
17773 (message "[was signed] %s" stat))
17775 (tinypgp-hash 'action 'put 'type nil 'global) ;Clear this
17776 (tinypgpd "tinypgp-decrypt-mail out: user" tinypgp-:user-now)))
17778 ;;; ----------------------------------------------------------------------
17781 (defun tinypgp-decrypt-region (beg end &optional no-replace type verb)
17782 "Decrypt region. Signal error is there is no decrypt message.
17786 BEG END int, region
17787 NO-REPLACE flag, store contents to `tinypgp-:register'.
17788 If values is 'review and verb is non-nil, also display
17789 content in separate buffer. Calls `tinypgp-view-register'
17790 TYPE string, Decrypt type: conventional, base64 or pgp
17791 VERB flag, verbose messages"
17794 (tinypgpd "tinypgp-decrypt-region interactive")
17795 (ti::list-merge-elements
17796 (ti::i-macro-region-body)
17799 (tinypgp-i-args-decrypt))))
17801 (let* ((fid "tinypgp-decrypt-region")
17802 user) ;Must be defined due to macro
17804 (tinypgpd fid "in:" beg end no-replace type verb (current-buffer))
17806 (tinypgp-hash 'action 'put 'now 'decrypt 'global)
17807 (tinypgp-hash 'action 'put 'type type 'global)
17808 (tinypgp-hash 'action 'put 'no-replace no-replace 'global)
17810 (if (null (save-excursion (ti::pmin) (ti::mail-pgp-block-area 'msg)))
17811 (error "No PGP encrypt block found."))
17813 (tinypgpd fid "in:" beg end no-replace verb)
17814 (tinypgp-cmd-macro 'decrypt user nil "Decrypting..." no-replace)
17816 (when (and no-replace verb)
17817 (or (get-buffer-window tinypgp-:buffer-view t) ;already visible
17818 (eq no-replace 'preview)
17819 (y-or-n-p "View content in temp buffer? "))
17820 (tinypgp-view-register))
17822 (tinypgp-hash 'action 'put 'type nil 'global)))
17825 ;;{{{ interactive: regular crypting
17827 ;;; ............................................................ &cypt ...
17829 ;;; ----------------------------------------------------------------------
17832 (defun tinypgp-crypt-mail (password &optional no-replace comment verb)
17833 "Crypt mail buffer.
17837 PASSWORD pass phrase
17838 NO-REPLACE store contents to `tinypgp-:register'.
17839 COMMENT Additional comment added
17840 VERB verbose messages"
17843 (ti::compat-read-password "Crypt password: ")
17844 current-prefix-arg))
17845 (let* ((beg (ti::mail-text-start))
17847 (verb (or verb (interactive-p))))
17848 (tinypgp-hash 'action 'put 'now 'crypt 'global)
17849 (tinypgp-crypt-region beg end password no-replace comment verb)))
17851 ;;; ----------------------------------------------------------------------
17854 (defun tinypgp-crypt-region
17855 (beg end password &optional no-replace comment verb)
17861 PASSWORD pass phrase
17862 NO-REPLACE store contents to `tinypgp-:register'.
17863 COMMENT The comment string.
17864 VERB verbose messages"
17867 (barf-if-buffer-read-only)
17868 (ti::i-macro-region-body
17869 (read-from-minibuffer "Crypt password: ")
17873 (let* ((obuffer (current-buffer)))
17874 (tinypgp-hash 'action 'put 'now 'crypt 'global)
17876 (with-current-buffer (tinypgp-ti::temp-buffer)
17877 (insert-buffer-substring obuffer beg end)
17878 (ti::pmin) (tinypgp-file-control 'source-write)
17880 (tinypgp-crypt-do-with-pgp
17881 tinypgp-:file-source tinypgp-:file-output password (or comment ""))
17886 (insert-file-contents tinypgp-:file-output)
17887 (set-register tinypgp-:register (buffer-string)))
17889 (with-current-buffer obuffer
17890 (delete-region beg end) (goto-char beg)
17891 (insert-file-contents tinypgp-:file-output)))))
17892 (tinypgp-file-control 'source-kill)))
17895 ;;{{{ interactive, extra, header toggle
17897 ;;; ..................................................... &interactive ...
17899 ;;; ----------------------------------------------------------------------
17902 (defun tinypgp-xpgp-header-mode-toggle (&optional arg)
17903 "Toggle X-pgp header mode with ARG.
17906 `tinypgp-:header-sign-table' ,this variable overrides the signing mode."
17908 (ti::bool-toggle tinypgp-:xpgp-signing-mode arg)
17909 (if (interactive-p)
17911 (concat "TinyPgp: X-Pgp header mode: "
17912 (if tinypgp-:xpgp-signing-mode
17915 (tinypgp-update-modeline)
17916 tinypgp-:xpgp-signing-mode) ;return the changed value
17918 ;;; ----------------------------------------------------------------------
17921 (defun tinypgp-xpgp-header-toggle ()
17922 "Togle moving signature FROM/TO headers."
17925 ((null (tinypgp-mail-buffer-p 'message)))
17927 (ti::save-line-column-macro nil nil ;preserve user's position
17928 (with-buffer-modified
17930 ((ti::mail-pgp-headers-p)
17931 (tinypgp-signature-from-header))
17932 ((ti::mail-pgp-normal-p)
17933 (tinypgp-signature-move-to-header nil 'no-cnv))
17935 (message "No PGP signature found..."))))))))
17937 ;;; ----------------------------------------------------------------------
17939 (defun tinypgp-hide-gnus (&optional unhide)
17940 "Hide or UNHIDE pgp signature in GNUS."
17941 (let* ((buffer (if (boundp 'gnus-article-buffer)
17942 ;; Silence byteComp.
17943 (symbol-value 'gnus-article-buffer))))
17944 (when (stringp buffer)
17945 (with-current-buffer buffer
17948 ;;; ----------------------------------------------------------------------
17950 (defun tinypgp-hide (&optional unhide)
17951 "Hide PGP signatures, optionally UNHIDE."
17952 (ti::mail-pgp-signature-normal-do-region
17953 (tinypgp-invisible-region area-beg area-end unhide)
17954 ;; return value on success
17957 ;;; ----------------------------------------------------------------------
17959 (defun tinypgp-show ()
17960 "Show PGP signature."
17961 (tinypgp-hide 'show))
17963 ;;; ----------------------------------------------------------------------
17966 (defun tinypgp-hide-show-toggle ()
17967 "Togle hiding and showing the PGP signature."
17971 (if (tinypgp-hidden-p)
17974 (if (and (interactive-p)
17976 (message "No signature found to un/hide"))))
17979 ;;{{{ interactive, keyserver submit
17981 ;;; ................................................ &keyserver-submit ...
17983 ;;; ----------------------------------------------------------------------
17985 (defun tinypgp-keysrv-send-email-command (email command &optional arg)
17986 "Send to EMAIL address a keyserver COMMAND with ARG.
17987 The COMMAND is placed in the subject line. If command is 'add' then
17988 the current buffer is sent to keyserver.
17990 See keyserver documentation for more up to date command definitions:
17992 Command Message body contains
17993 --------------------------------------------------------------------
17994 ADD Your PGP public key (key to add is body of msg) (-ka)
17995 INDEX List all PGP keys the server knows about (-kv)
17996 VERBOSE INDEX List all PGP keys, verbose format (-kvv)
17997 GET Get the whole public key ring (-kxa *)
17998 GET <userid> Get just that one key (-kxa <userid>)
17999 MGET <userid> Get all keys which match <userid>
18000 LAST <n> Get all keys uploaded during last <n> days
18001 --------------------------------------------------------------------"
18003 (let* ((obuffer (current-buffer))
18008 (setq arg1 (tinypgp-ask-email-keyserver))
18009 (setq arg2 (completing-read
18011 (ti::list-to-assoc-menu
18012 '("help" "add" "index" "verbose index" "get"
18018 '(("get" . "<userid>")
18019 ("mget" . "<userid>")
18020 ("last" . "<nbr of days>"))))
18023 (read-from-minibuffer
18024 (format "%s, possible additional parameter %s: "
18027 (list arg1 arg2 arg3)))
18029 ;; .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . interactive end ..
18030 (let ((obuffer (current-buffer))
18033 (if (ti::nil-p email) (error "email is invalid."))
18034 (if (ti::nil-p command) (error "command is invalid."))
18037 ((string= "index" command)
18038 (if (null (y-or-n-p "\
18039 Really List all PGP keys the server knows about (-kv)? "))
18042 ((string= "verbose index" command)
18043 (if (null (y-or-n-p "\
18044 Really List all PGP keys, verbose format (-kvv) "))
18047 ((string= "get" command)
18048 (if (null (y-or-n-p "\
18049 Really Get the whole public key ring (-kxa *) "))
18052 ((string= "mget" command)
18053 (if (null (y-or-n-p (format "\
18054 Really Get all keys which match <userid %s> " arg)))
18057 ((and (string= "add" command)
18060 (unless (ti::mail-pgp-public-key-p)
18061 (error "I can't send this buffer, no public key found."))
18063 (setq insert-flag t))
18065 ((member command '("help" "last"))
18069 (error "unsupported command %s to %s" command email)))
18071 (ti::mail-sendmail-macro email command 'send
18072 ;;; (pop-to-buffer (current-buffer)) (ti::d! "__ksrv")
18074 (insert-buffer obuffer)))))
18077 ;;{{{ interactive: misc
18079 ;;; ........................................................... &imisc ...
18081 ;;; ----------------------------------------------------------------------
18083 (defun tinypgp-pgp-stream-forward-study (&optional verb)
18084 "Find PGP stream and display information from it. VERB.
18085 The information is stored to `tinypgp-:register'.
18087 Interactive call note:
18089 If can't find stream forward, then go to `point-min' and try searching
18094 (if (setq info (ti::mail-pgp-stream-forward-info 'search 'any))
18095 (set-register tinypgp-:register info)
18096 (setq info "Can't intepret/find PGP stream."))
18102 ;;; ........................................................ &examples ...
18103 ;;; - Rip code with tinylib.el/ti::package-rip-magic
18104 ;;; - Here is how I control PGP message sending: For company mail,
18105 ;;; I don't use PGP, but for outside wordl I use quite often.
18106 ;;; - Do not use autosigning if you decide to use this kind of control.
18108 ;;* (add-hook 'mail-send-hook 'my-tinypgp-ask-if-send-pgp-mail)
18110 ;;* ;;; ----------------------------------------------------------------------
18112 ;;* (defun my-tinypgp-ask-if-send-pgp-mail ()
18113 ;;* "See if we should ask to sign the mail with PGP.
18114 ;;* - If there is already PGP blocks, do nothing.
18115 ;;* - If these are local host email addresses, do not ask PGP signing.
18117 ;;* (require 'tinylibmail)
18118 ;;* (save-excursion
18119 ;;* (let* ((to (or (mail-fetch-field "to") ""))
18120 ;;* (subject (or (mail-fetch-field "subject") ""))
18121 ;;* ;; Exclude my local host addresses, Anon and remail posts
18123 ;;* (skip-address-p
18124 ;;* (or (string-match (concat
18125 ;;* "ntc\\|nokia\\|tne[0-9]\\|[an][na][0-9]"
18126 ;;* "\\|remail\\|@anon"
18129 ;;* ;; local mail addresses do not have @ --> skip PGP
18130 ;;* ;; TO field does not exist in news article
18132 ;;* (not (string-match "@" to))
18134 ;;* (mime (ti::re-search-check
18135 ;;* "^--[[]\\|^--+Multi\\|--pgp-"
18136 ;;* 0 '(ti::pmin)))
18137 ;;* (diff (ti::re-search-check
18138 ;;* "diff[ \t]+-[ucr]\\|^--- .*199[0-9]"))
18142 ;;* (defvar my-:pgp-previous-mail-subject nil)
18145 ;;* ;; .............................................. untabify maybe ...
18146 ;;* ;; Remove TABS; so that receiver can see the text as written
18148 ;;* (when (and (null diff) ;Skip diff message
18149 ;;* (not (ti::mail-pgp-encrypted-p)) ;already encrypted
18150 ;;* (not (ti::mail-pgp-p)) ;or other pgp
18152 ;;* (untabify (ti::mail-text-start) (point-max))
18155 ;;* ;; ........................................ should we sign this? ...
18156 ;;* ;; Raise flag if NO.
18158 ;;* (setq pgp-ask-no
18159 ;;* (or (not (featurep 'tinypgp))
18163 ;;* ;; In news this function is called twice, prevent asking
18164 ;;* ;; in the second time.
18166 ;;* (string= (or my-:pgp-previous-mail-subject "") subject)
18169 ;;* ;; ............................................ do signing maybe ...
18170 ;;* (when (and (null (ti::mail-pgp-p)) ;no previous pgp
18171 ;;* (null pgp-ask-no) ;Not a special message
18172 ;;* (y-or-n-p "PGP sign message? ")
18174 ;;* (call-interactively 'tinypgp-sign-mail))
18176 ;;* ;; - Well, I just want to have confirmation after C-c C-c
18177 ;;* ;; - Many times I have changed my mind, or missed something I
18178 ;;* ;; should have added. At this point there is a short break to
18179 ;;* ;; have a glimpse on the message
18180 ;;* ;; - I want to see the "Subject", because I may have auto-replied
18181 ;;* ;; and started talking about whole different things -->
18182 ;;* ;; I should have chnaged the subject. This way I don't
18183 ;;* ;; forgot to change it.
18185 ;;* (if (null (y-or-n-p (concat "Sending msg: " subject " ")))
18186 ;;* (error "Abort"))
18188 ;;* (setq my-:pgp-previous-mail-subject subject)
18189 ;;* nil ;hook return value
18193 ;;{{{ final install
18195 (setq tinypgp-:debug t)
18196 (when (null debug-on-error)
18197 (setq debug-on-error t))
18200 (tinypgp-install-modes) ;; Do this every time when package is loaded
18201 (tinypgp-install-to-current-emacs)
18203 ;; Until this package is labelled Alpha
18205 (unless (featurep 'tinypgp)
18206 (setq debug-on-error t)
18207 (tinypgp-initial-message))
18209 (tinypgp-newnym-account-expiry-warnings) ;when Newnym defined
18212 (run-hooks 'tinypgp-:load-hook)
18214 (error "TinyPgpg is no longer maintained. It will be removed in newar future.")
18218 ;;; tinypgp.el ends here