This commit was manufactured by cvs2svn to create branch 'emiko-1_14-epg'.
authortomo <tomo>
Mon, 20 Feb 2006 04:17:02 +0000 (04:17 +0000)
committertomo <tomo>
Mon, 20 Feb 2006 04:17:02 +0000 (04:17 +0000)
35 files changed:
ChangeLog
Makefile
NEWS
README.en
SEMI-ELS
SEMI-MK
VERSION
ftp.in
mail-mime-setup.el
mime-bbdb.el
mime-edit.el
mime-image.el
mime-mc.el
mime-partial.el
mime-pgp.el
mime-play.el
mime-setup.el
mime-ui-en.sgml
mime-ui-en.texi
mime-ui-ja.sgml
mime-ui-ja.texi
mime-vcard.el [new file with mode: 0644]
mime-view.el
mime-w3.el
pgg-def.el [new file with mode: 0644]
pgg-gpg.el [new file with mode: 0644]
pgg-parse.el [new file with mode: 0644]
pgg-pgp.el [new file with mode: 0644]
pgg-pgp5.el [new file with mode: 0644]
pgg.el [new file with mode: 0644]
pgg.texi [new file with mode: 0644]
postpet.el [new file with mode: 0644]
semi-def.el
semi-setup.el
signature.el

index 7591d3e..17d3e77 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+2006-02-18  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * mime-edit.el (mime-edit-delete-trailing-whitespace): New
+       Function for RFC3156.
+       (mime-edit-sign-pgp-mime): Use it.
+
+2003-12-18  Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg-gpg.el (pgg-gpg-process-region): Set environment variable
+       LANGUAGE as well.  GNU gettext gives precedence to LANGUAGE over
+       LC_ALL, when different language code is specified.  Thanks to
+       Tatsuya Kinoshita <tats@vega.ocn.ne.jp>.
+       [cf. <emacs-mime-ja:1599>]
+
+2003-12-17  Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg-gpg.el (pgg-gpg-messages-locale): New user option.
+       (pgg-gpg-process-region): Set environment variable LC_ALL when
+       pgg-gpg-messages-locale is specified.
+
+       * pgg-def.el (pgg-messages-locale): New user option.
+
+       * mime-pgp.el (mime-verify-application/pgp-signature): Copy
+       messages from pgg-errors-buffer.
+       (mime-add-application/pgp-keys): Ditto.
+
+2005-09-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-view.el (mime-view-insert-fontified-text-content): Disable
+       support modes.
+
+2005-06-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mime-view.el (mime-display-text/richtext): Withdraw the last
+       change.
+       (mime-display-text/enriched): Ditto.
+
+2005-06-09  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mime-view.el (mime-display-text/richtext): Turn off
+       adaptive-fill-mode while executing richtext-decode.
+       (mime-display-text/enriched): Turn off adaptive-fill-mode while
+       executing enriched-decode.
+
+2004-10-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mime-view.el (mime-view-insert-fontified-text-content): Inhibit
+       font-lock when running the major-mode function instead of forcing
+       execution of jit-lock.
+
+2004-10-21  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-view.el (mime-view-insert-fontified-text-content): Use
+       dummy absolute path in buffer-file-name. (by Katsumi Yamaoka)
+       Force fontify for jit-lock-mode.
+
+2004-09-27  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-edit.el (mime-edit-temp-message-buffer): Define.
+       * mime-play.el (mime-view-temp-message-buffer): Ditto.
+       (mime-preview-quitting-method-for-mime-show-message-mode): Change
+       accordingly.
+
+2004-09-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * README.en (CVS based development): Mention anonymous CVS access;
+       remove the description about developers' pserver access.
+
+2003-11-15  Simon Josefsson  <jas@extundo.com>
+
+       * pgg-gpg.el (pgg-scheme-lookup-key): Use regexp match instead of
+       split-string (split-string is different between emacs 21.2 and
+       21.4).  Reported by ultrasoul@ultrasoul.com (David D. Smith).
+
+2004-09-15  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-view.el (mime-preview-follow-current-entity): Avoid error
+       on null entity.
+       (mime-preview-find-boundary-info): Ditto.
+       Avoid error at the beginning of buffer.
+
+2004-08-29  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       Merge following changes from semi-1_14 branch:
+
+       * pgg-gpg.el (pgg-gpg-process-region): Use `make-temp-file' instead of
+       `make-temp-name'.
+       Add --yes option to overwrite existing output file;
+       Remove needless set-default-file-modes.
+       * pgg-pgp5.el (pgg-pgp5-process-region): Ditto.
+       (pgg-scheme-verify-region): Ditto.
+       (pgg-scheme-snarf-keys-region): Ditto.
+       * pgg-pgp.el (pgg-pgp-process-region): Ditto.
+       (pgg-scheme-verify-region): Ditto.
+       (pgg-scheme-snarf-keys-region): Ditto.
+       * mime-pgp.el (mime-verify-application/pgp-signature): Ditto.
+       * mime-play.el (mime-activate-mailcap-method): Make a temporary
+       directory of a temporary file for the mailcap application.
+       (mime-mailcap-method-sentinel): Follow the change above.
+       (mime-require-safe-directory): New function.
+       (mime-store-message/partial-piece): Use it.
+       Set `default-file-modes' for `make-directory'.
+       * mime-edit.el (mime-edit-split-and-send): Remove local variable
+       `mime-edit-draft-file-name'.
+
+       * mime-play.el (mime-play-delete-file-immediately): New user option.
+       (mime-mailcap-method-sentinel): Use it.
+       (mime-mailcap-delete-played-files): New function; set up for
+       `kill-emacs-hook'.
+
+2004-08-03  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-edit.el (mime-edit-mime-version-field-for-message/partial):
+       Fix usage of mime-encode-field-body.
+
+2004-07-24  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-view.el (mime-display-multipart/related): Do nothing when
+       the part is not found.
+
+2004-04-18  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * mime-edit.el (mime-file-types): Add application/pdf. Use base64
+       for application/postscript.
+       (mime-content-types): Add application/pdf.
+
+2004-04-04  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-edit.el (mime-file-types): Add application/vnd.ms-excel.
+       (mime-content-types): Add application/vnd.ms-excel and
+       application/msword.
+
+2004-02-12  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-image.el (mime-display-image): Ignore errors about image
+       decoding.
+
+2004-01-15  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mime-edit.el (mime-edit-normalize-body): Fix a comment that the
+       problem related to `replace-match' has been fixed at 2004-01-15,
+       thanks to Handa-san.
+
+2003-12-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mime-edit.el (mime-edit-normalize-body): Don't use the
+       `(replace-match "\\1\r\n")' form since it may convert the unibyte
+       string into multibyte in Emacs 21.4.
+
+2003-12-12  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-edit.el (mime-edit-user-agent-value): Add a setting for
+       XEmacs CHISE.
+
+2002-05-18  ARISAWA Akihiro  <ari@mbf.sphere.ne.jp>
+
+       * mime-play.el (mime-activate-mailcap-method): Don't use
+       `binary-to-text-funcall'. (Thanks to TANAKA Shingo)
+
+2003-12-14  Tatsuya Kinoshita  <tats@vega.ocn.ne.jp>
+
+       * mime-edit.el (mime-charset-type-list): Add entry for iso-8859-1[45].
+
+2003-08-16  Daiki Ueno <ueno@unixuser.org>
+
+       * Don't autoload S/MIME stuff.
+
+       * pgg-def.el (pgg-overriding-user-id): New variable.
+       * pgg.el (pgg-universal-user-id-argument): New command.
+       * pgg-gpg.el (pgg-scheme-encrypt-region): Prefer
+       pgg-overriding-user-id to pgg-gpg-user-id.
+       (pgg-scheme-decrypt-region): Ditto.
+       (pgg-scheme-sign-region): Ditto.
+       (pgg-scheme-insert-key): Ditto.
+
+2003-05-22  Daiki Ueno <ueno@unixuser.org>
+
+       * mime-play.el (mime-activate-mailcap-method): Undo the last change.
+
+2003-05-12  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-edit.el (turn-on-mime-edit): Protect 1st arg of `message'.
+       * mime-view.el (mime-preview-follow-current-entity): Ditto.
+
+2003-05-11  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-w3.el (mime-preview-text/html): Protect 1st arg of `message'.
+       * mime-play.el (mime-mailcap-method-sentinel): Ditto.
+       (mime-view-message/external-anon-ftp): Ditto.
+       (mime-view-message/external-url): Ditto.
+
+2003-05-02  Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-play.el (mime-activate-mailcap-method): Check the existance
+       of the temporary file.
+       [cf. <Wanderlust:11835>]
+
+2003-04-05  Yoichi NAKAYAMA  <yoichi@geiin.org>
+
+       * mime-view.el (mime-preview-toggle-display): Use boundary with
+       children.
+
+2003-02-08  Yoichi NAKAYAMA  <yoichi@eken.phys.nagoya-u.ac.jp>
+
+       * mime-view.el (mime-save-situation-examples): Bind print-length
+       and print-level.
+
+2002-11-05  Yoichi NAKAYAMA  <yoichi@eken.phys.nagoya-u.ac.jp>
+
+       * mime-view.el (mime-preview-find-boundary-info): Change the name of
+       the argument from get-mother to with-children along its effect.
+
+2002-11-03  Yoichi NAKAYAMA  <yoichi@eken.phys.nagoya-u.ac.jp>
+
+       * mime-edit.el (mime-edit-decode-single-part-in-buffer): Decode text
+       part only.
+
+2002-11-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mime-view.el (mime-view-insert-fontified-text-content): Make
+       sure font-lock is loaded before using it.
+
+2002-10-26  Yoichi NAKAYAMA  <yoichi@eken.phys.nagoya-u.ac.jp>
+
+       * mime-view.el (mime-preview-find-boundary-info): Fix logic. Do not
+       refer next to next part before examining the next part.
+
+2002-08-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * mime-edit.el (mime-edit-user-agent-value): Add
+       `xemacs-extra-name'.
+
+2002-04-16   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-edit.el (mime-file-types): Add setting of *.jpeg for image/jpeg.
+
+2002-03-06   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-view-read-charset): Remove redundant checking for
+       sanity when reading MIME-charset.
+       [cf. <emacs-mime-ja:995>]
+
+2002-02-14  Yuuichi Teranishi <teranisi@gohome.org>
+
+       * mime-image.el (mime-image-create) [XEmacs]: Ignore errors about
+       to obtain the instance of glyph's image.
+       [cf. <emacs-mime-ja:989>]
+
+2001-11-27   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-w3.el: Don't use `url-register-protocol' if it is not fboundp;
+       announce `url-cid' feature instead.
+       [cf. <Wanderlust:8566>]
+
+       (url-cid): Change return value for the current URL package.
+
+2001-11-05  Yuuichi Teranishi  <teranisi@gohome.org>
+
+       * mime-play.el (mime-play-entity): Use return value of
+       `mime-entity-situation' to get content type information;
+       Fix problem when method is invoked at menu selection;
+       Fix the message displayed on echo buffer when no method is specified;
+       Clear minibuffer after `y-or-n-p'.
+
+       * semi-def.el (mime-should-use-popup-menu) [Emacs]: Use
+       `event-basic-type' instead of `event-modifiers' to detect mouse
+       operation.
+
+2001-10-02   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el: Add `mime-view-maybe-inherit-widget-keymap' to
+       `mime-view-mode-map' instead of `mime-view-define-keymap-hook'.
+       [cf. <emacs-mime-ja:950>]
+
+       * mime-bbdb.el: Add `mime-bbdb/define-keys' to `mime-view-mode-map'
+       instead of `mime-view-define-keymap-hook'.
+
+2001-09-27  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * mime-edit.el (mime-edit-content-end): Return the value of
+       `point-max' when the function `next-single-property-change'
+       returns nil.
+
+2001-09-25   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-view-entity-content): New function.
+       (mime-view-insert-text-content): Try to display compressed contents.
+       (mime-view-filter-text-content): New function.
+       (mime-view-automatic-conversion): New variable.
+
+2001-09-25   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-view-insert-fontified-text-content): Don't use
+       `set-visited-filename'; set `buffer-file-name' temporarily.
+
+2001-09-25   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-view-guess-encoding): Rename from
+       `mime-view-default-content-transfer-encoding'.
+       (mime-view-read-encoding): Rename from
+       `mime-view-read-content-transfer-encoding'.
+       (mime-view-guess-charset): Rename from `mime-view-default-charset'.
+       Use `mime-entity-parameters'.
+
+       * semi-def.el (mime-user-interface-product): Bump up to EMIKO 1.14.1.
+
+2001-09-24   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-view-default-charset): Rename from
+       `mime-view-default-mime-charset'.
+       (mime-view-read-charset): Rename from `mime-view-read-mime-charset'.
+       (mime-preview-toggle-display): Respect "*charset" rather than
+       "*mime-charset".
+
+2001-09-24   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el: Require `mcharset'.
+       (mime-view-insert-text-content): Rewrite.
+       (mime-view-default-content-transfer-encoding): New function.
+       (mime-view-read-content-transfer-encoding): New function.
+       (mime-view-default-mime-charset): New function.
+       (mime-view-read-mime-charset): New function.
+       (mime-preview-toggle-display): If called with a prefix argument ask
+       user how to decode the entity.
+
+2001-09-24   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-view-insert-text-content): New function.
+       (mime-view-insert-fontified-text-content): Rename from
+       `mime-display-inline-fontify'.
+       (mime-display-text/plain): Use `mime-view-insert-text-content'
+       instead of `mime-insert-text-content'.
+       (mime-display-text/richtext): Likewise.
+       (mime-display-text/enriched): Likewise.
+       (mime-display-application/emacs-lisp): Likewise.
+
+2001-09-24   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-preview-toggle-display): When both "type" and
+       "*type" conditions are not specified, the entity should be regarded
+       as invisible.
+
+2001-09-24   Daiki Ueno  <ueno@unixuser.org>
+
+       * semi-def.el (mime-should-use-popup-menu): New function.
+       (mime-menu-select): New function which wraps the call of the function
+       `mime-popup-menu-select'.
+
+       * mime-play.el (mime-play-entity): Uniquify menu items before asking
+       user.
+
+2001-09-24   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-display-inline-fontify): Reset the visited
+       filename.
+
+2001-09-24   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-preview-inline-fontify): New variable.
+       (mime-display-text/plain): Fontify the attached part as possible.
+       (mime-display-inline-fontify): Make the second argument MODE optional.
+
+2001-09-23   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el: Add setting to fontify the inline part of
+       application/emacs-lisp.
+       (mime-display-inline-fontify): New function stolen from mm-view.el.
+       (mime-display-application/emacs-lisp): Use it.
+
+2001-09-10   Daiki Ueno  <ueno@unixuser.org>
+
+       * semi-def.el (mime-browse-url-regexp): Add ";".
+
+2001-09-08   Daiki Ueno  <ueno@unixuser.org>
+
+       * semi-setup.el (call-after-load): Abolish.
+       - Use locate-library instead of module-installed-p not to require
+       `path-util'.
+       - Delay referring to `mime-setup-enable-inline-image',
+       `mime-setup-enable-inline-html', `mime-setup-enable-vcard', and
+       `mime-setup-enable-pgp' until when `mime-view' is loaded.
+
+2001-08-10  Kenichi OKADA <okada@opaopa.org>
+
+       * semi-def.el (mime-browse-url-regexp): Allow nntps and ftps.
+
+2001-06-12  Yuuichi Teranishi <teranisi@gohome.org>
+
+       * mime-view.el (mime-display-multipart/related): When "start"
+       parameter specifies part, treat the part as root.
+
+2001-06-12  Akihiro Arisawa  <ari@mbf.sphere.ne.jp>
+
+       * mime-view.el (mime-display-multipart/related): New function; set up
+       for `mime-preview-condition'.
+
+2001-06-02   Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg.texi (Registering backend): New section.
+
+       * pgg.el (pgg-decrypt-condition): Add RIJNDAEL, RIJNDAEL192,
+       and RIJNDAEL256 for GnuPG
+
+2001-06-02   Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg.texi: New file.
+
+2001-05-06   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-display-message/partial-button): Don't use
+       `mime-add-button'. [cf. <Elips:4199>]
+
+       * mime-edit.el (mime-edit-normalize-body): Use
+       `remove-text-properties' instead of `visible-region'.
+
+2001-05-05   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-edit.el (mime-edit-sign-smime): Use OpenSSL output as it is.
+       (mime-edit-encrypt-smime): Ditto.
+
+       * semi-setup.el: Revive setting for application/x-pkcs7-signature.
+
+2001-05-05   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-pgp.el: Add autoload settings for S/MIME functions.
+       (mime-verify-application/pkcs7-signature): New implementation.
+
+       * mime-edit.el (mime-edit-sign-smime): New implementation.
+       (mime-edit-encrypt-smime): Ditto.
+
+       * semi-setup.el: Revive setting for application/x-pkcs7-signature.
+
+       * smime.el: Removed.
+
+       * SEMI-ELS (semi-modules-to-compile): Don't compile smime.el.
+
+2001-04-19  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * mime-bbdb.el: Load "bbdb-hooks" when the symbol function
+       `bbdb-extract-field-value' is not bound or it is set up as an
+       autoloaded function. [cf. <emacs-mime-ja:799,842,843,844,845,846>]
+
+2001-04-17  YAMASHITA Junji   <ysjj@unixuser.org>
+
+       * semi-def.el (mime-browse-url-regexp): Allow https.
+
+2001-03-06  Hiroya Murata     <lapis-lazuli@pop06.odn.ne.jp>
+
+       * mime-edit.el (mime-edit-set-parameter): Get rid of the duplicated
+       optional fields.
+
+2000-12-28  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-view.el: Revert to use `static'.
+
+2000-12-26   Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg-pgp.el (pgg-pgp-messages-coding-system): Abolish.
+       (pgg-pgp-process-region): Use `binary-funcall' instead of
+       `binary-to-text-funcall'.
+
+       * pgg-pgp5.el (pgg-pgp5-messages-coding-system): Abolish.
+       (pgg-pgp5-process-region): Use `binary-funcall' instead of
+       `binary-to-text-funcall'.
+
+\f
+2000-12-28  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * SEMI: Version 1.14.3 (Ushinoya) released.
+
+       * mime-view.el (mime-view-read-situation-examples-file): Don't try
+       to read situation-examples-file is it is nil.
+       (mime-situation-examples-file): Avoid to read
+       situation-examples-file at compile time.
+
+2000-12-28  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-view.el (mime-view-read-situation-examples-file): Display
+       warning. [cf. <emacs-mime-ja:680>]
+
+2000-12-27  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-view.el (mime-view-mailcap-files): New user option.
+       (mime-view-read-mailcap-files): Renamed from
+       `mime-view-read-mailcap'; read `mime-view-mailcap-files'.
+
+       * mime-view.el (mime-view-read-situation-examples-file): New
+       function; don't occur error.
+       (mime-view-read-mailcap): New function.
+
+2000-12-27  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-play.el (mime-play-messages-coding-system): Renamed from
+       `mime-mailcap-method-messages-coding-system'.
+
+       * pgg-def.el (pgg-messages-coding-system): Change default value to
+       nil.
+
+2000-12-27  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-play.el (mime-activate-mailcap-method): Fix typo.
+
+2000-12-26   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-play.el (mime-mailcap-method-messages-coding-system): New
+       variable.
+       (mime-activate-mailcap-method): Use it.
+
+\f
+2000-12-25  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * SEMI: Version 1.14.2 (Daish\e-Dòji)\e-A released.
+
+       * README.en (Required environment): Update to FLIM 1.14.2.
+
+       * mail-mime-setup.el (mail-setup-hook): Don't add
+       `eword-decode-header'.
+
+2000-12-23  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-view.el (mime-view-define-keymap): Return
+       `mime-view-mode-map' instead of set up as local keymap; don't call
+       `mime-view-define-keymap-hook'.
+       (mime-display-message): Add new optional argument `keymap'.
+
+       * mime-play.el (mime-store-message/partial-piece): Use
+       `binary-insert-encoded-file' and `binary-write-decoded-region'
+       instead of `binary-insert-file-contents' and
+       `binary-write-region'.
+
+2000-12-23  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * smime.el (smime-process-region): Use `binary-funcall' instead of
+       `binary-start-process-shell-command'.
+       (smime-verify-region): Use `binary-write-decoded-region' and
+       `binary-insert-encoded-file' instead of `binary-write-region' and
+       `binary-insert-file-contents'.
+
+       * pgg-pgp5.el (pgg-pgp5-messages-coding-system): New variable.
+       (pgg-pgp5-process-region): Use `binary-to-text-funcall' instead of
+       `binary-start-process-shell-command'.
+       (pgg-scheme-verify-region): Use `binary-write-decoded-region'
+       instead of `binary-write-region'.
+
+       * pgg-pgp.el (pgg-pgp-messages-coding-system): New variable.
+       (pgg-pgp-process-region): Use `binary-to-text-funcall' instead of
+       `binary-start-process-shell-command'.
+       (pgg-scheme-verify-region): Use `binary-write-decoded-region'
+       instead of `binary-write-region'.
+
+       * pgg-gpg.el (pgg-gpg-process-region): Use
+       `binary-to-text-funcall' instead of `binary-start-process'.
+
+2000-12-22   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-view-define-keymap): Bind [down-mouse-3]
+       instead of `mouse-button-3'.
+
+\f
+2000-12-22  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * SEMI: Version 1.14.1 (Kaga-Onsen) released.
+
+       * README.en (Required environment): Require FLIM 1.14.1 or later;
+       update required emacsen.
+
+2000-12-22  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * pgg-gpg.el (pgg-gpg-process-region): Use
+       `pgg-gpg-messages-coding-system'.
+
+2000-12-21  Tadashi Watanabe  <watanabe@sigmaitec.co.jp>
+
+       * pgg-gpg.el (pgg-scheme-verify-region): Use a "-" as the name for
+       the file with the signed material.
+
+2000-12-21   Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg-def.el (pgg-messages-coding-system): New user option.
+
+       * pgg-gpg.el (pgg-gpg-messages-coding-system): New variable.
+       (pgg-gpg-process-region): Don't use `binary-start-process'; bind
+       `coding-system-for-read' to `pgg-gpg-messages-coding-system'.
+
+2000-12-20  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * SEMI: Version 1.14.0 (Iburihashi) released.
+
+2000-12-19  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-edit.el (mime-edit-mime-version-field-for-message/partial):
+       Use `mime-encode-field-body' instead of `eword-encode-field-body'.
+
+2000-12-19  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-edit.el (mime-edit-translate-header): Use
+       `mime-encode-header-in-buffer' instead of `eword-encode-header'.
+       (mime-edit-encrypt-pgp-mime): Likewise.
+       (mime-edit-translate-single-part-tag): Likewise.
+
+2000-12-17  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * postpet.el: Require `mime'.
+
+       * pgg-parse.el (pgg-format-key-identifier): Don't use
+       `string-to-int-list'.
+       (pgg-read-bytes): Likewise.
+       (pgg-read-body): Likewise.
+
+2000-12-16  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * smime.el: Require `raw-io'.
+       (smime-process-region): Use `binary-start-process-shell-command'.
+
+       * pgg-pgp5.el (pgg-pgp5-process-region): Use
+       `binary-start-process-shell-command'.
+
+       * pgg-pgp.el (pgg-pgp-process-region): Use
+       `binary-start-process-shell-command'.
+
+       * pgg-gpg.el (pgg-gpg-process-region): Use `binary-start-process'.
+
+2000-12-15  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * pgg-def.el: Require `custom' instead of `pcustom'.
+
+2000-12-15  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * Makefile (tar): Use `cvs tag -R' instead of `cvs tag -RF'.
+
+2000-12-15  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * smime.el (smime-process-region): Don't use `as-binary-process'.
+       (smime-verify-region): Use `binary-write-region' instead of
+       `write-region-as-binary'; use `binary-insert-file-contents'
+       instead of `insert-file-contents-as-binary'.
+
+       * semi-def.el: Don't require `poe'.
+
+       * pgg-pgp5.el (pgg-pgp5-process-region): Don't use
+       `as-binary-process'.
+       (pgg-scheme-verify-region): Use `binary-write-region' instead of
+       `write-region-as-binary'.
+       (pgg-scheme-snarf-keys-region): Don't use
+       `write-region-as-raw-text-CRLF'.
+
+       * pgg-pgp.el (pgg-pgp-process-region): Don't use
+       `as-binary-process'.
+       (pgg-scheme-verify-region): Use `binary-write-region' instead of
+       `write-region-as-binary'.
+       (pgg-scheme-snarf-keys-region): Don't use
+       `write-region-as-raw-text-CRLF'.
+
+       * pgg-parse.el: Don't require `poem'; require `custom' instead of
+       `pcustom'.
+
+       * pgg-gpg.el (pgg-gpg-process-region): Don't use
+       `as-binary-output-file' and
+       `insert-file-contents-as-raw-text-CRLF'.
+
+       * mime-view.el: Don't require `emu'.
+       (mouse-button-3): New variable.
+
+       * mime-play.el (mime-store-message/partial-piece): Use
+       `binary-insert-file-contents' instead of
+       `insert-file-contents-as-binary'; don't use
+       `as-binary-input-file'; use `binary-write-region' instead of
+       `write-region-as-binary'.
+
+2000-12-07  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-w3.el: Avoid error even if `w3' is not found.
+
+2000-11-26  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-view.el: Use `mime-conf' instead of `mailcap'.
+
+       * mime-play.el (mime-activate-mailcap-method): Use
+       `mime-format-mailcap-command' instead of `mailcap-format-command'.
+
+2000-10-31   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-edit.el: Don't require `invisible'.
+       (mime-edit-insert-voice): Don't use `mime-edit-invisible-region'.
+       (mime-edit-insert-binary-file): Ditto.
+       (mime-edit-content-end): Don't use `mime-edit-invisible-p' and
+       `mime-edit-next-visible-point'.
+       (mime-edit-invisible-region): Abolish.
+       (mime-edit-invisible-p): Abolish.
+       (mime-edit-next-visible-point): Abolish.
+       (turn-on-mime-edit): Don't call `enable-invisible'.
+       (mime-edit-exit): Don't call `end-of-invisible'.
+
+2000-10-31   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-edit.el (mime-edit-insert-voice): Add text-property
+       `mime-edit-invisible'.
+       (mime-edit-insert-binary-file): Ditto.
+       (mime-edit-content-end): Check text-property `mime-edit-invisible'
+       instead of `invisible'.
+       (mime-edit-invisible-region): New function.
+       (mime-edit-invisible-p): New function.
+       (mime-edit-next-visible-point): New function.
+
+2000-10-19  Takanori Saneto  <sanewo@ba2.so-net.ne.jp>
+
+       * pgg-pgp.el (pgg-pgp-process-region): bind process-environment
+       locally so that setenv's effect won't last forever.
+       pgg-pgp5.el (pgg-pgp5-process-region): Ditto.
+
+2000-09-29  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-edit.el (mime-file-types): Fix to use application/msword
+       instead of application/winword.
+
+2000-09-13   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-play.el (mime-play-entity): Pass easymenu-style menu to
+       `mime-popup-menu-select'.
+
+       * semi-def.el (mime-popup-menu-popup): Rename from `mime-menu-popup'.
+       (mime-popup-menu-select): Rename from `select-menu-alist'.
+       (mime-popup-menu-select) [XEmacs]: Use `get-popup-menu-response'.
+       (mime-popup-menu-bogus-filter-constructor): Abolish argument `name'.
+
+2000-09-13   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-view-xemacs-popup-menu): Abolish.
+       (mime-view-menu-title): Abolish.
+       (mime-view-menu-list): Rewrite in easymenu-style.
+       (mime-view-popup-menu): New function.
+       (mime-view-define-keymap): Simplify; don't check `emacs-major-version'.
+
+       * semi-def.el (mime-menu-bogus-filter-constructor): New macro.
+       (mime-menu-popup): New macro.
+       (select-menu-alist): Rewrite with `defun-maybe-cond'.
+       (mime-insert-button): Use `widget-convert-button'.
+       (mime-url-link): New widget.
+
+2000-09-12   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (widget-keymap): Declare.
+       (mime-view-maybe-inherit-widget-keymap): New function.
+       (mime-view-define-keymap-hook): Add
+       `mime-view-maybe-inherit-widget-keymap'.
+
+       * semi-def.el: Add setting for `widget-convert-button' to
+       autoload "wid-edit".
+       (mime-button-mother-dispatcher): Abolish.
+       (mime-button-dispatcher): Abolish.
+       (mime-add-button): Abolish.
+       (mime-button-action): New function.
+       (mime-button): New widget.
+       (mime-add-url-buttons): Rewrite with `url-link' widget.
+       (mime-button-face): Abolish.
+       (mime-button-mouse-face): Abolish.
+
+2000-08-28   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-view.el (mime-display-entity): Call `mime-add-url-buttons'.
+
+2000-08-22   Daiki Ueno  <ueno@unixuser.org>
+
+       * SEMI-ELS: Compile `mime-vcard' only when vcard.el is available.
+
+2000-08-21   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-vcard.el: New module.
+
+       * semi-setup.el: Remove `application/x-pkcs7-signature',
+       `application/x-pkcs7-mime'.
+       Set up for "text/x-vcard".
+       (mime-setup-enable-vcard): New variable.
+
+       * pgg-parse.el (pgg-decode-packets): Use `buffer-string' instead
+       of `buffer-substring'.
+
+       * mime-view.el: Add setting for 'vcard-parse-string',
+       `vcard-format-string' and `vcard-filter-html' to autoload "vcard".
+       Set up for "text/x-vcard".
+       Add setting for `fill-flowed' to autoload "flow-fill".
+       (mime-display-text/plain): Handle "format=flowed".
+       (mime-preview-fill-flowed-text): New variable.
+
+2000-08-11  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-display-text/plain): Display warning message
+       when `mime-insert-text-content' fails.
+
+2000-08-04   Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg-gpg.el (pgg-gpg-process-region): Don't bind
+       coding-system-for-read.
+
+\f
+2000-07-12  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * REMI: Version 1.14.2 (Hokuhoku-\e-DÃ’shima)\e-A released.
+
+       * README.en (Required environment): Modify for FLIM-Chao 1.14.1.
+
+2000-07-11  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-pgp.el (mime-view-application/pgp): Setup local variable
+       `mime-view-temp-message-buffer' of preview-buffer.
+       (mime-view-application/pkcs7-mime): Likewise.
+
+       * mime-play.el
+       (mime-preview-quitting-method-for-mime-show-message-mode): Don't
+       use `mime-entity-buffer'; refer `mime-view-temp-message-buffer'.
+       (mime-store-message/partial-piece): Use
+       `insert-file-contents-as-binary' instead of
+       `(as-binary-input-file (insert-file-contents ...))'; use
+       `write-region-as-binary' instead of
+       `(as-binary-output-file (write-region ...)); setup local variable
+       `mime-view-temp-message-buffer' of preview-buffer.
+
+2000-07-04  Yuuichi Teranishi  <teranisi@gohome.org>
+
+       * mime-image.el (mime-image-insert) [XEmacs]:
+       Insert `string' only if it is non-nil.
+
+2000-06-27   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-image.el (mime-image-insert): Synch with the latest image.el.
+       (mime-display-image): Don't pass underlying string "x".
+
+2000-06-23  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-edit.el (mime-edit-preview-message): Set up local variable
+       `mime-edit-temp-message-buffer'.
+       (mime-edit-quitting-method): Refer `mime-edit-temp-message-buffer'
+       to avoid to use `mime-entity-buffer'.
+
+2000-06-21  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-view.el (mime-view-mode): Use
+       `mime-entity-set-content-type' and `mime-entity-set-encoding'
+       instead of `mime-entity-set-content-type-internal' and
+       `mime-entity-set-encoding-internal'.
+
+       * mime-w3.el (mime-preview-text/html): Use
+       `mime-find-root-entity'.
+
+2000-06-09   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-edit.el (mime-edit-insert-key): Insert a text tag when
+       the buffer has any trailing text.
+
+2000-06-05  Shugo Maeda <shugo@ruby-lang.org>
+
+       * pgg-gpg.el (pgg-scheme-insert-key): Don't quote user id.
+
+2000-05-25  Tanaka Akira      <akr@m17n.org>
+
+        * README.en: Update for CVS via SSH.
+
+2000-05-21   Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg-gpg.el (pgg-gpg-process-region): Abolish redundant nconc.
+
+2000-05-16   Daiki Ueno  <ueno@unixuser.org>
+
+       * mime-image.el (mime-image-create) [XEmacs]: Don't call
+       `make-image-instance' directly.
+
+2000-05-02   Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg-gpg.el (pgg-scheme-encrypt-region): Don't quote recipient;
+       concatenate all arguments destructively.
+
+2000-04-28  MORIOKA Tomohiko  <tomo@kanji.zinbun.kyoto-u.ac.jp>
+
+       * mime-edit.el (mime-charset-type-list): Add `iso-2022-jp-3'.
+
+2000-04-13   Daiki Ueno  <ueno@unixuser.org>
+
+       * pgg-gpg.el: Fix author's mailing address.
+       (pgg-gpg-process-region): Add --output option; set status fd to 2.
+       (pgg-gpg-possibly-cache-passphrase): New function.
+       (pgg-gpg-shell-file-name): Abolish.
+       (pgg-gpg-shell-command-switch): Abolish.
+       (pgg-scheme-lookup-key): Work on temp buffer.
+
+2000-03-01  Yoshiki Hayashi <yoshiki@xemacs.org>
+
+       * mime-image.el (mime-display-image): Don't wait for redisplay.
+
+\f
+2000-03-01  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * REMI: Version 1.14.1 (Mushigawa\e-Dòsugi)\e-A released.
+
+2000-03-01  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-view-define-keymap): Add new binding
+       `mime-preview-show-header' for C-c C-v C-f and C-c C-v h; add new
+       binding `mime-preview-show-content' for C-c C-v C-c; add new
+       binding `mime-preview-hide-header' for C-c C-d C-f and C-c C-d h;
+       add new binding `mime-preview-hide-content' for C-c C-d C-c.
+       (mime-preview-toggle-display): New function.
+       (mime-preview-toggle-header): Add new optional argument
+       `force-visible'; use `mime-preview-toggle-display'.
+       (mime-preview-toggle-content): Likewise.
+       (mime-preview-show-header): New function.
+       (mime-preview-show-content): New function.
+       (mime-preview-hide-header): New function.
+       (mime-preview-hide-content): New function.
+
+2000-02-25  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-situation-examples-file-coding-system): New
+       variable.
+       (mime-save-situation-examples): Use `with-temp-buffer'; try to
+       save as `mime-situation-examples-file-coding-system'.
+       - Use with-temp-buffer to load `mime-situation-examples-file';
+       setup `mime-situation-examples-file-coding-system' when
+       mime-situation-examples-file is loaded;
+
+2000-02-25  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-view-define-keymap): Change keybind for
+       `mime-preview-toggle-header' to C-c C-t h and C-c C-t C-f.
+
+2000-02-24  Mito              <mit@nines.nec.co.jp>
+
+       * mime-edit.el (mime-edit-normalize-body): Fix number of arguments
+       against enriched-encode.
+
+2000-02-23  Daiki Ueno        <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-image.el (mime-image-normalize-xbm-buffer): New inline
+       function.
+       (mime-image-create) [XEmacs || Emacs21]: Use it for XBM data.
+       (mime-display-image): Don't create temporary file.
+
+2000-02-22  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-delq-null-situation): Accept multiple ignored
+       values.
+       (mime-unify-situations): t is also regarded as an ignored-value.
+       (mime-preview-follow-current-entity): Eliminate unused local
+       variable `str'.
+
+2000-02-22  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-play.el (mime-play-find-every-situations): Renamed from
+       `mime-view-find-every-situations'.
+
+       * mime-view.el (mime-view-find-every-situations): Moved to
+       mime-play.el.
+
+2000-02-22  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-play.el (mime-play-entity): Specify
+       `mime-view-find-every-situations' as an optional argument
+       `every-situations'.
+
+       * mime-view.el (mime-unify-situations): Add new optional argument
+       `every-situations'; use it instead of
+       `mime-view-find-every-situations'.
+       (mime-display-multipart/alternative): Modify `body' property
+       instead of `body-presentation-method' property of
+       preview-situation.
+
+       * semi-setup.el: Use `eval-after-load' for text/html related
+       setting.
+
+2000-02-21   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * semi-def.el (mime-user-interface-product): Bump up to
+       EMIKO 1.13.12.
+
+       * pgg.el (pgg-temp-buffer-show-function): Use
+       `shrink-window-if-larger-than-buffer'.
+
+       * pgg-gpg.el (pgg-gpg-process-region): Fix cleanup form.
+
+       * pgg-pgp.el (pgg-pgp-process-region): Ditto.
+
+       * pgg-pgp5.el (pgg-pgp5-process-region): Ditto.
+
+       * semi-setup.el (mime-setup-enable-inline-image): Remove checking
+       of bitmap-mule; use `eval-after-load' instead of
+       `call-after-loaded' to require `mime-image'.
+
+       * mime-image.el (mime-display-image): Set default umask to 077.
+       (mime-image-create): Use `nothing-image-instance-p'.
+
+       * mime-pgp.el: When it is compiled, define `smime-output-buffer'
+       and `smime-errors-buffer' to avoid compiler warning.
+
+       * mime-edit.el: Ditto.
+
+       * mime-pgp.el
+       (mime-view-application/pkcs7-mime): Regard smime-type as
+       "enveloped-data" unless it is specified.
+
+       * smime.el (smime-directory-files): Abolish.
+       (smime-verify-region): Abolish local variable `args'.
+
+2000-02-20   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-image.el: Remove X-Face setting; require cl when compiling.
+       (mime-image-format-alist): Remove image/x-mag and image/x-pic.
+       (mime-image-type-available-p): New function.
+       (mime-image-create): New function.
+       (mime-image-insert): New function.
+       (mime-display-image): Rewrite.
+
+       * mime-edit.el
+       (mime-edit-define-charset): Handle 'mime-charset-comment.
+
+2000-02-18  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-view-define-keymap): Change binding of
+       `mime-preview-toggle-content' from C-c C-t C-b to C-c C-t C-c.
+       (mime-preview-toggle-content): Renamed from
+       `mime-preview-toggle-body'.
+
+\f
+2000-02-17  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * REMI: Version 1.14.0 (Uragawara) released.
+
+2000-02-17  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-view-define-keymap): Add new binding
+       `mime-preview-toggle-body' for C-c C-t C-b.
+       (mime-preview-toggle-body): New command.
+
+       * semi-def.el (mime-add-button): Don't use overlay.
+
+2000-02-17  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-preview-condition): Add default setting of
+       multipart; declare body of message/partial, message/rfc822 and
+       message/news are visible.
+       (mime-display-entity): Check `*body' or `body' property of
+       situation.
+
+2000-02-17  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-display-entity): Find
+       `header-presentation-method' only if `header-is-visible'.
+
+2000-02-10  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-display-entity): Don't use
+       `mime-goto-header-start-point'.
+
+2000-02-10  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-display-message): Use `major-mode' of
+       current-buffer as default value of `original-major-mode'; don't
+       use `mime-entity-header-buffer'.
+       (mime-preview-follow-current-entity): Use `mime-insert-header' to
+       insert header; don't use `mime-entity-header-buffer',
+       `mime-entity-header-start-point' and
+       `mime-entity-header-end-point'.
+
+2000-02-10  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-preview-follow-current-entity): Use
+       `mime-view-entity-body' to find body.
+
+2000-02-10  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-preview-find-boundary-info): Fix problem when
+       entity is in boundary of mother entity.
+       (mime-preview-follow-current-entity): Check header information of
+       `mime-view-situation' property.
+
+2000-02-09  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-preview-find-boundary-info): Use <last point>
+       - 1 instead of <last point> to get `mime-view-entity' property.
+
+       * mime-view.el (mime-preview-follow-current-entity): Fix problem
+       in multipart entity.
+
+2000-02-07  Yoshiki Hayashi  <yoshiki@xemacs.org>
+
+       * mime-pgp.el: Fix doc string.
+       * pgg-def.el: Ditto.
+       * pgg-gpg.el: Ditto.
+       * pgg-parse.el: Ditto.
+       * pgg-pgp.el: Ditto.
+       * pgg-pgp5.el: Ditto.
+       * pgg.el: Ditto.
+
+2000-02-02  Nakagawa, Makoto  <Makoto.Nakagawa@jp.compaq.com>
+
+       * pgg-pgp5.el (pgg-scheme-verify-region): Copy the contents of
+       `pgg-errors-buffer' to `pgg-output-buffer'.
+
+2000-02-02   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-temp-buffer-show-function): Don't check if the
+       selected window is the only window.
+
+2000-02-01  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * semi-setup.el (mime-setup-enable-inline-image): Use "(fboundp
+       'create-image)" to detect Emacs 21.
+       Use `eval-after-load' instead of `call-after-loaded' to require
+       `mime-image'.
+
+2000-02-01  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-view-define-keymap): Change keybind for
+       `mime-preview-toggle-header' to "\C-c\C-t\C-h".
+
+2000-02-01   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-image.el: Add checking for `x-face-mule'.
+
+       * pgg.el,pgp-gpg.el,pgg-pgp.el,pgg-pgp5.el
+       (pgg-scheme-lookup-key): Rename from
+       `pgg-scheme-lookup-key-string'.
+       (pgg-scheme-decrypt-region): Use `pgg-scheme-lookup-key'.
+       (pgg-scheme-sign-region): Ditto.
+
+       * pgg-gpg.el (pgg-scheme-lookup-key): Generate *PGG-output* buffer
+       if it does not exist.
+
+2000-01-24   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * semi-def.el (mime-user-interface-product): Bump up to
+       EMIKO 1.13.10.
+
+       * mime-image.el [Emacs21]: Require `image' when compiling.
+       (image-normalize): Use `create-image' with 3rd arg `data-p'.
+        (create-image): Advice it to accept 3rd arg `data-p'.
+
+       * pgg-pgp.el. pgg-pgp5.el
+       (pgg-scheme-verify-region): Don't send buffer contents.
+
+       * mime-pgp.el (mime-view-application/pkcs7-mime): Rename from
+       `mime-decrypt-application/pkcs7-mime'; handle `smime-type'
+       parameter; abolish local variable `representation-type'.
+
+       * semi-setup.el: Rename `mime-decrypt-application/pkcs7-mime' to
+       `mime-view-application/pkcs7-mime'.
+
+2000-01-18   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el,pgp-gpg.el,pgg-pgp.el,pgg-pgp5.el
+       (pgg-scheme-lookup-key-string,pgg-scheme-encrypt-region,
+       pgg-scheme-decrypt-region,pgg-scheme-sign-region,
+       pgg-scheme-verify-region,pgg-scheme-insert-key,
+       pgg-scheme-snarf-keys-region): Prepend `pgg-scheme' to each symbol.
+
+       * pgg.el
+       (pgg-encrypt-region,pgg-decrypt-region,pgg-sign-region,
+       pgg-verify-region,pgg-insert-key,pgg-snarf-keys-region,
+       pgg-lookup-key-string): Don't use `luna-send'.
+
+2000-01-17  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-view-entity-button-visible-p): Comment out.
+       (mime-display-entity): Don't use
+       `mime-view-entity-button-visible-p'.
+
+2000-01-17  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-find-entity-preview-situation): New function.
+       (mime-display-multipart/alternative): Use
+       `mime-find-entity-preview-situation'.
+       (mime-display-entity): Likewise; prefer`*entity-button' and
+       `*header'.
+       (mime-preview-toggle-header): Modify `*header' instead of
+       `header'; update `mime-preview-situation-example-list'.
+
+2000-01-17  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-unify-situations): Fixed.
+       (mime-view-define-keymap): Add new binding
+       `mime-preview-toggle-header' for C-c h.
+       (mime-preview-find-boundary-info): New function.
+       (mime-preview-follow-current-entity): Use
+       `mime-preview-find-boundary-info'.
+       (mime-preview-toggle-header): New command.
+
+2000-01-16  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-play.el (mime-play-entity): Modify for
+       `mime-unify-situations'.
+
+       * mime-view.el (mime-unify-situations): Add new optional argument
+       `required-name'; use it instead of `method'.
+       (mime-display-multipart/alternative): Use `mime-unify-situations'.
+       (mime-display-entity): Likewise.
+
+2000-01-16  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-reduce-situation-examples): New function;
+       delete `mime-reduce-acting-situation-examples'.
+
+2000-01-16  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-view.el (mime-view-find-every-situations): Renamed from
+       `mime-view-find-every-acting-situation'; changed to variable.
+       (mime-situation-examples-file): Renamed from
+       `mime-acting-situation-examples-file'.
+       (mime-preview-situation-example-list-max-size): New variable.
+       (mime-save-situation-examples): Renamed from
+       `mime-save-acting-situation-examples'; save
+       `mime-preview-situation-example-list' if it is not null.
+
+2000-01-16  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-play.el (mime-acting-situation-example-list): Moved to
+       mime-view.el.
+       (mime-acting-situation-example-list-max-size): Likewise.
+       (mime-save-acting-situation-examples): Likewise.
+       (mime-reduce-acting-situation-examples): Likewise.
+
+       * mime-view.el (mime-preview-situation-example-list): New
+       variable.
+       (mime-acting-situation-example-list): Moved from mime-play.el.
+       (mime-acting-situation-example-list-max-size): Likewise.
+       (mime-save-acting-situation-examples): Likewise.
+       (mime-reduce-acting-situation-examples): Likewise.
+       (mime-view-load-hook): Abolished.
+
+2000-01-16  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-play.el (mime-play-entity): Use `mime-unify-situations'.
+
+       * mime-view.el (mime-unify-situations): New function.
+
+2000-01-16  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * mime-play.el (mime-compare-situation-with-example): Moved to
+       mime-view.el.
+       (mime-sort-situation): Likewise.
+
+       * mime-view.el (mime-compare-situation-with-example): Moved from
+       mime-play.el.
+       (mime-sort-situation): Likewise.
+
+2000-01-16  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * postpet.el: New module.
+
+       * SEMI-ELS (semi-modules-to-compile): Add `postpet'.
+
+       * mime-play.el (mime-delq-null-situation): Moved to mime-view.el.
+
+       * mime-view.el: Add setting for
+       `mime-display-application/x-postpet' to autoload "postpet".
+       (mime-delq-null-situation): Moved from mime-play.el.
+       (unpack): Moved to postpet.el.
+       (unpack-skip): Likewise.
+       (unpack-fixed): Likewise.
+       (unpack-byte): Likewise.
+       (unpack-short): Likewise.
+       (unpack-long): Likewise.
+       (unpack-string): Likewise.
+       (unpack-string-sjis): Likewise.
+       (postpet-decode): Likewise.
+       (mime-display-application/x-postpet): Likewise.
+
+2000-01-11  Nakagawa, Makoto  <Makoto.Nakagawa@jp.compaq.com>
+
+       * pgg-pgp.el, pgg-pgp5.el
+       (pgg-scheme-lookup-key-string): Fix number of arguments against
+       call-process.
+
+       * pgg-pgp5.el (pgg-scheme-verify-region): Analize process output
+       to see whether verify successed or not.
+
+2000-01-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * Makefile, README.en: Update for the new CVS server.
+
+1999-12-28   Daiki Ueno       <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-edit.el (mime-edit-user-agent-value): Don't require
+       `apel-ver' directly.
+
+1999-12-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * mime-edit.el (mime-edit-user-agent-value): Use `error' instead of
+       `file-error' for the handler of `condition-case' because XEmacs
+       does not signal an error named `file-error' if the required feature
+       is not provided.
+
+1999-12-16  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * semi-setup.el (mime-setup-decode-message-header): Comment out.
+       (mime-edit-mode-hook): Don't use
+       `mime-setup-decode-message-header'.
+       (mu-cite/pre-cite-hook): Don't use `eword-decode-header'.
+
+1999-12-14  Akihiro Arisawa   <ari@atesoft.advantest.co.jp>
+
+       * mime-view.el (mime-preview-follow-current-entity): Fetch field of
+       `mime-view-following-required-fields-list' from parent entity if it
+       is not exist in current entity.
+
+1999-12-13  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * README.en: Update for the recent ML address and ftp site.
+
+1999-12-11  Daiki Ueno        <ueno@ueda.info.waseda.ac.jp>
+
+       * smime.el (smime-encrypt-region): Delete entity header.
+       (smime-sign-region): Ditto.
+
+       * mime-edit.el: Fix autoload settings for `smime-sign-region' and
+       `smime-encrypt-region.
+       (mime-edit-sign-smime): Set Content-Type
+       `application/pkcs7-signature' instead of
+       `application/x-pkcs7-signature'; add Content-Description.
+       (mime-edit-encrypt-smime): Set content-type
+       `application/pkcs7-mime' instead of `x-application/pkcs7-mime'.
+
+       * mime-pgp.el: Fix autoload settings for `smime-verify-region' and
+       `smime-decrypt-region.
+       (mime-decrypt-application/pkcs7-mime):
+       Bind `inhibit-read-only' to t.
+
+1999-12-09  Daiki Ueno        <ueno@ueda.info.waseda.ac.jp>
+
+       * semi-def.el (mime-user-interface-product): Bump up to
+       EMIKO 1.13.9.
+
+       * smime.el: Require `static' when compiling.
+       (smime-directory-files): New macro.
+       (smime-find-certificate): Use it.
+
+1999-12-08  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * smime.el (smime-verify-region): Abolish local variable `cert-file'.
+       (smime-find-certificate): Rename from `smime-search-certificate'.
+
+       * mime-edit.el: Add autoload settings for `smime-encrypt-region' and
+       `smime-sign-region'.
+       (mime-edit-process-multipart-1): Handle type "smime-signed" and
+       "smime-encrypted".
+       (mime-edit-sign-smime): New function.
+       (mime-edit-encrypt-smime): New function.
+       (mime-edit-enclose-smime-signed-region): New function.
+       (mime-edit-enclose-smime-encrypted-region): New function.
+
+       * mime-pgp.el: Add autoload settings for `smime-decrypt-region' and
+       `smime-verify-region'.
+       (mime-verify-application/pkcs7-signature): New function.
+       (mime-decrypt-application/pkcs7-mime): New function.
+
+       * semi-setup.el: Set up for `mime-verify-application/pkcs7-signature'
+       and `mime-decrypt-application/pkcs7-mime'.
+
+1999-12-08  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * smime.el (smime-x509-hash): Use `call-process' instead of
+       `call-process-region'.
+       (smime-x509-subject): Ditto.
+
+1999-12-08  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * SEMI-ELS (semi-modules-to-compile): Add smime.el.
+
+       * smime.el: New file.
+
+1999-11-30  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * mime-edit.el (mime-edit-decode-message-in-buffer): Don't decode
+       the message header twice.
+
+1999-11-30  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-remove-passphrase-cache): Add checking whether
+       the passphrase has already been expired.
+
+1999-11-26  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-edit.el (mime-edit-pgp-user-id): New variable.
+       (mime-edit-sign-pgp-mime): Undo last change; refer
+       `mime-edit-pgp-user-id'.
+       (mime-edit-encrypt-pgp-mime): Ditto.
+
+       * pgg-gpg.el, pgg-pgp.el, pgg-pgp5.el
+       (encrypt-region): Refer `pgg-<impl>-user-id' if specified.
+       (sign-region): Ditto.
+       (decrypt-region): Ditto.
+       (insert-key): Ditto.
+
+1999-11-26  Nakagawa, Makoto  <Makoto.Nakagawa@jp.compaq.com>
+
+       * mime-edit.el (mime-edit-sign-pgp-mime): Regard
+       `pgg-default-user-id' as more preferrable if it's specified.
+       (mime-edit-encrypt-pgp-mime): Ditto.
+
+1999-11-22  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * semi-def.el (mime-user-interface-product): Bump up to
+       EMIKO 1.13.8.
+
+       * pgg.el (pgg-remove-passphrase-cache): Don't unbind passphrase.
+
+1999-11-20  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-edit.el (mime-edit-sign-pgp-mime): Bind
+       `pgg-default-user-id' to the canonical address of From field.
+
+       * pgg-def.el (pgg-cache-passphrase): New user option.
+
+       * pgg.el (pgg-read-passphrase): Refer `pgg-cache-passphrase'.
+       (pgg-remove-passphrase-cache): Fill cached passphrase with `_'.
+
+       * pgg-gpg.el, pgg-pgp.el, pgg-pgp5.el (sign-region): Refer
+       `pgg-cache-passphrase'.
+
+1999-11-17  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * mime-image.el (mime-display-image): Use
+       `mime-image-normalize-xbm' if the feature `xemacs' is provided or
+       the variable `image-types' is bound.
+
+1999-11-17  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-image.el (mime-image-normalize-xbm): Work for the future
+       FSF Emacsen as well.
+       (mime-display-image): Always use `mime-image-normalize-xbm'.
+
+1999-11-17  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * mime-image.el (mime-image-normalize-xbm): New macro.
+       (mime-display-image): Use it.
+
+1999-11-13  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-temp-buffer-show-function): New function.
+       (pgg-display-output-buffer): Use it.
+       (pgg-save-coding-system): Use buffer narrowing.
+       (pgg-encrypt-region, pgg-decrypt-region, pgg-sign-region,
+       pgg-verify-region): Assume that the current region has already
+       been narrowed.
+
+1999-11-13  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-def.el (pgg-default-keyserver-address): Default to
+       `wwwkeys.pgp.net'.
+
+       * pgg.el (pgg-save-coding-system): New macro.
+       (pgg-display-output-buffer): New function.
+       (pgg-encrypt-region, pgg-decrypt-region, pgg-sign-region,
+       pgg-verify-region, pgg-insert-key, pgg-snarf-keys-region):
+       Add documentation string; use `pgg-save-coding-system'.
+       (pgg-fetch-key): Fix documentation.
+
+1999-11-11  Akihiro Arisawa   <ari@atesoft.advantest.co.jp>
+
+       * mime-image.el (image-normalize): Use `write-region-as-binary'.
+
+1999-11-11  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-pgp.el, pgg-pgp5.el (verify-region): Set default umask to 077.
+
+1999-11-10  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-gpg.el (pgg-gpg-process-region): Enclose `start-process'
+       with `as-binary-process'.
+
+       * pgg-pgp.el (pgg-pgp-process-region): Enclose `start-process'
+       with `as-binary-process'.
+
+       * pgg-pgp5.el (pgg-pgp5-process-region): Enclose `start-process'
+       with `as-binary-process'.
+
+       * mime-edit.el (mime-edit-set-sign): Remove duplication.
+       (mime-edit-set-encrypt): Ditto.
+       (mime-edit-encrypt-pgp-mime): Encode header before encrypting.
+
+       * mime-image.el (image-insert-at-point): Check the number of the
+       arguments of `insert-image'.
+       (mime-display-image): Rewrite.
+
+1999-11-10  Yoshiki Hayashi  <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * mime-play.el: (mime-save-directory): New variable.
+       (mime-save-content): Don't force filename parameter to be used.
+
+1999-11-09  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-pgp.el, pgg-pgp5.el
+       (sign-region): Don't convert line break code.
+
+1999-11-07  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-pgp.el (mime-verify-application/pgp-signature): Don't
+       scroll MIME-echo buffer, just set window starting point.
+       (mime-add-application/pgp-keys): Ditto.
+
+1999-11-06  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-sign-region): Add optional argument `cleartext'.
+
+       * mime-ui-en.sgml, mime-ui-ja.sgml: Remove description about
+       `pgp-functions-alist' and `pgp-function'; add description about
+       `pgg-default-scheme' and `pgg-scheme'.
+
+       * NEWS (PGP 5.0i and GnuPG are now supported for PGP/MIME):
+       New section.
+
+       * pgg-gpg.el, pgg-pgp.el, pgg-pgp5.el (encrypt-region): Add
+       sender's user id to the recipients list if `pgg-encrypt-for-me' is
+       specified.
+
+       * pgg-def.el (pgg-encrypt-for-me): New user option.
+
+       * mime-edit.el:
+       (mime-edit-decode-multipart-in-buffer): Sync up with semi-pgpgpg_20.
+       (mime-edit-decode-message-in-buffer): Ditto.
+       (mime-edit-decode-single-part-in-buffer): Ditto.
+
+1999-11-06   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-verify-region): Bind `pgg-scheme' in the predicate
+       of whether to fetch signer's public key.
+       (pgg-convert-lbt-region): New macro.
+       (pgg-as-lbt): New macro.
+
+       * mime-edit.el (mime-edit-encrypt-pgp-mime): Extract canonical
+       address of From field to use it as default user id; tokenize
+       bodies of the recipient fields.
+       (mime-edit-make-encrypt-recipient-header): Undo last change.
+       (mime-edit-translate-buffer): Do `undo-boundary'
+       before translating.
+
+       * pgg-gpg.el (sign-region): Use `pgg-as-lbt'.
+       (pgg-gpg-process-region): Use `pgg-convert-lbt-region'.
+       (encrypt-region): Don't ask passphrase.
+
+       * pgg-pgp5.el (sign-region): Use `pgg-as-lbt'.
+       (pgg-pgp5-process-region): Use `pgg-convert-lbt-region'.
+       (encrypt-region): Don't ask passphrase.
+
+       * pgg-pgp.el (verify-region): Fill errors buffer.
+       (pgg-pgp-process-region): Use `pgg-convert-lbt-region'.
+       (sign-region): Use `pgg-as-lbt'.
+       (encrypt-region): Don't ask passphrase.
+
+1999-11-06   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-parse.el (pgg-byte-after): Always pass the first argument
+       of `char-after'.
+
+1999-11-05   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-pgp.el (sign-region): Fix regexp for the beginning of armor.
+
+       * pgg-gpg.el (encrypt-region): Don't use "--textmode" in GPG
+       arguments, replace line break code with CRLF while signing
+       instead.
+
+1999-11-05   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-pgp.el (mime-verify-application/pgp-signature): Copy the
+       messages in PGG buffers to MIME-echo buffer instead of binding
+       `pgg-output-buffer'.
+       (mime-add-application/pgp-keys): Likewise.
+
+       * pgg-gpg.el (verify-region): Fill errors buffer whether
+       verification has succeeded or not.
+
+1999-11-05   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-gpg.el, pgg-pgp.el, pgg-pgp5.el (snarf-keys-region):
+       Use `pgg-process-when-success'.
+
+       * pgg.el (pgg-encrypt-region): Add autoload cookie.
+       (pgg-decrypt-region): Ditto.
+       (pgg-sign-region): Ditto.
+       (pgg-verify-region): Don't modify the buffer; add autload cookie.
+       (pgg-snarf-keys-region): Add interactive spec; add autload cookie.
+       (pgg-insert-key): Add interactive spec; add autload cookie.
+
+1999-11-05   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-gpg.el (pgg-gpg-shell-command-switch): New user option.
+       (pgg-gpg-process-region): Bind `shell-command-switch' to the value
+       of `pgg-gpg-shell-command-switch'.
+
+       * pgg-pgp.el (pgg-pgp-shell-command-switch): New user option.
+       (pgg-pgp-process-region): Bind `shell-command-switch' to the value
+       of `pgg-pgp-shell-command-switch'.
+
+       * pgg-pgp5.el (pgg-pgp5-shell-command-switch): New user option.
+       (pgg-pgp5-process-region): Bind `shell-command-switch' to the value
+       of `pgg-pgp5-shell-command-switch'.
+
+       * pgg-gpg.el, pgg-pgp.el, pgg-pgp5.el (sign-region): Use fixed end
+       position of the signature.
+
+       * mime-pgp.el: Add autoload for `pgg-decrypt-region',
+       `pgg-verify-region', `pgg-snarf-keys-region'.
+       (mime-view-application/pgp): Don't use `pgp-function'.
+       (mime-verify-application/pgp-signature): Ditto.
+       (mime-add-application/pgp-keys): Ditto.
+       (mime-pgp-command): Abolish.
+       (mime-pgp-default-language): Abolish.
+       (mime-pgp-good-signature-regexp-alist): Abolish.
+       (mime-pgp-key-expected-regexp-alist): Abolish
+       (mime-pgp-check-signature): Abolish.
+
+       * semi-def.el (pgp-function-alist): Abolish.
+       (pgp-function): Abolish.
+
+       * mime-edit.el: Add autoload for `pgg-encrypt-region',
+       `pgg-sign-region', `pgg-insert-key'.
+       (mime-edit-sign-pgp-mime): Throw an error when
+       `pgg-sign-region' returns nil; don't use `pgp-function'.
+       (mime-edit-encrypt-pgp-mime): Throw an error when
+       `pgg-encrypt-region' returns nil; don't use `pgp-function'.
+       (mime-edit-sign-pgp-kazu): Don't use `pgp-function'.
+       (mime-edit-encrypt-pgp-mime): Ditto.
+
+1999-11-05   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-pgp.el (mime-add-application/pgp-keys): Don't display
+       public key block; snarf keys immediately.
+
+       * pgg.el (pgg-insert-url-with-program): Call program asynchronously.
+
+1999-11-05   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-def.el (pgg-echo-buffer): New variable.
+
+       * pgg.el (pgg-process-when-success): New macro.
+       (pgg-insert-url-with-w3): New function.
+       (pgg-insert-url-program): New variable.
+       (pgg-insert-url-extra-arguments): New variable.
+       (pgg-insert-url-function): New variable.
+       (pgg-fetch-key): Use it.
+       (pgg-encrypt-region): If called interactively, popup
+       `pgg-echo-buffer' to display encryption status.
+       (pgg-decrypt-region): Likewise.
+       (pgg-sign-region): Likewise.
+       (pgg-verify-region): Likewise.
+
+       * pgg-gpg.el (lookup-key-string): Use `call-process' instead of
+       `pgg-gpg-process-region'.
+       (encrypt-region): Use `pgg-process-when-success'; if the output
+       buffer is empty, don't copy errors, just return nil.
+       (decrypt-region): Likewise.
+       (verify-region): Check the contents of status buffer to looking
+       for `GOODSIG' response.
+       (sign-region): Accept optional argument `clearsign'.
+
+       * pgg-pgp.el (lookup-key-string): Use `call-process' instead of
+       `pgg-pgp-process-region'.
+       (encrypt-region): Use `pgg-process-when-success'; if the output
+       buffer is empty, don't copy errors, just return nil.
+       (decrypt-region): Likewise.
+       (verify-region): Likewise.
+       (sign-region): Accept optional argument `clearsign'.
+
+       * pgg-pgp5.el (lookup-key-string): Use `call-process' instead of
+       `pgg-pgp5-process-region'.
+       (encrypt-region): Use `pgg-process-when-success'; if the output
+       buffer is empty, don't copy errors, just return nil.
+       (decrypt-region): Likewise.
+       (verify-region): Likewise.
+       (sign-region): Accept optional argument `clearsign'.
+
+1999-11-04   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-verify-region): Ignore all errors encountered on
+       calling `pgg-fetch-key'.
+
+1999-11-04  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-pgp.el (mime-verify-application/pgp-signature): Enclose
+       with `unwind-protect' to be sure of deleting *.asc files.
+
+       * pgg-pgp.el (pgg-pgp-process-region): Set `PGPPASSFD' before
+       starting PGP process.
+
+       * pgg-pgp5.el (pgg-pgp5-process-region): Ditto.
+
+1999-11-04  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-parse.el (pgg-parse-crc24): Don't use any `write' ops.
+       (pgg-parse-crc24-string): Use `ccl-execute-on-string'.
+
+1999-11-04  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-edit.el (mime-edit-set-sign): Preserve last status of
+       `mime-edit-pgp-processing'.
+       (mime-edit-set-encrypt): Ditto.
+       (mime-edit-pgp-enclose-buffer): Process
+       `mime-edit-pgp-enclose-buffer' consequently.
+
+       * pgg-parse.el (pgg-decode-packets): Don't use
+       `mime-encode-string'.
+       (pgg-ignore-packet-checksum): Default to t.
+
+1999-11-04  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el: Rename the field name `cipher-algorithm' to
+       `symmetric-key-algorithm'.
+       (pgg-verify-condition): Fix documentation.
+       (pgg-decrypt-condition): Ditto.
+
+1999-11-04  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * mime-edit.el (mime-edit-preview-message): Inherit the value of
+       `mime-edit-pgp-processing'.
+
+1999-11-04  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-encrypt-region): Add interactive spec.
+       (pgg-decrypt-region): Ditto.
+       (pgg-sign-region): Ditto.
+       (pgg-verify-region): Add optional argument `fetch' to fetch
+       signer's public key.
+
+       * pgg-def.el (pgg-default-keyserver-address): New variable.
+
+       * semi-def.el (pgp-function-alist): Remove `lookup-key'.
+
+       * mime-pgp.el (mime-display-application/pgp-signature): Abolish.
+       (mime-display-application/pgp-encrypted): Abolish.
+       (mime-display-application/pgp-keys): Abolish.
+       (mime-pgp-keyserver-url-template): Abolish.
+       (mime-pgp-keyserver-address): Abolish.
+       (mime-pgp-keyserver-port): Abolish.
+       (mime-pgp-keyserver-protocol): Abolish.
+       (mime-pgp-fetch-key): Abolish.
+
+       * semi-setup.el: Delete default setting of
+       `mime-display-application/pgp-signature', 
+       `mime-display-application/pgp-encrypted',
+       `mime-display-application/pgp-keys'
+
+1999-11-03  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-fetch-key): Protect `buffer-file-name'.
+
+       * pgg-gpg.el (snarf-keys-region): Add `-' as extra argument of
+       gpg --import; convert status code into an integer.
+
+1999-11-03  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * semi-def.el (pgp-function-alist): Add `lookup-key'.
+
+       * pgg.el, pgg-gpg.el, pgg-pgp5.el, pgg-pgp.el:
+       Rename generic function `lookup-key' to `lookup-key-string';
+       add optional argument `type'.
+
+       * pgg-def.el (pgg-truncate-key-identifier): New macro.
+
+       * pgg.el: Rename generic function `lookup-key' to
+       `lookup-key-string'; add optional argument `type'.
+       (pgg-fetch-key): New function.
+       (pgg-snarf-keys-region): Fix typo.
+       (pgg-lookup-key-string): New function.
+       (pgg-read-passphrase): Use `pgg-truncate-key-identifier'.
+       (pgg-add-passphrase-cache): Ditto.
+
+       * mime-pgp.el (mime-pgp-keyserver-url-template): New variable
+       imported from semi-pgpgpg.
+       (mime-pgp-keyserver-address): Ditto.
+       (mime-pgp-keyserver-port): Ditto.
+       (mime-pgp-keyserver-protocol): New variable.
+       (mime-pgp-fetch-key): New function.
+       (mime-verify-application/pgp-signature): Prompt user to fetch
+       signer's public key.
+
+1999-11-03  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-fetch-public-key): New function.
+
+       * pgg-pgp.el (lookup-key): New generic function.
+       (encrypt-region): Use `lookup-key'; cache passphrase if the
+       encryption has done successfully.
+       (sign-region): Likewise.
+       (decrypt-region): Use `lookup-key'.
+
+       * pgg.el (pgg-scheme): Remove all slots.
+       (pgg-decrypt-codition): Rename tag `cipher-algorithm' to
+       `symmetric-key-algorithm'.
+       (lookup-key): Add documentation about the new generic function.
+
+       * pgg-parse.el (pgg-decode-armor-region): Remove autoload cookie.
+       (pgg-armor-header-lines): New variable.
+
+1999-11-02  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg.el (pgg-add-passphrase-cache): Use only four octets of the key.
+       (pgg-read-passphrase): Ditto.
+       
+       * pgg-pgp5.el (lookup-key): New generic function. 
+       (encrypt-region): Use `lookup-key'; cache passphrase if the
+       encryption has done successfully.
+       (sign-region): Likewise.
+       (decrypt-region): Use `lookup-key'.
+
+1999-11-02  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-parse.el
+       (pgg-parse-public-key-encrypted-session-key-packet):
+       Rename tag `public-key-identifier' to `key-identifier'.
+
+       * mime-pgp.el
+       (mime-display-application/pgp-encrypted): Refer it.
+
+       * pgg.el (pgg-passphrase-cache-expiry): New variable.
+       (pgg-passphrase-cache): New variable.
+       (pgg-read-passphrase): Add optional argument `key'.
+       (pgg-add-passphrase-cache): New function.
+       (pgg-remove-passphrase-cache): New function.
+
+       * pgg-gpg.el (lookup-key): New generic function.
+       (encrypt-region): Use `lookup-key'; cache passphrase if the
+       encryption has done successfully.
+       (sign-region): Likewise.
+       (decrypt-region): Use `lookup-key'.
+
+1999-11-02  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pgg-parse.el (pgg-parse-length-type): Fix typo.
+       (pgg-parse-public-key-encrypted-session-key-packet): Use
+       `pgg-read-bytes-string' instead of `pgg-read-bytes'.
+
+1999-11-02  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * mime-edit.el (mime-edit-sign-pgp-mime): Rewrite with PGG functions.
+       (mime-edit-encrypt-pgp-mime): Likewise.
+       (mime-edit-encrypt-recipient-fields-list): Return recipients as list.
+
+       * mime-pgp.el: Add comment that this module is based on
+       draft-yamamoto-openpgp-mime-00.txt (OpenPGP/MIME) and RFC 2440
+       (OpenPGP Message Format) as well. 
+       (mime-verify-application/pgp-signature): Use
+       `pgg-verify-region' instead of `mime-pgp-check-signature'.
+       (mime-display-application/pgp-signature): New function.
+       (mime-display-application/pgp-encrypted): New function.
+       (mime-display-application/pgp-keys): New function.
+
+       * semi-setup.el: Set up for
+       `mime-display-application/pgp-signature', 
+       `mime-display-application/pgp-encrypted',
+       `mime-display-application/pgp-keys'.
+       (mime-setup-enable-pgp): Default to t.
+
+       * SEMI-ELS (semi-modules-to-compile): Add `pgg', `pgg-parse',
+       `pgg-gpg', `pgg-pgp' and `pgg-pgp5' instead of `mime-mc'.
+
+       * EMIKO-VERSION, pgg-def.el, pgg.el, pgg-gpg.el, 
+       pgg-pgp5.el, pgg-pgp.el, pgg-parse.el: New file.
+
+       * mime-image.el (mime-display-image): Rewrite.
+
+       * semi-def.el (mime-user-interface-product): Modify for EMIKO.
+       (pgp-function-alist): Replace each method with PGG function.
+
+       * mime-view.el (mime-view-popup-menu): New variable.
+       (mime-view-popup-menu): New function.
+       (mime-view-define-keymap): Bind `mime-view-popup-menu' to
+       `mouse-button-3'.
+
+1999-11-01  Tanaka Akira  <akr@jaist.ac.jp>
+
+       * mime-view.el (mime-display-application/x-postpet): New function.
+       (mime-preview-condition): Set up for
+       'mime-preview-application/x-postpet.
+       (unpack): New macro.
+       (unpack-skip): New function.
+       (unpack-fixed): New function.
+       (unpack-byte): New function.
+       (unpack-short): New function.
+       (unpack-long): New function.
+       (unpack-string): New function.
+       (unpack-string-sjis): New function.
+       (postpet-decode): New function.
+
+1999-10-17  Yoshiki Hayashi  <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * SEMI-MK (install-semi-package): Delte auto-autoloads.el
+       and custom-load.el
+
+\f
 1999-10-16  MORIOKA Tomohiko  <tomo@m17n.org>
 
        * SEMI: Version 1.13.7 (Awazu) released.
index 84d8c26..179e75c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,11 +2,11 @@
 # Makefile for SEMI kernel.
 #
 
-PACKAGE = semi
-API    = 1.13
-RELEASE = 7
+PACKAGE = emiko
+API    = 1.14
+RELEASE = 1
 
-FLIM_API= 1.13
+FLIM_API= 1.14
 
 TAR    = tar
 RM     = /bin/rm -f
@@ -24,7 +24,7 @@ VERSION_SPECIFIC_LISPDIR = NONE
 GOMI   = *.elc
 
 VERSION        = $(API).$(RELEASE)
-ARC_DIR = /pub/mule/semi/semi-$(API)-for-flim-$(FLIM_API)
+ARC_DIR = /home/ueno/public_html/emacs-lisp
 
 
 elc:
@@ -51,9 +51,9 @@ clean:
 
 tar:
        cvs commit
-       sh -c 'cvs tag -RF $(PACKAGE)-`echo $(VERSION) | tr . _`; \
+       sh -c 'cvs tag -R $(PACKAGE)-`echo $(VERSION) | tr . _`; \
        cd /tmp; \
-       cvs -d :pserver:anonymous@chamonix.jaist.ac.jp:/hare/cvs/root \
+       cvs -d :pserver:anonymous@cvs.m17n.org:/cvs/root \
                export -d $(PACKAGE)-$(VERSION) \
                -r $(PACKAGE)-`echo $(VERSION) | tr . _` \
                semi'
diff --git a/NEWS b/NEWS
index 529574f..eaebaeb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,17 @@ Copyright (C) 1998,1999 Free Software Foundation, Inc.
 
 * Changes in SEMI 1.13
 
+** PGP 5.0i and GnuPG are now supported for PGP/MIME
+
+  You can select the various PGP or GnuPG commands by the user option
+`pgg-default-scheme' or `pgg-scheme'. The former is for encrypting and
+signing, the latter could be bound for controlling which command is
+used to process the incoming PGP armors. Note that Mailcrypt is not
+needed anymore. A user interface for editing or viewing has never
+changed. Note also that `pgp-function' and `pgp-functions-alist' are
+abolished in this version.
+
+
 ** Requires FLIM 1.13 API
 
 
index 7f2d51b..b1cd6b6 100644 (file)
--- a/README.en
+++ b/README.en
@@ -40,17 +40,19 @@ Required environment
   19.14.  SEMI also does not support Emacs 19.29 to 19.34, XEmacs
   19.15 or XEmacs 20.2 without mule, but SEMI may work with them.
 
-  SEMI requires APEL (9.20 or later) and FLIM (1.13.1 or later)
+  SEMI also does not support Emacs 19.29 to 19.34, XEmacs 19.15 or
+  XEmacs 20.2, but SEMI may work with them.
+
+  SEMI requires APEL (9.22 or later) and FLIM (1.14.2 or later)
   package.  Please install them before installing it.  APEL package is
   available at:
 
-       ftp://ftp.etl.go.jp/pub/mule/apel/
+       ftp://ftp.m17n.org/pub/mule/apel/
 
   and FLIM package is available at:
 
-       ftp://ftp.etl.go.jp/pub/mule/flim/flim-1.13/
-
-  PGP/MIME and application/pgp require mailcrypt or tiny-pgp package.
+       http://www.kanji.zinbun.kyoto-u.ac.jp/~tomo/comp/emacsen/lisp/
+                                                       flim/flim-1.14/
 
 
 Installation
@@ -179,35 +181,54 @@ Mailing lists
 =============
 
   If you write bug-reports and/or suggestions for improvement, please
-  send them to the tm Mailing List:
+  send them to the EMACS-MIME Mailing List:
+
+       emacs-mime-en@m17n.org  (English)
+       emacs-mime-ja@m17n.org  (Japanese)
+
+  Via the EMACS-MIME ML, you can report SEMI bugs, obtain the latest
+  release of SEMI, and discuss future enhancements to SEMI.  To join
+  the EMACS-MIME ML, send an e-mail to
+
+       emacs-mime-en-ctl@m17n.org      (English)
+       emacs-mime-ja-ctl@m17n.org      (Japanese)
 
-       bug-tm-en@chamonix.jaist.ac.jp  (English)
-       bug-tm-ja@chamonix.jaist.ac.jp  (Japanese)
+  containing
 
-  Via the tm ML, you can report SEMI bugs, obtain the latest release
-  of SEMI, and discuss future enhancements to SEMI.  To join the tm
-  ML, send an empty e-mail to
+       subscribe YOUR NAME
 
-       tm-en-help@chamonix.jaist.ac.jp (English)
-       tm-ja-help@chamonix.jaist.ac.jp (Japanese)
+  in its contents.
 
   Notice that you should not send mail to author(s), such as
   morioka@jaist.ac.jp, directly.  Because your problem may occur in
   other environments (if not, it might be your problem, not bug of
-  SEMI).  We should discuss in the tm mailing lists.  Anyway
+  SEMI).  We should discuss in the EMACS-MIME mailing lists.  Anyway
   direct-mail for authors might be ignored.  Please send mail to the
-  tm mailing lists.
+  EMACS-MIME mailing lists.
 
 
 CVS based development
 =====================
 
+  The SEMI development sources can be accessed via CVS pserver.  To
+  check out the SEMI sources, what you should do for the first time
+  is:
+
+  % cvs -d :pserver:anonymous@cvs.m17n.org:/cvs/root login
+  CVS password: [CR] # NULL string
+
+  Then you can get the latest SEMI sources by the following:
+
+  % cvs -d :pserver:anonymous@cvs.m17n.org:/cvs/root checkout -r emiko-1_14 semi
+
   If you would like to join CVS based development, please send mail to
 
-       cvs@chamonix.jaist.ac.jp
+       cvs@cvs.m17n.org
+
+  with your account name and your public key for ssh.  cvsroot is
+  :ext:cvs@cvs.m17n.org:/cvs/root.
 
-  with your account name and UNIX style crypted password.  We hope you 
-  will join the open development.
+  We hope you will join the open development.
 
 
 Authors
index 6ffa7fc..b77be5a 100644 (file)
--- a/SEMI-ELS
+++ b/SEMI-ELS
@@ -6,7 +6,9 @@
 
 (setq semi-modules-to-compile
       '(signature
-       semi-def mime-view mime-play mime-partial mime-edit
+       pgg-def pgg pgg-parse pgg-gpg pgg-pgp5 pgg-pgp mime-pgp
+       semi-def mime-view mime-play mime-partial postpet
+       mime-edit
        semi-setup mail-mime-setup))
 
 (setq semi-modules-not-to-compile nil)
@@ -23,9 +25,9 @@
                     (nconc semi-modules-not-to-compile i-modules))
               )
             )))
-       '((mailcrypt    mime-pgp mime-mc)
-         (bbdb         mime-bbdb)
+       '((bbdb         mime-bbdb)
          (w3           mime-w3)
+         (vcard        mime-vcard)
          ))
 
 (if (or (string-match "XEmacs" emacs-version)
diff --git a/SEMI-MK b/SEMI-MK
index bd5f525..2aed7f1 100644 (file)
--- a/SEMI-MK
+++ b/SEMI-MK
@@ -90,6 +90,8 @@ LISPDIR=%s\n" PREFIX LISPDIR))
                         (expand-file-name SEMI_PREFIX
                                           (expand-file-name "lisp"
                                                             PACKAGEDIR)))
+  (delete-file "./auto-autoloads.el")
+  (delete-file "./custom-load.el")
   )
 
 ;;; SEMI-MK ends here
diff --git a/VERSION b/VERSION
index 9c1fa27..959d424 100644 (file)
--- a/VERSION
+++ b/VERSION
 1.13.5 Meih\e-Dò\e-A                     \e$(BL@Jv\e(B
 1.13.6 Komatsu                 \e$(B>.>>\e(B
 1.13.7 Awazu                   \e$(B0@DE\e(B
+1.14.0 Iburihashi              \e$(BF066\e(B
+1.14.1 Kaga-Onsen              \e$(B2C2l29@t\e(B
+1.14.2 Daish\e-Dòji\e-A          \e$(BBg@;;{\e(B
+1.14.3 Ushinoya                \e$(B5m%NC+\e(B
+------ Hosorogi                \e$(B:YO$LZ\e(B
+------ Awara-Onsen             \e$(B028629@t\e(B
 :      :                       :
 -------        Tsuruga                 \e$(BFX2l\e(B             ; = JR \e$(B>.IM@~\e(B
 -------        Shin-Hikida             \e$(B?7I%ED\e(B
@@ -91,7 +97,7 @@
 -------        Kawake                  \e$(B2OLS\e(B
 -------        Torahime                \e$(B8WI1\e(B
 -------        Nagahama                \e$(BD9IM\e(B
-------- Tamura                 \e$(BEDB<\e(B
+-------        Tamura                  \e$(BEDB<\e(B
 -------        Sakata                  \e$(B:dED\e(B
        (Maibara)               (\e$(BJF86\e(B)           ; = JR \e$(BEl3$F;K\@~\e(B
 
 1.13.5 Fijieda                 \e$(BF#;^\e(B
 1.13.6 Rokug\e-Dò\e-A                    \e$(BO;9g\e(B
 1.13.7 Shimada                 \e$(BEgED\e(B
------- Kanaya                  \e$(B6bC+\e(B     ; = \e$(BBg0f@nE4F;\e(B
+1.14.0 Kanaya                  \e$(B6bC+\e(B     ; = \e$(BBg0f@nE4F;\e(B
 ------ Kikugawa                \e$(B5F@n\e(B
 ------ Kakegawa                \e$(B3]@n\e(B     ; = \e$(BE7N5IML>8PE4F;\e(B
 ------ Fukuroi                 \e$(BB^0f\e(B
 1.13.0 Saigata                 \e$(B:T3c\e(B     ; = JR \e$(B?.1[K\@~\e(B
 1.13.1 Kubiki                  \e$(B$/$S$-\e(B
 1.13.2 \e-DÃ’ike-Ikoinomori\e-A           \e$(BBgCS$$$3$$$N?9\e(B
+1.14.0 Uragawara               \e$(B$&$i$,$o$i\e(B
+1.14.1 Mushigawa\e-Dòsugi\e-A            \e$(BCn@nBg?y\e(B
+1.14.2 Hokuhoku-\e-DÃ’shima\e-A           \e$(B$[$/$[$/BgEg\e(B
+1.14.3 Matsudai                \e$(B$^$D$@$$\e(B
 
 
 [etc.]
diff --git a/ftp.in b/ftp.in
index 848fbe2..f15aa34 100644 (file)
--- a/ftp.in
+++ b/ftp.in
@@ -2,18 +2,14 @@
 
   It is available from
 
-    ftp://ftp.m17n.org/pub/mule/semi/semi-API-for-flim-FLIM_API
+    http://www.kanji.zinbun.kyoto-u.ac.jp/~tomo/comp/emacsen/lisp/semi/semi-API-for-flim-FLIM_API/
 
-or
-
-    ftp://ftp.etl.go.jp/pub/mule/semi/semi-API-for-flim-FLIM_API
-
---[[message/external-body;
-       access-type=anon-ftp;
-       site="ftp.m17n.org";
-       directory="/pub/mule/semi/semi-API-for-flim-FLIM_API";
-       name="PACKAGE-VERSION.tar.gz";
-       mode=image]]
+--[[message/external-body; access-type=URL;
+       URL*0="http://";
+       URL*1="www.kanji.zinbun.kyoto-u.ac.jp/~tomo/";
+       URL*2="comp/emacsen/lisp/";
+       URL*3="semi/semi-API-for-flim-FLIM_API/";
+       URL*4="PACKAGE-VERSION.tar.gz"]]
 Content-Type: application/octet-stream;
        name="PACKAGE-VERSION.tar.gz";
        type=tar;
index 710d15b..75fa595 100644 (file)
@@ -1,6 +1,6 @@
 ;;; mail-mime-setup.el --- setup file for mail-mode.
 
-;; Copyright (C) 1994,1995,1996,1997,1998 Free Software Foundation, Inc.
+;; Copyright (C) 1994,1995,1996,1997,1998,2000 Free Software Foundation, Inc.
 
 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
 ;; Keywords: mail-mode, MIME, multimedia, multilingual, encoded-word
@@ -19,8 +19,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
 (autoload 'turn-on-mime-edit "mime-edit"
   "Unconditionally turn on MIME-Edit minor mode." t)
 
-(autoload 'eword-decode-header "eword-decode"
-  "Decode MIME encoded-words in header fields." t)
+;; (autoload 'eword-decode-header "eword-decode"
+;;   "Decode MIME encoded-words in header fields." t)
 
 
 ;;; @ for mail-mode, RMAIL and VM
 ;;;
 
-(add-hook 'mail-setup-hook 'eword-decode-header)
+;; (add-hook 'mail-setup-hook 'eword-decode-header)
 (add-hook 'mail-setup-hook 'turn-on-mime-edit 'append)
 (add-hook 'mail-send-hook  'mime-edit-maybe-translate)
 (set-alist 'mime-edit-split-message-sender-alist
            'mail-mode (function
                        (lambda ()
                          (interactive)
-                         (funcall send-mail-function)
-                         )))
+                         (funcall send-mail-function))))
 
 
 ;;; @ for signature
 ;;;
 
 (if mime-setup-use-signature
-    (setq mail-signature nil)
-  )
+    (setq mail-signature nil))
 
 
 ;;; @ end
index 1b61d64..2258149 100644 (file)
@@ -21,8 +21,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
@@ -42,8 +42,7 @@
       "Returns a regexp matching the address of the logged-in user"
       '(or bbdb-user-mail-names
           (setq bbdb-user-mail-names
-                (concat "\\b" (regexp-quote (user-login-name)) "\\b"))))
-    ))
+                (concat "\\b" (regexp-quote (user-login-name)) "\\b"))))))
 
 
 ;;; @ User Variables
@@ -81,8 +80,7 @@ For framepop users: If empty, `framepop-banish' is used instead.")
             methods (cdr methods)))
     (if (string= address "") (setq address nil))
     (if (string= phrase "") (setq phrase nil))
-    (list phrase address)
-    ))
+    (list phrase address)))
 
 (or mime-bbdb/use-mail-extr
     (progn
@@ -91,8 +89,7 @@ For framepop users: If empty, `framepop-banish' is used instead.")
           (fset 'tm:mail-extract-address-components
                 (symbol-function 'mail-extract-address-components)))
       (fset 'mail-extract-address-components
-           (symbol-function 'mime-bbdb/extract-address-components))
-      ))
+           (symbol-function 'mime-bbdb/extract-address-components))))
 
 
 ;;; @ bbdb-extract-field-value
@@ -102,15 +99,19 @@ For framepop users: If empty, `framepop-banish' is used instead.")
     (progn
       ;; (require 'bbdb-hooks) ; not provided.
       ;; (or (fboundp 'bbdb-extract-field-value) ; defined as autoload
-      (or (fboundp 'bbdb-header-start)
-          (load "bbdb-hooks"))
+
+      ;; almost BBDB functions are autoloaded.
+      ;; (or (fboundp 'bbdb-header-start)
+      (or (and (fboundp 'bbdb-extract-field-value)
+              (not (eq 'autoload (car-safe (symbol-function
+                                            'bbdb-extract-field-value)))))
+         (load "bbdb-hooks"))
       (fset 'tm:bbdb-extract-field-value
-            (symbol-function 'bbdb-extract-field-value))
+           (symbol-function 'bbdb-extract-field-value))
       (defun bbdb-extract-field-value (field)
         (let ((value (tm:bbdb-extract-field-value field)))
           (and value
-               (eword-decode-string value))))
-      ))
+               (eword-decode-string value))))))
 
 
 ;;; @ full-name canonicalization methods
@@ -120,25 +121,21 @@ For framepop users: If empty, `framepop-banish' is used instead.")
   (let (dest)
     (while (string-match "\\s +" str)
       (setq dest (cons (substring str 0 (match-beginning 0)) dest))
-      (setq str (substring str (match-end 0)))
-      )
+      (setq str (substring str (match-end 0))))
     (or (string= str "")
         (setq dest (cons str dest)))
     (setq dest (nreverse dest))
-    (mapconcat 'identity dest " ")
-    ))
+    (mapconcat 'identity dest " ")))
 
 (defun mime-bbdb/canonicalize-dots (str)
   (let (dest)
     (while (string-match "\\." str)
       (setq dest (cons (substring str 0 (match-end 0)) dest))
-      (setq str (substring str (match-end 0)))
-      )
+      (setq str (substring str (match-end 0))))
     (or (string= str "")
         (setq dest (cons str dest)))
     (setq dest (nreverse dest))
-    (mapconcat 'identity dest " ")
-    ))
+    (mapconcat 'identity dest " ")))
 
 (defvar mime-bbdb/canonicalize-full-name-methods
   '(eword-decode-string
@@ -168,15 +165,13 @@ the user confirms the creation."
                 (string-match (bbdb-user-mail-names)
                              (std11-address-string addr)))
             (setq from (or (mime-entity-fetch-field message 'To)
-                          from))
-         )
+                          from)))
         (if from
             (bbdb-annotate-message-sender
              (mime-decode-field-body from 'From) t
              (or (bbdb-invoke-hook-for-value mime-bbdb/auto-create-p)
                  offer-to-create)
-             offer-to-create))
-        ))))
+             offer-to-create))))))
 
 (defun mime-bbdb/annotate-sender (string)
   "Add a line to the end of the Notes field of the BBDB record
@@ -239,10 +234,9 @@ displaying the record corresponding to the sender of the current message."
 (defun mime-bbdb/define-keys ()
   (let ((mime-view-mode-map (current-local-map)))
     (define-key mime-view-mode-map ";" 'mime-bbdb/edit-notes)
-    (define-key mime-view-mode-map ":" 'mime-bbdb/show-sender)
-    ))
+    (define-key mime-view-mode-map ":" 'mime-bbdb/show-sender)))
 
-(add-hook 'mime-view-define-keymap-hook 'mime-bbdb/define-keys)
+(add-hook 'mime-view-mode-hook 'mime-bbdb/define-keys)
 
 
 ;;; @ for signature.el
@@ -252,8 +246,7 @@ displaying the record corresponding to the sender of the current message."
   "Extract sigtype information from BBDB."
   (let ((record (bbdb-search-simple nil addr)))
     (and record
-         (bbdb-record-getprop record 'sigtype))
-    ))
+         (bbdb-record-getprop record 'sigtype))))
 
 (defun signature/set-bbdb-sigtype (sigtype addr)
   "Add sigtype information to BBDB."
@@ -266,31 +259,25 @@ displaying the record corresponding to the sender of the current message."
     (if record
         (progn
           (bbdb-record-putprop record 'sigtype sigtype)
-          (bbdb-change-record record nil))
-      )))
+          (bbdb-change-record record nil)))))
 
 (defun signature/get-sigtype-from-bbdb (&optional verbose)
   (let* ((to (std11-field-body "To"))
          (addr (and to
                     (car (cdr (mail-extract-address-components to)))))
          (sigtype (signature/get-bbdb-sigtype addr))
-         return
-         )
+         return)
     (if addr
         (if verbose
             (progn
               (setq return (signature/get-sigtype-interactively sigtype))
               (if (and (not (string-equal return sigtype))
                        (y-or-n-p
-                        (format "Register \"%s\" for <%s>? " return addr))
-                       )
-                  (signature/set-bbdb-sigtype return addr)
-                )
+                        (format "Register \"%s\" for <%s>? " return addr)))
+                  (signature/set-bbdb-sigtype return addr))
               return)
           (or sigtype
-              (signature/get-signature-file-name))
-          ))
-    ))
+              (signature/get-signature-file-name))))))
 
 
 ;;; @ end
index 81b7613..816cd3b 100644 (file)
@@ -1,9 +1,10 @@
 ;;; mime-edit.el --- Simple MIME Composer for GNU Emacs
 
-;; Copyright (C) 1993,94,95,96,97,98,99 Free Software Foundation, Inc.
+;; Copyright (C) 1993,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
 
 ;; Author: UMEDA Masanobu <umerin@mse.kyutech.ac.jp>
-;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     MORIOKA Tomohiko <tomo@kanji.zinbun.kyoto-u.ac.jp>
+;;     Daiki Ueno <ueno@unixuser.org>
 ;; Created: 1994/08/21 renamed from mime.el
 ;;     Renamed: 1997/2/21 from tm-edit.el
 ;; Keywords: MIME, multimedia, multilingual, mail, news
@@ -22,8 +23,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 (require 'sendmail)
 (require 'mail-utils)
 (require 'mel)
-(require 'eword-encode) ; eword-encode-field-body
 (require 'mime-view)
 (require 'signature)
 (require 'alist)
-(require 'invisible)
+(require 'pgg-def)
+(require 'pgg-parse)
+
+(autoload 'pgg-encrypt-region "pgg"
+  "PGP encryption of current region." t)
+(autoload 'pgg-sign-region "pgg"
+  "PGP signature of current region." t)
+(autoload 'pgg-insert-key "pgg"
+  "Insert PGP public key at point." t)
+(autoload 'smime-encrypt-buffer "smime"
+  "S/MIME encryption of current buffer.")
+(autoload 'smime-sign-buffer "smime"
+  "S/MIME signature of current buffer.")
 
 
 ;;; @ version
@@ -212,14 +224,15 @@ To insert a signature file automatically, call the function
        ("mail-server"
        ("server" "ftpmail@nic.karrn.ad.jp")
        ("subject"))
-       ("url"         ("url"))
-       ))
+       ("url"         ("url"))))
      ("rfc822")
-     ("news")
-     )
+     ("news"))
     ("application"
      ("octet-stream" ("type" "" "tar" "shar"))
      ("postscript")
+     ("pdf")
+     ("msword")
+     ("vnd.ms-excel")
      ("vnd.ms-powerpoint")
      ("x-kiss" ("x-cnf")))
     ("image"
@@ -230,11 +243,9 @@ To insert a signature file automatically, call the function
      ("x-pic")
      ("x-mag")
      ("x-xwd")
-     ("x-xbm")
-     )
+     ("x-xbm"))
     ("audio" ("basic"))
-    ("video" ("mpeg"))
-    )
+    ("video" ("mpeg")))
   "*Alist of content-type, subtype, parameters and its values.")
 
 (defcustom mime-file-types
@@ -245,34 +256,29 @@ To insert a signature file automatically, call the function
     ("\\.cc$"
      "application" "octet-stream" (("type" . "C++"))
      "7bit"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
 
     ("\\.el$"
      "application" "octet-stream" (("type" . "emacs-lisp"))
      "7bit"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
 
     ("\\.lsp$"
      "application" "octet-stream" (("type" . "common-lisp"))
      "7bit"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
 
     ("\\.pl$"
      "application" "octet-stream" (("type" . "perl"))
      "7bit"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
 
     ;; Text or translated text
 
     ("\\.txt$"
      "text"    "plain"         nil
      nil
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
 
      ;; .rc : procmail modules pm-xxxx.rc
      ;; *rc : other resource files
@@ -280,8 +286,7 @@ To insert a signature file automatically, call the function
     ("\\.\\(rc\\|lst\\|log\\|sql\\|mak\\)$\\|\\..*rc$"
      "text"    "plain"         nil
      nil
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
 
     ("\\.html$"
      "text"    "html"          nil
@@ -291,8 +296,7 @@ To insert a signature file automatically, call the function
     ("\\.diff$\\|\\.patch$"
      "application" "octet-stream" (("type" . "patch"))
      nil
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
 
     ("\\.signature"
      "text"    "plain"         nil     nil     nil     nil)
@@ -301,127 +305,112 @@ To insert a signature file automatically, call the function
     ;;  Octect binary text
 
     ("\\.doc$"                         ;MS Word
-     "application" "winword" nil
+     "application" "msword" nil
      "base64"
-     "attachment" (("filename" . file))
-     )
+     "attachment" (("filename" . file)))
+    ("\\.xls$"                         ; MS Excel
+     "application" "vnd.ms-excel" nil
+     "base64"
+     "attachment" (("filename" . file)))
     ("\\.ppt$"                         ; MS Power Point
      "application" "vnd.ms-powerpoint" nil
      "base64"
-     "attachment" (("filename" . file))
-     )
+     "attachment" (("filename" . file)))
 
     ("\\.pln$"
      "text"    "plain"         nil
      nil
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.ps$"
      "application" "postscript"        nil
-     "quoted-printable"
-     "attachment"      (("filename" . file))
-     )
+     "base64"
+     "attachment"      (("filename" . file)))
+    ("\\.pdf$"
+     "application" "pdf"       nil
+     "base64"
+     "attachment"      (("filename" . file)))
 
     ;;  Pure binary
 
-    ("\\.jpg$"
+    ("\\.jpg$\\|\\.jpeg$"
      "image"   "jpeg"          nil
      "base64"
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.gif$"
      "image"   "gif"           nil
      "base64"
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.png$"
      "image"   "png"           nil
      "base64"
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.tiff$"
      "image"   "tiff"          nil
      "base64"
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.pic$"
      "image"   "x-pic"         nil
      "base64"
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.mag$"
      "image"   "x-mag"         nil
      "base64"
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.xbm$"
      "image"   "x-xbm"         nil
      "base64"
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.xwd$"
      "image"   "x-xwd"         nil
      "base64"
-     "inline"          (("filename" . file))
-     )
+     "inline"          (("filename" . file)))
     ("\\.au$"
      "audio"   "basic"         nil
      "base64"
-     "attachment"              (("filename" . file))
-     )
+     "attachment"              (("filename" . file)))
     ("\\.mpg$"
      "video"   "mpeg"          nil
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     ("\\.tar\\.gz$"
      "application" "octet-stream" (("type" . "tar+gzip"))
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     ("\\.tgz$"
      "application" "octet-stream" (("type" . "tar+gzip"))
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     ("\\.tar\\.Z$"
      "application" "octet-stream" (("type" . "tar+compress"))
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     ("\\.taz$"
      "application" "octet-stream" (("type" . "tar+compress"))
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     ("\\.gz$"
      "application" "octet-stream" (("type" . "gzip"))
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     ("\\.Z$"
      "application" "octet-stream" (("type" . "compress"))
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     ("\\.lzh$"
      "application" "octet-stream" (("type" . "lha"))
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
     ("\\.zip$"
      "application" "zip" nil
      "base64"
-     "attachment"      (("filename" . file))
-     )
+     "attachment"      (("filename" . file)))
 
     ;; Rest
 
     (".*"
      "application" "octet-stream" nil
      nil
-     "attachment"      (("filename" . file)))
-    )
+     "attachment"      (("filename" . file))))
   "*Alist of file name, types, parameters, and default encoding.
 If encoding is nil, it is determined from its contents."
   :type `(repeat
@@ -429,8 +418,7 @@ If encoding is nil, it is determined from its contents."
                ;; primary-type
                (choice :tag "Primary-Type"
                        ,@(nconc (mapcar (lambda (cell)
-                                          (list 'item (car cell))
-                                          )
+                                          (list 'item (car cell)))
                                         mime-content-types)
                                 '(string)))
                ;; subtype
@@ -439,8 +427,7 @@ If encoding is nil, it is determined from its contents."
                           (apply #'nconc
                                  (mapcar (lambda (cell)
                                            (mapcar (lambda (cell)
-                                                     (list 'item (car cell))
-                                                     )
+                                                     (list 'item (car cell)))
                                                    (cdr cell)))
                                          mime-content-types))
                           '(string)))
@@ -452,8 +439,7 @@ If encoding is nil, it is determined from its contents."
                        ,@(cons
                           '(const nil)
                           (mapcar (lambda (cell)
-                                    (list 'item cell)
-                                    )
+                                    (list 'item cell))
                                   (mime-encoding-list))))
                ;; disposition-type
                (choice :tag "Disposition-Type"
@@ -463,8 +449,7 @@ If encoding is nil, it is determined from its contents."
                        string)
                ;; parameters
                (repeat :tag "Parameters of Content-Disposition field"
-                       (cons string (choice string symbol)))
-               ))
+                       (cons string (choice string symbol)))))
   :group 'mime-edit)
 
 
@@ -482,7 +467,10 @@ If encoding is nil, it is determined from its contents."
     (iso-8859-7                8 "quoted-printable")
     (iso-8859-8                8 "quoted-printable")
     (iso-8859-9                8 "quoted-printable")
+    (iso-8859-14       8 "quoted-printable")
+    (iso-8859-15       8 "quoted-printable")
     (iso-2022-jp       7 "base64")
+    (iso-2022-jp-3     7 "base64")
     (iso-2022-kr       7 "base64")
     (euc-kr            8 "base64")
     (cn-gb             8 "base64")
@@ -492,8 +480,7 @@ If encoding is nil, it is determined from its contents."
     (shift_jis         8 "base64")
     (tis-620           8 "base64")
     (iso-2022-jp-2     7 "base64")
-    (iso-2022-int-1    7 "base64")
-    ))
+    (iso-2022-int-1    7 "base64")))
 
 (defvar mime-transfer-level 7
   "*A number of network transfer level.  It should be bigger than 7.")
@@ -502,15 +489,13 @@ If encoding is nil, it is determined from its contents."
 (defsubst mime-encoding-name (transfer-level &optional not-omit)
   (cond ((> transfer-level 8) "binary")
        ((= transfer-level 8) "8bit")
-       (not-omit "7bit")
-       ))
+       (not-omit "7bit")))
 
 (defvar mime-transfer-level-string
   (mime-encoding-name mime-transfer-level 'not-omit)
   "A string formatted version of mime-transfer-level")
 (make-variable-buffer-local 'mime-transfer-level-string)
 
-
 ;;; @@ about content transfer encoding
 
 (defvar mime-content-transfer-encoding-priority-list
@@ -632,8 +617,13 @@ If it is not specified for a major-mode,
          " ("
          (mime-product-code-name mime-library-product)
          ") "
+         (if (fboundp 'apel-version)
+             (concat (apel-version) " "))
          (if (featurep 'xemacs)
-             (concat (cond ((featurep 'utf-2000)
+             (concat (cond ((and (featurep 'chise)
+                                 (boundp 'xemacs-chise-version))
+                            (concat "CHISE-MULE/" xemacs-chise-version))
+                           ((featurep 'utf-2000)
                             (concat "UTF-2000-MULE/" utf-2000-version))
                            ((featurep 'mule) "MULE"))
                      " XEmacs"
@@ -652,7 +642,14 @@ If it is not specified for a major-mode,
                                  ;; XEmacs versions earlier than 21.1.1.
                                  (format " (patch %d)" emacs-patch-level))
                                 (t ""))
-                          " (" xemacs-codename ") ("
+                          " (" xemacs-codename ")"
+                          ;; `xemacs-extra-name' has appeared in the
+                          ;; development version of XEmacs 21.5-b8.
+                          (if (and (boundp 'xemacs-extra-name)
+                                   (symbol-value 'xemacs-extra-name))
+                              (concat " " (symbol-value 'xemacs-extra-name))
+                            "")
+                          " ("
                           system-configuration ")")
                        " (" emacs-version ")"))
            (let ((ver (if (string-match "\\.[0-9]+$" emacs-version)
@@ -670,8 +667,7 @@ If it is not specified for a major-mode,
                                    (if (string-match "^Meadow-" mver)
                                        (concat " Meadow/"
                                                (substring mver
-                                                          (match-end 0)))
-                                     ))))
+                                                          (match-end 0)))))))
                    (concat "MULE/" mule-version
                            " (based on Emacs " ver ")"))
                (concat "Emacs/" ver " (" system-configuration ")")))))
@@ -693,9 +689,9 @@ Tspecials means any character that matches with it in header must be quoted.")
 
 (defconst mime-edit-mime-version-field-for-message/partial
   (concat "MIME-Version:"
-         (eword-encode-field-body
+         (mime-encode-field-body
           (concat " 1.0 (split by " mime-edit-version ")\n")
-          "MIME-Version:"))
+          "MIME-Version"))
   "MIME version field for message/partial.")
 
 
@@ -780,12 +776,11 @@ Tspecials means any character that matches with it in header must be quoted.")
     (encrypted "Enclose as encrypted"  mime-edit-enclose-pgp-encrypted-region)
     (quote     "Verbatim region"       mime-edit-enclose-quote-region)
     (key       "Insert Public Key"     mime-edit-insert-key)
-    (split     "About split"           mime-edit-set-split)
-    (sign      "About sign"            mime-edit-set-sign)
-    (encrypt   "About encryption"      mime-edit-set-encrypt)
+    (split     "Set splitting"         mime-edit-set-split)
+    (sign      "PGP sign"              mime-edit-set-sign)
+    (encrypt   "PGP encrypt"           mime-edit-set-encrypt)
     (preview   "Preview Message"       mime-edit-preview-message)
-    (level     "Toggle transfer-level" mime-edit-toggle-transfer-level)
-    )
+    (level     "Toggle transfer-level" mime-edit-toggle-transfer-level))
   "MIME-edit menubar entry.")
 
 (cond ((featurep 'xemacs)
@@ -802,10 +797,8 @@ Tspecials means any character that matches with it in header must be quoted.")
                       (mapcar (function
                                (lambda (item)
                                  (vector (nth 1 item)(nth 2 item)
-                                         mime-edit-mode-flag)
-                                 ))
-                              mime-edit-menu-list)))
-               )))
+                                         mime-edit-mode-flag)))
+                              mime-edit-menu-list))))))
 
        ;; modified by Steven L. Baur <steve@miranova.com>
        ;;      1995/12/6 (c.f. [tm-en:209])
@@ -816,9 +809,7 @@ Tspecials means any character that matches with it in header must be quoted.")
                                             (vector (nth 1 item)
                                                     (nth 2 item)
                                                     t)))
-                                mime-edit-menu-list)))
-          )
-       )
+                                mime-edit-menu-list)))))
       ((>= emacs-major-version 19)
        (define-key mime-edit-mode-map [menu-bar mime-edit]
         (cons mime-edit-menu-title
@@ -827,12 +818,8 @@ Tspecials means any character that matches with it in header must be quoted.")
                (lambda (item)
                  (define-key mime-edit-mode-map
                    (vector 'menu-bar 'mime-edit (car item))
-                   (cons (nth 1 item)(nth 2 item))
-                   )
-                 ))
-              (reverse mime-edit-menu-list)
-              )
-       ))
+                   (cons (nth 1 item)(nth 2 item)))))
+              (reverse mime-edit-menu-list))))
 
 
 ;;; @ functions
@@ -982,8 +969,7 @@ User customizable variables (not documented all of them):
        (mime-edit-again)
       (make-local-variable 'mime-edit-touched-flag)
       (setq mime-edit-touched-flag t)
-      (turn-on-mime-edit)
-      )))
+      (turn-on-mime-edit))))
 
 
 (cond ((featurep 'xemacs)
@@ -991,16 +977,14 @@ User customizable variables (not documented all of them):
                       '((" MIME-Edit "  mime-transfer-level-string))
                       mime-edit-mode-map
                       nil
-                      'mime-edit-mode)
-       )
+                      'mime-edit-mode))
       (t
        (set-alist 'minor-mode-alist
                  'mime-edit-mode-flag
                  '((" MIME-Edit "  mime-transfer-level-string)))
        (set-alist 'minor-mode-map-alist
                  'mime-edit-mode-flag
-                 mime-edit-mode-map)
-       ))
+                 mime-edit-mode-map)))
 
 
 ;;;###autoload
@@ -1019,10 +1003,7 @@ User customizable variables (not documented all of them):
 
     ;; Define menu for XEmacs.
     (if (featurep 'xemacs)
-       (mime-edit-define-menu-for-xemacs)
-      )
-
-    (enable-invisible)
+       (mime-edit-define-menu-for-xemacs))
 
     ;; I don't care about saving these.
     (setq paragraph-start
@@ -1033,9 +1014,9 @@ User customizable variables (not documented all of them):
                     paragraph-separate))
     (run-hooks 'mime-edit-mode-hook)
     (message
+     "%s"
      (substitute-command-keys
-      "Type \\[mime-edit-exit] to exit MIME mode, and type \\[mime-edit-help] to get help."))
-    ))
+      "Type \\[mime-edit-exit] to exit MIME mode, and type \\[mime-edit-help] to get help."))))
 
 ;;;###autoload
 (defalias 'edit-mime 'turn-on-mime-edit) ; for convenience
@@ -1048,8 +1029,7 @@ just return to previous mode."
   (interactive "P")
   (if (not mime-edit-mode-flag)
       (if (null no-error)
-         (error "You aren't editing a MIME message.")
-       )
+         (error "You aren't editing a MIME message."))
     (if (not nomime)
        (progn
          (run-hooks 'mime-edit-translate-hook)
@@ -1058,19 +1038,15 @@ just return to previous mode."
     (setq mime-edit-mode-flag nil)
     (if (and (featurep 'xemacs)
             (featurep 'menubar))
-       (delete-menu-item (list mime-edit-menu-title))
-      )
-    (end-of-invisible)
+       (delete-menu-item (list mime-edit-menu-title)))
     (set-buffer-modified-p (buffer-modified-p))
     (run-hooks 'mime-edit-exit-hook)
-    (message "Exit MIME editor mode.")
-    ))
+    (message "Exit MIME editor mode.")))
 
 (defun mime-edit-maybe-translate ()
   (interactive)
   (mime-edit-exit nil t)
-  (call-interactively 'mime-edit-maybe-split-and-send)
-  )
+  (call-interactively 'mime-edit-maybe-split-and-send))
 
 (defun mime-edit-help ()
   "Show help message about MIME mode."
@@ -1091,15 +1067,12 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
          (progn
            ;; Make a space between the following message.
            (insert "\n")
-           (forward-char -1)
-           ))
+           (forward-char -1)))
       (if (and (member (cadr ret) '("enriched"))
               (fboundp 'enriched-mode))
          (enriched-mode t)
        (if (boundp 'enriched-mode)
-           (enriched-mode -1)
-         ))
-      )))
+           (enriched-mode -1))))))
 
 (defun mime-edit-insert-file (file &optional verbose)
   "Insert a message from a file."
@@ -1110,15 +1083,12 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
          (parameters (nth 2 guess))
          (encoding (nth 3 guess))
          (disposition-type (nth 4 guess))
-         (disposition-params (nth 5 guess))
-         )
+         (disposition-params (nth 5 guess)))
     (if verbose
        (setq type    (mime-prompt-for-type type)
-             subtype (mime-prompt-for-subtype type subtype)
-             ))
+             subtype (mime-prompt-for-subtype type subtype)))
     (if (or (interactive-p) verbose)
-       (setq encoding (mime-prompt-for-encoding encoding))
-      )
+       (setq encoding (mime-prompt-for-encoding encoding)))
     (if (or (consp parameters) (stringp disposition-type))
        (let ((rest parameters) cell attribute value)
          (setq parameters "")
@@ -1128,11 +1098,9 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
            (setq value (cdr cell))
            (if (eq value 'file)
                (setq value (std11-wrap-as-quoted-string
-                            (file-name-nondirectory file)))
-             )
+                            (file-name-nondirectory file))))
            (setq parameters (concat parameters "; " attribute "=" value))
-           (setq rest (cdr rest))
-           )
+           (setq rest (cdr rest)))
          (if disposition-type
              (progn
                (setq parameters
@@ -1145,17 +1113,12 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
                  (setq value (cdr cell))
                  (if (eq value 'file)
                      (setq value (std11-wrap-as-quoted-string
-                                  (file-name-nondirectory file)))
-                   )
+                                  (file-name-nondirectory file))))
                  (setq parameters
                        (concat parameters "; " attribute "=" value))
-                 (setq rest (cdr rest))
-                 )
-               ))
-         ))
+                 (setq rest (cdr rest)))))))
     (mime-edit-insert-tag type subtype parameters)
-    (mime-edit-insert-binary-file file encoding)
-    ))
+    (mime-edit-insert-binary-file file encoding)))
 
 (defun mime-edit-insert-external ()
   "Insert a reference to external body."
@@ -1185,14 +1148,14 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
     (mime-edit-insert-tag "audio" "basic" nil)
     (mime-edit-define-encoding encoding)
     (save-restriction
-      (narrow-to-region (1- (point))(point))
+      (narrow-to-region (point)(point))
       (unwind-protect
          (funcall mime-edit-voice-recorder encoding)
        (progn
          (insert "\n")
-         (invisible-region (point-min)(point-max))
-         (goto-char (point-max))
-         )))))
+         (add-text-properties
+          (point-min)(point-max) '(invisible t mime-edit-invisible t))
+         (goto-char (point-max)))))))
 
 (defun mime-edit-insert-signature (&optional arg)
   "Insert a signature file."
@@ -1202,11 +1165,8 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
           (lambda ()
            (let ((items (mime-find-file-type signature-file-name)))
              (apply (function mime-edit-insert-tag)
-                    (car items) (cadr items) (list (caddr items))))
-            )))
-        )
-    (insert-signature arg)
-    ))
+                    (car items) (cadr items) (list (caddr items))))))))
+    (insert-signature arg)))
 
 \f
 ;; Insert a new tag around a point.
@@ -1219,15 +1179,12 @@ If nothing is inserted, return nil."
     (mime-edit-goto-tag)
     (if (and (re-search-forward mime-edit-tag-regexp nil t)
             (< (match-beginning 0) p)
-            (< p (match-end 0))
-            )
+            (< p (match-end 0)))
        (goto-char (match-beginning 0))
-      (goto-char p)
-      ))
+      (goto-char p)))
   (let ((oldtag nil)
        (newtag nil)
-       (current (point))
-       )
+       (current (point)))
     (setq pritype
          (or pritype
              (mime-prompt-for-type)))
@@ -1245,8 +1202,7 @@ If nothing is inserted, return nil."
            (if (mime-edit-goto-tag)
                (buffer-substring (match-beginning 0) (match-end 0))
              ;; Assume content type is 'text/plan'.
-             (mime-make-tag "text" "plain")
-             )))
+             (mime-make-tag "text" "plain"))))
     ;; We are only interested in TEXT.
     (if (and oldtag
             (not (mime-test-content-type
@@ -1265,8 +1221,7 @@ If nothing is inserted, return nil."
       ;; Restore previous point.
       (goto-char current)
       nil                              ;Nothing is created.
-      )
-    ))
+      )))
 
 (defun mime-edit-insert-binary-file (file &optional encoding)
   "Insert binary FILE at point.
@@ -1278,31 +1233,23 @@ Optional argument ENCODING specifies an encoding method such as base64."
                       (let ((en (downcase encoding)))
                         (or (string-equal en "7bit")
                             (string-equal en "8bit")
-                            (string-equal en "binary")
-                            )))))
-        )
+                            (string-equal en "binary")))))))
     (save-restriction
-      (narrow-to-region tagend (point))
+      (narrow-to-region (point)(point))
       (mime-insert-encoded-file file encoding)
       (if hide-p
-         (progn
-           (invisible-region (point-min) (point-max))
-           (goto-char (point-max))
-           )
-       (goto-char (point-max))
-       ))
+         (add-text-properties
+          (point-min)(point-max) '(invisible t mime-edit-invisible t)))
+      (goto-char (point-max)))
     (or hide-p
        (looking-at mime-edit-tag-regexp)
        (= (point)(point-max))
-       (mime-edit-insert-tag "text" "plain")
-       )
+       (mime-edit-insert-tag "text" "plain"))
     ;; Define encoding even if it is 7bit.
     (if (stringp encoding)
        (save-excursion
          (goto-char tagend) ; Make sure which line the tag is on.
-         (mime-edit-define-encoding encoding)
-         ))
-    ))
+         (mime-edit-define-encoding encoding)))))
 
 \f
 ;; Commands work on a current message flagment.
@@ -1317,17 +1264,14 @@ Optional argument ENCODING specifies an encoding method such as base64."
             (goto-char (1- (match-beginning 0))) ;For multiline tag
             )
            (t
-            (goto-char (point-max))
-            ))
+            (goto-char (point-max))))
       ;; Then search for the beginning.
       (re-search-backward mime-edit-end-tag-regexp nil t)
       (or (looking-at mime-edit-beginning-tag-regexp)
          ;; Restore previous point.
          (progn
            (goto-char current)
-           nil
-           ))
-      )))
+           nil)))))
 
 (defun mime-edit-content-beginning ()
   "Return the point of the beginning of content."
@@ -1348,31 +1292,28 @@ Optional argument ENCODING specifies an encoding method such as base64."
         (concat "\n" (regexp-quote mail-header-separator)
                 (if mime-ignore-preceding-spaces
                     "[ \t\n]*\n" "\n")) nil 'move)
-       (point))
-      )))
+       (point)))))
 
 (defun mime-edit-content-end ()
   "Return the point of the end of content."
   (save-excursion
     (if (mime-edit-goto-tag)
        (progn
-         (goto-char (match-end 0))
-         (if (invisible-p (point))
-             (next-visible-point (point))
+         (goto-char (1+ (match-end 0)))
+         (if (get-text-property (point) 'mime-edit-invisible)
+             (or (next-single-property-change (point) 'mime-edit-invisible)
+                 (point-max))
            ;; Move to the end of this text.
            (if (re-search-forward mime-edit-tag-regexp nil 'move)
                ;; Don't forget a multiline tag.
-               (goto-char (match-beginning 0))
-             )
-           (point)
-           ))
+               (goto-char (match-beginning 0)))
+           (point)))
       ;; Assume the message begins with text/plain.
       (goto-char (mime-edit-content-beginning))
       (if (re-search-forward mime-edit-tag-regexp nil 'move)
          ;; Don't forget a multiline tag.
          (goto-char (match-beginning 0)))
-      (point))
-    ))
+      (point))))
 
 (defun mime-edit-define-charset (charset)
   "Set charset of current tag to CHARSET."
@@ -1384,9 +1325,12 @@ Optional argument ENCODING specifies an encoding method such as base64."
           (mime-create-tag
            (mime-edit-set-parameter
             (mime-edit-get-contype tag)
-            "charset" (upcase (symbol-name charset)))
-           (mime-edit-get-encoding tag)))
-         ))))
+            "charset"
+            (let ((comment (get charset 'mime-charset-comment)))
+              (if comment
+                  (concat (upcase (symbol-name charset)) " (" comment ")")
+                (upcase (symbol-name charset)))))
+           (mime-edit-get-encoding tag)))))))
 
 (defun mime-edit-define-encoding (encoding)
   "Set encoding of current tag to ENCODING."
@@ -1394,13 +1338,11 @@ Optional argument ENCODING specifies an encoding method such as base64."
     (if (mime-edit-goto-tag)
        (let ((tag (buffer-substring (match-beginning 0) (match-end 0))))
          (delete-region (match-beginning 0) (match-end 0))
-         (insert (mime-create-tag (mime-edit-get-contype tag) encoding)))
-      )))
+         (insert (mime-create-tag (mime-edit-get-contype tag) encoding))))))
 
 (defun mime-edit-choose-charset ()
   "Choose charset of a text following current point."
-  (detect-mime-charset-region (point) (mime-edit-content-end))
-  )
+  (detect-mime-charset-region (point) (mime-edit-content-end)))
 
 (defun mime-make-text-tag (&optional subtype)
   "Make a tag for a text after current point.
@@ -1431,10 +1373,8 @@ Otherwise, it is obtained from mime-content-types."
   (and (stringp tag)
        (or (string-match mime-edit-single-part-tag-regexp tag)
           (string-match mime-edit-multipart-beginning-regexp tag)
-          (string-match mime-edit-multipart-end-regexp tag)
-          )
-       (substring tag (match-beginning 1) (match-end 1))
-       ))
+          (string-match mime-edit-multipart-end-regexp tag))
+       (substring tag (match-beginning 1) (match-end 1))))
 
 (defun mime-edit-get-encoding (tag)
   "Return encoding of TAG."
@@ -1463,8 +1403,7 @@ Nil if no such parameter."
     (if (string-match "\n[^ \t\n\r]+:" contype)
        (setq ctype (substring contype 0 (match-beginning 0))
              opt-fields (substring contype (match-beginning 0)))
-      (setq ctype contype)
-      )
+      (setq ctype contype))
     (if (string-match
         (concat
          ";[ \t\n]*\\("
@@ -1474,7 +1413,7 @@ Nil if no such parameter."
        ;; Change value
        (concat (substring ctype 0 (match-beginning 1))
                parameter "=" value
-               (substring contype (match-end 1))
+               (substring ctype (match-end 1))
                opt-fields)
       (concat ctype "; " parameter "=" value opt-fields)
       )))
@@ -1503,8 +1442,7 @@ Nil if no such parameter."
       (if (string-match (car (car guesses)) file)
          (setq guess (cdr (car guesses))))
       (setq guesses (cdr guesses)))
-    guess
-    ))
+    guess))
 
 (defun mime-prompt-for-type (&optional default)
   "Ask for Content-type."
@@ -1516,15 +1454,12 @@ Nil if no such parameter."
                             mime-content-types
                             nil
                             'require-match ;Type must be specified.
-                            default
-                            ))
+                            default))
       (if (string-equal type "")
          (progn
            (message "Content type is required.")
            (beep)
-           (sit-for 1)
-           ))
-      )
+           (sit-for 1))))
     type))
 
 (defun mime-prompt-for-subtype (type &optional default)
@@ -1532,8 +1467,7 @@ Nil if no such parameter."
   (let ((subtypes (cdr (assoc type mime-content-types))))
     (or (and default
             (assoc default subtypes))
-       (setq default (car (car subtypes)))
-       ))
+       (setq default (car (car subtypes)))))
   (let* ((answer
          (completing-read
           (if default
@@ -1543,8 +1477,7 @@ Nil if no such parameter."
           (cdr (assoc type mime-content-types))
           nil
           'require-match               ;Subtype must be specified.
-          nil
-          )))
+          nil)))
     (if (string-equal answer "") default answer)))
 
 (defun mime-prompt-for-parameters (pritype subtype &optional delimiter)
@@ -1558,8 +1491,7 @@ Optional DELIMITER specifies parameter delimiter (';' by default)."
                 (mime-prompt-for-parameters-1
                  (cdr (assoc subtype
                              (cdr (assoc pritype mime-content-types))))))
-          delimiter
-          )))
+          delimiter)))
     (if (and (stringp parameters)
             (not (string-equal parameters "")))
        (concat delimiter parameters)
@@ -1572,7 +1504,7 @@ Optional DELIMITER specifies parameter delimiter (';' by default)."
 
 (defun mime-prompt-for-parameter (parameter)
   "Ask for PARAMETER.
-Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
+Parameter must be '(PROMPT CHOICE1 (CHOICE2...))."
   (let* ((prompt (car parameter))
         (choices (mapcar (function
                           (lambda (e)
@@ -1600,8 +1532,7 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
                      ;; Note: control characters ignored!
                      (if (string-match mime-tspecials-regexp answer)
                          (concat "\"" answer "\"") answer)))
-         (mime-prompt-for-parameters-1 (cdr (assoc answer (cdr parameter)))))
-    ))
+         (mime-prompt-for-parameters-1 (cdr (assoc answer (cdr parameter)))))))
 
 (defun mime-prompt-for-encoding (default)
   "Ask for Content-Transfer-Encoding."
@@ -1610,8 +1541,7 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
            (setq encoding
                  (completing-read
                   "What transfer encoding: "
-                  (mime-encoding-alist) nil t default)
-                 )
+                  (mime-encoding-alist) nil t default))
            ""))
     encoding))
 
@@ -1626,21 +1556,19 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
 
 (defun mime-edit-translate-header ()
   "Encode the message header into network representation."
-  (eword-encode-header 'code-conversion)
-  (run-hooks 'mime-edit-translate-header-hook)
-  )
+  (mime-encode-header-in-buffer 'code-conversion)
+  (run-hooks 'mime-edit-translate-header-hook))
 
 (defun mime-edit-translate-buffer ()
   "Encode the tagged MIME message in current buffer in MIME compliant message."
   (interactive)
+  (undo-boundary)
   (if (catch 'mime-edit-error
        (save-excursion
-         (run-hooks 'mime-edit-translate-buffer-hook)
-         ))
+         (run-hooks 'mime-edit-translate-buffer-hook)))
       (progn
        (undo)
-       (error "Translation error!")
-       )))
+       (error "Translation error!"))))
 
 (defun mime-edit-find-inmost ()
   (goto-char (point-min))
@@ -1653,26 +1581,22 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
        (widen)
        (if (re-search-forward end-exp nil t)
            (setq eb (match-beginning 0))
-         (setq eb (point-max))
-         )
+         (setq eb (point-max)))
        (narrow-to-region be eb)
        (goto-char be)
        (if (re-search-forward mime-edit-multipart-beginning-regexp nil t)
            (progn
              (narrow-to-region (match-beginning 0)(point-max))
-             (mime-edit-find-inmost)
-             )
+             (mime-edit-find-inmost))
          (widen)
-         (list type bb be eb)
-         ))))
+         (list type bb be eb)))))
 
 (defun mime-edit-process-multipart-1 (boundary)
   (let ((ret (mime-edit-find-inmost)))
     (if ret
        (let ((type (car ret))
              (bb (nth 1 ret))(be (nth 2 ret))
-             (eb (nth 3 ret))
-             )
+             (eb (nth 3 ret)))
          (narrow-to-region bb eb)
          (delete-region bb be)
          (setq bb (point-min))
@@ -1681,28 +1605,25 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
          (goto-char eb)
          (if (looking-at mime-edit-multipart-end-regexp)
              (let ((beg (match-beginning 0))
-                   (end (match-end 0))
-                   )
+                   (end (match-end 0)))
                (delete-region beg end)
                (or (looking-at mime-edit-beginning-tag-regexp)
                    (eobp)
-                   (insert (concat (mime-make-text-tag) "\n"))
-                   )))
+                   (insert (concat (mime-make-text-tag) "\n")))))
          (cond ((string-equal type "quote")
-                (mime-edit-enquote-region bb eb)
-                )
+                (mime-edit-enquote-region bb eb))
                ((string-equal type "pgp-signed")
-                (mime-edit-sign-pgp-mime bb eb boundary)
-                )
+                (mime-edit-sign-pgp-mime bb eb boundary))
                ((string-equal type "pgp-encrypted")
-                (mime-edit-encrypt-pgp-mime bb eb boundary)
-                )
+                (mime-edit-encrypt-pgp-mime bb eb boundary))
                ((string-equal type "kazu-signed")
-                (mime-edit-sign-pgp-kazu bb eb boundary)
-                )
+                (mime-edit-sign-pgp-kazu bb eb boundary))
                ((string-equal type "kazu-encrypted")
-                (mime-edit-encrypt-pgp-kazu bb eb boundary)
-                )
+                (mime-edit-encrypt-pgp-kazu bb eb boundary))
+               ((string-equal type "smime-signed")
+                (mime-edit-sign-smime bb eb boundary))
+               ((string-equal type "smime-encrypted")
+                (mime-edit-encrypt-smime bb eb boundary))
                (t
                 (setq boundary
                       (nth 2 (mime-edit-translate-region bb eb
@@ -1711,8 +1632,7 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
                 (insert
                  (format "--[[multipart/%s;
  boundary=\"%s\"][7bit]]\n"
-                         type boundary))
-                ))
+                         type boundary))))
          boundary))))
 
 (defun mime-edit-enquote-region (beg end)
@@ -1722,8 +1642,7 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
       (goto-char beg)
       (while (re-search-forward mime-edit-single-part-tag-regexp nil t)
        (let ((tag (buffer-substring (match-beginning 0)(match-end 0))))
-         (replace-match (concat "- " (substring tag 1)))
-         )))))
+         (replace-match (concat "- " (substring tag 1))))))))
 
 (defun mime-edit-dequote-region (beg end)
   (save-excursion
@@ -1733,30 +1652,65 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
       (while (re-search-forward
              mime-edit-quoted-single-part-tag-regexp nil t)
        (let ((tag (buffer-substring (match-beginning 0)(match-end 0))))
-         (replace-match (concat "-" (substring tag 2)))
-         )))))
+         (replace-match (concat "-" (substring tag 2))))))))
+
+(defvar mime-edit-pgp-user-id nil)
+
+(defun mime-edit-delete-trailing-whitespace ()
+  (save-match-data
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward "[ \t]+$" nil t)
+       (delete-region (match-beginning 0) (match-end 0))))))
 
 (defun mime-edit-sign-pgp-mime (beg end boundary)
   (save-excursion
     (save-restriction
-      (narrow-to-region beg end)
-      (let* ((ret
-             (mime-edit-translate-region beg end boundary))
+      (let* ((from (std11-field-body "From" mail-header-separator))
+            (ret (progn 
+                   (narrow-to-region beg end)
+                   (mime-edit-translate-region beg end boundary)))
             (ctype    (car ret))
             (encoding (nth 1 ret))
-            (pgp-boundary (concat "pgp-sign-" boundary)))
+            (pgp-boundary (concat "pgp-sign-" boundary))
+            micalg)
+       (mime-edit-delete-trailing-whitespace) ; RFC3156
        (goto-char beg)
        (insert (format "Content-Type: %s\n" ctype))
        (if encoding
-           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
-         )
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
        (insert "\n")
-       (or (as-binary-process
-            (funcall (pgp-function 'mime-sign)
-                     (point-min)(point-max) nil nil pgp-boundary))
-           (throw 'mime-edit-error 'pgp-error)
-           )
-       ))))
+       (or (let ((pgg-default-user-id 
+                  (or mime-edit-pgp-user-id
+                      (if from 
+                          (nth 1 (std11-extract-address-components from))
+                        pgg-default-user-id))))
+             (pgg-sign-region (point-min)(point-max)))
+           (throw 'mime-edit-error 'pgp-error))
+       (setq micalg
+             (cdr (assq 'hash-algorithm
+                        (cdar (with-current-buffer pgg-output-buffer
+                                (pgg-parse-armor-region 
+                                 (point-min)(point-max))))))
+             micalg 
+             (if micalg
+                 (concat "; micalg=pgp-" (downcase (symbol-name micalg)))
+               ""))
+       (goto-char beg)
+       (insert (format "--[[multipart/signed;
+ boundary=\"%s\"%s;
+ protocol=\"application/pgp-signature\"][7bit]]
+--%s
+" pgp-boundary micalg pgp-boundary))
+       (goto-char (point-max))
+       (insert (format "\n--%s
+Content-Type: application/pgp-signature
+Content-Transfer-Encoding: 7bit
+
+" pgp-boundary))
+       (insert-buffer-substring pgg-output-buffer)
+       (goto-char (point-max))
+       (insert (format "\n--%s--\n" pgp-boundary))))))
 
 (defvar mime-edit-encrypt-recipient-fields-list '("To" "cc"))
 
@@ -1771,53 +1725,57 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
         (header (and (stringp from)
                      (if (string-equal from "")
                          ""
-                       (format "From: %s\n" from)
-                       )))
+                       (format "From: %s\n" from))))
         recipients)
     (while (and names values)
       (let ((name (car names))
-           (value (car values))
-           )
+           (value (car values)))
        (and (stringp value)
             (or (string-equal value "")
                 (progn
                   (setq header (concat header name ": " value "\n")
                         recipients (if recipients
                                        (concat recipients " ," value)
-                                     value))
-                  ))))
+                                     value))))))
       (setq names (cdr names)
-           values (cdr values))
-      )
-    (vector from recipients header)
-    ))
+           values (cdr values)))
+    (vector from recipients header)))
 
 (defun mime-edit-encrypt-pgp-mime (beg end boundary)
   (save-excursion
     (save-restriction
       (let (from recipients header)
-       (let ((ret (mime-edit-make-encrypt-recipient-header)))
-         (setq from (aref ret 0)
-               recipients (aref ret 1)
-               header (aref ret 2))
-         )
-       (narrow-to-region beg end)
-       (let* ((ret
-               (mime-edit-translate-region beg end boundary))
-              (ctype    (car ret))
-              (encoding (nth 1 ret))
-              (pgp-boundary (concat "pgp-" boundary)))
-         (goto-char beg)
-         (insert header)
-         (insert (format "Content-Type: %s\n" ctype))
-         (if encoding
-             (insert (format "Content-Transfer-Encoding: %s\n" encoding))
-           )
-         (insert "\n")
-         (or (funcall (pgp-function 'encrypt)
-                      recipients (point-min) (point-max) from)
-             (throw 'mime-edit-error 'pgp-error)
-             )
+        (let ((ret (mime-edit-make-encrypt-recipient-header)))
+          (setq from (aref ret 0)
+                recipients (aref ret 1)
+                header (aref ret 2)))
+        (narrow-to-region beg end)
+        (let* ((ret
+                (mime-edit-translate-region beg end boundary))
+               (ctype    (car ret))
+               (encoding (nth 1 ret))
+               (pgp-boundary (concat "pgp-" boundary)))
+          (goto-char beg)
+          (insert header)
+          (insert (format "Content-Type: %s\n" ctype))
+          (if encoding
+              (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
+          (insert "\n")
+         (mime-encode-header-in-buffer)
+         (or (let ((pgg-default-user-id 
+                    (or mime-edit-pgp-user-id
+                        (if from 
+                            (nth 1 (std11-extract-address-components from))
+                          pgg-default-user-id))))                   
+               (pgg-encrypt-region 
+                (point-min) (point-max) 
+                (mapcar (lambda (recipient)
+                          (nth 1 (std11-extract-address-components
+                                  recipient)))
+                        (split-string recipients 
+                                      "\\([ \t\n]*,[ \t\n]*\\)+"))))
+             (throw 'mime-edit-error 'pgp-error))
+         (delete-region (point-min)(point-max))
          (goto-char beg)
          (insert (format "--[[multipart/encrypted;
  boundary=\"%s\";
@@ -1830,9 +1788,9 @@ Content-Type: application/octet-stream
 Content-Transfer-Encoding: 7bit
 
 " pgp-boundary pgp-boundary pgp-boundary))
+         (insert-buffer-substring pgg-output-buffer)
          (goto-char (point-max))
-         (insert (format "\n--%s--\n" pgp-boundary))
-         )))))
+         (insert (format "\n--%s--\n" pgp-boundary)))))))
 
 (defun mime-edit-sign-pgp-kazu (beg end boundary)
   (save-excursion
@@ -1845,27 +1803,21 @@ Content-Transfer-Encoding: 7bit
        (goto-char beg)
        (insert (format "Content-Type: %s\n" ctype))
        (if encoding
-           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
-         )
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
        (insert "\n")
-       (or (as-binary-process
-            (funcall (pgp-function 'traditional-sign)
-                     beg (point-max)))
-           (throw 'mime-edit-error 'pgp-error)
-           )
+       (or (pgg-sign-region beg (point-max) 'clearsign)
+           (throw 'mime-edit-error 'pgp-error))
        (goto-char beg)
        (insert
         "--[[application/pgp; format=mime][7bit]]\n")
-       ))
-    ))
+       ))))
 
 (defun mime-edit-encrypt-pgp-kazu (beg end boundary)
   (save-excursion
     (let (recipients header)
       (let ((ret (mime-edit-make-encrypt-recipient-header)))
        (setq recipients (aref ret 1)
-             header (aref ret 2))
-       )
+             header (aref ret 2)))
       (save-restriction
        (narrow-to-region beg end)
        (let* ((ret
@@ -1876,20 +1828,70 @@ Content-Transfer-Encoding: 7bit
          (insert header)
          (insert (format "Content-Type: %s\n" ctype))
          (if encoding
-             (insert (format "Content-Transfer-Encoding: %s\n" encoding))
-           )
+             (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
          (insert "\n")
-         (or (as-binary-process
-              (funcall (pgp-function 'encrypt)
-                       recipients beg (point-max) nil 'maybe)
-              )
-             (throw 'mime-edit-error 'pgp-error)
-             )
+         (or (pgg-encrypt-region beg (point-max) recipients)
+             (throw 'mime-edit-error 'pgp-error))
          (goto-char beg)
          (insert
           "--[[application/pgp; format=mime][7bit]]\n")
-         ))
-      )))
+         )))))
+
+(defun mime-edit-sign-smime (beg end boundary)
+  (save-excursion
+    (save-restriction
+      (let* ((ret (progn 
+                   (narrow-to-region beg end)
+                   (mime-edit-translate-region beg end boundary)))
+            (ctype    (car ret))
+            (encoding (nth 1 ret))
+            (smime-boundary (concat "smime-sign-" boundary)))
+       (goto-char beg)
+       (insert (format "Content-Type: %s\n" ctype))
+       (if encoding
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
+       (insert "\n")
+       (let (buffer-undo-list)
+         (goto-char (point-min))
+         (while (progn (end-of-line) (not (eobp)))
+           (insert "\r")
+           (forward-line 1))
+         (or (smime-sign-buffer)
+             (throw 'mime-edit-error 'pgp-error)))
+       (goto-char beg)
+       (if (re-search-forward "^Content-Type:\\s-*" nil t)
+           (let* ((start (match-beginning 0))
+                  (body (buffer-substring (match-end 0) (std11-field-end))))
+             (delete-region start (line-beginning-position 2))
+             (goto-char beg)
+             (insert "--[[" body "][7bit]]\n")))))))
+
+(defun mime-edit-encrypt-smime (beg end boundary)
+  (save-excursion
+    (save-restriction
+      (let* ((ret (progn 
+                   (narrow-to-region beg end)
+                   (mime-edit-translate-region beg end boundary)))
+            (ctype    (car ret))
+            (encoding (nth 1 ret)))
+       (goto-char beg)
+       (insert (format "Content-Type: %s\n" ctype))
+       (if encoding
+           (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
+       (insert "\n")
+       (goto-char (point-min))
+       (while (progn (end-of-line) (not (eobp)))
+         (insert "\r")
+         (forward-line 1))
+       (or (smime-encrypt-buffer)
+           (throw 'mime-edit-error 'pgp-error))
+       (goto-char beg)
+       (if (re-search-forward "^Content-Type:\\s-*" nil t)
+           (let* ((start (match-beginning 0))
+                  (body (buffer-substring (match-end 0) (std11-field-end))))
+             (delete-region start (line-beginning-position 2))
+             (goto-char beg)
+             (insert "--[[" body "]]\n")))))))
 
 (defsubst replace-space-with-underline (str)
   (mapconcat (function
@@ -1897,13 +1899,11 @@ Content-Transfer-Encoding: 7bit
                (char-to-string
                 (if (eq arg ?\ )
                     ?_
-                  arg)))) str "")
-  )
+                  arg)))) str ""))
 
 (defun mime-edit-make-boundary ()
   (concat mime-multipart-boundary "_"
-         (replace-space-with-underline (current-time-string))
-         ))
+         (replace-space-with-underline (current-time-string))))
 
 (defun mime-edit-translate-body ()
   "Encode the tagged MIME body in current buffer in MIME compliant message."
@@ -1914,8 +1914,7 @@ Content-Transfer-Encoding: 7bit
          ret)
       (while (mime-edit-process-multipart-1
              (format "%s-%d" boundary i))
-       (setq i (1+ i))
-       )
+       (setq i (1+ i)))
       (save-restriction
        ;; We are interested in message body.
        (let* ((beg
@@ -1935,8 +1934,7 @@ Content-Transfer-Encoding: 7bit
                  (point))))
          (setq ret (mime-edit-translate-region
                     beg end
-                    (format "%s-%d" boundary i)))
-         ))
+                    (format "%s-%d" boundary i)))))
       (mime-edit-dequote-region (point-min)(point-max))
       (let ((contype (car ret))                ;Content-Type
            (encoding (nth 1 ret))      ;Content-Transfer-Encoding
@@ -1944,8 +1942,7 @@ Content-Transfer-Encoding: 7bit
        ;; Insert User-Agent field
        (and mime-edit-insert-user-agent-field
             (or (mail-position-on-field "User-Agent")
-                (insert mime-edit-user-agent-value)
-                ))
+                (insert mime-edit-user-agent-value)))
        ;; Make primary MIME headers.
        (or (mail-position-on-field "MIME-Version")
            (insert mime-edit-mime-version-value))
@@ -1963,8 +1960,7 @@ Content-Transfer-Encoding: 7bit
        (if encoding
            (progn
              (mail-position-on-field "Content-Transfer-Encoding")
-             (insert encoding)))
-       ))))
+             (insert encoding)))))))
 
 (defun mime-edit-translate-single-part-tag (boundary &optional prefix)
   "Translate single-part-tag to MIME header."
@@ -1981,18 +1977,15 @@ Content-Transfer-Encoding: 7bit
            (insert "Content-Type: " contype "\n")
            (if encoding
                (insert "Content-Transfer-Encoding: " encoding "\n"))
-           (eword-encode-header)
-           )
+           (mime-encode-header-in-buffer))
          (cons (and contype
                     (downcase contype))
                (and encoding
-                    (downcase encoding))))
-       )))
+                    (downcase encoding)))))))
 
 (defun mime-edit-translate-region (beg end &optional boundary multipart)
   (or boundary
-      (setq boundary (mime-edit-make-boundary))
-      )
+      (setq boundary (mime-edit-make-boundary)))
   (save-excursion
     (save-restriction
       (narrow-to-region beg end)
@@ -2018,8 +2011,7 @@ Content-Transfer-Encoding: 7bit
                  (buffer-substring (match-beginning 0) (match-end 0)))
            (delete-region (match-beginning 0) (1+ (match-end 0)))
            (setq contype (mime-edit-get-contype tag))
-           (setq encoding (mime-edit-get-encoding tag))
-           ))
+           (setq encoding (mime-edit-get-encoding tag))))
         (t
          ;; It's a multipart message.
          (goto-char (point-min))
@@ -2039,10 +2031,8 @@ Content-Transfer-Encoding: 7bit
            (setq encoding (car prio))
            ;; Insert the trailer.
            (goto-char (point-max))
-           (insert "\n--" boundary "--\n")
-           )))
-        (list contype encoding boundary nparts)
-        ))))
+           (insert "\n--" boundary "--\n"))))
+        (list contype encoding boundary nparts)))))
 
 (defun mime-edit-normalize-body ()
   "Normalize the body part by inserting appropriate message tags."
@@ -2061,23 +2051,19 @@ Content-Transfer-Encoding: 7bit
       (if (looking-at "[ \t]+$")
          (delete-region (match-beginning 0) (match-end 0)))
       (let ((beg (point))
-           (end (mime-edit-content-end))
-           )
+           (end (mime-edit-content-end)))
        (if (= end (point-max))
            nil
          (goto-char end)
          (or (looking-at mime-edit-beginning-tag-regexp)
              (eobp)
-             (insert (mime-make-text-tag) "\n")
-             ))
-       (visible-region beg end)
-       (goto-char beg)
-       )
+             (insert (mime-make-text-tag) "\n")))
+       (remove-text-properties beg end '(invisible mime-edit-invisible))
+       (goto-char beg))
       (cond
        ((mime-test-content-type contype "message")
        ;; Content-type "message" should be sent as is.
-       (forward-line 1)
-       )
+       (forward-line 1))
        ((mime-test-content-type contype "text")
        ;; Define charset for text if necessary.
        (setq charset (if charset
@@ -2087,15 +2073,13 @@ Content-Transfer-Encoding: 7bit
        (cond ((string-equal contype "text/x-rot13-47-48")
               (save-excursion
                 (forward-line)
-                (mule-caesar-region (point) (mime-edit-content-end))
-                ))
+                (mule-caesar-region (point) (mime-edit-content-end))))
              ((string-equal contype "text/enriched")
               (save-excursion
                 (let ((beg (progn
                              (forward-line)
                              (point)))
-                      (end (mime-edit-content-end))
-                      )
+                      (end (mime-edit-content-end)))
                   ;; Patch for hard newlines
                    ;; (save-excursion
                    ;;   (goto-char beg)
@@ -2104,12 +2088,10 @@ Content-Transfer-Encoding: 7bit
                    ;;                        (point)
                    ;;                        'hard t)))
                   ;; End patch for hard newlines
-                  (enriched-encode beg end)
+                  (enriched-encode beg end nil)
                   (goto-char beg)
                   (if (search-forward "\n\n")
-                      (delete-region beg (match-end 0))
-                    )
-                  ))))
+                      (delete-region beg (match-end 0)))))))
        ;; Point is now on current tag.
        ;; Define encoding and encode text if necessary.
        (or encoding    ;Encoding is not specified.
@@ -2140,24 +2122,26 @@ Content-Transfer-Encoding: 7bit
                                            x-ctext))
                            (while (progn
                                     (replace-match "\e(BFrom ")
-                                    (re-search-forward "^From " nil t)
-                                    ))
-                         (setq encoding "quoted-printable")
-                         )))))
+                                    (re-search-forward "^From " nil t)))
+                         (setq encoding "quoted-printable"))))))
              ;; canonicalize line break code
              (or (member encoding '(nil "7bit" "8bit" "quoted-printable"))
                  (save-restriction
                    (narrow-to-region beg (mime-edit-content-end))
                    (goto-char beg)
                    (while (re-search-forward "\\(\\=\\|[^\r]\\)\n" nil t)
-                     (replace-match "\\1\r\n"))))
+                     ;; In a certain period, `replace-match' with "\\N"
+                     ;; converted 8-bit characters into multibyte string,
+                     ;; but it has been fixed at 2004-01-15.
+                     ;;(replace-match "\\1\r\n"))))
+                     (backward-char 1)
+                     (insert "\r")
+                     (forward-char 1))))
              (goto-char beg)
              (mime-encode-region beg (mime-edit-content-end)
                                  (or encoding "7bit"))
-             (mime-edit-define-encoding encoding)
-             ))
-       (goto-char (mime-edit-content-end))
-       )
+             (mime-edit-define-encoding encoding)))
+       (goto-char (mime-edit-content-end)))
        ((null encoding)                ;Encoding is not specified.
        ;; Application, image, audio, video, and any other
        ;; unknown content-type without encoding should be
@@ -2167,9 +2151,7 @@ Content-Transfer-Encoding: 7bit
               (end (mime-edit-content-end)))
          (mime-encode-region beg end encoding)
          (mime-edit-define-encoding encoding))
-       (forward-line 1)
-       ))
-      )))
+       (forward-line 1))))))
 
 (defun mime-delete-field (field)
   "Delete header FIELD."
@@ -2191,8 +2173,7 @@ Content-Transfer-Encoding: 7bit
 and insert data encoded as ENCODING."
   (message "Start the recording on %s.  Type C-g to finish the recording..."
           (system-name))
-  (mime-insert-encoded-file "/dev/audio" encoding)
-  )
+  (mime-insert-encoded-file "/dev/audio" encoding))
 
 \f
 ;;; @ Other useful commands.
@@ -2206,10 +2187,8 @@ and insert data encoded as ENCODING."
     (if (and inserter (fboundp inserter))
        (progn
          (mime-edit-insert-tag "message" "rfc822")
-         (funcall inserter message)
-         )
-      (message "Sorry, I don't have message inserter for your MUA.")
-      )))
+         (funcall inserter message))
+      (message "Sorry, I don't have message inserter for your MUA."))))
 
 (defun mime-edit-insert-mail (&optional message)
   (interactive)
@@ -2217,10 +2196,8 @@ and insert data encoded as ENCODING."
     (if (and inserter (fboundp inserter))
        (progn
          (mime-edit-insert-tag "message" "rfc822")
-         (funcall inserter message)
-         )
-      (message "Sorry, I don't have mail inserter for your MUA.")
-      )))
+         (funcall inserter message))
+      (message "Sorry, I don't have mail inserter for your MUA."))))
 
 (defun mime-edit-inserted-message-filter ()
   (save-excursion
@@ -2231,17 +2208,13 @@ and insert data encoded as ENCODING."
        ;; for Emacs 18
        ;; (if (re-search-forward "^$" (marker-position (mark-marker)))
        (if (re-search-forward "^$" (mark t))
-           (narrow-to-region header-start (match-beginning 0))
-         )
+           (narrow-to-region header-start (match-beginning 0)))
        (goto-char header-start)
        (while (and (re-search-forward
                     mime-edit-yank-ignored-field-regexp nil t)
                    (setq beg (match-beginning 0))
-                   (setq end (1+ (std11-field-end)))
-                   )
-         (delete-region beg end)
-         )
-       ))))
+                   (setq end (1+ (std11-field-end))))
+         (delete-region beg end))))))
 
 
 ;;; @ multipart enclosure
@@ -2255,66 +2228,64 @@ and insert data encoded as ENCODING."
       (insert (format "--<<%s>>-{\n" type))
       (goto-char (point-max))
       (insert (format "--}-<<%s>>\n" type))
-      (goto-char (point-max))
-      )
+      (goto-char (point-max)))
     (or (looking-at mime-edit-beginning-tag-regexp)
        (eobp)
-       (insert (mime-make-text-tag) "\n")
-       )
-    ))
+       (insert (mime-make-text-tag) "\n"))))
 
 (defun mime-edit-enclose-quote-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'quote beg end)
-  )
+  (mime-edit-enclose-region-internal 'quote beg end))
 
 (defun mime-edit-enclose-mixed-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'mixed beg end)
-  )
+  (mime-edit-enclose-region-internal 'mixed beg end))
 
 (defun mime-edit-enclose-parallel-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'parallel beg end)
-  )
+  (mime-edit-enclose-region-internal 'parallel beg end))
 
 (defun mime-edit-enclose-digest-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'digest beg end)
-  )
+  (mime-edit-enclose-region-internal 'digest beg end))
 
 (defun mime-edit-enclose-alternative-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'alternative beg end)
-  )
+  (mime-edit-enclose-region-internal 'alternative beg end))
 
 (defun mime-edit-enclose-pgp-signed-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'pgp-signed beg end)
-  )
+  (mime-edit-enclose-region-internal 'pgp-signed beg end))
 
 (defun mime-edit-enclose-pgp-encrypted-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'pgp-encrypted beg end)
-  )
+  (mime-edit-enclose-region-internal 'pgp-encrypted beg end))
 
 (defun mime-edit-enclose-kazu-signed-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'kazu-signed beg end)
-  )
+  (mime-edit-enclose-region-internal 'kazu-signed beg end))
 
 (defun mime-edit-enclose-kazu-encrypted-region (beg end)
   (interactive "*r")
-  (mime-edit-enclose-region-internal 'kazu-encrypted beg end)
-  )
+  (mime-edit-enclose-region-internal 'kazu-encrypted beg end))
+
+(defun mime-edit-enclose-smime-signed-region (beg end)
+  (interactive "*r")
+  (mime-edit-enclose-region-internal 'smime-signed beg end))
+
+(defun mime-edit-enclose-smime-encrypted-region (beg end)
+  (interactive "*r")
+  (mime-edit-enclose-region-internal 'smime-encrypted beg end))
 
 (defun mime-edit-insert-key (&optional arg)
   "Insert a pgp public key."
   (interactive "P")
   (mime-edit-insert-tag "application" "pgp-keys")
   (mime-edit-define-encoding "7bit")
-  (funcall (pgp-function 'insert-key))
-  )
+  (pgg-insert-key)
+  (if (and (not (eobp))
+          (not (looking-at mime-edit-single-part-tag-regexp)))
+      (insert (mime-make-text-tag) "\n")))
 
 
 ;;; @ flag setting
@@ -2323,13 +2294,11 @@ and insert data encoded as ENCODING."
 (defun mime-edit-set-split (arg)
   (interactive
    (list
-    (y-or-n-p "Do you want to enable split? ")
-    ))
+    (y-or-n-p "Do you want to enable split? ")))
   (setq mime-edit-split-message arg)
   (if arg
       (message "This message is enabled to split.")
-    (message "This message is not enabled to split.")
-    ))
+    (message "This message is not enabled to split.")))
 
 (defun mime-edit-toggle-transfer-level (&optional transfer-level)
   "Toggle transfer-level is 7bit or 8bit through.
@@ -2340,24 +2309,20 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
       (setq mime-transfer-level transfer-level)
     (if (< mime-transfer-level 8)
        (setq mime-transfer-level 8)
-      (setq mime-transfer-level 7)
-      ))
+      (setq mime-transfer-level 7)))
   (message (format "Current transfer-level is %d bit"
                   mime-transfer-level))
   (setq mime-transfer-level-string
        (mime-encoding-name mime-transfer-level 'not-omit))
-  (force-mode-line-update)
-  )
+  (force-mode-line-update))
 
 (defun mime-edit-set-transfer-level-7bit ()
   (interactive)
-  (mime-edit-toggle-transfer-level 7)
-  )
+  (mime-edit-toggle-transfer-level 7))
 
 (defun mime-edit-set-transfer-level-8bit ()
   (interactive)
-  (mime-edit-toggle-transfer-level 8)
-  )
+  (mime-edit-toggle-transfer-level 8))
 
 
 ;;; @ pgp
@@ -2369,51 +2334,47 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
 (defun mime-edit-set-sign (arg)
   (interactive
    (list
-    (y-or-n-p "Do you want to sign? ")
-    ))
+    (y-or-n-p "Do you want to sign? ")))
   (if arg
       (progn
-       (setq mime-edit-pgp-processing 'sign)
-       (message "This message will be signed.")
-       )
-    (if (eq mime-edit-pgp-processing 'sign)
-       (setq mime-edit-pgp-processing nil)
-      )
-    (message "This message will not be signed.")
-    ))
+       (or (memq 'sign mime-edit-pgp-processing)
+           (setq mime-edit-pgp-processing 
+                 (nconc mime-edit-pgp-processing 
+                        (copy-sequence '(sign)))))
+       (message "This message will be signed."))
+    (setq mime-edit-pgp-processing 
+         (delq 'sign mime-edit-pgp-processing))
+    (message "This message will not be signed.")))
 
 (defun mime-edit-set-encrypt (arg)
   (interactive
    (list
-    (y-or-n-p "Do you want to encrypt? ")
-    ))
+    (y-or-n-p "Do you want to encrypt? ")))
   (if arg
       (progn
-       (setq mime-edit-pgp-processing 'encrypt)
-       (message "This message will be encrypt.")
-       )
-    (if (eq mime-edit-pgp-processing 'encrypt)
-       (setq mime-edit-pgp-processing nil)
-      )
-    (message "This message will not be encrypt.")
-    ))
+       (or (memq 'encrypt mime-edit-pgp-processing)
+           (setq mime-edit-pgp-processing 
+                 (nconc mime-edit-pgp-processing 
+                        (copy-sequence '(encrypt)))))
+       (message "This message will be encrypt."))
+    (setq mime-edit-pgp-processing
+         (delq 'encrypt mime-edit-pgp-processing))
+    (message "This message will not be encrypt.")))
 
 (defun mime-edit-pgp-enclose-buffer ()
   (let ((beg (save-excursion
               (goto-char (point-min))
               (if (search-forward (concat "\n" mail-header-separator "\n"))
-                  (match-end 0)
-                )))
-       (end (point-max))
-       )
+                  (match-end 0)))))
     (if beg
-       (cond ((eq mime-edit-pgp-processing 'sign)
-              (mime-edit-enclose-pgp-signed-region beg end)
-              )
-             ((eq mime-edit-pgp-processing 'encrypt)
-              (mime-edit-enclose-pgp-encrypted-region beg end)
-              ))
-      )))
+       (dolist (pgp-processing mime-edit-pgp-processing)
+         (case pgp-processing
+           (sign
+            (mime-edit-enclose-pgp-signed-region 
+             beg (point-max)))
+           (encrypt
+            (mime-edit-enclose-pgp-encrypted-region 
+             beg (point-max))))))))
 
 
 ;;; @ split
@@ -2426,29 +2387,22 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
   (insert mime-edit-mime-version-field-for-message/partial)
   (insert (format "\
 Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
-                 id number total separator))
-  )
+                 id number total separator)))
 
 (defun mime-edit-split-and-send
   (&optional cmd lines mime-edit-message-max-length)
   (interactive)
   (or lines
       (setq lines
-           (count-lines (point-min) (point-max)))
-      )
+           (count-lines (point-min) (point-max))))
   (or mime-edit-message-max-length
       (setq mime-edit-message-max-length
            (or (cdr (assq major-mode mime-edit-message-max-lines-alist))
-               mime-edit-message-default-max-lines))
-      )
-  (let* ((mime-edit-draft-file-name
-         (or (buffer-file-name)
-             (make-temp-name
-              (expand-file-name "mime-draft" temporary-file-directory))))
-        (separator mail-header-separator)
-        (id (concat "\""
-                    (replace-space-with-underline (current-time-string))
-                    "@" (system-name) "\"")))
+               mime-edit-message-default-max-lines)))
+  (let ((separator mail-header-separator)
+       (id (concat "\""
+                   (replace-space-with-underline (current-time-string))
+                   "@" (system-name) "\"")))
     (run-hooks 'mime-edit-before-split-hook)
     (let ((the-buf (current-buffer))
          (copy-buf (get-buffer-create " *Original Message*"))
@@ -2466,9 +2420,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
               (function
                (lambda ()
                  (interactive)
-                 (error "Split sender is not specified for `%s'." major-mode)
-                 ))
-              ))
+                 (error "Split sender is not specified for `%s'." major-mode)))))
          (mime-edit-partial-number 1)
          data)
       (save-excursion
@@ -2480,13 +2432,11 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
               (concat "^" (regexp-quote separator) "$") nil t)
              (let ((he (match-beginning 0)))
                (replace-match "")
-               (narrow-to-region (point-min) he)
-               ))
+               (narrow-to-region (point-min) he)))
          (goto-char (point-min))
          (while (re-search-forward mime-edit-split-blind-field-regexp nil t)
            (delete-region (match-beginning 0)
-                          (1+ (std11-field-end)))
-           )))
+                          (1+ (std11-field-end))))))
       (while (< mime-edit-partial-number total)
        (erase-buffer)
        (save-excursion
@@ -2495,10 +2445,8 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                      (point-min)
                      (progn
                        (goto-line mime-edit-message-max-length)
-                       (point))
-                     ))
-         (delete-region (point-min)(point))
-         )
+                       (point))))
+         (delete-region (point-min)(point)))
        (mime-edit-insert-partial-header
         header subject id mime-edit-partial-number total separator)
        (insert data)
@@ -2506,28 +2454,23 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
          (message (format "Sending %d/%d..."
                           mime-edit-partial-number total))
          (call-interactively command)
-         (message (format "Sending %d/%d... done"
-                          mime-edit-partial-number total))
-         )
+         (message (format "Sending %d/%d...done"
+                          mime-edit-partial-number total)))
        (setq mime-edit-partial-number
-             (1+ mime-edit-partial-number))
-       )
+             (1+ mime-edit-partial-number)))
       (erase-buffer)
       (save-excursion
        (set-buffer copy-buf)
        (setq data (buffer-string))
-       (erase-buffer)
-       )
+       (erase-buffer))
       (mime-edit-insert-partial-header
        header subject id mime-edit-partial-number total separator)
       (insert data)
       (save-excursion
        (message (format "Sending %d/%d..."
                         mime-edit-partial-number total))
-       (message (format "Sending %d/%d... done"
-                        mime-edit-partial-number total))
-       )
-      )))
+       (message (format "Sending %d/%d...done"
+                        mime-edit-partial-number total))))))
 
 (defun mime-edit-maybe-split-and-send (&optional cmd)
   (interactive)
@@ -2535,18 +2478,17 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
   (let ((mime-edit-message-max-length
         (or (cdr (assq major-mode mime-edit-message-max-lines-alist))
             mime-edit-message-default-max-lines))
-       (lines (count-lines (point-min) (point-max)))
-       )
+       (lines (count-lines (point-min) (point-max))))
     (if (and (> lines mime-edit-message-max-length)
             mime-edit-split-message)
-       (mime-edit-split-and-send cmd lines mime-edit-message-max-length)
-      )))
+       (mime-edit-split-and-send cmd lines mime-edit-message-max-length))))
 
 
 ;;; @ preview message
 ;;;
 
 (defvar mime-edit-buffer nil) ; buffer local variable
+(defvar mime-edit-temp-message-buffer nil) ; buffer local variable
 
 (defun mime-edit-preview-message ()
   "preview editing MIME message."
@@ -2557,43 +2499,40 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
         (buf-name (buffer-name))
         (temp-buf-name (concat "*temp-article:" buf-name "*"))
         (buf (get-buffer temp-buf-name))
-        )
+        (pgp-processing mime-edit-pgp-processing))
     (if buf
        (progn
          (switch-to-buffer buf)
-         (erase-buffer)
-         )
+         (erase-buffer))
       (setq buf (get-buffer-create temp-buf-name))
-      (switch-to-buffer buf)
-      )
+      (switch-to-buffer buf))
     (insert str)
     (setq major-mode 'mime-temp-message-mode)
     (make-local-variable 'mail-header-separator)
     (setq mail-header-separator separator)
     (make-local-variable 'mime-edit-buffer)
     (setq mime-edit-buffer the-buf)
+    (setq mime-edit-pgp-processing pgp-processing)
 
     (run-hooks 'mime-edit-translate-hook)
     (mime-edit-translate-buffer)
     (goto-char (point-min))
     (if (re-search-forward
         (concat "^" (regexp-quote separator) "$"))
-       (replace-match "")
-      )
+       (replace-match ""))
     (mime-view-buffer)
-    ))
+    (make-local-variable 'mime-edit-temp-message-buffer)
+    (setq mime-edit-temp-message-buffer buf)))
 
 (defun mime-edit-quitting-method ()
   "Quitting method for mime-view."
-  (let* ((entity (get-text-property (point-min) 'mime-view-entity))
-        (temp (mime-entity-buffer entity))
+  (let* ((temp mime-edit-temp-message-buffer)
         buf)
     (mime-preview-kill-buffer)
     (set-buffer temp)
     (setq buf mime-edit-buffer)
     (kill-buffer temp)
-    (switch-to-buffer buf)
-    ))
+    (switch-to-buffer buf)))
 
 (set-alist 'mime-preview-quitting-method-alist
           'mime-temp-message-mode
@@ -2616,7 +2555,12 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
     string))
 
 (defun mime-edit-decode-multipart-in-buffer (content-type not-decode-text)
-  (let* ((subtype (mime-content-type-subtype content-type))
+  (let* ((subtype
+         (or
+          (cdr (assoc (mime-content-type-parameter content-type "protocol")
+                      '(("application/pgp-encrypted" . pgp-encrypted)
+                        ("application/pgp-signature" . pgp-signed))))
+          (mime-content-type-subtype content-type)))
         (boundary (mime-content-type-parameter content-type "boundary"))
         (boundary-pat (concat "\n--" (regexp-quote boundary) "[ \t]*\n")))
     (re-search-forward boundary-pat nil t)
@@ -2640,29 +2584,45 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
            (save-excursion
              (if (re-search-forward boundary-pat nil t)
                  (setq end (match-beginning 0))
-               (setq end (point-max))
-               )
+               (setq end (point-max)))
              (save-restriction
                (narrow-to-region beg end)
-               (mime-edit-decode-message-in-buffer
-                (if (eq subtype 'digest)
-                    (eval-when-compile
-                      (make-mime-content-type 'message 'rfc822))
-                  )
-                not-decode-text)
-               (goto-char (point-max))
-               ))))
-       ))
+               (cond
+                ((eq subtype 'pgp-encrypted)
+                 (when (and
+                        (progn
+                          (goto-char (point-min))
+                          (re-search-forward "^-+BEGIN PGP MESSAGE-+$"
+                                             nil t))
+                        (prog1 
+                            (save-window-excursion
+                              (pgg-decrypt-region (match-beginning 0)
+                                                  (point-max)))
+                          (delete-region (point-min)(point-max))))
+                   (insert-buffer-substring pgg-output-buffer)
+                   (mime-edit-decode-message-in-buffer 
+                    nil not-decode-text)
+                   (delete-region (goto-char (point-min))
+                                  (if (search-forward "\n\n" nil t)
+                                      (match-end 0)
+                                    (point-min)))
+                   (goto-char (point-max))))
+                (t 
+                 (mime-edit-decode-message-in-buffer
+                  (if (eq subtype 'digest)
+                      (eval-when-compile
+                        (make-mime-content-type 'message 'rfc822)))
+                  not-decode-text)
+                 (goto-char (point-max))))))))))
     (goto-char (point-min))
     (or (= (point-min) 1)
        (delete-region (point-min)
                       (if (search-forward "\n\n" nil t)
                           (match-end 0)
-                        (point-min)
-                        )))
-    ))
+                        (point-min))))))
 
-(defun mime-edit-decode-single-part-in-buffer (content-type not-decode-text)
+(defun mime-edit-decode-single-part-in-buffer
+  (content-type not-decode-text &optional content-disposition)
   (let* ((type (mime-content-type-primary-type content-type))
         (subtype (mime-content-type-subtype content-type))
         (ctype (format "%s/%s" type subtype))
@@ -2682,14 +2642,41 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                                       (concat "; " str)
                                     (setq bytes (+ bs 1))
                                     (concat ";\n " str)
-                                    )
-                                  ))))
+                                    )))))
                            (mime-content-type-parameters content-type) "")))
         encoding
         encoded
         (limit (save-excursion
                  (if (search-forward "\n\n" nil t)
-                     (1- (point))))))
+                     (1- (point)))))
+        (disposition-type
+         (mime-content-disposition-type content-disposition))
+        (disposition-str
+         (if disposition-type
+             (let ((bytes (+ 21 (length (format "%s" disposition-type)))))
+               (mapconcat (function
+                           (lambda (attr)
+                             (let* ((str (concat
+                                          (car attr)
+                                          "="
+                                          (if (string-equal "filename"
+                                                            (car attr))
+                                              (std11-wrap-as-quoted-string
+                                               (cdr attr))
+                                            (cdr attr))))
+                                    (bs (length str)))
+                               (setq bytes (+ bytes bs 2))
+                               (if (< bytes 76)
+                                   (concat "; " str)
+                                 (setq bytes (+ bs 1))
+                                 (concat ";\n " str)
+                                 ))))
+                          (mime-content-disposition-parameters
+                           content-disposition)
+                          "")))))
+    (if disposition-type
+       (setq pstr (format "%s\nContent-Disposition: %s%s"
+                          pstr disposition-type disposition-str)))
     (save-excursion
       (if (re-search-forward
           "^Content-Transfer-Encoding:" limit t)
@@ -2710,26 +2697,22 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                        (mime-decode-region
                         (match-end 0)(point-max) encoding)
                        (setq encoded t
-                             encoding nil)
-                       )))))))
-    (if (or encoded (not not-decode-text))
-       (progn
-         (save-excursion
-           (goto-char (point-min))
-           (while (re-search-forward "\r\n" nil t)
-             (replace-match "\n")
-             ))
-         (decode-mime-charset-region (point-min)(point-max)
-                                     (or charset default-mime-charset))
-         ))
+                             encoding nil))))))))
+    (if (and (eq type 'text)
+            (or encoded (not not-decode-text)))
+       (progn
+         (save-excursion
+           (goto-char (point-min))
+           (while (re-search-forward "\r\n" nil t)
+             (replace-match "\n")))
+         (decode-mime-charset-region (point-min)(point-max)
+                                     (or charset default-mime-charset))))
     (let ((he (if (re-search-forward "^$" nil t)
                  (match-end 0)
-               (point-min)
-               )))
+               (point-min))))
       (if (and (eq type 'text)
               (eq subtype 'x-rot13-47-48))
-         (mule-caesar-region he (point-max))
-       )
+         (mule-caesar-region he (point-max)))
       (if (= (point-min) 1)
          (progn
            (goto-char he)
@@ -2737,14 +2720,11 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
             (concat "\n"
                     (mime-create-tag
                      (format "%s/%s%s" type subtype pstr)
-                     encoding)))
-           )
+                     encoding))))
        (delete-region (point-min) he)
        (insert
         (mime-create-tag (format "%s/%s%s" type subtype pstr)
-                         encoding))
-       ))
-    ))
+                         encoding))))))
 
 ;;;###autoload
 (defun mime-edit-decode-message-in-buffer (&optional default-content-type
@@ -2758,26 +2738,24 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
            (cond
             ((and (eq type 'application)
                   (eq (mime-content-type-subtype ctl) 'pgp-signature))
-             (delete-region (point-min)(point-max))
-             )
+             (delete-region (point-min)(point-max)))
             ((eq type 'multipart)
-             (mime-edit-decode-multipart-in-buffer ctl not-decode-text)
-             )
+             (mime-edit-decode-multipart-in-buffer ctl not-decode-text))
             (t
-             (mime-edit-decode-single-part-in-buffer ctl not-decode-text)
-             )))
+             (mime-edit-decode-single-part-in-buffer
+              ctl not-decode-text (mime-read-Content-Disposition)))))
        (or not-decode-text
            (decode-mime-charset-region (point-min) (point-max)
-                                       default-mime-charset))
-       )
-      (save-restriction
-       (std11-narrow-to-header)
-       (goto-char (point-min))
-       (while (re-search-forward mime-edit-again-ignored-field-regexp nil t)
-         (delete-region (match-beginning 0) (1+ (std11-field-end)))
-         ))
-      (mime-decode-header-in-buffer (not not-decode-text))
-      )))
+                                       default-mime-charset)))
+      (if (= (point-min) 1)
+         (progn
+           (save-restriction
+             (std11-narrow-to-header)
+             (goto-char (point-min))
+             (while (re-search-forward
+                     mime-edit-again-ignored-field-regexp nil t)
+               (delete-region (match-beginning 0) (1+ (std11-field-end)))))
+           (mime-decode-header-in-buffer (not not-decode-text)))))))
 
 ;;;###autoload
 (defun mime-edit-again (&optional not-decode-text no-separator not-turn-on)
@@ -2789,17 +2767,14 @@ converted to MIME-Edit tags."
   (if (search-forward
        (concat "\n" (regexp-quote mail-header-separator) "\n")
        nil t)
-      (replace-match "\n\n")
-    )
+      (replace-match "\n\n"))
   (mime-edit-decode-message-in-buffer nil not-decode-text)
   (goto-char (point-min))
   (or no-separator
       (and (re-search-forward "^$")
-          (replace-match mail-header-separator)
-          ))
+          (replace-match mail-header-separator)))
   (or not-turn-on
-      (turn-on-mime-edit)
-      ))
+      (turn-on-mime-edit)))
 
 
 ;;; @ end
index d5e4aa0..12e136d 100644 (file)
@@ -4,7 +4,9 @@
 ;; Copyright (C) 1996 Dan Rich
 
 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
-;;         Dan Rich <drich@morpheus.corp.sgi.com>
+;;     Dan Rich <drich@morpheus.corp.sgi.com>
+;;     Daiki Ueno <ueno@unixuser.org>
+;;     Katsumi Yamaoka  <yamaoka@jpl.org>
 ;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
 ;; Created: 1995/12/15
 ;;     Renamed: 1997/2/21 from tm-image.el
@@ -25,8 +27,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU XEmacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 ;;     If you use this program with MULE, please install
 
 ;;; Code:
 
-(require 'mime-view)
-(require 'alist)
+(eval-when-compile (require 'cl))
 
-(cond ((featurep 'xemacs)
-       (require 'images)
-       
-       (defun-maybe image-inline-p (format)
-        (or (memq format image-native-formats)
-            (find-if (function
-                      (lambda (native)
-                        (image-converter-chain format native)
-                        ))
-                     image-native-formats)
-            ))
-       
-       (image-register-netpbm-utilities)
-       (image-register-converter 'pic 'ppm "pictoppm")
-       (image-register-converter 'mag 'ppm "magtoppm")
-       
-       (defun bitmap-insert-xbm-file (file)
-        (let ((gl (make-glyph (list (cons 'x file))))
-              (e (make-extent (point) (point)))
-              )
-          (set-extent-end-glyph e gl)
-          ))
-       
-       ;;
-       ;; X-Face
-       ;;
-       (autoload 'highlight-headers "highlight-headers")
-       
-       (defun mime-preview-x-face-function-use-highlight-headers ()
-        (highlight-headers (point-min) (re-search-forward "^$" nil t) t)
-        )
-       
-       (add-hook 'mime-display-header-hook
-                'mime-preview-x-face-function-use-highlight-headers)
-       
-       )
-      ((featurep 'mule)
-       ;; for MULE 2.* or mule merged EMACS
-       (require 'x-face-mule)
-
-       (defvar image-native-formats '(xbm))
-       
-       (defun-maybe image-inline-p (format)
-        (memq format image-native-formats)
-        )
-       
-       (defun-maybe image-normalize (format data)
-        (and (eq format 'xbm)
-             (vector 'xbm ':data data)
-             ))
-       
-       ;;
-       ;; X-Face
-       ;;
-       (if (exec-installed-p uncompface-program exec-path)
-          (add-hook 'mime-display-header-hook
-                    'x-face-decode-message-header)
-        )
-       ))
-
-(or (fboundp 'image-invalid-glyph-p)
-    (defsubst image-invalid-glyph-p (glyph)
-      (or (null (aref glyph 0))
-         (null (aref glyph 2))
-         (equal (aref glyph 2) "")
-         ))
-    )
-
-(mapcar (function
-        (lambda (rule)
-          (let ((type    (car rule))
-                (subtype (nth 1 rule))
-                (format  (nth 2 rule)))
-            (if (image-inline-p format)
-                (ctree-set-calist-strictly
-                 'mime-preview-condition
-                 (list (cons 'type type)(cons 'subtype subtype)
-                       '(body . visible)
-                       (cons 'body-presentation-method #'mime-display-image)
-                       (cons 'image-format format))
-                 )))))
-       '((image jpeg           jpeg)
-         (image gif            gif)
-         (image tiff           tiff)
-         (image x-tiff         tiff)
-         (image xbm            xbm)
-         (image x-xbm          xbm)
-         (image x-xpixmap      xpm)
-         (image x-pic          pic)
-         (image x-mag          mag)
-         (image png            png)
-         ))
+(eval-when-compile (require 'static))
 
+(require 'mime-view)
+(require 'alist)
+(require 'path-util)
+
+(defsubst mime-image-normalize-xbm-buffer (buffer)
+  (save-excursion
+    (set-buffer buffer)
+    (let ((case-fold-search t) width height xbytes right margin)
+      (goto-char (point-min))
+      (or (re-search-forward "_width[\t ]+\\([0-9]+\\)" nil t)
+         (error "!! Illegal xbm file format" (current-buffer)))
+      (setq width (string-to-int (match-string 1))
+           xbytes (/ (+ width 7) 8))
+      (goto-char (point-min))
+      (or (re-search-forward "_height[\t ]+\\([0-9]+\\)" nil t)
+         (error "!! Illegal xbm file format" (current-buffer)))
+      (setq height (string-to-int (match-string 1)))
+      (goto-char (point-min))
+      (re-search-forward "0x[0-9a-f][0-9a-f],")
+      (delete-region (point-min) (match-beginning 0))
+      (goto-char (point-min))
+      (while (re-search-forward "[\n\r\t ,;}]" nil t)
+       (replace-match ""))
+      (goto-char (point-min))
+      (while (re-search-forward "0x" nil t)
+       (replace-match "\\x" nil t))
+      (goto-char (point-min))
+      (insert "(" (number-to-string width) " "
+             (number-to-string height) " \"")
+      (goto-char (point-max))
+      (insert "\")")
+      (goto-char (point-min))
+      (read (current-buffer)))))
+
+(static-if (featurep 'xemacs)
+    (progn
+      (defun mime-image-type-available-p (type)
+       (memq type (image-instantiator-format-list)))
+
+      (defun mime-image-create (file-or-data &optional type data-p &rest props)
+       (when (and data-p (eq type 'xbm))
+         (with-temp-buffer
+           (insert file-or-data)
+           (setq file-or-data
+                 (mime-image-normalize-xbm-buffer (current-buffer)))))
+       (let ((glyph
+              (make-glyph
+               (if (and type (mime-image-type-available-p type))
+                   (vconcat
+                    (list type (if data-p :data :file) file-or-data)
+                    props)
+                 file-or-data))))
+         (if (nothing-image-instance-p (ignore-errors
+                                         (glyph-image-instance glyph))) nil
+           glyph)))
+
+      (defun mime-image-insert (image &optional string area)
+       (let ((extent (make-extent (point)
+                                  (progn (and string
+                                              (insert string))
+                                         (point)))))
+         (set-extent-property extent 'invisible t)
+         (set-extent-end-glyph extent image))))
+  (condition-case nil
+      (progn
+       (require 'image)
+       (defalias 'mime-image-type-available-p 'image-type-available-p)
+       (defun mime-image-create
+         (file-or-data &optional type data-p &rest props)
+         (if (and data-p (eq type 'xbm))
+             (with-temp-buffer
+               (insert file-or-data)
+               (setq file-or-data
+                     (mime-image-normalize-xbm-buffer (current-buffer)))
+               (apply #'create-image (nth 2 file-or-data) type data-p
+                      (nconc
+                       (list :width (car file-or-data)
+                             :height (nth 1 file-or-data))
+                       props)))
+           (apply #'create-image file-or-data type data-p props)))
+       (defalias 'mime-image-insert 'insert-image))
+    (error
+     (condition-case nil
+        (progn
+          (require (if (featurep 'mule) 'bitmap ""))
+          (defun mime-image-read-xbm-buffer (buffer)
+            (condition-case nil
+                (mapconcat #'bitmap-compose
+                           (append (bitmap-decode-xbm
+                                    (bitmap-read-xbm-buffer
+                                     (current-buffer))) nil) "\n")
+              (error nil)))
+          (defun mime-image-insert (image &optional string area)
+            (insert image)))
+       (error
+       (defalias 'mime-image-read-xbm-buffer
+         'mime-image-normalize-xbm-buffer)
+       (defun mime-image-insert (image &optional string area)
+         (save-restriction
+           (narrow-to-region (point)(point))
+           (let ((face (gensym "mii")))
+             (or (facep face) (make-face face))
+             (set-face-stipple face image)
+             (let ((row (make-string (/ (car image)  (frame-char-width)) ? ))
+                 (height (/ (nth 1 image)  (frame-char-height)))
+                 (i 0))
+               (while (< i height)
+                 (set-text-properties (point) (progn (insert row)(point))
+                                      (list 'face face))
+                 (insert "\n")
+                 (setq i (1+ i)))))))))
+
+     (defun mime-image-type-available-p (type)
+       (eq type 'xbm))
+
+     (defun mime-image-create (file-or-data &optional type data-p &rest props)
+       (when (or (null type) (eq type 'xbm))
+        (with-temp-buffer
+          (if data-p
+              (insert file-or-data)
+            (insert-file-contents file-or-data))
+          (mime-image-read-xbm-buffer (current-buffer))))))))
+
+(defvar mime-image-format-alist
+  '((image jpeg                jpeg)
+    (image gif         gif)
+    (image tiff                tiff)
+    (image x-tiff      tiff)
+    (image xbm         xbm)
+    (image x-xbm       xbm)
+    (image x-xpixmap   xpm)
+    (image png         png)))
+
+(dolist (rule mime-image-format-alist)
+  (when (mime-image-type-available-p (nth 2 rule))
+    (ctree-set-calist-strictly
+     'mime-preview-condition
+     (list (cons 'type (car rule))(cons 'subtype (nth 1 rule))
+          '(body . visible)
+          (cons 'body-presentation-method #'mime-display-image)
+          (cons 'image-format (nth 2 rule))))))
+    
 
 ;;; @ content filter for images
 ;;;
 
 (defun mime-display-image (entity situation)
   (message "Decoding image...")
-  (let ((gl (image-normalize (cdr (assq 'image-format situation))
-                            (mime-entity-content entity))))
-    (cond ((image-invalid-glyph-p gl)
-          (setq gl nil)
-          (message "Invalid glyph!")
-          )
-         ((eq (aref gl 0) 'xbm)
-          (let ((xbm-file
-                 (make-temp-name
-                  (expand-file-name "tm" temporary-file-directory))))
-            (with-temp-buffer
-              (insert (aref gl 2))
-              (write-region (point-min)(point-max) xbm-file)
-              )
-            (message "Decoding image...")
-            (bitmap-insert-xbm-file xbm-file)
-            (delete-file xbm-file)
-            )
-          (message "Decoding image... done")
-          )
-         (t
-          (setq gl (make-glyph gl))
-          (let ((e (make-extent (point) (point))))
-            (set-extent-end-glyph e gl)
-            )
-          (message "Decoding image... done")
-          ))
-    )
-  (insert "\n")
-  )
-
+  (condition-case err
+      (let ((format (cdr (assq 'image-format situation)))
+           image)
+       (setq image (mime-image-create (mime-entity-content entity) format 'data))
+       (if (null image)
+           (message "Invalid glyph!")
+         (save-excursion
+           (mime-image-insert image)
+           (insert "\n")
+           (message "Decoding image...done"))))
+    (error nil err)))
 
 ;;; @ end
 ;;;
index 7e5cb26..65e2971 100644 (file)
@@ -19,8 +19,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
@@ -30,8 +30,7 @@
 (defun mime-mc-pgp-generic-parser (result)
   (let ((ret (mc-pgp-generic-parser result)))
     (if (consp ret)
-       (vector (car ret)(cdr ret))
-      )))
+       (vector (car ret)(cdr ret)))))
 
 (defun mime-mc-process-region
   (beg end passwd program args parser &optional buffer boundary)
@@ -87,12 +86,10 @@ Content-Transfer-Encoding: 7bit
 " boundary))
                        (insert-buffer-substring mybuf (car rgn) (cdr rgn))
                        (goto-char (point-max))
-                       (insert (format "\n--%s--\n" boundary))
-                       )
+                       (insert (format "\n--%s--\n" boundary)))
                    (delete-region beg end)
                    (goto-char beg)
-                   (insert-buffer-substring mybuf (car rgn) (cdr rgn))
-                   )
+                   (insert-buffer-substring mybuf (car rgn) (cdr rgn)))
                  (set-buffer mybuf)
                  (delete-region (car rgn) (cdr rgn)))))
          ;; Return nil on failure and exit code on success
@@ -111,8 +108,7 @@ Content-Transfer-Encoding: 7bit
        (buffer (get-buffer-create mc-buffer-name))
        passwd args key
        (parser (function mc-pgp-generic-parser))
-       (pgp-path mc-pgp-path)
-       )
+       (pgp-path mc-pgp-path))
     (setq key (mc-pgp-lookup-key (or id mc-pgp-user-id)))
     (setq passwd
          (mc-activate-passwd
@@ -128,9 +124,8 @@ Content-Transfer-Encoding: 7bit
                 (format "+clearsig=%s" (if unclear "off" "on"))
                 "+batchmode" "-u" (cdr key))))
     (if mc-pgp-comment
-       (setq args (cons (format "+comment=%s" mc-pgp-comment) args))
-      )
-    (message "Signing as %s ..." (car key))
+       (setq args (cons (format "+comment=%s" mc-pgp-comment) args)))
+    (message "Signing as %s..." (car key))
     (if (mime-mc-process-region
         start end passwd pgp-path args parser buffer boundary)
        (progn
@@ -142,7 +137,7 @@ Content-Transfer-Encoding: 7bit
 --[[multipart/signed; protocol=\"application/pgp-signature\";
  boundary=\"%s\"; micalg=pgp-md5][7bit]]\n" boundary))
                ))
-         (message "Signing as %s ... Done." (car key))
+         (message "Signing as %s...done" (car key))
          t)
       nil)))
 
@@ -152,8 +147,7 @@ Content-Transfer-Encoding: 7bit
                              'never)))
     (mc-pgp-encrypt-region
      (mc-split "\\([ \t\n]*,[ \t\n]*\\)+" recipients)
-     start end id nil)
-    ))
+     start end id nil)))
 
                
 ;;; @ end
index 618c5a6..c821a49 100644 (file)
@@ -20,8 +20,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
@@ -47,18 +47,15 @@ automatically."
     (setq full-file (concat root-dir "/FULL"))
     
     (if (null target)
-       (error "%s is not supported. Sorry." target)
-      )
+       (error "%s is not supported. Sorry." target))
     
     ;; if you can't parse the subject line, try simple decoding method
     (if (or (file-exists-p full-file)
-           (not (y-or-n-p "Merge partials?"))
-           )
+           (not (y-or-n-p "Merge partials?")))
        (mime-store-message/partial-piece entity situation)
       (setq subject-id (mime-entity-read-field entity 'Subject))
       (if (string-match "[0-9\n]+" subject-id)
-         (setq subject-id (substring subject-id 0 (match-beginning 0)))
-       )
+         (setq subject-id (substring subject-id 0 (match-beginning 0))))
       (save-excursion
        (set-buffer subject-buf)
        (while (search-backward subject-id nil t))
@@ -67,25 +64,18 @@ automatically."
            (let* ((message
                    ;; request message at the cursor in Subject buffer.
                    (save-window-excursion
-                     (funcall request-partial-message-method)
-                     ))
+                     (funcall request-partial-message-method)))
                   (situation (mime-entity-situation message))
                   (the-id (cdr (assoc "id" situation))))
              (when (string= the-id id)
                (with-current-buffer mother
-                 (mime-store-message/partial-piece message situation)
-                 )
+                 (mime-store-message/partial-piece message situation))
                (if (file-exists-p full-file)
-                   (throw 'tag nil)
-                 ))
+                   (throw 'tag nil)))
              (if (not (progn
                         (end-of-line)
-                        (search-forward subject-id nil t)
-                        ))
-                 (error "not found")
-               )
-             ))
-         )))))
+                        (search-forward subject-id nil t)))
+                 (error "not found")))))))))
 
 
 ;;; @ end
index fb76f45..7b4aa91 100644 (file)
@@ -1,8 +1,9 @@
 ;;; mime-pgp.el --- mime-view internal methods for PGP.
 
-;; Copyright (C) 1995,1996,1997,1998,1999 MORIOKA Tomohiko
+;; Copyright (C) 1995,1996,1997,1998,1999,2000 Free Software Foundation, Inc.
 
-;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Author: MORIOKA Tomohiko <tomo@m17n.org>
+;;     Daiki Ueno <ueno@unixuser.org>
 ;; Created: 1995/12/7
 ;;     Renamed: 1997/2/27 from tm-pgp.el
 ;; Keywords: PGP, security, MIME, multimedia, mail, news
@@ -21,8 +22,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 ;;         by Kazuhiko Yamamoto <kazu@is.aist-nara.ac.jp> (1995/10;
 ;;         expired)
 
+;;     [OpenPGP/MIME] draft-ietf-openpgp-mime-02.txt: "MIME
+;;         Security with OpenPGP" by
+;;         John W. Noerenberg II <jwn2@qualcomm.com>,
+;;         Dave Del Torto <ddt@cryptorights.org> and
+;;         Michael Elkins <michael_elkins@nai.com> (2000/8)
+
 ;;; Code:
 
 (require 'mime-play)
+(require 'pgg-def)
 
+(autoload 'pgg-decrypt-region "pgg"
+  "PGP decryption of current region." t)
+(autoload 'pgg-verify-region "pgg"
+  "PGP verification of current region." t)
+(autoload 'pgg-snarf-keys-region "pgg"
+  "Snarf PGP public keys in current region." t)
 
 ;;; @ Internal method for multipart/signed
 ;;;
         (new-name
          (format "%s-%s" (buffer-name) (mime-entity-number entity)))
         (mother (current-buffer))
-        representation-type)
-    (set-buffer (get-buffer-create new-name))
+        (preview-buffer (concat "*Preview-" (buffer-name) "*"))
+        representation-type message-buf)
+    (set-buffer (setq message-buf (get-buffer-create new-name)))
     (erase-buffer)
     (mime-insert-entity entity)
     (cond ((progn
             (goto-char (point-min))
             (re-search-forward "^-+BEGIN PGP SIGNED MESSAGE-+$" nil t))
-          (funcall (pgp-function 'verify))
+          (pgg-verify-region (match-beginning 0)(point-max) nil 'fetch)
           (goto-char (point-min))
           (delete-region
            (point-min)
            (point-max))
           (goto-char (point-min))
           (while (re-search-forward "^- -" nil t)
-            (replace-match "-")
-            )
+            (replace-match "-"))
           (setq representation-type (if (mime-entity-cooked-p entity)
-                                        'cooked))
-          )
+                                        'cooked)))
          ((progn
             (goto-char (point-min))
             (re-search-forward "^-+BEGIN PGP MESSAGE-+$" nil t))
-          (as-binary-process (funcall (pgp-function 'decrypt)))
-          (goto-char (point-min))
-          (delete-region (point-min)
-                         (and
-                          (search-forward "\n\n")
-                          (match-end 0)))
-          (setq representation-type 'binary)
-          ))
+          (pgg-decrypt-region (point-min)(point-max))
+          (delete-region (point-min)(point-max))
+          (insert-buffer pgg-output-buffer)
+          (setq representation-type 'binary)))
     (setq major-mode 'mime-show-message-mode)
-    (save-window-excursion (mime-view-buffer nil nil mother
-                                            nil representation-type))
-    (set-window-buffer p-win mime-preview-buffer)
-    ))
+    (save-window-excursion
+      (mime-view-buffer nil preview-buffer mother
+                       nil representation-type)
+      (make-local-variable 'mime-view-temp-message-buffer)
+      (setq mime-view-temp-message-buffer message-buf))
+    (set-window-buffer p-win preview-buffer)))
 
 
 ;;; @ Internal method for application/pgp-signature
 ;;;
-;;; It is based on RFC 2015 (PGP/MIME).
-
-(defvar mime-pgp-command "pgp"
-  "*Name of the PGP command.")
-
-(defvar mime-pgp-default-language 'en
-  "*Symbol of language for pgp.
-It should be ISO 639 2 letter language code such as en, ja, ...")
-
-(defvar mime-pgp-good-signature-regexp-alist
-  '((en . "Good signature from user.*$"))
-  "Alist of language vs regexp to detect ``Good signature''.")
-
-(defvar mime-pgp-key-expected-regexp-alist
-  '((en . "Key matching expected Key ID \\(\\S +\\) not found"))
-  "Alist of language vs regexp to detect ``Key expected''.")
-
-(defun mime-pgp-check-signature (output-buffer sig-file orig-file)
-  (save-excursion
-    (set-buffer output-buffer)
-    (erase-buffer))
-  (let* ((lang (or mime-pgp-default-language 'en))
-        (status (call-process-region (point-min)(point-max)
-                                     mime-pgp-command
-                                     nil output-buffer nil
-                                     sig-file orig-file (format "+language=%s" lang)))
-        (regexp (cdr (assq lang mime-pgp-good-signature-regexp-alist))))
-    (if (= status 0)
-       (save-excursion
-         (set-buffer output-buffer)
-         (goto-char (point-min))
-         (message
-          (cond ((not (stringp regexp))
-                 "Please specify right regexp for specified language")
-                ((re-search-forward regexp nil t)
-                 (buffer-substring (match-beginning 0) (match-end 0)))
-                (t "Bad signature")))
-         ))))
+;;; It is based on RFC 2015 (PGP/MIME) and
+;;; draft-ietf-openpgp-mime-02.txt (OpenPGP/MIME).
 
 (defun mime-verify-application/pgp-signature (entity situation)
   "Internal method to check PGP/MIME signature."
@@ -161,50 +136,33 @@ It should be ISO 639 2 letter language code such as en, ja, ...")
                   (1- knum)
                 (1+ knum)))
         (orig-entity (nth onum (mime-entity-children mother)))
-        (basename (expand-file-name "tm" temporary-file-directory))
-        (orig-file (make-temp-name basename))
-        (sig-file (concat orig-file ".sig"))
-        )
-    (mime-write-entity orig-entity orig-file)
-    (save-excursion (mime-show-echo-buffer))
+        (sig-file (make-temp-file "tm" nil ".asc")))
+    (save-excursion 
+      (mime-show-echo-buffer)
+      (set-buffer mime-echo-buffer-name)
+      (set-window-start 
+       (get-buffer-window mime-echo-buffer-name)
+       (point-max)))
     (mime-write-entity-content entity sig-file)
-    (or (mime-pgp-check-signature mime-echo-buffer-name sig-file orig-file)
-       (let (pgp-id)
-         (save-excursion
+    (unwind-protect
+       (with-temp-buffer
+         (mime-insert-entity orig-entity)
+         (goto-char (point-min))
+         (while (progn (end-of-line) (not (eobp)))
+           (insert "\r")
+           (forward-line 1))
+         (pgg-verify-region (point-min)(point-max) 
+                            sig-file 'fetch)
+         (save-excursion 
            (set-buffer mime-echo-buffer-name)
-           (goto-char (point-min))
-           (let ((regexp (cdr (assq (or mime-pgp-default-language 'en)
-                                    mime-pgp-key-expected-regexp-alist))))
-             (cond ((not (stringp regexp))
-                    (message
-                     "Please specify right regexp for specified language")
-                    )
-                   ((re-search-forward regexp nil t)
-                    (setq pgp-id
-                          (concat "0x" (buffer-substring-no-properties
-                                        (match-beginning 1)
-                                        (match-end 1))))
-                    ))))
-         (if (and pgp-id
-                  (y-or-n-p
-                   (format "Key %s not found; attempt to fetch? " pgp-id))
-                  )
-             (progn
-               (funcall (pgp-function 'fetch-key) (cons nil pgp-id))
-               (mime-pgp-check-signature mime-echo-buffer-name orig-file)
-               ))
-         ))
-    (let ((other-window-scroll-buffer mime-echo-buffer-name))
-      (scroll-other-window 8)
-      )
-    (delete-file orig-file)
-    (delete-file sig-file)
-    ))
+           (insert-buffer-substring pgg-errors-buffer)))
+      (delete-file sig-file))))
 
 
 ;;; @ Internal method for application/pgp-encrypted
 ;;;
-;;; It is based on RFC 2015 (PGP/MIME).
+;;; It is based on RFC 2015 (PGP/MIME) and
+;;; draft-ietf-openpgp-mime-02.txt (OpenPGP/MIME).
 
 (defun mime-decrypt-application/pgp-encrypted (entity situation)
   (let* ((entity-node-id (mime-entity-node-id entity))
@@ -214,36 +172,110 @@ It should be ISO 639 2 letter language code such as en, ja, ...")
                   (1- knum)
                 (1+ knum)))
         (orig-entity (nth onum (mime-entity-children mother))))
-    (mime-view-application/pgp orig-entity situation)
-    ))
+    (mime-view-application/pgp orig-entity situation)))
 
 
 ;;; @ Internal method for application/pgp-keys
 ;;;
-;;; It is based on RFC 2015 (PGP/MIME).
+;;; It is based on RFC 2015 (PGP/MIME) and
+;;; draft-ietf-openpgp-mime-02.txt (OpenPGP/MIME).
 
 (defun mime-add-application/pgp-keys (entity situation)
-  (let* ((start (mime-entity-point-min entity))
-        (end (mime-entity-point-max entity))
-        (entity-number (mime-entity-number entity))
-        (new-name (format "%s-%s" (buffer-name) entity-number))
-        (encoding (cdr (assq 'encoding situation)))
-        str)
-    (setq str (buffer-substring start end))
-    (switch-to-buffer new-name)
-    (setq buffer-read-only nil)
-    (erase-buffer)
-    (insert str)
+  (save-excursion 
+    (mime-show-echo-buffer)
+    (set-buffer mime-echo-buffer-name)
+    (set-window-start 
+     (get-buffer-window mime-echo-buffer-name)
+     (point-max)))
+  (with-temp-buffer
+    (mime-insert-entity-content entity)
+    (mime-decode-region (point-min) (point-max)
+                        (cdr (assq 'encoding situation)))
+    (pgg-snarf-keys-region (point-min)(point-max))
+    (save-excursion 
+      (set-buffer mime-echo-buffer-name)
+      (insert-buffer-substring pgg-errors-buffer))))
+
+
+;;; @ Internal method for application/pkcs7-signature
+;;;
+;;; It is based on the S/MIME user interface in Gnus.
+
+(defun mime-verify-application/pkcs7-signature (entity situation)
+  "Internal method to check S/MIME signature."
+  (with-temp-buffer
+    (mime-insert-entity (mime-find-root-entity entity))
+    (let ((good-signature (smime-noverify-buffer))
+         (good-certificate
+          (and (or smime-CA-file smime-CA-directory)
+               (smime-verify-buffer))))
+      (if (not good-signature)
+         ;; we couldn't verify message, fail with openssl output as message
+         (save-excursion
+           (mime-show-echo-buffer)
+           (set-buffer mime-echo-buffer-name)
+           (set-window-start 
+            (get-buffer-window mime-echo-buffer-name)
+            (point-max))
+            (insert-buffer-substring smime-details-buffer))
+       ;; verify mail addresses in mail against those in certificate
+       (when (and (smime-pkcs7-region (point-min)(point-max))
+                  (smime-pkcs7-certificates-region (point-min)(point-max)))
+         (if (not (member
+                   (downcase 
+                    (nth 1 (std11-extract-address-components
+                            (mime-entity-fetch-field
+                             (mime-find-root-entity entity) "From"))))
+                   (mime-smime-pkcs7-email-buffer (current-buffer))))
+             (message "Sender address forged")
+           (if good-certificate
+               (message "Ok (sender authenticated)")
+             (message "Integrity OK (sender unknown)"))))))))
+
+(defun mime-smime-pkcs7-email-buffer (buffer)
+  (with-temp-buffer
+    (insert-buffer-substring buffer)
     (goto-char (point-min))
-    (if (re-search-forward "^\n" nil t)
-       (delete-region (point-min) (match-end 0))
-      )
-    (mime-decode-region (point-min)(point-max) encoding)
-    (funcall (pgp-function 'snarf-keys))
-    (kill-buffer (current-buffer))
-    ))
-
-        
+    (let (addresses)
+      (while (re-search-forward "-----END CERTIFICATE-----" nil t)
+       (if (smime-pkcs7-email-region (point-min)(point))
+           (setq addresses (append (split-string
+                                    (buffer-substring (point-min)(point))
+                                    "[\n\r]+")
+                                   addresses)))
+       (delete-region (point-min)(point)))
+      (mapcar #'downcase addresses))))
+
+
+;;; @ Internal method for application/pkcs7-mime
+;;;
+;;; It is based on RFC 2633 (S/MIME version 3).
+
+(defun mime-view-application/pkcs7-mime (entity situation)
+  (let* ((p-win (or (get-buffer-window (current-buffer))
+                   (get-largest-window)))
+        (new-name
+         (format "%s-%s" (buffer-name) (mime-entity-number entity)))
+        (mother (current-buffer))
+        (preview-buffer (concat "*Preview-" (buffer-name) "*"))
+        message-buf)
+    (when (memq (or (cdr (assq 'smime-type situation)) 'enveloped-data)
+               '(enveloped-data signed-data))
+      (set-buffer (setq message-buf (get-buffer-create new-name)))
+      (let ((inhibit-read-only t)
+           buffer-read-only)
+       (erase-buffer)
+       (mime-insert-entity entity)
+       (smime-decrypt-buffer))
+      (setq major-mode 'mime-show-message-mode)
+      (save-window-excursion
+       (mime-view-buffer nil preview-buffer mother
+                         nil 'binary)
+       (make-local-variable 'mime-view-temp-message-buffer)
+       (setq mime-view-temp-message-buffer message-buf))
+      (set-window-buffer p-win preview-buffer))))
+
+
 ;;; @ end
 ;;;
 
index b4a03a2..f15f816 100644 (file)
@@ -1,8 +1,8 @@
 ;;; mime-play.el --- Playback processing module for mime-view.el
 
-;; Copyright (C) 1994,1995,1996,1997,1998,1999 Free Software Foundation, Inc.
+;; Copyright (C) 1994,95,96,97,98,99,2000 Free Software Foundation, Inc.
 
-;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Author: MORIOKA Tomohiko <tomo@m17n.org>
 ;; Created: 1995/9/26 (separated from tm-view.el)
 ;;     Renamed: 1997/2/21 from tm-play.el
 ;; Keywords: MIME, multimedia, mail, news
@@ -21,8 +21,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
 (eval-when-compile
   (condition-case nil
       (require 'bbdb)
-    (error (defvar bbdb-buffer-name nil)))
-  )
-
-(defvar mime-acting-situation-example-list nil)
-
-(defvar mime-acting-situation-example-list-max-size 16)
-
-(defun mime-save-acting-situation-examples ()
-  (let* ((file mime-acting-situation-examples-file)
-        (buffer (get-buffer-create " *mime-example*")))
-    (unwind-protect
-        (save-excursion
-          (set-buffer buffer)
-          (setq buffer-file-name file)
-          (erase-buffer)
-          (insert ";;; " (file-name-nondirectory file) "\n")
-          (insert "\n;; This file is generated automatically by "
-                  mime-view-version "\n\n")
-         (insert ";;; Code:\n\n")
-         (pp `(setq mime-acting-situation-example-list
-                    ',mime-acting-situation-example-list)
-             (current-buffer))
-         (insert "\n;;; "
-                  (file-name-nondirectory file)
-                  " ends here.\n")
-          (save-buffer))
-      (kill-buffer buffer))))
-
-(add-hook 'kill-emacs-hook 'mime-save-acting-situation-examples)
-
-(defun mime-reduce-acting-situation-examples ()
-  (let ((len (length mime-acting-situation-example-list))
-       i ir ic j jr jc ret
-       dest d-i d-j
-       (max-sim 0) sim
-       min-det-ret det-ret
-       min-det-org det-org
-       min-freq freq)
-    (setq i 0
-         ir mime-acting-situation-example-list)
-    (while (< i len)
-      (setq ic (car ir)
-           j 0
-           jr mime-acting-situation-example-list)
-      (while (< j len)
-       (unless (= i j)
-         (setq jc (car jr))
-         (setq ret (mime-compare-situation-with-example (car ic)(car jc))
-               sim (car ret)
-               det-ret (+ (length (car ic))(length (car jc)))
-               det-org (length (cdr ret))
-               freq (+ (cdr ic)(cdr jc)))
-         (cond ((< max-sim sim)
-                (setq max-sim sim
-                      min-det-ret det-ret
-                      min-det-org det-org
-                      min-freq freq
-                      d-i i
-                      d-j j
-                      dest (cons (cdr ret) freq))
-                )
-               ((= max-sim sim)
-                (cond ((> min-det-ret det-ret)
-                       (setq min-det-ret det-ret
-                             min-det-org det-org
-                             min-freq freq
-                             d-i i
-                             d-j j
-                             dest (cons (cdr ret) freq))
-                       )
-                      ((= min-det-ret det-ret)
-                       (cond ((> min-det-org det-org)
-                              (setq min-det-org det-org
-                                    min-freq freq
-                                    d-i i
-                                    d-j j
-                                    dest (cons (cdr ret) freq))
-                              )
-                             ((= min-det-org det-org)
-                              (cond ((> min-freq freq)
-                                     (setq min-freq freq
-                                           d-i i
-                                           d-j j
-                                           dest (cons (cdr ret) freq))
-                                     ))
-                              ))
-                       ))
-                ))
-         )
-       (setq jr (cdr jr)
-             j (1+ j)))
-      (setq ir (cdr ir)
-           i (1+ i)))
-    (if (> d-i d-j)
-       (setq i d-i
-             d-i d-j
-             d-j i))
-    (setq jr (nthcdr (1- d-j) mime-acting-situation-example-list))
-    (setcdr jr (cddr jr))
-    (if (= d-i 0)
-       (setq mime-acting-situation-example-list
-             (cdr mime-acting-situation-example-list))
-      (setq ir (nthcdr (1- d-i) mime-acting-situation-example-list))
-      (setcdr ir (cddr ir))
-      )
-    (if (setq ir (assoc (car dest) mime-acting-situation-example-list))
-       (setcdr ir (+ (cdr ir)(cdr dest)))
-      (setq mime-acting-situation-example-list
-           (cons dest mime-acting-situation-example-list))
-      )))
+    (error (defvar bbdb-buffer-name nil))))
+
+(defcustom mime-save-directory "~/"
+  "*Name of the directory where MIME entity will be saved in.
+If t, it means current directory."
+  :group 'mime-view
+  :type '(choice (const :tag "Current directory" t)
+                (directory)))
+
+(defcustom mime-play-delete-file-immediately t
+  "If non-nil, delete played file immediately."
+  :group 'mime-view
+  :type 'boolean)
+
+(defvar mime-play-find-every-situations t
+  "*Find every available situations if non-nil.")
+
+(defvar mime-play-messages-coding-system nil
+  "Coding system to be used for external MIME playback method.")
 
 
 ;;; @ content decoder
@@ -172,74 +81,7 @@ If MODE is specified, play as it.  Default MODE is \"play\"."
              (setq situation
                    (cons (cons 'ignore-examples ignore-examples)
                          situation)))
-         (mime-play-entity entity situation)
-         ))))
-
-(defun mime-sort-situation (situation)
-  (sort situation
-       #'(lambda (a b)
-           (let ((a-t (car a))
-                 (b-t (car b))
-                 (order '((type . 1)
-                          (subtype . 2)
-                          (mode . 3)
-                          (method . 4)
-                          (major-mode . 5)
-                          (disposition-type . 6)
-                          ))
-                 a-order b-order)
-             (if (symbolp a-t)
-                 (let ((ret (assq a-t order)))
-                   (if ret
-                       (setq a-order (cdr ret))
-                     (setq a-order 7)
-                     ))
-               (setq a-order 8)
-               )
-             (if (symbolp b-t)
-                 (let ((ret (assq b-t order)))
-                   (if ret
-                       (setq b-order (cdr ret))
-                     (setq b-order 7)
-                     ))
-               (setq b-order 8)
-               )
-             (if (= a-order b-order)
-                 (string< (format "%s" a-t)(format "%s" b-t))
-               (< a-order b-order))
-             )))
-  )
-
-(defsubst mime-delq-null-situation (situations field
-                                              &optional ignored-value)
-  (let (dest)
-    (while situations
-      (let* ((situation (car situations))
-            (cell (assq field situation)))
-       (if cell
-           (or (eq (cdr cell) ignored-value)
-               (setq dest (cons situation dest))
-               )))
-      (setq situations (cdr situations)))
-    dest))
-
-(defun mime-compare-situation-with-example (situation example)
-  (let ((example (copy-alist example))
-       (match 0))
-    (while situation
-      (let* ((cell (car situation))
-            (key (car cell))
-            (ecell (assoc key example)))
-       (when ecell
-         (if (equal cell ecell)
-             (setq match (1+ match))
-           (setq example (delq ecell example))
-           ))
-       )
-      (setq situation (cdr situation))
-      )
-    (cons match example)
-    ))
+         (mime-play-entity entity situation)))))
 
 ;;;###autoload
 (defun mime-play-entity (entity &optional situation ignored-method)
@@ -247,100 +89,46 @@ If MODE is specified, play as it.  Default MODE is \"play\"."
 It decodes the entity to call internal or external method.  The method
 is selected from variable `mime-acting-condition'.  If MODE is
 specified, play as it.  Default MODE is \"play\"."
-  (let (method ret)
-    (in-calist-package 'mime-view)
-    (setq ret
-         (mime-delq-null-situation
-          (ctree-find-calist mime-acting-condition
-                             (mime-entity-situation entity situation)
-                             mime-view-find-every-acting-situation)
-          'method ignored-method))
-    (or (assq 'ignore-examples situation)
-       (if (cdr ret)
-           (let ((rest ret)
-                 (max-score 0)
-                 (max-escore 0)
-                 max-examples
-                 max-situations)
-             (while rest
-               (let ((situation (car rest))
-                     (examples mime-acting-situation-example-list))
-                 (while examples
-                   (let* ((ret
-                           (mime-compare-situation-with-example
-                            situation (caar examples)))
-                          (ret-score (car ret)))
-                     (cond ((> ret-score max-score)
-                            (setq max-score ret-score
-                                  max-escore (cdar examples)
-                                  max-examples (list (cdr ret))
-                                  max-situations (list situation))
-                            )
-                           ((= ret-score max-score)
-                            (cond ((> (cdar examples) max-escore)
-                                   (setq max-escore (cdar examples)
-                                         max-examples (list (cdr ret))
-                                         max-situations (list situation))
-                                   )
-                                  ((= (cdar examples) max-escore)
-                                   (setq max-examples
-                                         (cons (cdr ret) max-examples))
-                                   (or (member situation max-situations)
-                                       (setq max-situations
-                                             (cons situation max-situations)))
-                                   )))))
-                   (setq examples (cdr examples))))
-               (setq rest (cdr rest)))
-             (when max-situations
-               (setq ret max-situations)
-               (while max-examples
-                 (let* ((example (car max-examples))
-                        (cell
-                         (assoc example mime-acting-situation-example-list)))
-                   (if cell
-                       (setcdr cell (1+ (cdr cell)))
-                     (setq mime-acting-situation-example-list
-                           (cons (cons example 0)
-                                 mime-acting-situation-example-list))
-                     ))
-                 (setq max-examples (cdr max-examples))
-                 )))))
+  (let* ((entity-situation (mime-entity-situation entity situation))
+        (ret (mime-unify-situations entity-situation
+                                    mime-acting-condition
+                                    mime-acting-situation-example-list
+                                    'method ignored-method
+                                    mime-play-find-every-situations))
+        method menu s)
+    (setq mime-acting-situation-example-list (cdr ret)
+         ret (car ret))
     (cond ((cdr ret)
-          (setq ret (select-menu-alist
-                     "Methods"
-                     (mapcar (function
-                              (lambda (situation)
-                                (cons
-                                 (format "%s"
-                                         (cdr (assq 'method situation)))
-                                 situation)))
-                             ret)))
-          (setq ret (mime-sort-situation ret))
-          (add-to-list 'mime-acting-situation-example-list (cons ret 0))
-          )
+          (while ret
+            (or (vassoc (setq method
+                              (format "%s"
+                                      (cdr (assq 'method
+                                                 (setq s (pop ret))))))
+                        menu)
+                (push (vector method s t) menu)))
+          (setq ret (mime-sort-situation
+                     (mime-menu-select "Play entity with: "
+                                       (cons "Methods" menu))))
+          (add-to-list 'mime-acting-situation-example-list (cons ret 0)))
          (t
-          (setq ret (car ret))
-          ))
+          (setq ret (car ret))))
     (setq method (cdr (assq 'method ret)))
     (cond ((and (symbolp method)
                (fboundp method))
-          (funcall method entity ret)
-          )
+          (funcall method entity ret))
          ((stringp method)
-          (mime-activate-mailcap-method entity ret)
-          )
+          (mime-activate-mailcap-method entity ret))
           ;; ((and (listp method)(stringp (car method)))
           ;;  (mime-activate-external-method entity ret)
           ;;  )
          (t
-          (mime-show-echo-buffer "No method are specified for %s\n"
+          (mime-show-echo-buffer "No method is specified for %s\n"
                                  (mime-type/subtype-string
-                                  (cdr (assq 'type situation))
-                                  (cdr (assq 'subtype situation))))
-          (if (y-or-n-p "Do you want to save current entity to disk?")
-              (mime-save-content entity situation))
-          ))
-    ))
+                                  (cdr (assq 'type entity-situation))
+                                  (cdr (assq 'subtype entity-situation))))
+          (when (y-or-n-p "Do you want to save current entity to disk?")
+            (message "")
+            (mime-save-content entity entity-situation))))))
 
 
 ;;; @ external decoder
@@ -351,34 +139,41 @@ specified, play as it.  Default MODE is \"play\"."
 (defun mime-activate-mailcap-method (entity situation)
   (let ((method (cdr (assoc 'method situation)))
        (name (mime-entity-safe-filename entity)))
-    (setq name
-         (if (and name (not (string= name "")))
-             (expand-file-name name temporary-file-directory)
-           (make-temp-name
-            (expand-file-name "EMI" temporary-file-directory))
-           ))
+    (setq name (expand-file-name (if (and name (not (string= name "")))
+                                    name
+                                  (make-temp-name "EMI"))
+                                (make-temp-file "EMI" 'directory)))
     (mime-write-entity-content entity name)
     (message "External method is starting...")
     (let ((process
           (let ((command
-                 (mailcap-format-command
+                 (mime-format-mailcap-command
                   method
-                  (cons (cons 'filename name) situation))))
+                  (cons (cons 'filename name) situation)))
+                (coding-system-for-read mime-play-messages-coding-system))
             (start-process command mime-echo-buffer-name
-                           shell-file-name shell-command-switch command)
-            )))
+                           shell-file-name shell-command-switch command))))
       (set-alist 'mime-mailcap-method-filename-alist process name)
-      (set-process-sentinel process 'mime-mailcap-method-sentinel)
-      )
-    ))
+      (set-process-sentinel process 'mime-mailcap-method-sentinel))))
 
 (defun mime-mailcap-method-sentinel (process event)
-  (let ((file (cdr (assq process mime-mailcap-method-filename-alist))))
-    (if (file-exists-p file)
-       (delete-file file)
-      ))
-  (remove-alist 'mime-mailcap-method-filename-alist process)
-  (message (format "%s %s" process event)))
+  (when mime-play-delete-file-immediately
+    (let ((file (cdr (assq process mime-mailcap-method-filename-alist))))
+      (when (file-exists-p file)
+       (ignore-errors
+        (delete-file file)
+        (delete-directory (file-name-directory file)))))
+    (remove-alist 'mime-mailcap-method-filename-alist process))
+  (message "%s %s" process event))
+
+(defun mime-mailcap-delete-played-files ()
+  (dolist (elem mime-mailcap-method-filename-alist)
+    (when (file-exists-p (cdr elem))
+      (ignore-errors
+       (delete-file (cdr elem))
+       (delete-directory (file-name-directory (cdr elem)))))))
+
+(add-hook 'kill-emacs-hook 'mime-mailcap-delete-played-files)
 
 (defvar mime-echo-window-is-shared-with-bbdb
   (module-installed-p 'bbdb)
@@ -387,8 +182,7 @@ specified, play as it.  Default MODE is \"play\"."
 (defvar mime-echo-window-height
   (function
    (lambda ()
-     (/ (window-height) 5)
-     ))
+     (/ (window-height) 5)))
   "*Size of mime-echo window.
 It allows function or integer.  If it is function,
 `mime-show-echo-buffer' calls it to get height of mime-echo window.
@@ -411,19 +205,14 @@ window.")
                   (- (window-height)
                      (if (functionp mime-echo-window-height)
                          (funcall mime-echo-window-height)
-                       mime-echo-window-height)
-                     )))
-       )
-      (set-window-buffer win mime-echo-buffer-name)
-      )
+                       mime-echo-window-height)))))
+      (set-window-buffer win mime-echo-buffer-name))
     (select-window win)
     (goto-char (point-max))
     (if forms
        (let ((buffer-read-only nil))
-         (insert (apply (function format) forms))
-         ))
-    (select-window the-win)
-    ))
+         (insert (apply (function format) forms))))
+    (select-window the-win)))
 
 
 ;;; @ file name
@@ -448,38 +237,34 @@ window.")
               (if (and subj
                        (or (string-match mime-view-file-name-regexp-1 subj)
                            (string-match mime-view-file-name-regexp-2 subj)))
-                  (substring subj (match-beginning 0)(match-end 0))
-                )))))
+                  (substring subj (match-beginning 0)(match-end 0)))))))
     (if filename
-       (replace-as-filename filename)
-      )))
+       (replace-as-filename filename))))
 
 
 ;;; @ file extraction
 ;;;
 
 (defun mime-save-content (entity situation)
-  (let* ((name (mime-entity-safe-filename entity))
-        (filename (if (and name (not (string-equal name "")))
-                      (expand-file-name name
-                                        (save-window-excursion
-                                          (call-interactively
-                                           (function
-                                            (lambda (dir)
-                                              (interactive "DDirectory: ")
-                                              dir)))))
-                    (save-window-excursion
-                      (call-interactively
-                       (function
-                        (lambda (file)
-                          (interactive "FFilename: ")
-                          (expand-file-name file)))))))
-        )
+  (let ((name (or (mime-entity-safe-filename entity)
+                 (format "%s" (mime-entity-media-type entity))))
+       (dir (if (eq t mime-save-directory)
+                default-directory
+              mime-save-directory))
+       filename)
+    (setq filename (read-file-name
+                   (concat "File name: (default "
+                           (file-name-nondirectory name) ") ")
+                   dir
+                   (concat (file-name-as-directory dir)
+                           (file-name-nondirectory name))))
+    (if (file-directory-p filename)
+       (setq filename (concat (file-name-as-directory filename)
+                              (file-name-nondirectory name))))
     (if (file-exists-p filename)
        (or (yes-or-no-p (format "File %s exists. Save anyway? " filename))
            (error "")))
-    (mime-write-entity-content entity filename)
-    ))
+    (mime-write-entity-content entity (expand-file-name filename))))
 
 
 ;;; @ file detection
@@ -492,8 +277,7 @@ window.")
     ("^II\\*\000"                      image tiff)
     ("^MM\000\\*"                      image tiff)
     ("^MThd"                           audio midi)
-    ("^\000\000\001\263"               video mpeg)
-    )
+    ("^\000\000\001\263"               video mpeg))
   "*Alist of regexp about magic-number vs. corresponding media-types.
 Each element looks like (REGEXP TYPE SUBTYPE).
 REGEXP is a regular expression to match against the beginning of the
@@ -509,8 +293,7 @@ SUBTYPE is symbol to indicate subtype of media-type.")
                    (if cell
                        (if (string-match (car cell) mdata)
                            (setq type (nth 1 cell)
-                                 subtype (nth 2 cell))
-                         )
+                                 subtype (nth 2 cell)))
                      t)))
        (setq rest (cdr rest))))
     (setq situation (del-alist 'method (copy-alist situation)))
@@ -529,15 +312,13 @@ SUBTYPE is symbol to indicate subtype of media-type.")
 (defun mime-preview-quitting-method-for-mime-show-message-mode ()
   "Quitting method for mime-view.
 It is registered to variable `mime-preview-quitting-method-alist'."
-  (let ((raw-buffer (mime-entity-buffer
-                    (get-text-property (point-min) 'mime-view-entity)))
-       (mother mime-mother-buffer)
+  (let ((mother mime-mother-buffer)
        (win-conf mime-preview-original-window-configuration))
-    (kill-buffer raw-buffer)
+    (if (buffer-live-p mime-view-temp-message-buffer)
+       (kill-buffer mime-view-temp-message-buffer))
     (mime-preview-kill-buffer)
     (set-window-configuration win-conf)
-    (pop-to-buffer mother)
-    ))
+    (pop-to-buffer mother)))
 
 (defun mime-view-message/rfc822 (entity situation)
   (let* ((new-name
@@ -553,28 +334,59 @@ It is registered to variable `mime-preview-quitting-method-alist'."
        (let ((m-win (get-buffer-window mother)))
          (if m-win
              (set-window-buffer m-win preview-buffer)
-           (switch-to-buffer preview-buffer)
-           )))))
+           (switch-to-buffer preview-buffer))))))
 
 
 ;;; @ message/partial
 ;;;
 
+(defun mime-require-safe-directory (dir)
+  "Create a directory DIR safely.
+The permission of the created directory becomes `700' (for the owner only).
+If the directory already exists and is writable by other users, an error
+occurs."
+  (let ((attr (file-attributes dir))
+       (orig-modes (default-file-modes)))
+    (if (and attr (eq (car attr) t)) ; directory already exists.
+       (unless (or (memq system-type '(windows-nt ms-dos OS/2 emx))
+                   (and (eq (nth 2 attr) (user-real-uid))
+                        (eq (file-modes dir) 448)))
+         (error "Invalid owner or permission for %s" dir))
+      (unwind-protect
+         (progn
+           (set-default-file-modes 448)
+           (make-directory dir))
+       (set-default-file-modes orig-modes)))))
+
+(defvar mime-view-temp-message-buffer nil) ; buffer local variable
+
 (defun mime-store-message/partial-piece (entity cal)
-  (let* ((root-dir
-         (expand-file-name
-          (concat "m-prts-" (user-login-name)) temporary-file-directory))
-        (id (cdr (assoc "id" cal)))
-        (number (cdr (assoc "number" cal)))
-        (total (cdr (assoc "total" cal)))
-        file
-        (mother (current-buffer)))
+  (let ((root-dir
+        (expand-file-name
+         (concat "m-prts-" (user-login-name)) temporary-file-directory))
+       (id (cdr (assoc "id" cal)))
+       (number (cdr (assoc "number" cal)))
+       (total (cdr (assoc "total" cal)))
+       file
+       (mother (current-buffer))
+       (orig-modes (default-file-modes)))
+    (mime-require-safe-directory root-dir)
     (or (file-exists-p root-dir)
-       (make-directory root-dir))
+       (unwind-protect
+           (progn
+             (set-default-file-modes 448)
+             (make-directory root-dir))
+         (set-default-file-modes orig-modes)))
     (setq id (replace-as-filename id))
     (setq root-dir (concat root-dir "/" id))
+
     (or (file-exists-p root-dir)
-       (make-directory root-dir))
+       (unwind-protect
+           (progn
+             (set-default-file-modes 448)
+             (make-directory root-dir))
+         (set-default-file-modes orig-modes)))
+
     (setq file (concat root-dir "/FULL"))
     (if (file-exists-p file)
        (let ((full-buf (get-buffer-create "FULL"))
@@ -584,14 +396,14 @@ It is registered to variable `mime-preview-quitting-method-alist'."
          (save-window-excursion
            (set-buffer full-buf)
            (erase-buffer)
-           (as-binary-input-file (insert-file-contents file))
+           (binary-insert-encoded-file file)
            (setq major-mode 'mime-show-message-mode)
            (mime-view-buffer (current-buffer) nil mother)
            (setq pbuf (current-buffer))
-           )
+           (make-local-variable 'mime-view-temp-message-buffer)
+           (setq mime-view-temp-message-buffer full-buf))
          (set-window-buffer pwin pbuf)
-         (select-window pwin)
-         )
+         (select-window pwin))
       (setq file (concat root-dir "/" number))
       (mime-write-entity-body entity file)
       (let ((total-file (concat root-dir "/CT")))
@@ -605,10 +417,8 @@ It is registered to variable `mime-preview-quitting-method-alist'."
                          (erase-buffer)
                          (insert total)
                          (write-region (point-min)(point-max) total-file)
-                         (kill-buffer (current-buffer))
-                         ))
-                   (string-to-number total)
-                   )
+                         (kill-buffer (current-buffer))))
+                   (string-to-number total))
                (and (file-exists-p total-file)
                     (save-excursion
                       (set-buffer (find-file-noselect total-file))
@@ -616,11 +426,8 @@ It is registered to variable `mime-preview-quitting-method-alist'."
                           (and (re-search-forward "[0-9]+" nil t)
                                (string-to-number
                                 (buffer-substring (match-beginning 0)
-                                                  (match-end 0)))
-                               )
-                        (kill-buffer (current-buffer))
-                        )))
-               )))
+                                                  (match-end 0))))
+                        (kill-buffer (current-buffer))))))))
       (if (and total (> total 0)
               (>= (length (directory-files root-dir nil "^[0-9]+$" t))
                   total))
@@ -633,36 +440,33 @@ It is registered to variable `mime-preview-quitting-method-alist'."
                  (while (<= i total)
                    (setq file (concat root-dir "/" (int-to-string i)))
                    (or (file-exists-p file)
-                       (throw 'tag nil)
-                       )
-                   (as-binary-input-file (insert-file-contents file))
+                       (throw 'tag nil))
+                   (binary-insert-encoded-file file)
                    (goto-char (point-max))
-                   (setq i (1+ i))
-                   ))
-               (as-binary-output-file
-                (write-region (point-min)(point-max)
-                              (expand-file-name "FULL" root-dir)))
+                   (setq i (1+ i))))
+               (binary-write-decoded-region
+                (point-min)(point-max)
+                (expand-file-name "FULL" root-dir))
                (let ((i 1))
                  (while (<= i total)
                    (let ((file (format "%s/%d" root-dir i)))
                      (and (file-exists-p file)
-                          (delete-file file)
-                          ))
-                   (setq i (1+ i))
-                   ))
+                          (delete-file file)))
+                   (setq i (1+ i))))
                (let ((file (expand-file-name "CT" root-dir)))
                  (and (file-exists-p file)
-                      (delete-file file)
-                      ))
-               (let ((pwin (or (get-buffer-window mother)
+                      (delete-file file)))
+               (let ((buf (current-buffer))
+                     (pwin (or (get-buffer-window mother)
                                (get-largest-window)))
                      (pbuf (mime-display-message
                             (mime-open-entity 'buffer (current-buffer))
                             nil mother nil 'mime-show-message-mode)))
+                 (with-current-buffer pbuf
+                   (make-local-variable 'mime-view-temp-message-buffer)
+                   (setq mime-view-temp-message-buffer buf))
                  (set-window-buffer pwin pbuf)
-                 (select-window pwin)
-                 )))))
-      )))
+                 (select-window pwin)))))))))
 
 
 ;;; @ message/external-body
@@ -671,32 +475,29 @@ It is registered to variable `mime-preview-quitting-method-alist'."
 (defvar mime-raw-dired-function
   (if (and (>= emacs-major-version 19) window-system)
       (function dired-other-frame)
-    (function mime-raw-dired-function-for-one-frame)
-    ))
+    (function mime-raw-dired-function-for-one-frame)))
 
 (defun mime-raw-dired-function-for-one-frame (dir)
   (let ((win (or (get-buffer-window mime-preview-buffer)
                 (get-largest-window))))
     (select-window win)
-    (dired dir)
-    ))
+    (dired dir)))
 
 (defun mime-view-message/external-anon-ftp (entity cal)
   (let* ((site (cdr (assoc "site" cal)))
         (directory (cdr (assoc "directory" cal)))
         (name (cdr (assoc "name" cal)))
         (pathname (concat "/anonymous@" site ":" directory)))
-    (message (concat "Accessing " (expand-file-name name pathname) " ..."))
+    (message "%s" (concat "Accessing " (expand-file-name name pathname) "..."))
     (funcall mime-raw-dired-function pathname)
     (goto-char (point-min))
-    (search-forward name)
-    ))
+    (search-forward name)))
 
 (defvar mime-raw-browse-url-function mime-browse-url-function)
 
 (defun mime-view-message/external-url (entity cal)
   (let ((url (cdr (assoc "url" cal))))
-    (message (concat "Accessing " url " ..."))
+    (message "%s" (concat "Accessing " url "..."))
     (funcall mime-raw-browse-url-function url)))
 
 
@@ -712,15 +513,12 @@ It is registered to variable `mime-preview-quitting-method-alist'."
       (erase-buffer)
       (mime-insert-text-content entity)
       (mule-caesar-region (point-min) (point-max))
-      (set-buffer-modified-p nil)
-      )
+      (set-buffer-modified-p nil))
     (let ((win (get-buffer-window (current-buffer))))
       (or (eq (selected-window) win)
-         (select-window (or win (get-largest-window)))
-         ))
+         (select-window (or win (get-largest-window)))))
     (view-buffer buf)
-    (goto-char (point-min))
-    ))
+    (goto-char (point-min))))
 
 
 ;;; @ end
@@ -728,26 +526,4 @@ It is registered to variable `mime-preview-quitting-method-alist'."
 
 (provide 'mime-play)
 
-(let* ((file mime-acting-situation-examples-file)
-       (buffer (get-buffer-create " *mime-example*")))
-  (if (file-readable-p file)
-      (unwind-protect
-         (save-excursion
-           (set-buffer buffer)
-           (erase-buffer)
-           (insert-file-contents file)
-           (eval-buffer)
-           ;; format check
-           (condition-case nil
-               (let ((i 0))
-                 (while (and (> (length mime-acting-situation-example-list)
-                                mime-acting-situation-example-list-max-size)
-                             (< i 16))
-                   (mime-reduce-acting-situation-examples)
-                   (setq i (1+ i))
-                   ))
-             (error (setq mime-acting-situation-example-list nil)))
-           )
-       (kill-buffer buffer))))
-
 ;;; mime-play.el ends here
index dae2871..49b677d 100644 (file)
@@ -19,8 +19,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
 
 (condition-case nil
     (load "gnus-mime-setup")
-  (error (message "gnus-mime-setup is not found."))
-  )
+  (error (message "gnus-mime-setup is not found.")))
 
 (condition-case nil
     (load "emh-setup")
-  (error (message "emh-setup is not found."))
-  )
+  (error (message "emh-setup is not found.")))
 
 
 ;;; @ end
index 6f1b876..5868fd0 100644 (file)
@@ -1,6 +1,6 @@
 <!doctype sinfo system>
 <head>
-<title>SEMI 1.8 Manual
+<title>SEMI 1.14 Manual
 <author>MORIOKA Tomohiko <mail>morioka@jaist.ac.jp</mail>
 <date>1998/07/03
 
@@ -34,56 +34,63 @@ Each MUA can use powerful MIME features to combine these features.
 <h1> MIME message viewing
 <node> MIME-View
 <p>
-MIME-View \e$B$O\e(B GNU Emacs \e$B$GF0:n$9$kHFMQE*$J\e(B MIME viewer \e$B$G$9!#\e(B
+MIME-View is a MIME viewer for wide use that runs on GNU Emacs.
 <p>
-MIME-View \e$B$O\e(B MIME message \e$B$r1\Mw$9$k$?$a$NMxMQ<T3&LL\e(B (user interface) 
-\e$B$N3K$G$"$j!"$3$N>e$G\e(B presentation-method \e$B$H8F$P$l$kI=<($r:n$k%W%m%0%i%`\e(B
-\e$B$rF0$+$7$?$j!"\e(Bacting-method \e$B$H8F$P$l$k\e(B entity \e$B$N=hM}%W%m%0%i%`$rF0$+$9\e(B
-\e$B$3$H$,2DG=$G!"$5$^$6$^$J<oN`$N\e(B entity \e$B$r07$&;v$,$G$-$k$h$&$K$J$C$F$$$^$9!#\e(B
+MIME-View is the kernel of the user interface for browsing MIME
+messages. You can start some presentation-method which is a program for
+creating some representation, or some acting-method which is a program
+for processing the entity. Then you can deal with a variety of entities.
 
 
 <h2> Basic design
 <node> Overview of MIME-View
 <p>
-Internet \e$B$NEE;R=q4J!&%M%C%H%K%e!<%9$J$I$N=qLL\e(B (message) \e$B$NI=8=7A<0$O\e(B 
-STD 11 \e$B$K4p$E$$$F$$$^$9!#\e(BSTD 11 \e$B$N=qLLK\BN\e(B (message body) \e$B$O9T$rM#0l$N\e(B
-\e$B9=B$$H$9$k4J0WJ8LL\e(B (plain text) \e$B$G$"$j!"J8;zId9f$b\e(B us-ascii \e$B$HDj$a$i$l\e(B
-\e$B$F$$$^$9!#<B:]$K$O!"J8;zId9f$r\e(B us-ascii \e$B$NBe$o$j$K$=$N8@8l7w$GMQ$$$i$l\e(B
-\e$B$kJ8;zId9f$H$7$?!XCO0h2=$5$l$?\e(B STD 11\e$B!Y=qLL$bMQ$$$i$l$F$-$^$7$?$,!"$3\e(B
-\e$B$N>l9g$b=qLL$NJ8;zId9f$O#1$D$G$9!#$3$N$?$a!"MxMQ<T3&LL\e(B (Message User
-Agent) \e$B$O!"$7$P$7$P!"\e(Bbyte \e$BNs\e(B = us-ascii \e$BJ8;zNs!"$J$$$7$O!"\e(Bbyte \e$BNs\e(B = \e$B$=\e(B
-\e$B$N8@8l7w$GMQ$$$kJ8;zId9f$NJ8;zNs$N$h$&$K8+Jo$7$F$-$^$7$?!#\e(B
-<p>
-\e$B$7$+$7$J$,$i!"\e(BMIME \e$B$G$O=qLL$O\e(B entity \e$B$rC10L$H$9$kLZ9=B$$K$J$j!"$^$?!"\e(B
-\e$B#1$D$N=qLL$GJ#?t$NJ8;zId9f$rMQ$$$k$3$H$,$G$-$^$9!#$^$?!"\e(Bentity \e$B$NFbMF\e(B
-\e$B$OJ8LL$d3($N$h$&$JC1=c$KI=<(2DG=$J$b$N$@$1$G$J$/!"2;@<$dF02h$J$I$N0lDj\e(B
-\e$B;~4V:F@8$5$l$k$h$&$J$b$N$dFCDj$N%"%W%j%1!<%7%g%s$N%G!<%?$d%W%m%0%i%`$N\e(B
-\e$B%=!<%9!"$"$k$$$O!"\e(Bftp \e$B$d\e(B mail service \e$B$NMxMQK!$d\e(B URL \e$B$H$$$C$?7A$GI=$5\e(B
-\e$B$l$?30It;2>H$J$I$N$5$^$6$^$J$b$N$,9M$($i$^$9!#$3$N$?$a!"I=<($@$1$r9M$(\e(B
-\e$B$F$$$?\e(B STD 11 \e$B$K$*$1$kMxMQ<T3&LL$NC1=c$J1dD9$G$O\e(B MIME \e$B$NA4$F$N5!G=$r07\e(B
-\e$B$&$3$H$O$G$-$^$;$s!#$D$^$j!"\e(BMIME \e$B$N7A<0$K9g$o$;$FI|9f$9$k$@$1$G$OIT==\e(B
-\e$BJ,$G$"$j!"MxMQ<T$H$NBPOCE*$J:F@8=hM}$r9MN8$9$kI,MW$,$"$j$^$9!#\e(BMIME \e$B=q\e(B
-\e$BLL$N7A<0$O<+F0=hM}$,$7$d$9$/@_7W$5$l$F$$$^$9$,!"\e(BMIME \e$B=qLL$K4^$^$l$kFb\e(B
-\e$BMF$NCf$K$O%;%-%e%j%F%#!<>e$NLdBj$+$i<+F0=hM}$r$9$k$Y$-$G$J$$$b$N$,$"$j!"\e(B
-\e$B$3$&$$$C$?$b$N$N:F@8$K4X$7$F$OMxMQ<T$NH=CG$r6D$0$h$&$K@_7W$5$l$k$Y$-$G\e(B
-\e$B$7$g$&!#7k6I!"\e(BMIME \e$B=qLL$r07$&$?$a$K$O\e(B STD 11 \e$B$*$h$S\e(B MIME \e$B$N9=J8$G5-=R\e(B
-\e$B$5$l$?%a%C%;!<%8$N>pJs8r49MQI=8=$H$=$N2r<a7k2L$G$"$kI=<(2hLL$d:F@8Ey$N\e(B
-\e$B=hM}$r6hJL$7$F9M$($kI,MW$,$"$j$^$9!#$^$?!"MxMQ<T$H$NBPOCE*$J:F@8=hM}$,\e(B
-\e$BI,MW$G$9!#\e(B
-<p>
-\e$B$3$N$?$a!"\e(BMIME-View \e$B$O#1$D$N=qLL$KBP$7$F!">pJs8r49MQI=8=$r3JG<$9$k\e(B 
-mime-raw-buffer \e$B$HI=<(MQI=8=$r3JG<$9$k\e(B mime-preview-buffer \e$B$N#2$D$N\e(B 
-buffer \e$B$rMQ$$$^$9!#\e(B
-<p>
-MIME-View \e$B$O\e(B mime-preview-buffer \e$B$KBP$7$F\e(B mime-view-mode \e$B$H$$$&\e(B MIME
-message \e$B$r1\Mw$9$k$?$a$N\e(B mode \e$B$rDs6!$7$^$9!#MxMQ<T$O$3$3$G3F\e(B entity \e$B$K\e(B
-\e$BBP$7$FA`:n$r9T$&$3$H$,$G$-$^$9!#\e(B
+The representation form of the internet messages in electric letters
+or in net news is based on STD 11. The STD 11 message body is a plain
+text which consists of lines as its only structure, and the character
+code is fixed as us-ascii. Actually, there are ``localized STD 11''
+messages that use some character code in their linguistic range
+instead of using us-ascii. Even in that case, the character code in
+the message is single. Therefore, Message User Agents have considered
+(byte row) = (us-ascii string), or (byte row) = (string in the
+character code in the linguistic range).
+<p>
+Although, the MIME message has the tree structure in entity unit.
+And one message can contain multiple character codes. The content of
+an entity can be not only a letter or an image that can be displayed
+simply, but also can be a voice or an animation that are played for
+some time interval, a data for some specific application, a source
+code of some program, or an external reference that consists of
+the usage of ftp or mail service, or some URL. Therefore the simple
+extension of STD 11 user interface, which only consider displaying
+the message, cannot treat all of the MIME functionalities.
+Then it is not sufficient to decode message along its MIME type, but
+it is also required to consider a playback processing through some
+dialogue with the user. The format of MIME messages is designed
+to easily be passed to automatic processing. But some contents in the
+MIME message should not be passed to automatic processing for security
+reasons. So it should be designed to ask user in such cases.
+After all, in order to deal with MIME message, it is required to
+distinguish the representation for information exchange which is
+written in STD 11 or MIME construction, and its result
+after some interpretation which is a display screen or a playback
+process. It is also needed to converse with user for playback
+processing.
+<p>
+Therefore, MIME-View uses two buffers for one document, one is the
+mime-raw-buffer that stores the representation for information exchange,
+and the other is the mime-preview-buffer that stores the representation
+for displaying.
+<p>
+MIME-View provides a mode in the mime-preview-buffer for reading MIME
+message, which is called as mime-view-mode. User can manipulate each
+entity there.
 
 
 <h2> Presentation of mime-preview-buffer
 <node> MIME-Preview
 <p>
-mime-view-mode \e$B$G$O3F\e(B entity \e$B$KBP$7$F\e(B
+mime-view-mode displays information about each entity as
 <p>
 <verb>
        [entity-button]
@@ -94,15 +101,15 @@ mime-view-mode \e$B$G$O3F\e(B entity \e$B$KBP$7$F\e(B
 </verb>
 <p>
 <noindent>
-\e$B$H$$$&>pJs$rI=<($7$^$9!#$3$l$i$O>r7o$K=>$C$F\e(B design \e$B$rJQ99$7$?$j!"I=<(\e(B
-\e$B$rM^@)$9$k$3$H$b$G$-$^$9!#\e(B
+You can change their design or inhibit showing some of them, according
+to some condition
 <p>
-\e$B0J2<$K!"I=<(Nc$r<($7$^$9!#\e(B
+See following example
 
 
 <verb>
-From: morioka@jaist.ac.jp (\e$B<i2,\e(B \e$BCNI'\e(B / MORIOKA Tomohiko)
-Subject: Re: \e$B<ALd!)\e(B
+From: morioka@jaist.ac.jp (MORIOKA Tomohiko)
+Subject: Re: question?
 Newsgroups: zxr.message.mime
 Date: 22 Oct 93 11:02:44
 Mime-Version: 1.0
@@ -110,9 +117,9 @@ Organization: Japan Advanced Institute of Science and Technology,
         Ishikawa, Japan
 
 [1  (text/plain)]
-  MIME-Edit mode \e$B$K$*$1$k!"\e(BMIME message \e$B$N:n$jJ}!#\e(B
+  How to compose MIME message in MIME-Edit mode.
 
-  C-c C-x ? \e$B$r2!$9$H\e(B help \e$B$,=P$F$/$k!#\e(B
+  C-c C-x ? shows its help.
 
 C-c C-x C-t    insert a text message.
 C-c C-x TAB    insert a (binary) file.
@@ -122,153 +129,155 @@ C-c C-x C-y     insert a mail or news message.
 C-c C-x RET    insert a mail message.
 C-c C-x C-s    insert a signature file at end.
 C-c C-x t      insert a new MIME tag.
-C-c C-x a      enclose as multipart/alternative.
-C-c C-x p      enclose as multipart/parallel.
-C-c C-x m      enclose as multipart/mixed.
-C-c C-x d      enclose as multipart/digest.
-C-c C-x s      enclose as PGP signed.
-C-c C-x e      enclose as PGP encrypted.
+C-c C-m C-a    enclose as multipart/alternative.
+C-c C-m C-p    enclose as multipart/parallel.
+C-c C-m C-m    enclose as multipart/mixed.
+C-c C-m C-d    enclose as multipart/digest.
+C-c C-m C-s    enclose as PGP signed.
+C-c C-m C-e    enclose as PGP encrypted.
 C-c C-x C-k    insert PGP public key.
-C-c C-x C-p    preview editing MIME message.
+C-c C-x p      preview editing MIME message.
 ...
 
-\e$B$C$FLu$G!"\e(BC-c C-x C-i \e$B$r2!$7$F!"A^F~$7$?$$\e(B binary file \e$B$r;XDj$7$^$9!#\e(B
+therefore, you should type C-c C-x C-i and specify the binary file
+which you want to insert.
 
-  binary file \e$B$N\e(B MIME encoding \e$B$K$O!"IaDL!"\e(BBase64 \e$B$r;XDj$7$^$9!#\e(B
+  You should select Base64 as MIME encoding for binary file.
 
 [2  (image/gif)]
 
 [3  (text/plain)]
 
-  \e$B$3$s$JIw$K!"3(F~$j\e(B message \e$B$N$G$->e$,$j!#\e(B
+  Like above, you can compose the message with image.
 
-\e$B".".".".".".".".".".".\e(B \e$B%m%7%"%s!&%F%#!<$r0lGU!#\e(B \e$B".".".".".".".".".".".\e(B
-\e$B".".".".".\e(B  \e$B!y\e(B \e$B%8%c%`$G$O$J$/%^!<%^%l!<%I$G$b$J$/K*L*$G\e(B \e$B!y\e(B  \e$B".".".".".\e(B
-\e$B".".".".".\e(B         \e$B'.'0'2$$'0','!\e(B  \e$B'4'0'.'0'7'*','0\e(B         \e$B".".".".".\e(B
-\e$B".".".".".".".\e(B  Internet E-mail: &lt;morioka@jaist.ac.jp&gt;  \e$B".".".".".".".\e(B
+==================== Take A Cup Of Russian Tea  ======================
+=========  ** Not With Jam Nor Marmalade But With Honey **  ==========
+=========                 MORIOKA TOMOHIKO                  ==========
+==============  Internet E-mail: &lt;morioka@@jaist.ac.jp&gt;  ==============
 </verb>
 
 
 <h3> entity-button
 <node> entity-button
 <p>
-<concept>entity-button</concept> \e$B$O\e(B entity \e$B$N@hF,$K$"$C$F!"$=$N\e(B entity 
-\e$B$K4X$9$kBg$^$+$J>pJs$rI=<($9$kItJ,$G$9!#\e(B
+<concept>entity-button</concept> is a tag on the top of the entity
+which shows brief information of the part.
 <p>
-\e$BI8=`$G$O\e(B
+Normally, it appears as
 
 <verb>
         [1.3 test (text/plain)]
 </verb>
 
-<noindent>
-\e$B$N$h$&$J46$8$KI=<($5$l$^$9!#\e(B
 <p>
-\e$B:G=i$N?t;z$O\e(B message \e$BCf$N$3$N\e(B entity \e$B$N0LCV$r@aHV9f$N$h$&$KI=$7$?$b$N\e(B
-\e$B$G!"\e(B<concept>entity-number</concept> \e$B$H8F$S$^$9!#\e(B
+The number on the head describes the place of the entity in the
+message (like the section number) and it is called as
+<concept>entity-number</concept>.
 <p>
-\e$B#2HVL\$NJ8;zNs$OI=Bj$rI=$7$^$9!#$3$N>pJs$O!"\e(B
+The string in the next describes its title. This information is
+taken from
 
 <ol>
-<li>Content-Description field \e$B$b$7$/$O\e(B Subject field \e$B$K=q$+$l$?I=Bj\e(B
-<li>Content-Disposition field \e$B$N\e(B filename parameter \e$B$K=q$+$l$?\e(B file \e$BL>\e(B
-<li>Content-Type field \e$B$N\e(B name parameter \e$B$K=q$+$l$?\e(B file \e$BL>\e(B
-<li> uuencode \e$B$N>l9g$N\e(B file \e$BL>\e(B
+<li>Title described in Content-Description field or Subject field
+<li>File name specified by filename parameter in Content-Disposition field
+<li>File name specified by name parameter in Content-Type field
+<li>File name for uuencode'ing
 </ol>
 
 <noindent>
-\e$B$+$i:n$j$^$9!#$I$l$bB8:_$7$J$$>l9g$O6uGr$,I=<($5$l$^$9!#\e(B
+If none of them are specified, displays a blank.
 <p>
-\e$B#3HVL\$N3g8L$NCf$N>pJs$O$=$N\e(B entity \e$B$N\e(B media-type/subtype \e$B$rI=$7$^$9!#\e(B
-\e$BHs\e(B MIME entity \e$B$N>l9g!"\e(B<code>nil</code> \e$B$,I=<($5$l$^$9!#\e(B
+The 3rd item in the parenthesis describes media-type/subtype of
+the entity. If it is is not MIME entity, it displays <code>nil</code>.
 <p>
-\e$B$3$N\e(B entity-button \e$B$O\e(B entity \e$B$NFbMF$r>]D'$9$k\e(B icon \e$B$N$h$&$JLr3d$r2L$?\e(B
-\e$B$7$^$9!#Nc$($P!"\e(B
+This entity-button plays a role like icon that symbolically
+shows the content of the entity. For example, push <kbd>v</kbd> on
 
 <verb>
         [2  (image/gif)]
 </verb>
 
 <noindent>
-\e$B$N>e$G\e(B <kbd>v</kbd> \e$B$r2!$;$P$3$3$KF~$C$F$$$k3($,I=<($5$l$^$9!#\e(B
+shows up the image contained there.
 <p>
-\e$B$^$?!"\e(Bmouse \e$BA`:n$,2DG=$J>l9g!"\e(Bentity-button \e$B$rBh#2%\%?%s!J\e(B3 button
-mouse \e$B$N>l9g!"Cf1{$N%\%?%s!K$G2!$;$P!"F1MM$K$=$N3($,I=<($5$l$^$9!#\e(B
+If the mouse operation is possible, you can display the image
+by pushing 2nd button (the middle button for 3 button mouse) too.
 
 
 <h3> entity-header
 <node> entity-header
 <p>
-<concept>entity-header</concept> \e$B$O$"$k\e(B entity \e$B$N\e(B header \e$B$rI=<($9$kIt\e(B
-\e$BJ,$G$9!J!V$=$N$^$^$d$s$1!W$C$FE\$i$J$$$G!#$=$&$$$&$b$s$J$s$G$9!K!#\e(B
-
+<concept>entity-header</concept> is the header of the entity.
+(Don't blame me as ``You say nothing more than as it is'',
+It is no more than that.)
 
 <h3> entity-body
 <node> entity-body
 <p>
-<concept>entity-body</concept> \e$B$O\e(B part \e$B$NFbMF$rI=<($9$kItJ,$G$9!#\e(B
+<concept>entity-body</concept> is the content of the part.
 <p>
-\e$B$3$l$b$R$M$j$,B-$j$J$$$G$9$,!"$^$"!"$=$&$$$&$b$s$G$9!#\e(B
+Sophistication does not seem enough here also, but it is really such
+a thing.
 <p>
-\e$B$H$O$$$(!"<B:]$K$O>/$7$R$M$C$F$^$9!#\e(B
+Though, it actually be twisted a little.
 <p>
-text entity \e$B$N>l9g$O\e(B charset \e$B$K1~$8$F\e(B code \e$BJQ49$7$?$j$7$^$9$7!"\e(BXEmacs 
-\e$B$G$O\e(B image entity \e$B$rJQ49$7$J$$$H$$$1$J$$$7!#\e(B
+The text entity is passed to code conversion according to its charset,
+and the image entity should be converted on XEmacs.
 <p>
-\e$B>\$7$/$O$^$?8e$G!#\e(B
+Details will be described later.
 
 
 <h2> Operation in mime-preview-buffer
 <node> mime-view-mode
 <p>
-mime-preview-buffer \e$B$K$O0J2<$N5!G=$,$"$j$^$9!#\e(B
+mime-preview-buffer posesses following functionalities.
 <p>
 <kl>
 <kt>u
 <kd>
-\e$B>e$N\e(B part \e$B$KLa$k!J\e(Bmessage \e$B$N0lHV>e$N\e(B part \e$B$G$3$l$r9T$J$&$H\e(B Summary
-mode \e$B$KLa$k\e(B (*1)\e$B!K\e(B
+go back to upper part (in the first part of the message,
+go back to the Summary mode (*1))
 </kd>
-<kt>p<kd>\e$BA0$N\e(B part \e$B$K0\F0$9$k\e(B
+<kt>p<kd>go to previous part
 </kd>
-<kt>M-TAB<kd>\e$BA0$N\e(B part \e$B$K0\F0$9$k\e(B
+<kt>M-TAB<kd>go to previous part
 </kd>
-<kt>n<kd>\e$B<!$N\e(B part \e$B$K0\F0$9$k\e(B
+<kt>n<kd>go to next part
 </kd>
-<kt>TAB<kd>\e$B<!$N\e(B part \e$B$K0\F0$9$k\e(B
+<kt>TAB<kd>go to next part
 </kd>
-<kt>SPC<kd>scroll up \e$B$9$k\e(B
+<kt>SPC<kd>scroll up
 </kd>
-<kt>M-SPC<kd>scroll down \e$B$9$k\e(B
+<kt>M-SPC<kd>scroll down
 </kd>
-<kt>DEL<kd>scroll down \e$B$9$k\e(B
+<kt>DEL<kd>scroll down
 </kd>
-<kt>RET<kd>\e$B<!$N9T$K0\F0$9$k\e(B
+<kt>RET<kd>go to next line
 </kd>
-<kt>M-RET<kd>\e$BA0$N9T$K0\F0$9$k\e(B
+<kt>M-RET<kd>go to previous line
 </kd>
-<kt>v<kd>part \e$B$r:F@8$9$k\e(B (*2)
+<kt>v<kd>play current part (*2)
 </kd>
-<kt>e<kd>part \e$B$+$i\e(B file \e$B$r<h$j=P$9\e(B (*2)
+<kt>e<kd>extract file from current part (*2)
 </kd>
-<kt>C-c C-p<kd>part \e$B$r0u:~$9$k\e(B (*2)
+<kt>C-c C-p<kd>print current part (*2)
 </kd>
 <kt>mouse-button-2
 <kd>
-preview-buffer \e$BCf$N\e(B mouse button \e$B$r5/F0$9$k\e(B
+start the mouse button in preview-buffer
 <p>
-content-button \e$B$r2!$;$P!"$=$N\e(B part \e$B$,:F@8$5$l$k\e(B(*2)
+on content-button, play current part (*2)
 <p>
-URL-button \e$B$r2!$;$P!"$=$N\e(B WWW browser \e$B$,5/F0$5$l$k\e(B
+on URL-button, start WWW browser
 </kd>
 </kl>
 <p>
-<memo title="\e$BCm0U\e(B">
+<memo title="Notice">
 <p>
-(*1) MUA \e$B$G\e(B mime-view \e$B$N@_Dj$r$7$F$$$J$$>l9g!"\e(BSummary mode \e$B$K$OLa$j$^\e(B
-\e$B$;$s!#\e(B
+(*1) Do not go back to Summary mode unless appropriately
+configured for mime-view in the MUA.
 <p>
-(*2) \e$B<B:]$NF0:n$OBP1~$9$k\e(B method \e$B$K0M$j$^$9!#\e(B
+(*2) actual behavior depends on the associated method
 </memo>
 
 
@@ -370,7 +379,7 @@ Insert signature.
 </dd>
 <kt>C-c C-x C-k
 <kd>
-Insert <dref>PGP</dref> public key. (It requires Mailcrypt package.)
+Insert <dref>PGP</dref> public key.
 </kd>
 <kt>C-c C-x t
 <kd>
@@ -388,27 +397,27 @@ Operations to make enclosure are following:
 <kd>
 Enclose specified region as multipart/alternative.
 </kd>
-<kt>C-c C-x C-p
+<kt>C-c C-m C-p
 <kd>
 Enclose specified region as multipart/parallel.
 </kd>
-<kt>C-c C-x C-m
+<kt>C-c C-m C-m
 <kd>
 Enclose specified region as multipart/mixed.
 </kd>
-<kt>C-c C-x C-d
+<kt>C-c C-m C-d
 <kd>
 Enclose specified region as multipart/digest.
 </kd>
-<kt>C-c C-x C-s
+<kt>C-c C-m C-s
 <kd>
 Digital-sign to specified region. <cf node="PGP">
 </kd>
-<kt>C-c C-x C-e
+<kt>C-c C-m C-e
 <kd>
 Encrypt to specified region. <cf node="PGP">
 </kd>
-<kt>C-c C-x C-q
+<kt>C-c C-m C-q
 <kd>
 avoid to encode tags in specified region.  In other words, tags is
 interpreted as such string.  (In current version, it may be
@@ -609,29 +618,31 @@ mime-edit provides PGP encryption, signature and inserting public-key
 features based on <concept>PGP/MIME</concept> (RFC 2015) or
 <concept>PGP-kazu</concept> (draft-kazu-pgp-mime-00.txt).
 <p>
-This feature requires pgp command and pgp interface package, such as
-<a file="mailcrypt">Mailcrypt package</a>.
+This feature requires your pgp command.
 
-<defvar name="pgp-function-alist">
-<p>
-Alist of service names vs. corresponding functions and its filenames.
-Each element looks like <code>(SERVICE FUNCTION FILE)</code>.
-<p>
-SERVICE is a symbol of PGP processing.  It allows `verify', `decrypt',
-`fetch-key', `snarf-keys', `mime-sign', `traditional-sign', `encrypt'
-or `insert-key'.
+<defvar name="pgg-default-scheme">
 <p>
-Function is a symbol of function to do specified SERVICE.
+Version of PGP or GnuPG command to be used for encryption or sign.
+The value should be a symbol.  Allowed versions are <code>gpg</code>,
+<code>pgp</code> or <code>pgp5</code>.
+</defvar>
+
+<defvar name="pgg-scheme">
 <p>
-FILE is string of filename which has definition of corresponding
-FUNCTION.
+Version of PGP or GnuPG command to be used for decryption or verification.
+The value should be a symbol.  Allowed versions are <code>gpg</code>,
+<code>pgp</code> or <code>pgp5</code>.
 </defvar>
 
-<defun name="pgp-function">
-           <args> method
+<defvar name="pgg-insert-url-function">
 <p>
-Return function to do service <var>method</var>.
-</defun>
+The function to fetch public key from the keyserver.
+Use Emacs/W3 by the default setting. To use emacs-w3m
+instead, set as follows:
+<lisp>
+(setq pgg-insert-url-function #'w3m-retrieve)
+</lisp>
+</defvar>
 
 
 <h2> Mouse button
index 9946c5f..7271050 100644 (file)
@@ -1,13 +1,13 @@
 \input texinfo.tex
 @setfilename mime-ui-en.info
-@settitle{SEMI 1.8 Manual}
+@settitle{SEMI 1.14 Manual}
 @titlepage
-@title SEMI 1.8 Manual
+@title SEMI 1.14 Manual
 @author MORIOKA Tomohiko <morioka@@jaist.ac.jp>
 @subtitle 1998/07/03
 @end titlepage
 @node Top, Introduction, (dir), (dir)
-@top SEMI 1.8 Manual
+@top SEMI 1.14 Manual
 
 @ifinfo
 
@@ -32,7 +32,7 @@ user interface.@refill
 
 SEMI provides two user interfaces: MIME-View and MIME-Edit.@refill
 
+
 MIME-View is a kernel of user interface to display or operate MIME
 messages, STD 11 messages or ``localized RFC 822'' messages.@refill
 
@@ -44,12 +44,12 @@ Each MUA can use powerful MIME features to combine these features.
 @node MIME-View, MIME-Edit, Introduction, Top
 @chapter MIME message viewing
 
-MIME-View \e$B$O\e(B GNU Emacs \e$B$GF0:n$9$kHFMQE*$J\e(B MIME viewer \e$B$G$9!#\e(B@refill
+MIME-View is a MIME viewer for wide use that runs on GNU Emacs.@refill
 
-MIME-View \e$B$O\e(B MIME message \e$B$r1\Mw$9$k$?$a$NMxMQ<T3&LL\e(B (user interface) 
-\e$B$N3K$G$"$j!"$3$N>e$G\e(B presentation-method \e$B$H8F$P$l$kI=<($r:n$k%W%m%0%i%`\e(B
-\e$B$rF0$+$7$?$j!"\e(Bacting-method \e$B$H8F$P$l$k\e(B entity \e$B$N=hM}%W%m%0%i%`$rF0$+$9\e(B
-\e$B$3$H$,2DG=$G!"$5$^$6$^$J<oN`$N\e(B entity \e$B$r07$&;v$,$G$-$k$h$&$K$J$C$F$$$^$9!#\e(B
+MIME-View is the kernel of the user interface for browsing MIME
+messages. You can start some presentation-method which is a program for
+creating some representation, or some acting-method which is a program
+for processing the entity. Then you can deal with a variety of entities.
 
 
 @menu
@@ -61,44 +61,52 @@ MIME-View \e$B$O\e(B MIME message \e$B$r1\Mw$9$k$?$a$NMxMQ<T3&LL\e(B (user interface
 @node Overview of MIME-View, MIME-Preview, MIME-View, MIME-View
 @section Basic design
 
-Internet \e$B$NEE;R=q4J!&%M%C%H%K%e!<%9$J$I$N=qLL\e(B (message) \e$B$NI=8=7A<0$O\e(B STD
-11 \e$B$K4p$E$$$F$$$^$9!#\e(BSTD 11 \e$B$N=qLLK\BN\e(B (message body) \e$B$O9T$rM#0l$N9=B$$H\e(B
-\e$B$9$k4J0WJ8LL\e(B (plain text) \e$B$G$"$j!"J8;zId9f$b\e(B us-ascii \e$B$HDj$a$i$l$F$$$^$9!#\e(B
-\e$B<B:]$K$O!"J8;zId9f$r\e(B us-ascii \e$B$NBe$o$j$K$=$N8@8l7w$GMQ$$$i$l$kJ8;zId9f$H\e(B
-\e$B$7$?!XCO0h2=$5$l$?\e(B STD 11\e$B!Y=qLL$bMQ$$$i$l$F$-$^$7$?$,!"$3$N>l9g$b=qLL$N\e(B
-\e$BJ8;zId9f$O#1$D$G$9!#$3$N$?$a!"MxMQ<T3&LL\e(B (Message User Agent) \e$B$O!"$7$P$7\e(B
-\e$B$P!"\e(Bbyte \e$BNs\e(B = us-ascii \e$BJ8;zNs!"$J$$$7$O!"\e(Bbyte \e$BNs\e(B = \e$B$=$N8@8l7w$GMQ$$$kJ8\e(B
-\e$B;zId9f$NJ8;zNs$N$h$&$K8+Jo$7$F$-$^$7$?!#\e(B@refill
-
-\e$B$7$+$7$J$,$i!"\e(BMIME \e$B$G$O=qLL$O\e(B entity \e$B$rC10L$H$9$kLZ9=B$$K$J$j!"$^$?!"#1\e(B
-\e$B$D$N=qLL$GJ#?t$NJ8;zId9f$rMQ$$$k$3$H$,$G$-$^$9!#$^$?!"\e(Bentity \e$B$NFbMF$OJ8\e(B
-\e$BLL$d3($N$h$&$JC1=c$KI=<(2DG=$J$b$N$@$1$G$J$/!"2;@<$dF02h$J$I$N0lDj;~4V:F\e(B
-\e$B@8$5$l$k$h$&$J$b$N$dFCDj$N%"%W%j%1!<%7%g%s$N%G!<%?$d%W%m%0%i%`$N%=!<%9!"\e(B
-\e$B$"$k$$$O!"\e(Bftp \e$B$d\e(B mail service \e$B$NMxMQK!$d\e(B URL \e$B$H$$$C$?7A$GI=$5$l$?30It;2\e(B
-\e$B>H$J$I$N$5$^$6$^$J$b$N$,9M$($i$^$9!#$3$N$?$a!"I=<($@$1$r9M$($F$$$?\e(B STD
-11 \e$B$K$*$1$kMxMQ<T3&LL$NC1=c$J1dD9$G$O\e(B MIME \e$B$NA4$F$N5!G=$r07$&$3$H$O$G$-\e(B
-\e$B$^$;$s!#$D$^$j!"\e(BMIME \e$B$N7A<0$K9g$o$;$FI|9f$9$k$@$1$G$OIT==J,$G$"$j!"MxMQ\e(B
-\e$B<T$H$NBPOCE*$J:F@8=hM}$r9MN8$9$kI,MW$,$"$j$^$9!#\e(BMIME \e$B=qLL$N7A<0$O<+F0=h\e(B
-\e$BM}$,$7$d$9$/@_7W$5$l$F$$$^$9$,!"\e(BMIME \e$B=qLL$K4^$^$l$kFbMF$NCf$K$O%;%-%e%j\e(B
-\e$B%F%#!<>e$NLdBj$+$i<+F0=hM}$r$9$k$Y$-$G$J$$$b$N$,$"$j!"$3$&$$$C$?$b$N$N:F\e(B
-\e$B@8$K4X$7$F$OMxMQ<T$NH=CG$r6D$0$h$&$K@_7W$5$l$k$Y$-$G$7$g$&!#7k6I!"\e(BMIME 
-\e$B=qLL$r07$&$?$a$K$O\e(B STD 11 \e$B$*$h$S\e(B MIME \e$B$N9=J8$G5-=R$5$l$?%a%C%;!<%8$N>pJs\e(B
-\e$B8r49MQI=8=$H$=$N2r<a7k2L$G$"$kI=<(2hLL$d:F@8Ey$N=hM}$r6hJL$7$F9M$($kI,MW\e(B
-\e$B$,$"$j$^$9!#$^$?!"MxMQ<T$H$NBPOCE*$J:F@8=hM}$,I,MW$G$9!#\e(B@refill
-
-\e$B$3$N$?$a!"\e(BMIME-View \e$B$O#1$D$N=qLL$KBP$7$F!">pJs8r49MQI=8=$r3JG<$9$k\e(B 
-mime-raw-buffer \e$B$HI=<(MQI=8=$r3JG<$9$k\e(B mime-preview-buffer \e$B$N#2$D$N\e(B 
-buffer \e$B$rMQ$$$^$9!#\e(B@refill
-
-MIME-View \e$B$O\e(B mime-preview-buffer \e$B$KBP$7$F\e(B mime-view-mode \e$B$H$$$&\e(B MIME
-message \e$B$r1\Mw$9$k$?$a$N\e(B mode \e$B$rDs6!$7$^$9!#MxMQ<T$O$3$3$G3F\e(B entity \e$B$K\e(B
-\e$BBP$7$FA`:n$r9T$&$3$H$,$G$-$^$9!#\e(B
+The representation form of the internet messages in electric letters
+or in net news is based on STD 11. The STD 11 message body is a plain
+text which consists of lines as its only structure, and the character
+code is fixed as us-ascii. Actually, there are ``localized STD 11''
+messages that use some character code in their linguistic range
+instead of using us-ascii. Even in that case, the character code in
+the message is single. Therefore, Message User Agents have considered
+(byte row) = (us-ascii string), or (byte row) = (string in the
+character code in the linguistic range).@refill
+
+Although, the MIME message has the tree structure in entity unit.
+And one message can contain multiple character codes. The content of
+an entity can be not only a letter or an image that can be displayed
+simply, but also can be a voice or an animation that are played for
+some time interval, a data for some specific application, a source
+code of some program, or an external reference that consists of
+the usage of ftp or mail service, or some URL. Therefore the simple
+extension of STD 11 user interface, which only consider displaying
+the message, cannot treat all of the MIME functionalities.
+Then it is not sufficient to decode message along its MIME type, but
+it is also required to consider a playback processing through some
+dialogue with the user. The format of MIME messages is designed
+to easily be passed to automatic processing. But some contents in the
+MIME message should not be passed to automatic processing for security
+reasons. So it should be designed to ask user in such cases.
+After all, in order to deal with MIME message, it is required to
+distinguish the representation for information exchange which is
+written in STD 11 or MIME construction, and its result
+after some interpretation which is a display screen or a playback
+process. It is also needed to converse with user for playback
+processing.@refill
+
+Therefore, MIME-View uses two buffers for one document, one is the
+mime-raw-buffer that stores the representation for information exchange,
+and the other is the mime-preview-buffer that stores the representation
+for displaying.@refill
+
+MIME-View provides a mode in the mime-preview-buffer for reading MIME
+message, which is called as mime-view-mode. User can manipulate each
+entity there.
 
 
 @node MIME-Preview, mime-view-mode, Overview of MIME-View, MIME-View
 @section Presentation of mime-preview-buffer
 
-mime-view-mode \e$B$G$O3F\e(B entity \e$B$KBP$7$F\e(B@refill
+mime-view-mode displays information about each entity as@refill
 
 @example
        [entity-button]
@@ -109,15 +117,15 @@ mime-view-mode \e$B$G$O3F\e(B entity \e$B$KBP$7$F\e(B@refill
 @end example
 
 @noindent
-\e$B$H$$$&>pJs$rI=<($7$^$9!#$3$l$i$O>r7o$K=>$C$F\e(B design \e$B$rJQ99$7$?$j!"I=<(\e(B
-\e$B$rM^@)$9$k$3$H$b$G$-$^$9!#\e(B
+You can change their design or inhibit showing some of them, according
+to some condition.
 
-\e$B0J2<$K!"I=<(Nc$r<($7$^$9!#\e(B
+See following example
 
 
 @example
-From: morioka@@jaist.ac.jp (\e$B<i2,\e(B \e$BCNI'\e(B / MORIOKA Tomohiko)
-Subject: Re: \e$B<ALd!)\e(B
+From: morioka@@jaist.ac.jp (MORIOKA Tomohiko)
+Subject: Re: question?
 Newsgroups: zxr.message.mime
 Date: 22 Oct 93 11:02:44
 Mime-Version: 1.0
@@ -125,9 +133,9 @@ Organization: Japan Advanced Institute of Science and Technology,
         Ishikawa, Japan
 
 [1  (text/plain)]
-  MIME-Edit mode \e$B$K$*$1$k!"\e(BMIME message \e$B$N:n$jJ}!#\e(B
+  How to compose MIME message in MIME-Edit mode.
 
-  C-c C-x ? \e$B$r2!$9$H\e(B help \e$B$,=P$F$/$k!#\e(B
+  C-c C-x ? shows its help.
 
 C-c C-x C-t    insert a text message.
 C-c C-x TAB    insert a (binary) file.
@@ -137,30 +145,31 @@ C-c C-x C-y       insert a mail or news message.
 C-c C-x RET    insert a mail message.
 C-c C-x C-s    insert a signature file at end.
 C-c C-x t      insert a new MIME tag.
-C-c C-x a      enclose as multipart/alternative.
-C-c C-x p      enclose as multipart/parallel.
-C-c C-x m      enclose as multipart/mixed.
-C-c C-x d      enclose as multipart/digest.
-C-c C-x s      enclose as PGP signed.
-C-c C-x e      enclose as PGP encrypted.
+C-c C-m C-a    enclose as multipart/alternative.
+C-c C-m C-p    enclose as multipart/parallel.
+C-c C-m C-m    enclose as multipart/mixed.
+C-c C-m C-d    enclose as multipart/digest.
+C-c C-m C-s    enclose as PGP signed.
+C-c C-m C-e    enclose as PGP encrypted.
 C-c C-x C-k    insert PGP public key.
-C-c C-x C-p    preview editing MIME message.
+C-c C-x p      preview editing MIME message.
 ...
 
-\e$B$C$FLu$G!"\e(BC-c C-x C-i \e$B$r2!$7$F!"A^F~$7$?$$\e(B binary file \e$B$r;XDj$7$^$9!#\e(B
+therefore, you should type C-c C-x C-i and specify the binary file
+which you want to insert.
 
-  binary file \e$B$N\e(B MIME encoding \e$B$K$O!"IaDL!"\e(BBase64 \e$B$r;XDj$7$^$9!#\e(B
+  You should select Base64 as MIME encoding for binary file.
 
 [2  (image/gif)]
 
 [3  (text/plain)]
 
-  \e$B$3$s$JIw$K!"3(F~$j\e(B message \e$B$N$G$->e$,$j!#\e(B
+  Like above, you can compose the message with image.
 
-\e$B".".".".".".".".".".".\e(B \e$B%m%7%"%s!&%F%#!<$r0lGU!#\e(B \e$B".".".".".".".".".".".\e(B
-\e$B".".".".".\e(B  \e$B!y\e(B \e$B%8%c%`$G$O$J$/%^!<%^%l!<%I$G$b$J$/K*L*$G\e(B \e$B!y\e(B  \e$B".".".".".\e(B
-\e$B".".".".".\e(B         \e$B'.'0'2$$'0','!\e(B  \e$B'4'0'.'0'7'*','0\e(B         \e$B".".".".".\e(B
-\e$B".".".".".".".\e(B  Internet E-mail: <morioka@@jaist.ac.jp>  \e$B".".".".".".".\e(B
+==================== Take A Cup Of Russian Tea  ======================
+=========  ** Not With Jam Nor Marmalade But With Honey **  ==========
+=========                 MORIOKA TOMOHIKO                  ==========
+==============  Internet E-mail: <morioka@@jaist.ac.jp>  ==============
 @end example
 
 
@@ -176,141 +185,144 @@ C-c C-x C-p     preview editing MIME message.
 @cindex entity-number
 @cindex entity-button
 
-@strong{entity-button} \e$B$O\e(B entity \e$B$N@hF,$K$"$C$F!"$=$N\e(B entity \e$B$K4X$9$kBg\e(B
-\e$B$^$+$J>pJs$rI=<($9$kItJ,$G$9!#\e(B@refill
+@strong{entity-button} is a tag on the top of the entity
+which shows brief information of the part.@refill
 
-\e$BI8=`$G$O\e(B
+Normally, it appears as
 
 @example
         [1.3 test (text/plain)]
 @end example
 
 @noindent
-\e$B$N$h$&$J46$8$KI=<($5$l$^$9!#\e(B
 
-\e$B:G=i$N?t;z$O\e(B message \e$BCf$N$3$N\e(B entity \e$B$N0LCV$r@aHV9f$N$h$&$KI=$7$?$b$N$G!"\e(B
-@strong{entity-number} \e$B$H8F$S$^$9!#\e(B@refill
+The number on the head describes the place of the entity in the
+message (like the section number) and it is called as
+@strong{entity-number}.@refill
 
-\e$B#2HVL\$NJ8;zNs$OI=Bj$rI=$7$^$9!#$3$N>pJs$O!"\e(B
+The string in the next describes its title. This information is
+taken from
 
 @enumerate
 @item
-Content-Description field \e$B$b$7$/$O\e(B Subject field \e$B$K=q$+$l$?I=Bj\e(B
+Title described in Content-Description field or Subject field
 @item
-Content-Disposition field \e$B$N\e(B filename parameter \e$B$K=q$+$l$?\e(B file \e$BL>\e(B
+File name specified by filename parameter in Content-Disposition field
 @item
-Content-Type field \e$B$N\e(B name parameter \e$B$K=q$+$l$?\e(B file \e$BL>\e(B
+File name specified by name parameter in Content-Type field
 @item
- uuencode \e$B$N>l9g$N\e(B file \e$BL>\e(B
+File name for uuencode'ing
 @end enumerate
 
 @noindent
-\e$B$+$i:n$j$^$9!#$I$l$bB8:_$7$J$$>l9g$O6uGr$,I=<($5$l$^$9!#\e(B
+If none of them are specified, displays a blank.
 
-\e$B#3HVL\$N3g8L$NCf$N>pJs$O$=$N\e(B entity \e$B$N\e(B media-type/subtype \e$B$rI=$7$^$9!#Hs\e(B 
-MIME entity \e$B$N>l9g!"\e(B@code{nil} \e$B$,I=<($5$l$^$9!#\e(B@refill
+The 3rd item in the parenthesis describes media-type/subtype of
+the entity. If it is is not MIME entity, it displays @code{nil}.
+@refill
 
-\e$B$3$N\e(B entity-button \e$B$O\e(B entity \e$B$NFbMF$r>]D'$9$k\e(B icon \e$B$N$h$&$JLr3d$r2L$?\e(B
-\e$B$7$^$9!#Nc$($P!"\e(B
+This entity-button plays a role like icon that symbolically
+shows the content of the entity. For example, push @kbd{v} on
 
 @example
         [2  (image/gif)]
 @end example
 
 @noindent
-\e$B$N>e$G\e(B @kbd{v} \e$B$r2!$;$P$3$3$KF~$C$F$$$k3($,I=<($5$l$^$9!#\e(B
+shows up the image contained there.
 
-\e$B$^$?!"\e(Bmouse \e$BA`:n$,2DG=$J>l9g!"\e(Bentity-button \e$B$rBh#2%\%?%s!J\e(B3 button
-mouse \e$B$N>l9g!"Cf1{$N%\%?%s!K$G2!$;$P!"F1MM$K$=$N3($,I=<($5$l$^$9!#\e(B
+If the mouse operation is possible, you can display the image
+by pushing 2nd button (the middle button for 3 button mouse) too.
 
 
 @node entity-header, entity-body, entity-button, MIME-Preview
 @subsection entity-header
 @cindex entity-header
 
-@strong{entity-header} \e$B$O$"$k\e(B entity \e$B$N\e(B header \e$B$rI=<($9$kIt\e(B
-\e$BJ,$G$9!J!V$=$N$^$^$d$s$1!W$C$FE\$i$J$$$G!#$=$&$$$&$b$s$J$s$G$9!K!#\e(B
-
+@strong{entity-header} is the header of the entity.
+(Don't blame me as ``You say nothing more than as it is'',
+It is no more than that.)
 
 @node entity-body,  , entity-header, MIME-Preview
 @subsection entity-body
 @cindex entity-body
 
-@strong{entity-body} \e$B$O\e(B part \e$B$NFbMF$rI=<($9$kItJ,$G$9!#\e(B@refill
+@strong{entity-body} is the content of the part.@refill
 
-\e$B$3$l$b$R$M$j$,B-$j$J$$$G$9$,!"$^$"!"$=$&$$$&$b$s$G$9!#\e(B@refill
+Sophistication does not seem enough here also, but it is really such
+a thing.@refill
 
-\e$B$H$O$$$(!"<B:]$K$O>/$7$R$M$C$F$^$9!#\e(B@refill
+Though, it actually be twisted a little.@refill
 
-text entity \e$B$N>l9g$O\e(B charset \e$B$K1~$8$F\e(B code \e$BJQ49$7$?$j$7$^$9$7!"\e(BXEmacs \e$B$G\e(B
-\e$B$O\e(B image entity \e$B$rJQ49$7$J$$$H$$$1$J$$$7!#\e(B@refill
+The text entity is passed to code conversion according to its charset,
+and the image entity should be converted on XEmacs.@refill
 
-\e$B>\$7$/$O$^$?8e$G!#\e(B
+Details will be described later.
 
 
 @node mime-view-mode,  , MIME-Preview, MIME-View
 @section Operation in mime-preview-buffer
 
-mime-preview-buffer \e$B$K$O0J2<$N5!G=$,$"$j$^$9!#\e(B@refill
+mime-preview-buffer posesses following functionalities.@refill
 
 @table @kbd
 @item @key{u}
-\e$B>e$N\e(B part \e$B$KLa$k!J\e(Bmessage \e$B$N0lHV>e$N\e(B part \e$B$G$3$l$r9T$J$&$H\e(B Summary
-mode \e$B$KLa$k\e(B (*1)\e$B!K\e(B
+go back to upper part (in the first part of the message,
+go back to the Summary mode (*1))
 
 @item @key{p}
-\e$BA0$N\e(B part \e$B$K0\F0$9$k\e(B
+go to previous part
 
 @item @key{M-TAB}
-\e$BA0$N\e(B part \e$B$K0\F0$9$k\e(B
+go to previous part
 
 @item @key{n}
-\e$B<!$N\e(B part \e$B$K0\F0$9$k\e(B
+go to next part
 
 @item @key{TAB}
-\e$B<!$N\e(B part \e$B$K0\F0$9$k\e(B
+go to next part
 
 @item @key{SPC}
-scroll up \e$B$9$k\e(B
+scroll up
 
 @item @key{M-SPC}
-scroll down \e$B$9$k\e(B
+scroll down
 
 @item @key{DEL}
-scroll down \e$B$9$k\e(B
+scroll down
 
 @item @key{RET}
-\e$B<!$N9T$K0\F0$9$k\e(B
+go to next line
 
 @item @key{M-RET}
-\e$BA0$N9T$K0\F0$9$k\e(B
+go to previous line
 
 @item @key{v}
-part \e$B$r:F@8$9$k\e(B (*2)
+play current part (*2)
 
 @item @key{e}
-part \e$B$+$i\e(B file \e$B$r<h$j=P$9\e(B (*2)
+extract file from current part (*2)
 
 @item @key{C-c C-p}
-part \e$B$r0u:~$9$k\e(B (*2)
+print current part (*2)
 
 @item @key{mouse-button-2}
-preview-buffer \e$BCf$N\e(B mouse button \e$B$r5/F0$9$k\e(B
+start the mouse button in preview-buffer
 
-content-button \e$B$r2!$;$P!"$=$N\e(B part \e$B$,:F@8$5$l$k\e(B(*2)@refill
+on content-button, play current part (*2)@refill
 
-URL-button \e$B$r2!$;$P!"$=$N\e(B WWW browser \e$B$,5/F0$5$l$k\e(B@refill
+on URL-button, start WWW browser@refill
 
 @end table
 
 @noindent
-@strong{[\e$BCm0U\e(B]}
+@strong{[Notice]}
 @quotation
 
-(*1) MUA \e$B$G\e(B mime-view \e$B$N@_Dj$r$7$F$$$J$$>l9g!"\e(BSummary mode \e$B$K$OLa$j$^$;\e(B
-\e$B$s!#\e(B@refill
+(*1) Do not go back to Summary mode unless appropriately
+configured for mime-view in the MUA.@refill
 
-(*2) \e$B<B:]$NF0:n$OBP1~$9$k\e(B method \e$B$K0M$j$^$9!#\e(B
+(*2) actual behavior depends on the associated method
 @end quotation
 
 
@@ -441,22 +453,22 @@ Operations to make enclosure are following:
 @item @key{C-c C-m C-a}
 Enclose specified region as multipart/alternative.
 
-@item @key{C-c C-x C-p}
+@item @key{C-c C-m C-p}
 Enclose specified region as multipart/parallel.
 
-@item @key{C-c C-x C-m}
+@item @key{C-c C-m C-m}
 Enclose specified region as multipart/mixed.
 
-@item @key{C-c C-x C-d}
+@item @key{C-c C-m C-d}
 Enclose specified region as multipart/digest.
 
-@item @key{C-c C-x C-s}
+@item @key{C-c C-m C-s}
 Digital-sign to specified region. (cf. @ref{PGP})
 
-@item @key{C-c C-x C-e}
+@item @key{C-c C-m C-e}
 Encrypt to specified region. (cf. @ref{PGP})
 
-@item @key{C-c C-x C-q}
+@item @key{C-c C-m C-q}
 avoid to encode tags in specified region.  In other words, tags is
 interpreted as such string.  (In current version, it may be
 incomplete.  Maybe PGP-signature does not work for this enclosure.)
@@ -667,7 +679,7 @@ Regular expression to match field-name to be ignored when split sending.
 
 
 @menu
-* PGP::                         
+* PGP::                         Encryption, Sign
 * Buttons::                     Mouse button
 * Acting-condition configuration::  Utility for configuration
 @end menu
@@ -681,29 +693,33 @@ mime-edit provides PGP encryption, signature and inserting public-key
 features based on @strong{PGP/MIME} (RFC 2015) or @strong{PGP-kazu}
 (draft-kazu-pgp-mime-00.txt).@refill
 
-This feature requires pgp command and pgp interface package, such as
-Mailcrypt package (@ref{(mailcrypt)}).
+This feature requires your pgp command.
 
-@defvar pgp-function-alist
+@defvar pgg-default-scheme
 
-Alist of service names vs. corresponding functions and its filenames.
-Each element looks like @code{(SERVICE FUNCTION FILE)}.@refill
+Version of PGP or GnuPG command to be used for encryption or sign.
+The value should be a symbol.  Allowed versions are @code{gpg},
+@code{pgp} or @code{pgp5}.@refill
+@end defvar
 
-SERVICE is a symbol of PGP processing.  It allows `verify', `decrypt',
-`fetch-key', `snarf-keys', `mime-sign', `traditional-sign', `encrypt' or
-`insert-key'.@refill
 
-Function is a symbol of function to do specified SERVICE.@refill
+@defvar pgg-scheme
 
-FILE is string of filename which has definition of corresponding
-FUNCTION.
+Version of PGP or GnuPG command to be used for decryption or verification.
+The value should be a symbol.  Allowed versions are @code{gpg},
+@code{pgp} or @code{pgp5}.@refill
 @end defvar
 
 
-@defun pgp-function method
+@defvar pgg-insert-url-function
 
-Return function to do service @var{method}.
-@end defun
+The function to fetch public key from the keyserver.
+Use Emacs/W3 by the default setting. To use emacs-w3m
+instead, set as follows:
+@lisp
+(setq pgg-insert-url-function #'w3m-retrieve)
+@end lisp
+@end defvar
 
 
 
index 2e1094a..e1656a0 100644 (file)
@@ -1,6 +1,6 @@
 <!doctype sinfo system>
 <head>
-<title>SEMI 1.8 \e$B@bL@=q\e(B
+<title>SEMI 1.14 \e$B@bL@=q\e(B
 <author>\e$B<i2,\e(B \e$BCNI'\e(B <mail>morioka@jaist.ac.jp</mail>
 <date>1998/07/03
 
@@ -125,14 +125,14 @@ C-c C-x C-y       insert a mail or news message.
 C-c C-x RET    insert a mail message.
 C-c C-x C-s    insert a signature file at end.
 C-c C-x t      insert a new MIME tag.
-C-c C-x a      enclose as multipart/alternative.
-C-c C-x p      enclose as multipart/parallel.
-C-c C-x m      enclose as multipart/mixed.
-C-c C-x d      enclose as multipart/digest.
-C-c C-x s      enclose as PGP signed.
-C-c C-x e      enclose as PGP encrypted.
+C-c C-m C-a    enclose as multipart/alternative.
+C-c C-m C-p    enclose as multipart/parallel.
+C-c C-m C-m    enclose as multipart/mixed.
+C-c C-m C-d    enclose as multipart/digest.
+C-c C-m C-s    enclose as PGP signed.
+C-c C-m C-e    enclose as PGP encrypted.
 C-c C-x C-k    insert PGP public key.
-C-c C-x C-p    preview editing MIME message.
+C-c C-x p      preview editing MIME message.
 ...
 
 \e$B$C$FLu$G!"\e(BC-c C-x C-i \e$B$r2!$7$F!"A^F~$7$?$$\e(B binary file \e$B$r;XDj$7$^$9!#\e(B
@@ -401,26 +401,26 @@ enclosure \e$B$r:n$k$?$a$NA`:n$H$7$F$O0J2<$N$h$&$J$b$N$,$"$j$^$9!#\e(B
 <kd>
 \e$B;XDj$7$?\e(B region \e$B$r\e(B multipart/alternative \e$B$H$7$F0O$_$^$9!#\e(B
 </kd>
-<kt>C-c C-x C-p
+<kt>C-c C-m C-p
 <kd>
 \e$B;XDj$7$?\e(B region \e$B$r\e(B multipart/parallel \e$B$H$7$F0O$_$^$9!#\e(B
 </kd>
-<kt>C-c C-x C-m
+<kt>C-c C-m C-m
 <kd>
 \e$B;XDj$7$?\e(B region \e$B$r\e(B multipart/mixed \e$B$H$7$F0O$_$^$9!#\e(B
 </kd>
-<kt>C-c C-x C-d
+<kt>C-c C-m C-d
 <kd>
 \e$B;XDj$7$?\e(B region \e$B$r\e(B multipart/digest \e$B$H$7$F0O$_$^$9!#\e(B
 </kd>
-<kt>C-c C-x C-s
+<kt>C-c C-m C-s
 <kd>
 \e$B;XDj$7$?\e(B region \e$B$KEE;R=pL>$r9T$$$^$9!#\e(B<cf node="PGP">
 </kd>
-<kt>C-c C-x C-e
+<kt>C-c C-m C-e
 <kd>
 \e$B;XDj$7$?\e(B region \e$B$r0E9f2=$7$^$9!#\e(B<cf node="PGP">
-<kt>C-c C-x C-q
+<kt>C-c C-m C-q
 <kd>
 \e$B;XDj$7$?\e(B region \e$BFb$N\e(B tag \e$B$rL58z$K$7!"$=$N\e(B tag \e$B$rJ8;zNs$H$7$FMxMQ$G$-$k\e(B
 \e$B$h$&$K$7$^$9!#!J8=:_$NHG$G$O$&$^$/F/$+$J$$$3$H$,$"$j$^$9!#$^$?!"EE;R=p\e(B
@@ -591,62 +591,63 @@ file="mime-ja">STD 11</dref> \e$B$r3HD%$7$F$$$k$,!"\e(Bmessage header \e$B$G$O\e(B
 <p>
 <defvar name="mime-edit-split-message">
 <p>
-Split large message if it is non-nil.
+Non-nil \e$B$J$i$PBg$-$J%a%C%;!<%8$rJ,3d$7$FAw?.$7$^$9!#\e(B
 </defvar>
 
 <defvar name="mime-edit-message-default-max-lines">
 <p>
-Default maximum lines of a message.
+\e$B%a%C%;!<%8$N:GBg9T?t$N%G%U%)%k%HCM$G$9!#\e(B
 </defvar>
 
 <defvar name="mime-edit-message-max-lines-alist">
 <p>
-Alist of major-mode vs maximum lines of a message.
+\e$B%a%8%c!<%b!<%IBP%a%C%;!<%8$N:GBg9T?t$+$i@.$kO"A[%j%9%H$G$9!#\e(B
 <p>
-If it is not specified for a major-mode,
-<code>mime-edit-message-default-max-lines</code> is used.
+\e$B%a%8%c!<%b!<%I$,$3$3$G;XDj$5$l$F$J$$>l9g$K$O\e(B
+<code>mime-edit-message-default-max-lines</code> \e$B$rMQ$$$^$9!#\e(B
 </defvar>
 
 <defvar name="mime-edit-split-blind-field-regexp">
 <p>
-Regular expression to match field-name to be ignored when split
-sending.
+\e$BJ,3dAw?.$N:]$KL5;k$5$l$k%U%#!<%k%IL>$K%^%C%A$9$k@55,I=8=$G$9!#\e(B
 </defvar>
 
 
 <h1> \e$B$=$NB>\e(B
 <node> Various
 <p>
-<h2> PGP
+<h2> \e$B0E9f2=!"=pL>\e(B
 <node> PGP
 <p>
 mime-edit \e$B$G$O\e(B <concept>PGP/MIME</concept> (RFC 2015) \e$B$*$h$S\e(B
 <concept>PGP-kazu</concept> (draft-kazu-pgp-mime-00.txt) \e$B$K$h$k0E9f2=!&\e(B
 \e$BEE;R=pL>!&8x3+80$NA^F~5!G=$rMxMQ$9$k$3$H$,$G$-$^$9!#\e(B
 <p>
-\e$BC"$7!"$3$N5!G=$rMxMQ$9$k$K$O\e(B <a file="mailcrypt">Mailcrypt package</a> 
-\e$B$H\e(B pgp command \e$B$,I,MW$G$9!#\e(B
+\e$BC"$7!"$3$N5!G=$rMxMQ$9$k$K$O3F<o\e(B pgp command \e$B$,I,MW$G$9!#\e(B
 
-<defvar name="pgp-function-alist">
-<p>
-Alist of service names vs. corresponding functions and its filenames.
-Each element looks like <code>(SERVICE FUNCTION FILE)</code>.
+<defvar name="pgg-default-scheme">
 <p>
-SERVICE is a symbol of PGP processing.  It allows `verify', `decrypt',
-`fetch-key', `snarf-keys', `mime-sign', `traditional-sign', `encrypt'
-or `insert-key'.
-<p>
-Function is a symbol of function to do specified SERVICE.
+\e$B0E9f2=$b$7$/$O=pL>$KMQ$$$k\e(B PGP \e$B$b$7$/$O\e(B GnuPG \e$B%3%^%s%I$N%P!<%8%g%s$G$9!#\e(B
+\e$BCM$O\e(B symbol \e$B$r;XDj$7$^$9!#;H$($k%P!<%8%g%s$O\e(B <code>gpg</code>\e$B!"\e(B
+<code>pgp</code> \e$B$b$7$/$O\e(B <code>pgp5</code> \e$B$G$9!#\e(B
+</defvar>
+
+<defvar name="pgg-scheme">
 <p>
-FILE is string of filename which has definition of corresponding
-FUNCTION.
+\e$BI|9f$b$7$/$O8!>Z$KMQ$$$k\e(B PGP \e$B$b$7$/$O\e(B GnuPG \e$B%3%^%s%I$N%P!<%8%g%s$G$9!#\e(B
+\e$BCM$O\e(B symbol \e$B$r;XDj$7$^$9!#;H$($k%P!<%8%g%s$O\e(B <code>gpg</code>\e$B!"\e(B
+<code>pgp</code> \e$B$b$7$/$O\e(B <code>pgp5</code> \e$B$G$9!#\e(B
 </defvar>
 
-<defun name="pgp-function">
-           <args> method
+<defvar name="pgg-insert-url-function">
 <p>
-Return function to do service <var>method</var>.
-</defun>
+\e$B80%5!<%P$+$i8x3+80$r<h$j4s$;$k:]$K;H$&4X?t$G$9!#%G%U%)%k%H$G$O\e(B
+Emacs/W3 \e$B$r;H$&@_Dj$K$J$C$F$$$^$9!#\e(Bemacs-w3m \e$B$r;H$&>l9g$K$O\e(B
+\e$B<!$N$h$&$K@_Dj$7$^$9!#\e(B
+<lisp>
+(setq pgg-insert-url-function #'w3m-retrieve)
+</lisp>
+</defvar>
 
 
 <h2> \e$B2!KU\e(B
@@ -654,17 +655,18 @@ Return function to do service <var>method</var>.
 <p>
 <defvar name="mime-button-face">
 <p>
-Face used for content-button or URL-button of MIME-Preview buffer.
+MIME-Preview \e$B%P%C%U%!$G\e(B  content-button \e$B$b$7$/$O\e(B URL-button  \e$B$KMQ$$$k\e(B
+face \e$B$G$9!#\e(B
 </defvar>
 
 <defvar name="mime-button-mouse-face">
 <p>
-Face used for MIME-preview buffer mouse highlighting.
+MIME-preview \e$B%P%C%U%!$G%^%&%9$r%O%$%i%$%H$9$k:]$KMQ$$$k\e(B face \e$B$G$9!#\e(B
 </defvar>
 
 <defvar name="mime-browse-url-function">
 <p>
-Function to browse URL.
+URL \e$B$r%V%i%&%:$9$k4X?t$G$9!#\e(B
 </defvar>
 
 
index 24583c1..8fe71de 100644 (file)
@@ -1,13 +1,13 @@
 \input texinfo.tex
 @setfilename mime-ui-ja.info
-@settitle{SEMI 1.8 \e$B@bL@=q\e(B}
+@settitle{SEMI 1.14 \e$B@bL@=q\e(B}
 @titlepage
-@title SEMI 1.8 \e$B@bL@=q\e(B
+@title SEMI 1.14 \e$B@bL@=q\e(B
 @author \e$B<i2,\e(B \e$BCNI'\e(B <morioka@@jaist.ac.jp>
 @subtitle 1998/07/03
 @end titlepage
 @node Top, Introduction, (dir), (dir)
-@top SEMI 1.8 \e$B@bL@=q\e(B
+@top SEMI 1.14 \e$B@bL@=q\e(B
 
 @ifinfo
 
@@ -141,14 +141,14 @@ C-c C-x C-y       insert a mail or news message.
 C-c C-x RET    insert a mail message.
 C-c C-x C-s    insert a signature file at end.
 C-c C-x t      insert a new MIME tag.
-C-c C-x a      enclose as multipart/alternative.
-C-c C-x p      enclose as multipart/parallel.
-C-c C-x m      enclose as multipart/mixed.
-C-c C-x d      enclose as multipart/digest.
-C-c C-x s      enclose as PGP signed.
-C-c C-x e      enclose as PGP encrypted.
+C-c C-m C-a    enclose as multipart/alternative.
+C-c C-m C-p    enclose as multipart/parallel.
+C-c C-m C-m    enclose as multipart/mixed.
+C-c C-m C-d    enclose as multipart/digest.
+C-c C-m C-s    enclose as PGP signed.
+C-c C-m C-e    enclose as PGP encrypted.
 C-c C-x C-k    insert PGP public key.
-C-c C-x C-p    preview editing MIME message.
+C-c C-x p      preview editing MIME message.
 ...
 
 \e$B$C$FLu$G!"\e(BC-c C-x C-i \e$B$r2!$7$F!"A^F~$7$?$$\e(B binary file \e$B$r;XDj$7$^$9!#\e(B
@@ -455,22 +455,22 @@ enclosure \e$B$r:n$k$?$a$NA`:n$H$7$F$O0J2<$N$h$&$J$b$N$,$"$j$^$9!#\e(B
 @item @key{C-c C-m C-a}
 \e$B;XDj$7$?\e(B region \e$B$r\e(B multipart/alternative \e$B$H$7$F0O$_$^$9!#\e(B
 
-@item @key{C-c C-x C-p}
+@item @key{C-c C-m C-p}
 \e$B;XDj$7$?\e(B region \e$B$r\e(B multipart/parallel \e$B$H$7$F0O$_$^$9!#\e(B
 
-@item @key{C-c C-x C-m}
+@item @key{C-c C-m C-m}
 \e$B;XDj$7$?\e(B region \e$B$r\e(B multipart/mixed \e$B$H$7$F0O$_$^$9!#\e(B
 
-@item @key{C-c C-x C-d}
+@item @key{C-c C-m C-d}
 \e$B;XDj$7$?\e(B region \e$B$r\e(B multipart/digest \e$B$H$7$F0O$_$^$9!#\e(B
 
-@item @key{C-c C-x C-s}
+@item @key{C-c C-m C-s}
 \e$B;XDj$7$?\e(B region \e$B$KEE;R=pL>$r9T$$$^$9!#\e(B(cf. @ref{PGP})
 
-@item @key{C-c C-x C-e}
+@item @key{C-c C-m C-e}
 \e$B;XDj$7$?\e(B region \e$B$r0E9f2=$7$^$9!#\e(B(cf. @ref{PGP})
 
-@item @key{C-c C-x C-q}
+@item @key{C-c C-m C-q}
 \e$B;XDj$7$?\e(B region \e$BFb$N\e(B tag \e$B$rL58z$K$7!"$=$N\e(B tag \e$B$rJ8;zNs$H$7$FMxMQ$G$-$k\e(B
 \e$B$h$&$K$7$^$9!#!J8=:_$NHG$G$O$&$^$/F/$+$J$$$3$H$,$"$j$^$9!#$^$?!"EE;R=p\e(B
 \e$BL>$H$NJ;MQ$K4X$7$F$bIT40A4$G$9!K\e(B
@@ -653,28 +653,28 @@ body \e$B$K$*$$$F!"\e(B8bit \e$B$N\e(B data \e$B$r;H$($k$h$&$K\e(B STD 11 (@ref{(mime-
 
 @defvar mime-edit-split-message
 
-Split large message if it is non-nil.
+Non-nil \e$B$J$i$PBg$-$J%a%C%;!<%8$rJ,3d$7$FAw?.$7$^$9!#\e(B
 @end defvar
 
 
 @defvar mime-edit-message-default-max-lines
 
-Default maximum lines of a message.
+\e$B%a%C%;!<%8$N:GBg9T?t$N%G%U%)%k%HCM$G$9!#\e(B
 @end defvar
 
 
 @defvar mime-edit-message-max-lines-alist
 
-Alist of major-mode vs maximum lines of a message.@refill
+\e$B%a%8%c!<%b!<%IBP%a%C%;!<%8$N:GBg9T?t$+$i@.$kO"A[%j%9%H$G$9!#\e(B@refill
 
-If it is not specified for a major-mode,
-@code{mime-edit-message-default-max-lines} is used.
+\e$B%a%8%c!<%b!<%I$,$3$3$G;XDj$5$l$F$J$$>l9g$K$O\e(B
+@code{mime-edit-message-default-max-lines} \e$B$rMQ$$$^$9!#\e(B
 @end defvar
 
 
 @defvar mime-edit-split-blind-field-regexp
 
-Regular expression to match field-name to be ignored when split sending.
+\e$BJ,3dAw?.$N:]$KL5;k$5$l$k%U%#!<%k%IL>$K%^%C%A$9$k@55,I=8=$G$9!#\e(B
 @end defvar
 
 
@@ -684,7 +684,7 @@ Regular expression to match field-name to be ignored when split sending.
 
 
 @menu
-* PGP::                         
+* PGP::                         \e$B0E9f2=!"=pL>\e(B
 * Buttons::                     \e$B2!KU\e(B
 * Acting-condition configuration::  \e$B<B9T>r7o$N@_Dj\e(B
 @end menu
@@ -698,29 +698,33 @@ mime-edit \e$B$G$O\e(B @strong{PGP/MIME} (RFC 2015) \e$B$*$h$S\e(B@strong{PGP-kazu}
 (draft-kazu-pgp-mime-00.txt) \e$B$K$h$k0E9f2=!&EE;R=pL>!&8x3+80$NA^F~5!G=$r\e(B
 \e$BMxMQ$9$k$3$H$,$G$-$^$9!#\e(B@refill
 
-\e$BC"$7!"$3$N5!G=$rMxMQ$9$k$K$O\e(B Mailcrypt package (@ref{(mailcrypt)}) \e$B$H\e(B 
-pgp command \e$B$,I,MW$G$9!#\e(B
+\e$BC"$7!"$3$N5!G=$rMxMQ$9$k$K$O3F<o\e(B pgp command \e$B$,I,MW$G$9!#\e(B
 
-@defvar pgp-function-alist
+@defvar pgg-default-scheme
 
-Alist of service names vs. corresponding functions and its filenames.
-Each element looks like @code{(SERVICE FUNCTION FILE)}.@refill
+\e$B0E9f2=$b$7$/$O=pL>$KMQ$$$k\e(B PGP \e$B$b$7$/$O\e(B GnuPG \e$B%3%^%s%I$N%P!<%8%g%s$G$9!#\e(B
+\e$BCM$O\e(B symbol \e$B$r;XDj$7$^$9!#;H$($k%P!<%8%g%s$O\e(B @code{gpg}\e$B!"\e(B
+@code{pgp} \e$B$b$7$/$O\e(B @code{pgp5} \e$B$G$9!#\e(B@refill
+@end defvar
 
-SERVICE is a symbol of PGP processing.  It allows `verify', `decrypt',
-`fetch-key', `snarf-keys', `mime-sign', `traditional-sign', `encrypt' or
-`insert-key'.@refill
 
-Function is a symbol of function to do specified SERVICE.@refill
+@defvar pgg-scheme
 
-FILE is string of filename which has definition of corresponding
-FUNCTION.
+\e$BI|9f$b$7$/$O8!>Z$KMQ$$$k\e(B PGP \e$B$b$7$/$O\e(B GnuPG \e$B%3%^%s%I$N%P!<%8%g%s$G$9!#\e(B
+\e$BCM$O\e(B symbol \e$B$r;XDj$7$^$9!#;H$($k%P!<%8%g%s$O\e(B @code{gpg}\e$B!"\e(B
+@code{pgp} \e$B$b$7$/$O\e(B @code{pgp5} \e$B$G$9!#\e(B@refill
 @end defvar
 
 
-@defun pgp-function method
+@defvar pgg-insert-url-function
 
-Return function to do service @var{method}.
-@end defun
+\e$B80%5!<%P$+$i8x3+80$r<h$j4s$;$k:]$K;H$&4X?t$G$9!#%G%U%)%k%H$G$O\e(B
+Emacs/W3 \e$B$r;H$&@_Dj$K$J$C$F$$$^$9!#\e(Bemacs-w3m \e$B$r;H$&>l9g$K$O\e(B
+\e$B<!$N$h$&$K@_Dj$7$^$9!#\e(B
+@lisp
+(setq pgg-insert-url-function #'w3m-retrieve)
+@end lisp
+@end defvar
 
 
 
@@ -729,19 +733,20 @@ Return function to do service @var{method}.
 
 @defvar mime-button-face
 
-Face used for content-button or URL-button of MIME-Preview buffer.
+MIME-Preview \e$B%P%C%U%!$G\e(B  content-button \e$B$b$7$/$O\e(B URL-button  \e$B$KMQ$$$k\e(B
+face \e$B$G$9!#\e(B
 @end defvar
 
 
 @defvar mime-button-mouse-face
 
-Face used for MIME-preview buffer mouse highlighting.
+MIME-preview \e$B%P%C%U%!$G%^%&%9$r%O%$%i%$%H$9$k:]$KMQ$$$k\e(B face \e$B$G$9!#\e(B
 @end defvar
 
 
 @defvar mime-browse-url-function
 
-Function to browse URL.
+URL \e$B$r%V%i%&%:$9$k4X?t$G$9!#\e(B
 @end defvar
 
 
diff --git a/mime-vcard.el b/mime-vcard.el
new file mode 100644 (file)
index 0000000..af6cd89
--- /dev/null
@@ -0,0 +1,69 @@
+;;; mime-vcard.el --- mime-view content filter for vCard.
+
+;; Copyright (C) 2000 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Keywords: vCard, MIME, multimedia, mail, news
+
+;; This file is part of SEMI (Sample of Elastic MIME Interfaces).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+
+;;; Commentary:
+;; 
+
+;;; Code:
+
+(require 'vcard)
+
+(defvar mime-vcard-standard-filters
+  (cons #'mime-vcard-filter-quoted-printable
+       vcard-standard-filters))
+
+(defun mime-vcard-filter-quoted-printable (key data)
+  (save-match-data
+    (when (string-match ";\\(encoding=\\)?quoted-printable$" key)
+      (while (string-match "\\(=[0-9A-F][0-9A-F]\\)+" data)
+       (setq data
+             (replace-match
+              (concat
+               (string-as-multibyte
+                (decode-coding-string
+                 (mime-decode-string
+                  (match-string 0 data) "quoted-printable")
+                 'raw-text-dos)))
+              t t data))))
+    data))
+
+(defun mime-display-text/x-vcard (entity situation)
+  (save-restriction
+    (narrow-to-region (point-max)(point-max))
+    (let ((vcard-standard-filters mime-vcard-standard-filters))
+      (insert
+       (string-as-multibyte
+       (vcard-format-string
+        (vcard-parse-string
+         (mime-entity-content entity)
+         #'vcard-standard-filter)))))
+    (if (not (eq (char-after (1- (point))) ?\n))
+        (insert "\n"))
+    (mime-add-url-buttons)
+    (run-hooks 'mime-display-text/x-vcard-hook)))
+
+(provide 'mime-vcard)
+
+;;; mime-vcard.el ends here
index 119d972..33dc314 100644 (file)
@@ -1,8 +1,8 @@
 ;;; mime-view.el --- interactive MIME viewer for GNU Emacs
 
-;; Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
+;; Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
 
-;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Author: MORIOKA Tomohiko <tomo@m17n.org>
 ;; Created: 1994/07/13
 ;;     Renamed: 1994/08/31 from tm-body.el
 ;;     Renamed: 1997/02/19 from tm-view.el
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
-(require 'emu)
 (require 'mime)
 (require 'semi-def)
 (require 'calist)
 (require 'alist)
-(require 'mailcap)
+(require 'mime-conf)
+(require 'mcharset)
+
+(eval-when-compile (require 'static))
 
 
 ;;; @ version
   "MIME view mode"
   :group 'mime)
 
-(defcustom mime-view-find-every-acting-situation t
-  "*Find every available acting-situation if non-nil."
-  :group 'mime-view
-  :type 'boolean)
-
-(defcustom mime-acting-situation-examples-file "~/.mime-example"
-  "*File name of example about acting-situation demonstrated by user."
+(defcustom mime-situation-examples-file "~/.mime-example"
+  "*File name of situation-examples demonstrated by user."
   :group 'mime-view
   :type 'file)
 
@@ -72,6 +69,18 @@ buttom. Nil means don't scroll at all."
                 (const :tag "On" t)
                 (sexp :tag "Situation" 1)))
 
+(defcustom mime-view-mailcap-files
+  (let ((files '("/etc/mailcap" "/usr/etc/mailcap" "~/.mailcap")))
+    (or (member mime-mailcap-file files)
+       (setq files (cons mime-mailcap-file files)))
+    files)
+  "List of mailcap files."
+  :group 'mime-view
+  :type '(repeat file))
+
+(defvar mime-view-automatic-conversion 'undecided)
+
+
 ;;; @ in raw-buffer (representation space)
 ;;;
 
@@ -83,35 +92,13 @@ buttom. Nil means don't scroll at all."
 (defvar mime-raw-representation-type-alist
   '((mime-show-message-mode     . binary)
     (mime-temp-message-mode     . binary)
-    (t                          . cooked)
-    )
+    (t                          . cooked))
   "Alist of major-mode vs. representation-type of mime-raw-buffer.
 Each element looks like (SYMBOL . REPRESENTATION-TYPE).  SYMBOL is
 major-mode or t.  t means default.  REPRESENTATION-TYPE must be
 `binary' or `cooked'.")
 
 
-;; (defun mime-raw-find-entity-from-point (point &optional message-info)
-;;   "Return entity from POINT in mime-raw-buffer.
-;; If optional argument MESSAGE-INFO is not specified,
-;; `mime-message-structure' is used."
-;;   (or message-info
-;;       (setq message-info mime-message-structure))
-;;   (if (and (<= (mime-entity-point-min message-info) point)
-;;            (<= point (mime-entity-point-max message-info)))
-;;       (let ((children (mime-entity-children message-info)))
-;;         (catch 'tag
-;;           (while children
-;;             (let ((ret
-;;                    (mime-raw-find-entity-from-point point (car children))))
-;;               (if ret
-;;                   (throw 'tag ret)
-;;                 ))
-;;             (setq children (cdr children)))
-;;           message-info))))
-;; (make-obsolete 'mime-raw-find-entity-from-point "don't use it.")
-
-
 ;;; @ in preview-buffer (presentation space)
 ;;;
 
@@ -137,8 +124,7 @@ mother-buffer."
   (if (and recursive mime-mother-buffer)
       (save-excursion
        (set-buffer mime-mother-buffer)
-       (mime-preview-original-major-mode recursive)
-       )
+       (mime-preview-original-major-mode recursive))
     (cdr (assq 'major-mode
               (get-text-property (or point
                                      (if (> (point) (buffer-size))
@@ -158,15 +144,13 @@ mother-buffer."
       (setq rest (or (mime-entity-content-type entity)
                     (make-mime-content-type 'text 'plain))
            situation (cons (car rest) situation)
-           rest (cdr rest))
-      )
+           rest (cdr rest)))
     (unless (assq 'subtype situation)
       (or rest
          (setq rest (or (cdr (mime-entity-content-type entity))
                         '((subtype . plain)))))
       (setq situation (cons (car rest) situation)
-           rest (cdr rest))
-      )
+           rest (cdr rest)))
     (while rest
       (setq param (car rest))
       (or (assoc (car param) situation)
@@ -181,8 +165,7 @@ mother-buffer."
          (setq situation (cons (cons 'disposition-type
                                      (mime-content-disposition-type rest))
                                situation)
-               rest (mime-content-disposition-parameters rest))
-       ))
+               rest (mime-content-disposition-parameters rest))))
     (while rest
       (setq param (car rest)
            name (car param))
@@ -224,41 +207,306 @@ mother-buffer."
     
     situation))
 
+(defsubst mime-delq-null-situation (situations field
+                                              &rest ignored-values)
+  (let (dest)
+    (while situations
+      (let* ((situation (car situations))
+            (cell (assq field situation)))
+       (if cell
+           (or (memq (cdr cell) ignored-values)
+               (setq dest (cons situation dest)))))
+      (setq situations (cdr situations)))
+    dest))
+
+(defun mime-compare-situation-with-example (situation example)
+  (let ((example (copy-alist example))
+       (match 0))
+    (while situation
+      (let* ((cell (car situation))
+            (key (car cell))
+            (ecell (assoc key example)))
+       (when ecell
+         (if (equal cell ecell)
+             (setq match (1+ match))
+           (setq example (delq ecell example)))))
+      (setq situation (cdr situation)))
+    (cons match example)))
+
+(defun mime-sort-situation (situation)
+  (sort situation
+       #'(lambda (a b)
+           (let ((a-t (car a))
+                 (b-t (car b))
+                 (order '((type . 1)
+                          (subtype . 2)
+                          (mode . 3)
+                          (method . 4)
+                          (major-mode . 5)
+                          (disposition-type . 6)))
+                 a-order b-order)
+             (if (symbolp a-t)
+                 (let ((ret (assq a-t order)))
+                   (if ret
+                       (setq a-order (cdr ret))
+                     (setq a-order 7)))
+               (setq a-order 8))
+             (if (symbolp b-t)
+                 (let ((ret (assq b-t order)))
+                   (if ret
+                       (setq b-order (cdr ret))
+                     (setq b-order 7)))
+               (setq b-order 8))
+             (if (= a-order b-order)
+                 (string< (format "%s" a-t)(format "%s" b-t))
+               (< a-order b-order))))))
+
+(defun mime-unify-situations (entity-situation
+                             condition situation-examples
+                             &optional required-name ignored-value
+                             every-situations)
+  (let (ret)
+    (in-calist-package 'mime-view)
+    (setq ret
+         (ctree-find-calist condition entity-situation
+                            every-situations))
+    (if required-name
+       (setq ret (mime-delq-null-situation ret required-name
+                                           ignored-value t)))
+    (or (assq 'ignore-examples entity-situation)
+       (if (cdr ret)
+           (let ((rest ret)
+                 (max-score 0)
+                 (max-escore 0)
+                 max-examples
+                 max-situations)
+             (while rest
+               (let ((situation (car rest))
+                     (examples situation-examples))
+                 (while examples
+                   (let* ((ret
+                           (mime-compare-situation-with-example
+                            situation (caar examples)))
+                          (ret-score (car ret)))
+                     (cond ((> ret-score max-score)
+                            (setq max-score ret-score
+                                  max-escore (cdar examples)
+                                  max-examples (list (cdr ret))
+                                  max-situations (list situation)))
+                           ((= ret-score max-score)
+                            (cond ((> (cdar examples) max-escore)
+                                   (setq max-escore (cdar examples)
+                                         max-examples (list (cdr ret))
+                                         max-situations (list situation)))
+                                  ((= (cdar examples) max-escore)
+                                   (setq max-examples
+                                         (cons (cdr ret) max-examples))
+                                   (or (member situation max-situations)
+                                       (setq max-situations
+                                             (cons situation max-situations))))))))
+                   (setq examples (cdr examples))))
+               (setq rest (cdr rest)))
+             (when max-situations
+               (setq ret max-situations)
+               (while max-examples
+                 (let* ((example (car max-examples))
+                        (cell
+                         (assoc example situation-examples)))
+                   (if cell
+                       (setcdr cell (1+ (cdr cell)))
+                     (setq situation-examples
+                           (cons (cons example 0)
+                                 situation-examples))))
+                 (setq max-examples (cdr max-examples)))))))
+    (cons ret situation-examples)
+    ;; ret: list of situations
+    ;; situation-examples: new examples (notoce that contents of
+    ;;                     argument `situation-examples' has bees modified)
+    ))
+
 (defun mime-view-entity-title (entity)
   (or (mime-entity-read-field entity 'Content-Description)
       (mime-entity-read-field entity 'Subject)
       (mime-entity-filename entity)
       ""))
 
-
-;; (defsubst mime-raw-point-to-entity-node-id (point &optional message-info)
-;;   "Return entity-node-id from POINT in mime-raw-buffer.
-;; If optional argument MESSAGE-INFO is not specified,
-;; `mime-message-structure' is used."
-;;   (mime-entity-node-id (mime-raw-find-entity-from-point point message-info)))
-
-;; (make-obsolete 'mime-raw-point-to-entity-node-id "don't use it.")
-
-;; (defsubst mime-raw-point-to-entity-number (point &optional message-info)
-;;   "Return entity-number from POINT in mime-raw-buffer.
-;; If optional argument MESSAGE-INFO is not specified,
-;; `mime-message-structure' is used."
-;;   (mime-entity-number (mime-raw-find-entity-from-point point message-info)))
-
-;; (make-obsolete 'mime-raw-point-to-entity-number "don't use it.")
-
-;; (defun mime-raw-flatten-message-info (&optional message-info)
-;;   "Return list of entity in mime-raw-buffer.
-;; If optional argument MESSAGE-INFO is not specified,
-;; `mime-message-structure' is used."
-;;   (or message-info
-;;       (setq message-info mime-message-structure))
-;;   (let ((dest (list message-info))
-;;         (rcl (mime-entity-children message-info)))
-;;     (while rcl
-;;       (setq dest (nconc dest (mime-raw-flatten-message-info (car rcl))))
-;;       (setq rcl (cdr rcl)))
-;;     dest))
+(defvar mime-preview-situation-example-list nil)
+(defvar mime-preview-situation-example-list-max-size 16)
+;; (defvar mime-preview-situation-example-condition nil)
+
+(defun mime-find-entity-preview-situation (entity
+                                          &optional default-situation)
+  (or (let ((ret
+            (mime-unify-situations
+             (append (mime-entity-situation entity)
+                     default-situation)
+             mime-preview-condition
+             mime-preview-situation-example-list)))
+       (setq mime-preview-situation-example-list
+             (cdr ret))
+       (caar ret))
+      default-situation))
+
+  
+(defvar mime-acting-situation-example-list nil)
+(defvar mime-acting-situation-example-list-max-size 16)
+(defvar mime-situation-examples-file-coding-system nil)
+
+(defun mime-view-read-situation-examples-file (&optional file)
+  (or file
+      (setq file mime-situation-examples-file))
+  (if (and file
+          (file-readable-p file))
+      (with-temp-buffer
+       (insert-file-contents file)
+       (setq mime-situation-examples-file-coding-system
+              (static-cond
+              ((boundp 'buffer-file-coding-system)
+               (symbol-value 'buffer-file-coding-system))
+              ((boundp 'file-coding-system)
+               (symbol-value 'file-coding-system))
+              (t nil))
+             ;; (and (boundp 'buffer-file-coding-system)
+              ;;      buffer-file-coding-system)
+             )
+       (condition-case error
+           (eval-buffer)
+         (error (message "%s is broken: %s" file (cdr error))))
+       ;; format check
+       (condition-case nil
+           (let ((i 0))
+             (while (and (> (length mime-preview-situation-example-list)
+                            mime-preview-situation-example-list-max-size)
+                         (< i 16))
+               (setq mime-preview-situation-example-list
+                     (mime-reduce-situation-examples
+                      mime-preview-situation-example-list))
+               (setq i (1+ i))))
+         (error (setq mime-preview-situation-example-list nil)))
+       ;; (let ((rest mime-preview-situation-example-list))
+       ;;   (while rest
+       ;;     (ctree-set-calist-strictly 'mime-preview-condition
+       ;;                                (caar rest))
+       ;;     (setq rest (cdr rest))))
+       (condition-case nil
+           (let ((i 0))
+             (while (and (> (length mime-acting-situation-example-list)
+                            mime-acting-situation-example-list-max-size)
+                         (< i 16))
+               (setq mime-acting-situation-example-list
+                     (mime-reduce-situation-examples
+                      mime-acting-situation-example-list))
+               (setq i (1+ i))))
+         (error (setq mime-acting-situation-example-list nil))))))
+
+(defun mime-save-situation-examples ()
+  (if (or mime-preview-situation-example-list
+         mime-acting-situation-example-list)
+      (let ((file mime-situation-examples-file)
+           print-length print-level)
+       (with-temp-buffer
+         (insert ";;; " (file-name-nondirectory file) "\n")
+         (insert "\n;; This file is generated automatically by "
+                 mime-view-version "\n\n")
+         (insert ";;; Code:\n\n")
+         (if mime-preview-situation-example-list
+             (pp `(setq mime-preview-situation-example-list
+                        ',mime-preview-situation-example-list)
+                 (current-buffer)))
+         (if mime-acting-situation-example-list
+             (pp `(setq mime-acting-situation-example-list
+                        ',mime-acting-situation-example-list)
+                 (current-buffer)))
+         (insert "\n;;; "
+                 (file-name-nondirectory file)
+                 " ends here.\n")
+         (static-cond
+          ((boundp 'buffer-file-coding-system)
+           (setq buffer-file-coding-system
+                 mime-situation-examples-file-coding-system))
+          ((boundp 'file-coding-system)
+           (setq file-coding-system
+                 mime-situation-examples-file-coding-system)))
+         ;; (setq buffer-file-coding-system
+         ;;       mime-situation-examples-file-coding-system)
+         (setq buffer-file-name file)
+         (save-buffer)))))
+
+(add-hook 'kill-emacs-hook 'mime-save-situation-examples)
+
+(defun mime-reduce-situation-examples (situation-examples)
+  (let ((len (length situation-examples))
+       i ir ic j jr jc ret
+       dest d-i d-j
+       (max-sim 0) sim
+       min-det-ret det-ret
+       min-det-org det-org
+       min-freq freq)
+    (setq i 0
+         ir situation-examples)
+    (while (< i len)
+      (setq ic (car ir)
+           j 0
+           jr situation-examples)
+      (while (< j len)
+       (unless (= i j)
+         (setq jc (car jr))
+         (setq ret (mime-compare-situation-with-example (car ic)(car jc))
+               sim (car ret)
+               det-ret (+ (length (car ic))(length (car jc)))
+               det-org (length (cdr ret))
+               freq (+ (cdr ic)(cdr jc)))
+         (cond ((< max-sim sim)
+                (setq max-sim sim
+                      min-det-ret det-ret
+                      min-det-org det-org
+                      min-freq freq
+                      d-i i
+                      d-j j
+                      dest (cons (cdr ret) freq)))
+               ((= max-sim sim)
+                (cond ((> min-det-ret det-ret)
+                       (setq min-det-ret det-ret
+                             min-det-org det-org
+                             min-freq freq
+                             d-i i
+                             d-j j
+                             dest (cons (cdr ret) freq)))
+                      ((= min-det-ret det-ret)
+                       (cond ((> min-det-org det-org)
+                              (setq min-det-org det-org
+                                    min-freq freq
+                                    d-i i
+                                    d-j j
+                                    dest (cons (cdr ret) freq)))
+                             ((= min-det-org det-org)
+                              (cond ((> min-freq freq)
+                                     (setq min-freq freq
+                                           d-i i
+                                           d-j j
+                                           dest (cons (cdr ret) freq)))))))))))
+       (setq jr (cdr jr)
+             j (1+ j)))
+      (setq ir (cdr ir)
+           i (1+ i)))
+    (if (> d-i d-j)
+       (setq i d-i
+             d-i d-j
+             d-j i))
+    (setq jr (nthcdr (1- d-j) situation-examples))
+    (setcdr jr (cddr jr))
+    (if (= d-i 0)
+       (setq situation-examples
+             (cdr situation-examples))
+      (setq ir (nthcdr (1- d-i) situation-examples))
+      (setcdr ir (cddr ir)))
+    (if (setq ir (assoc (car dest) situation-examples))
+       (progn
+         (setcdr ir (+ (cdr ir)(cdr dest)))
+         situation-examples)
+      (cons dest situation-examples)
+      ;; situation-examples may be modified.
+      )))
 
 
 ;;; @ presentation of preview
@@ -270,21 +518,21 @@ mother-buffer."
 ;;; @@@ predicate function
 ;;;
 
-(defun mime-view-entity-button-visible-p (entity)
-  "Return non-nil if header of ENTITY is visible.
-Please redefine this function if you want to change default setting."
-  (let ((media-type (mime-entity-media-type entity))
-       (media-subtype (mime-entity-media-subtype entity)))
-    (or (not (eq media-type 'application))
-       (and (not (eq media-subtype 'x-selection))
-            (or (not (eq media-subtype 'octet-stream))
-                (let ((mother-entity (mime-entity-parent entity)))
-                  (or (not (eq (mime-entity-media-type mother-entity)
-                               'multipart))
-                      (not (eq (mime-entity-media-subtype mother-entity)
-                               'encrypted)))
-                  )
-                )))))
+;; (defun mime-view-entity-button-visible-p (entity)
+;;   "Return non-nil if header of ENTITY is visible.
+;; Please redefine this function if you want to change default setting."
+;;   (let ((media-type (mime-entity-media-type entity))
+;;         (media-subtype (mime-entity-media-subtype entity)))
+;;     (or (not (eq media-type 'application))
+;;         (and (not (eq media-subtype 'x-selection))
+;;              (or (not (eq media-subtype 'octet-stream))
+;;                  (let ((mother-entity (mime-entity-parent entity)))
+;;                    (or (not (eq (mime-entity-media-type mother-entity)
+;;                                 'multipart))
+;;                        (not (eq (mime-entity-media-subtype mother-entity)
+;;                                 'encrypted)))
+;;                    )
+;;                  )))))
 
 ;;; @@@ entity button generator
 ;;;
@@ -300,11 +548,9 @@ Please redefine this function if you want to change default setting."
                    (if (consp entity-node-id)
                        (mapconcat (function
                                    (lambda (num)
-                                     (format "%s" (1+ num))
-                                     ))
+                                     (format "%s" (1+ num))))
                                   (reverse entity-node-id) ".")
-                     "0"))
-               ))
+                     "0"))))
        (cond (access-type
              (let ((server (assoc "server" params)))
                (setq access-type (cdr access-type))
@@ -313,15 +559,12 @@ Please redefine this function if you want to change default setting."
                            num subject access-type (cdr server))
                (let ((site (cdr (assoc "site" params)))
                      (dir (cdr (assoc "directory" params)))
-                     (url (cdr (assoc "url" params)))
-                     )
+                     (url (cdr (assoc "url" params))))
                  (if url
                      (format "%s %s ([%s] %s)"
                              num subject access-type url)
                    (format "%s %s ([%s] %s:%s)"
-                           num subject access-type site dir))
-                 )))
-           )
+                           num subject access-type site dir))))))
           (t
            (let ((media-type (mime-entity-media-type entity))
                  (media-subtype (mime-entity-media-subtype entity))
@@ -340,10 +583,8 @@ Please redefine this function if you want to change default setting."
                                ""))))
                 (if (>= (+ (current-column)(length rest))(window-width))
                     "\n\t")
-                rest)))
-           )))
-     (function mime-preview-play-current-entity))
-    ))
+                rest))))))
+     (function mime-preview-play-current-entity))))
 
 
 ;;; @@ entity-header
@@ -381,8 +622,7 @@ Each elements are regexp of field-name.")
                                                        field-type field-value)
   (let ((s-field (assq field-type calist)))
     (cond ((null s-field)
-          (cons (cons field-type field-value) calist)
-          )
+          (cons (cons field-type field-value) calist))
          (t calist))))
 
 (define-calist-field-match-method
@@ -433,6 +673,15 @@ Each elements are regexp of field-name.")
  '((body . visible)
    (body-presentation-method . mime-display-text/plain)))
 
+(defvar mime-preview-fill-flowed-text
+  (module-installed-p 'flow-fill)
+  "If non-nil, fill RFC2646 \"flowed\" text.")
+
+(autoload 'fill-flowed "flow-fill")
+
+(defvar mime-preview-inline-fontify t
+  "If non-nil, fontify the inline part.")
+
 (ctree-set-calist-strictly
  'mime-preview-condition
  '((type . nil)
@@ -451,6 +700,20 @@ Each elements are regexp of field-name.")
    (body . visible)
    (body-presentation-method . mime-display-text/richtext)))
 
+(autoload 'mime-display-application/x-postpet "postpet")
+
+(ctree-set-calist-strictly
+ 'mime-preview-condition
+ '((type . application)(subtype . x-postpet)
+   (body . visible)
+   (body-presentation-method . mime-display-application/x-postpet)))
+
+(ctree-set-calist-strictly
+ 'mime-preview-condition
+ '((type . application)(subtype . emacs-lisp)
+   (body . visible)
+   (body-presentation-method . mime-display-application/emacs-lisp)))
+
 (ctree-set-calist-strictly
  'mime-preview-condition
  '((type . text)(subtype . t)
@@ -464,21 +727,38 @@ Each elements are regexp of field-name.")
    (body-presentation-method . mime-display-multipart/alternative)))
 
 (ctree-set-calist-strictly
- 'mime-preview-condition '((type . message)(subtype . partial)
-                          (body-presentation-method
-                           . mime-display-message/partial-button)))
+ 'mime-preview-condition
+ '((type . multipart)(subtype . related)
+   (body . visible)
+   (body-presentation-method . mime-display-multipart/related)))
+
+(ctree-set-calist-strictly
+ 'mime-preview-condition
+ '((type . multipart)(subtype . t)
+   (body . visible)
+   (body-presentation-method . mime-display-multipart/mixed)))
+
+(ctree-set-calist-strictly
+ 'mime-preview-condition
+ '((type . message)(subtype . partial)
+   (body . visible)
+   (body-presentation-method . mime-display-message/partial-button)))
 
 (ctree-set-calist-strictly
- 'mime-preview-condition '((type . message)(subtype . rfc822)
-                          (body-presentation-method . nil)
-                          (childrens-situation (header . visible)
-                                               (entity-button . invisible))))
+ 'mime-preview-condition
+ '((type . message)(subtype . rfc822)
+   (body . visible)
+   (body-presentation-method . mime-display-multipart/mixed)
+   (childrens-situation (header . visible)
+                       (entity-button . invisible))))
 
 (ctree-set-calist-strictly
- 'mime-preview-condition '((type . message)(subtype . news)
-                          (body-presentation-method . nil)
-                          (childrens-situation (header . visible)
-                                               (entity-button . invisible))))
+ 'mime-preview-condition
+ '((type . message)(subtype . news)
+   (body . visible)
+   (body-presentation-method . mime-display-multipart/mixed)
+   (childrens-situation (header . visible)
+                       (entity-button . invisible))))
 
 
 ;;; @@@ entity presentation
@@ -487,59 +767,53 @@ Each elements are regexp of field-name.")
 (defun mime-display-text/plain (entity situation)
   (save-restriction
     (narrow-to-region (point-max)(point-max))
-    (mime-insert-text-content entity)
+    (condition-case nil
+       (if (and mime-preview-inline-fontify
+                (mime-entity-filename entity)) ;should be an attachment.
+           (mime-view-insert-fontified-text-content entity situation)
+         (mime-view-insert-text-content entity situation))
+      (error (progn
+              (message "Can't decode current entity.")
+              (sit-for 1))))
     (run-hooks 'mime-text-decode-hook)
     (goto-char (point-max))
     (if (not (eq (char-after (1- (point))) ?\n))
-       (insert "\n")
-      )
+       (insert "\n"))
+    (if (and mime-preview-fill-flowed-text
+            (equal (cdr (assoc "format" situation)) "flowed"))
+       (fill-flowed))
     (mime-add-url-buttons)
-    (run-hooks 'mime-display-text/plain-hook)
-    ))
+    (run-hooks 'mime-display-text/plain-hook)))
 
 (defun mime-display-text/richtext (entity situation)
   (save-restriction
     (narrow-to-region (point-max)(point-max))
-    (mime-insert-text-content entity)
+    (mime-view-insert-text-content entity situation)
     (run-hooks 'mime-text-decode-hook)
     (let ((beg (point-min)))
       (remove-text-properties beg (point-max) '(face nil))
-      (richtext-decode beg (point-max))
-      )))
+      (richtext-decode beg (point-max)))))
 
 (defun mime-display-text/enriched (entity situation)
   (save-restriction
     (narrow-to-region (point-max)(point-max))
-    (mime-insert-text-content entity)
+    (mime-view-insert-text-content entity situation)
     (run-hooks 'mime-text-decode-hook)
     (let ((beg (point-min)))
       (remove-text-properties beg (point-max) '(face nil))
-      (enriched-decode beg (point-max))
-      )))
+      (enriched-decode beg (point-max)))))
 
 (defvar mime-view-announcement-for-message/partial
-  (if (and (>= emacs-major-version 19) window-system)
-      "\
-\[[ This is message/partial style split message. ]]
-\[[ Please press `v' key in this buffer          ]]
-\[[ or click here by mouse button-2.             ]]"
-    "\
-\[[ This is message/partial style split message. ]]
-\[[ Please press `v' key in this buffer.         ]]"
-    ))
+  "This is message/partial style split message.")
 
 (defun mime-display-message/partial-button (&optional entity situation)
   (save-restriction
     (goto-char (point-max))
     (if (not (search-backward "\n\n" nil t))
-       (insert "\n")
-      )
+       (insert "\n"))
     (goto-char (point-max))
-    (narrow-to-region (point-max)(point-max))
-    (insert mime-view-announcement-for-message/partial)
-    (mime-add-button (point-min)(point-max)
-                    #'mime-preview-play-current-entity)
-    ))
+    (mime-insert-button mime-view-announcement-for-message/partial
+                       #'mime-preview-play-current-entity)))
 
 (defun mime-display-multipart/mixed (entity situation)
   (let ((children (mime-entity-children entity))
@@ -551,8 +825,7 @@ Each elements are regexp of field-name.")
              (cons original-major-mode-cell default-situation)))
     (while children
       (mime-display-entity (car children) nil default-situation)
-      (setq children (cdr children))
-      )))
+      (setq children (cdr children)))))
 
 (defcustom mime-view-type-subtype-score-alist
   '(((text . enriched) . 3)
@@ -586,11 +859,8 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
          (mapcar (function
                   (lambda (child)
                     (let ((situation
-                           (or (ctree-match-calist
-                                mime-preview-condition
-                                (append (mime-entity-situation child)
-                                        default-situation))
-                               default-situation)))
+                           (mime-find-entity-preview-situation
+                            child default-situation)))
                       (if (cdr (assq 'body-presentation-method situation))
                           (let ((score
                                  (cdr
@@ -604,15 +874,12 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
                                        mime-view-type-subtype-score-alist)
                                       (assq
                                        t
-                                       mime-view-type-subtype-score-alist)
-                                      ))))
+                                       mime-view-type-subtype-score-alist)))))
                             (if (> score max-score)
                                 (setq p i
-                                      max-score score)
-                              )))
+                                      max-score score))))
                       (setq i (1+ i))
-                      situation)
-                    ))
+                      situation)))
                  children))
     (setq i 0)
     (while children
@@ -620,13 +887,129 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
            (situation (car situations)))
        (mime-display-entity child (if (= i p)
                                       situation
-                                    (del-alist 'body-presentation-method
-                                               (copy-alist situation))))
-       )
+                                    (put-alist 'body 'invisible
+                                               (copy-alist situation)))))
       (setq children (cdr children)
            situations (cdr situations)
-           i (1+ i))
-      )))
+           i (1+ i)))))
+
+(defun mime-display-multipart/related (entity situation)
+  (let* ((param-start (mime-parse-msg-id
+                      (std11-lexical-analyze
+                       (cdr (assoc "start"
+                                   (mime-content-type-parameters
+                                    (mime-entity-content-type entity)))))))
+        (start (or (and param-start (mime-find-entity-from-content-id
+                                     param-start
+                                     entity))
+                   (car (mime-entity-children entity))))
+        (original-major-mode-cell (assq 'major-mode situation))
+        (default-situation (cdr (assq 'childrens-situation situation))))
+    (when start
+      (if original-major-mode-cell
+         (setq default-situation
+               (cons original-major-mode-cell default-situation)))
+      (mime-display-entity start nil default-situation))))
+
+(defun mime-view-entity-content (entity situation)
+  (mime-decode-string
+   (mime-entity-body entity)
+   (mime-view-guess-encoding entity situation)))
+  
+(defun mime-view-insert-text-content (entity situation)
+  (let (compression-info)
+    (cond
+     ((and (mime-entity-filename entity)
+          (featurep 'jka-compr)
+          (jka-compr-installed-p)
+          (setq compression-info (jka-compr-get-compression-info
+                                  (mime-entity-filename entity))))
+      (insert
+       (mime-view-filter-text-content
+       (mime-view-entity-content entity situation)
+       (jka-compr-info-uncompress-program compression-info)
+       (jka-compr-info-uncompress-args compression-info))))
+     ((or (assq '*encoding situation)  ;should be specified by user
+         (assq '*charset situation))   ;should be specified by user
+      (insert
+       (decode-mime-charset-string
+       (mime-view-entity-content entity situation)
+       (mime-view-guess-charset entity situation)
+       'CRLF)))
+     (t
+      (mime-insert-text-content entity)))))
+
+;;; stolen (and renamed) from `mime-display-gzipped' of EMY 1.13.
+(defun mime-view-filter-text-content (content program args)
+  (with-temp-buffer
+    (static-cond
+     ((featurep 'xemacs)
+      (insert content)
+      (apply #'binary-to-text-funcall
+            mime-view-automatic-conversion
+            #'call-process-region (point-min)(point-max)
+            program t t args))
+     (t
+      (if (not (multibyte-string-p content))
+         (set-buffer-multibyte nil))
+      (insert content)
+      (apply #'binary-funcall
+            #'call-process-region (point-min)(point-max)
+            program t t args)
+      (set-buffer-multibyte t)
+      (decode-coding-region (point-min)(point-max)
+                           mime-view-automatic-conversion)))
+    (buffer-string)))
+
+;;; stolen (and renamed) from mm-view.el.
+(defun mime-view-insert-fontified-text-content (entity situation
+                                                      &optional mode)
+  ;; XEmacs @#$@ version of font-lock refuses to fully turn itself
+  ;; on for buffers whose name begins with " ".  That's why we use
+  ;; save-current-buffer/get-buffer-create rather than
+  ;; with-temp-buffer.
+  (let ((buffer (generate-new-buffer "*fontification*"))
+       filename)
+    (unwind-protect
+       (progn
+         (save-current-buffer
+           (set-buffer buffer)
+           (buffer-disable-undo)
+           (kill-all-local-variables)
+           (mime-view-insert-text-content entity situation)
+           (require 'font-lock)
+           (let ((font-lock-maximum-size nil)
+                 ;; Disable support modes, e.g., jit-lock, lazy-lock, etc.
+                 (font-lock-mode-hook nil)
+                 (font-lock-support-mode nil)
+                 ;; I find font-lock a bit too verbose.
+                 (font-lock-verbose nil))
+             (cond (mode
+                    (funcall mode))
+                   ((setq filename (mime-entity-filename entity))
+                    (let ((buffer-file-name
+                           (expand-file-name (file-name-nondirectory filename)
+                                             temporary-file-directory)))
+                      (set-auto-mode))))
+             ;; The mode function might have already turned on font-lock.
+             (unless (symbol-value 'font-lock-mode)
+               (font-lock-fontify-buffer)))
+           ;; By default, XEmacs font-lock uses non-duplicable text
+           ;; properties.  This code forces all the text properties
+           ;; to be copied along with the text.
+           (static-when (fboundp 'extent-list)
+             (map-extents (lambda (ext ignored)
+                            (set-extent-property ext 'duplicable t)
+                            nil)
+                          nil nil nil nil nil 'text-prop)))
+         (insert-buffer-substring buffer))
+      (kill-buffer buffer))))
+
+(defun mime-display-application/emacs-lisp (entity situation)
+  (save-restriction
+    (narrow-to-region (point-max)(point-max))
+    (mime-view-insert-fontified-text-content entity situation 'emacs-lisp-mode)
+    (run-hooks 'mime-text-decode-hook 'mime-display-text/plain-hook)))
 
 
 ;;; @ acting-condition
@@ -635,41 +1018,45 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
 (defvar mime-acting-condition nil
   "Condition-tree about how to process entity.")
 
-(if (file-readable-p mailcap-file)
-    (let ((entries (mailcap-parse-file)))
-      (while entries
-       (let ((entry (car entries))
-             view print shared)
-         (while entry
-           (let* ((field (car entry))
-                  (field-type (car field)))
-             (cond ((eq field-type 'view)  (setq view field))
-                   ((eq field-type 'print) (setq print field))
-                   ((memq field-type '(compose composetyped edit)))
-                   (t (setq shared (cons field shared))))
-             )
-           (setq entry (cdr entry))
+(defun mime-view-read-mailcap-files (&optional files)
+  (or files
+      (setq files mime-view-mailcap-files))
+  (let (entries file)
+    (while files
+      (setq file (car files))
+      (if (file-readable-p file)
+         (setq entries (append entries (mime-parse-mailcap-file file))))
+      (setq files (cdr files)))
+    (while entries
+      (let ((entry (car entries))
+           view print shared)
+       (while entry
+         (let* ((field (car entry))
+                (field-type (car field)))
+           (cond ((eq field-type 'view)  (setq view field))
+                 ((eq field-type 'print) (setq print field))
+                 ((memq field-type '(compose composetyped edit)))
+                 (t (setq shared (cons field shared))))
            )
-         (setq shared (nreverse shared))
-         (ctree-set-calist-with-default
-          'mime-acting-condition
-          (append shared (list '(mode . "play")(cons 'method (cdr view)))))
-         (if print
-             (ctree-set-calist-with-default
-              'mime-acting-condition
-              (append shared
-                      (list '(mode . "print")(cons 'method (cdr view))))
-              ))
-         )
-       (setq entries (cdr entries))
-       )))
+         (setq entry (cdr entry)))
+       (setq shared (nreverse shared))
+       (ctree-set-calist-with-default
+        'mime-acting-condition
+        (append shared (list '(mode . "play")(cons 'method (cdr view)))))
+       (if print
+           (ctree-set-calist-with-default
+            'mime-acting-condition
+            (append shared
+                    (list '(mode . "print")(cons 'method (cdr view)))))))
+      (setq entries (cdr entries)))))
+
+(mime-view-read-mailcap-files)
 
 (ctree-set-calist-strictly
  'mime-acting-condition
  '((type . application)(subtype . octet-stream)
    (mode . "play")
-   (method . mime-detect-content)
-   ))
+   (method . mime-detect-content)))
 
 (ctree-set-calist-with-default
  'mime-acting-condition
@@ -679,44 +1066,37 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
 (ctree-set-calist-strictly
  'mime-acting-condition
  '((type . text)(subtype . x-rot13-47)(mode . "play")
-   (method . mime-view-caesar)
-   ))
+   (method . mime-view-caesar)))
 (ctree-set-calist-strictly
  'mime-acting-condition
  '((type . text)(subtype . x-rot13-47-48)(mode . "play")
-   (method . mime-view-caesar)
-   ))
+   (method . mime-view-caesar)))
 
 (ctree-set-calist-strictly
  'mime-acting-condition
  '((type . message)(subtype . rfc822)(mode . "play")
-   (method . mime-view-message/rfc822)
-   ))
+   (method . mime-view-message/rfc822)))
 (ctree-set-calist-strictly
  'mime-acting-condition
  '((type . message)(subtype . partial)(mode . "play")
-   (method . mime-store-message/partial-piece)
-   ))
+   (method . mime-store-message/partial-piece)))
 
 (ctree-set-calist-strictly
  'mime-acting-condition
  '((type . message)(subtype . external-body)
    ("access-type" . "anon-ftp")
-   (method . mime-view-message/external-anon-ftp)
-   ))
+   (method . mime-view-message/external-anon-ftp)))
 
 (ctree-set-calist-strictly
  'mime-acting-condition
  '((type . message)(subtype . external-body)
    ("access-type" . "url")
-   (method . mime-view-message/external-url)
-   ))
+   (method . mime-view-message/external-url)))
 
 (ctree-set-calist-strictly
  'mime-acting-condition
  '((type . application)(subtype . octet-stream)
-   (method . mime-save-content)
-   ))
+   (method . mime-save-content)))
 
 
 ;;; @ quitting method
@@ -752,115 +1132,109 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
   (or preview-buffer
       (setq preview-buffer (current-buffer)))
   (let* (e nb ne nhb nbb)
-    (mime-goto-header-start-point entity)
     (in-calist-package 'mime-view)
     (or situation
        (setq situation
-             (or (ctree-match-calist mime-preview-condition
-                                     (append (mime-entity-situation entity)
-                                             default-situation))
-                 default-situation)))
+             (mime-find-entity-preview-situation entity default-situation)))
     (let ((button-is-invisible
-          (eq (cdr (assq 'entity-button situation)) 'invisible))
+          (eq (cdr (or (assq '*entity-button situation)
+                       (assq 'entity-button situation)))
+              'invisible))
          (header-is-visible
-          (eq (cdr (assq 'header situation)) 'visible))
-         (header-presentation-method
-          (or (cdr (assq 'header-presentation-method situation))
-              (cdr (assq (cdr (assq 'major-mode situation))
-                         mime-header-presentation-method-alist))))
-         (body-presentation-method
-          (cdr (assq 'body-presentation-method situation)))
+          (eq (cdr (or (assq '*header situation)
+                       (assq 'header situation)))
+              'visible))
+         (body-is-visible
+          (eq (cdr (or (assq '*body situation)
+                       (assq 'body situation)))
+              'visible))
          (children (mime-entity-children entity)))
       (set-buffer preview-buffer)
       (setq nb (point))
       (narrow-to-region nb nb)
       (or button-is-invisible
-         (if (mime-view-entity-button-visible-p entity)
-             (mime-view-insert-entity-button entity)
-           ))
-      (when header-is-visible
-       (setq nhb (point))
-       (if header-presentation-method
-           (funcall header-presentation-method entity situation)
-         (mime-insert-header entity
-                             mime-view-ignored-field-list
-                             mime-view-visible-field-list))
-       (run-hooks 'mime-display-header-hook)
-       (put-text-property nhb (point-max) 'mime-view-entity-header entity)
-       (goto-char (point-max))
-       (insert "\n")
-       )
+          ;; (if (mime-view-entity-button-visible-p entity)
+         (mime-view-insert-entity-button entity)
+          ;;   )
+         )
+      (if header-is-visible
+         (let ((header-presentation-method
+                (or (cdr (assq 'header-presentation-method situation))
+                    (cdr (assq (cdr (assq 'major-mode situation))
+                               mime-header-presentation-method-alist)))))
+           (setq nhb (point))
+           (if header-presentation-method
+               (funcall header-presentation-method entity situation)
+             (mime-insert-header entity
+                                 mime-view-ignored-field-list
+                                 mime-view-visible-field-list))
+           (mime-add-url-buttons)
+           (run-hooks 'mime-display-header-hook)
+           (put-text-property nhb (point-max) 'mime-view-entity-header entity)
+           (goto-char (point-max))
+           (insert "\n")))
       (setq nbb (point))
-      (cond (children)
-            ((functionp body-presentation-method)
-            (funcall body-presentation-method entity situation)
-            )
-           (t
-            (when button-is-invisible
-              (goto-char (point-max))
-              (mime-view-insert-entity-button entity)
-              )
-            (or header-is-visible
-                (progn
-                  (goto-char (point-max))
-                  (insert "\n")
-                  ))
-            ))
+      (unless children
+       (if body-is-visible
+           (let ((body-presentation-method
+                  (cdr (assq 'body-presentation-method situation))))
+             (if (functionp body-presentation-method)
+                 (funcall body-presentation-method entity situation)
+               (mime-display-text/plain entity situation)))
+         (when button-is-invisible
+           (goto-char (point-max))
+           (mime-view-insert-entity-button entity))
+         (unless header-is-visible
+           (goto-char (point-max))
+           (insert "\n"))))
       (setq ne (point-max))
       (widen)
       (put-text-property nb ne 'mime-view-entity entity)
       (put-text-property nb ne 'mime-view-situation situation)
       (put-text-property nbb ne 'mime-view-entity-body entity)
       (goto-char ne)
-      (if children
-         (if (functionp body-presentation-method)
-             (funcall body-presentation-method entity situation)
-           (mime-display-multipart/mixed entity situation)
-           ))
-      )))
+      (if (and children body-is-visible)
+         (let ((body-presentation-method
+                (cdr (assq 'body-presentation-method situation))))
+           (if (functionp body-presentation-method)
+               (funcall body-presentation-method entity situation)
+             (mime-display-multipart/mixed entity situation)))))))
 
 
 ;;; @ MIME viewer mode
 ;;;
 
-(defconst mime-view-menu-title "MIME-View")
-(defconst mime-view-menu-list
-  '((up                 "Move to upper entity"    mime-preview-move-to-upper)
-    (previous   "Move to previous entity" mime-preview-move-to-previous)
-    (next       "Move to next entity"     mime-preview-move-to-next)
-    (scroll-down "Scroll-down"             mime-preview-scroll-down-entity)
-    (scroll-up  "Scroll-up"               mime-preview-scroll-up-entity)
-    (play       "Play current entity"     mime-preview-play-current-entity)
-    (extract    "Extract current entity"  mime-preview-extract-current-entity)
-    (print      "Print current entity"    mime-preview-print-current-entity)
-    )
+(defconst mime-view-popup-menu-list
+  '("MIME-View"
+    ["Move to upper entity" mime-preview-move-to-upper]
+    ["Move to previous entity" mime-preview-move-to-previous]
+    ["Move to next entity" mime-preview-move-to-next]
+    ["Scroll-down" mime-preview-scroll-down-entity]
+    ["Scroll-up" mime-preview-scroll-up-entity]
+    ["Play current entity" mime-preview-play-current-entity]
+    ["Extract current entity" mime-preview-extract-current-entity]
+    ["Print current entity" mime-preview-print-current-entity])
   "Menu for MIME Viewer")
 
-(cond ((featurep 'xemacs)
-       (defvar mime-view-xemacs-popup-menu
-        (cons mime-view-menu-title
-              (mapcar (function
-                       (lambda (item)
-                         (vector (nth 1 item)(nth 2 item) t)
-                         ))
-                      mime-view-menu-list)))
-       (defun mime-view-xemacs-popup-menu (event)
-        "Popup the menu in the MIME Viewer buffer"
-        (interactive "e")
-        (select-window (event-window event))
-        (set-buffer (event-buffer event))
-        (popup-menu 'mime-view-xemacs-popup-menu))
-       (defvar mouse-button-2 'button2)
-       )
-      (t
-       (defvar mouse-button-2 [mouse-2])
-       ))
-
+(defun mime-view-popup-menu (event)
+  "Popup the menu in the MIME Viewer buffer"
+  (interactive "@e")
+  (mime-popup-menu-popup mime-view-popup-menu-list event))
+
+;;; The current local map is taken precendence over `widget-keymap',
+;;; because GNU Emacs' widget implementation doesn't set `local-map' property.
+;;;  So we need to specify derivation.
+(defvar widget-keymap)
+(defun mime-view-maybe-inherit-widget-keymap ()
+  (when (boundp 'widget-keymap)
+    (set-keymap-parent (current-local-map) widget-keymap)))
+
+(add-hook 'mime-view-mode-hook 'mime-view-maybe-inherit-widget-keymap)
+         
 (defun mime-view-define-keymap (&optional default)
   (let ((mime-view-mode-map (if (keymapp default)
                                (copy-keymap default)
-                             (make-sparse-keymap)
-                             )))
+                             (make-sparse-keymap))))
     (define-key mime-view-mode-map
       "u"        (function mime-preview-move-to-upper))
     (define-key mime-view-mode-map
@@ -887,6 +1261,28 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
       "e"        (function mime-preview-extract-current-entity))
     (define-key mime-view-mode-map
       "\C-c\C-p" (function mime-preview-print-current-entity))
+
+    (define-key mime-view-mode-map
+      "\C-c\C-t\C-f" (function mime-preview-toggle-header))
+    (define-key mime-view-mode-map
+      "\C-c\C-th" (function mime-preview-toggle-header))
+    (define-key mime-view-mode-map
+      "\C-c\C-t\C-c" (function mime-preview-toggle-content))
+
+    (define-key mime-view-mode-map
+      "\C-c\C-v\C-f" (function mime-preview-show-header))
+    (define-key mime-view-mode-map
+      "\C-c\C-vh" (function mime-preview-show-header))
+    (define-key mime-view-mode-map
+      "\C-c\C-v\C-c" (function mime-preview-show-content))
+
+    (define-key mime-view-mode-map
+      "\C-c\C-d\C-f" (function mime-preview-hide-header))
+    (define-key mime-view-mode-map
+      "\C-c\C-dh" (function mime-preview-hide-header))
+    (define-key mime-view-mode-map
+      "\C-c\C-d\C-c" (function mime-preview-hide-content))
+
     (define-key mime-view-mode-map
       "a"        (function mime-preview-follow-current-entity))
     (define-key mime-view-mode-map
@@ -906,38 +1302,17 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
     (define-key mime-view-mode-map
       [backspace] (function mime-preview-scroll-down-entity))
     (if (functionp default)
-       (cond ((featurep 'xemacs)
-              (set-keymap-default-binding mime-view-mode-map default)
-              )
-             (t
-              (setq mime-view-mode-map
-                    (append mime-view-mode-map (list (cons t default))))
-              )))
-    (if mouse-button-2
-       (define-key mime-view-mode-map
-         mouse-button-2 (function mime-button-dispatcher))
-      )
-    (cond ((featurep 'xemacs)
-          (define-key mime-view-mode-map
-            mouse-button-3 (function mime-view-xemacs-popup-menu))
-          )
-         ((>= emacs-major-version 19)
-          (define-key mime-view-mode-map [menu-bar mime-view]
-            (cons mime-view-menu-title
-                  (make-sparse-keymap mime-view-menu-title)))
-          (mapcar (function
-                   (lambda (item)
-                     (define-key mime-view-mode-map
-                       (vector 'menu-bar 'mime-view (car item))
-                       (cons (nth 1 item)(nth 2 item))
-                       )
-                     ))
-                  (reverse mime-view-menu-list)
-                  )
-          ))
-    (use-local-map mime-view-mode-map)
-    (run-hooks 'mime-view-define-keymap-hook)
-    ))
+       (if (featurep 'xemacs)
+           (set-keymap-default-binding mime-view-mode-map default)
+         (setq mime-view-mode-map
+               (append mime-view-mode-map (list (cons t default))))))
+    (define-key mime-view-mode-map
+      [down-mouse-3] (function mime-view-popup-menu))
+    ;; (run-hooks 'mime-view-define-keymap-hook)
+    mime-view-mode-map))
+
+(defvar mime-view-mode-default-map (mime-view-define-keymap))
+
 
 (defsubst mime-maybe-hide-echo-buffer ()
   "Clear mime-echo buffer and delete window for it."
@@ -948,17 +1323,15 @@ MEDIA-TYPE must be (TYPE . SUBTYPE), TYPE or t.  t means default."
          (erase-buffer)
          (let ((win (get-buffer-window buf)))
            (if win
-               (delete-window win)
-             ))
-         (bury-buffer buf)
-         ))))
+               (delete-window win)))
+         (bury-buffer buf)))))
 
 (defvar mime-view-redisplay nil)
 
 ;;;###autoload
 (defun mime-display-message (message &optional preview-buffer
                                     mother default-keymap-or-function
-                                    original-major-mode)
+                                    original-major-mode keymap)
   "View MESSAGE in MIME-View mode.
 
 Optional argument PREVIEW-BUFFER specifies the buffer of the
@@ -969,23 +1342,27 @@ Optional argument MOTHER specifies mother-buffer of the preview-buffer.
 Optional argument DEFAULT-KEYMAP-OR-FUNCTION is nil, keymap or
 function.  If it is a keymap, keymap of MIME-View mode will be added
 to it.  If it is a function, it will be bound as default binding of
-keymap of MIME-View mode."
+keymap of MIME-View mode.
+
+Optional argument ORIGINAL-MAJOR-MODE is major-mode of representation
+buffer of MESSAGE.  If it is nil, current `major-mode' is used.
+
+Optional argument KEYMAP is keymap of MIME-View mode.  If it is
+non-nil, DEFAULT-KEYMAP-OR-FUNCTION is ignored.  If it is nil,
+`mime-view-mode-default-map' is used."
   (mime-maybe-hide-echo-buffer)
   (let ((win-conf (current-window-configuration)))
     (or preview-buffer
        (setq preview-buffer
              (concat "*Preview-" (mime-entity-name message) "*")))
     (or original-major-mode
-       (setq original-major-mode
-             (with-current-buffer (mime-entity-header-buffer message)
-               major-mode)))
+       (setq original-major-mode major-mode))
     (let ((inhibit-read-only t))
       (set-buffer (get-buffer-create preview-buffer))
       (widen)
       (erase-buffer)
       (if mother
-         (setq mime-mother-buffer mother)
-       )
+         (setq mime-mother-buffer mother))
       (setq mime-preview-original-window-configuration win-conf)
       (setq major-mode 'mime-view-mode)
       (setq mode-name "MIME-View")
@@ -994,14 +1371,17 @@ keymap of MIME-View mode."
                             (header . visible)
                             (major-mode . ,original-major-mode))
                           preview-buffer)
-      (mime-view-define-keymap default-keymap-or-function)
+      (use-local-map
+       (or keymap
+          (if default-keymap-or-function
+              (mime-view-define-keymap default-keymap-or-function)
+            mime-view-mode-default-map)))
       (let ((point
             (next-single-property-change (point-min) 'mime-view-entity)))
        (if point
            (goto-char point)
          (goto-char (point-min))
-         (search-forward "\n\n" nil t)
-         ))
+         (search-forward "\n\n" nil t)))
       (run-hooks 'mime-view-mode-hook)
       (set-buffer-modified-p nil)
       (setq buffer-read-only t)
@@ -1029,11 +1409,9 @@ message.  It must be nil, `binary' or `cooked'.  If it is nil,
            (save-excursion
              (set-buffer raw-buffer)
              (cdr (or (assq major-mode mime-raw-representation-type-alist)
-                      (assq t mime-raw-representation-type-alist)))
-             )))
+                      (assq t mime-raw-representation-type-alist))))))
   (if (eq representation-type 'binary)
-      (setq representation-type 'buffer)
-    )
+      (setq representation-type 'buffer))
   (setq preview-buffer (mime-display-message
                        (mime-open-entity representation-type raw-buffer)
                        preview-buffer mother default-keymap-or-function))
@@ -1044,8 +1422,7 @@ message.  It must be nil, `binary' or `cooked'.  If it is nil,
          (let ((m-win (and mother (get-buffer-window mother))))
            (if m-win
                (set-window-buffer m-win preview-buffer)
-             (switch-to-buffer preview-buffer)
-             ))))))
+             (switch-to-buffer preview-buffer)))))))
 
 (defun mime-view-mode (&optional mother ctl encoding
                                 raw-buffer preview-buffer
@@ -1081,19 +1458,67 @@ button-2        Move to point under the mouse cursor
              (or (assq major-mode mime-raw-representation-type-alist)
                  (assq t mime-raw-representation-type-alist)))))
        (if (eq type 'binary)
-           (setq type 'buffer)
-         )
+           (setq type 'buffer))
        (setq mime-message-structure (mime-open-entity type raw-buffer))
        (or (mime-entity-content-type mime-message-structure)
-           (mime-entity-set-content-type-internal
-            mime-message-structure ctl))
-       )
+           (mime-entity-set-content-type mime-message-structure ctl)))
       (or (mime-entity-encoding mime-message-structure)
-         (mime-entity-set-encoding-internal mime-message-structure encoding))
-      ))
+         (mime-entity-set-encoding mime-message-structure encoding))))
   (mime-display-message mime-message-structure preview-buffer
-                       mother default-keymap-or-function)
-  )
+                       mother default-keymap-or-function))
+
+
+;;; @@ utility
+;;;
+
+(defun mime-preview-find-boundary-info (&optional with-children)
+  "Return boundary information of current part.
+If WITH-CHILDREN, refer boundary surrounding current part and its branches."
+  (let (entity
+       p-beg p-end
+       entity-node-id len)
+    (while (and
+           (null (setq entity
+                       (get-text-property (point) 'mime-view-entity)))
+           (> (point) (point-min)))
+      (backward-char))
+    (setq p-beg (previous-single-property-change (point) 'mime-view-entity))
+    (setq entity-node-id (and entity (mime-entity-node-id entity)))
+    (setq len (length entity-node-id))
+    (cond ((null p-beg)
+          (setq p-beg
+                (if (eq (next-single-property-change (point-min)
+                                                     'mime-view-entity)
+                        (point))
+                    (point)
+                  (point-min))))
+         ((eq (next-single-property-change p-beg 'mime-view-entity)
+              (point))
+          (setq p-beg (point))))
+    (setq p-end (next-single-property-change p-beg 'mime-view-entity))
+    (cond ((null p-end)
+          (setq p-end (point-max)))
+         ((null entity-node-id)
+          (setq p-end (point-max)))
+         (with-children
+          (save-excursion
+            (catch 'tag
+              (let (e i)
+                (while (setq e
+                             (next-single-property-change
+                              (point) 'mime-view-entity))
+                  (goto-char e)
+                  (let ((rc (mime-entity-node-id
+                             (get-text-property (point)
+                                                'mime-view-entity))))
+                    (or (and (>= (setq i (- (length rc) len)) 0)
+                             (equal entity-node-id (nthcdr i rc)))
+                        (throw 'tag nil)))
+                  (setq p-end (or (next-single-property-change
+                                   (point) 'mime-view-entity)
+                                  (point-max)))))
+              (setq p-end (point-max))))))
+    (vector p-beg p-end entity)))
 
 
 ;;; @@ playing
@@ -1108,8 +1533,7 @@ It decodes current entity to call internal or external method as
 \"extract\" mode.  The method is selected from variable
 `mime-acting-condition'."
   (interactive "P")
-  (mime-preview-play-current-entity ignore-examples "extract")
-  )
+  (mime-preview-play-current-entity ignore-examples "extract"))
 
 (defun mime-preview-print-current-entity (&optional ignore-examples)
   "Print current entity (maybe).
@@ -1117,8 +1541,7 @@ It decodes current entity to call internal or external method as
 \"print\" mode.  The method is selected from variable
 `mime-acting-condition'."
   (interactive "P")
-  (mime-preview-play-current-entity ignore-examples "print")
-  )
+  (mime-preview-play-current-entity ignore-examples "print"))
 
 
 ;;; @@ following
@@ -1129,144 +1552,73 @@ It decodes current entity to call internal or external method as
 It calls following-method selected from variable
 `mime-preview-following-method-alist'."
   (interactive)
-  (let (entity)
-    (while (null (setq entity
-                      (get-text-property (point) 'mime-view-entity)))
-      (backward-char)
-      )
-    (let* ((p-beg
-           (previous-single-property-change (point) 'mime-view-entity))
-          p-end
-          ph-end
-          (entity-node-id (mime-entity-node-id entity))
-          (len (length entity-node-id))
-          )
-      (cond ((null p-beg)
-            (setq p-beg
-                  (if (eq (next-single-property-change (point-min)
-                                                       'mime-view-entity)
-                          (point))
-                      (point)
-                    (point-min)))
-            )
-           ((eq (next-single-property-change p-beg 'mime-view-entity)
-                (point))
-            (setq p-beg (point))
-            ))
-      (setq p-end (next-single-property-change p-beg 'mime-view-entity))
-      (cond ((null p-end)
-            (setq p-end (point-max))
-            )
-           ((null entity-node-id)
-            (setq p-end (point-max))
-            )
-           (t
-            (save-excursion
-              (goto-char p-end)
-              (catch 'tag
-                (let (e)
-                  (while (setq e
-                               (next-single-property-change
-                                (point) 'mime-view-entity))
-                    (goto-char e)
-                    (let ((rc (mime-entity-node-id
-                               (get-text-property (point)
-                                                  'mime-view-entity))))
-                      (or (equal entity-node-id
-                                 (nthcdr (- (length rc) len) rc))
-                          (throw 'tag nil)
-                          ))
-                    (setq p-end e)
-                    ))
-                (setq p-end (point-max))
-                ))
-            ))
-      (setq ph-end
-           (previous-single-property-change p-end 'mime-view-entity-header))
-      (if (or (null ph-end)
-             (< ph-end p-beg))
-         (setq ph-end p-beg)
-       )
-      (let* ((mode (mime-preview-original-major-mode 'recursive))
-            (new-name
-             (format "%s-%s" (buffer-name) (reverse entity-node-id)))
-            new-buf
-            (the-buf (current-buffer))
-            fields)
-       (save-excursion
-         (set-buffer (setq new-buf (get-buffer-create new-name)))
-         (erase-buffer)
-         (insert-buffer-substring the-buf ph-end p-end)
-         (when (= ph-end p-beg)
-           (goto-char (point-min))
-           (insert ?\n))
-         (goto-char (point-min))
-          (let ((current-entity
-                (if (and (eq (mime-entity-media-type entity) 'message)
-                         (eq (mime-entity-media-subtype entity) 'rfc822))
-                    (mime-entity-children entity)
-                  entity))
-               str)
-           (while (and current-entity
-                       (progn
-                         (setq str
-                               (with-current-buffer
-                                   (mime-entity-header-buffer current-entity)
-                                 (save-restriction
-                                   (narrow-to-region
-                                    (mime-entity-header-start-point
-                                     current-entity)
-                                    (mime-entity-header-end-point
-                                     current-entity))
-                                   (std11-header-string-except
-                                    (concat
-                                     "^"
-                                     (apply (function regexp-or) fields)
-                                     ":") ""))))
-                         (if (and (eq (mime-entity-media-type
-                                       current-entity) 'message)
-                                  (eq (mime-entity-media-subtype
-                                       current-entity) 'rfc822))
-                             nil
-                           (if str
-                               (insert str)
-                             )
-                           t)))
-             (setq fields (std11-collect-field-names)
-                   current-entity (mime-entity-parent current-entity))
-             )
-           )
-         (let ((rest mime-view-following-required-fields-list)
-               field-name ret)
-           (while rest
-             (setq field-name (car rest))
-             (or (std11-field-body field-name)
-                 (progn
-                   (save-excursion
-                     (set-buffer the-buf)
-                     (setq ret
-                           (when mime-mother-buffer
-                             (set-buffer mime-mother-buffer)
-                             (mime-entity-fetch-field
-                              (get-text-property (point)
-                                                 'mime-view-entity)
-                              field-name))))
-                   (if ret
-                       (insert (concat field-name ": " ret "\n"))
-                     )))
-             (setq rest (cdr rest))
-             ))
-         (mime-decode-header-in-buffer)
-         )
-       (let ((f (cdr (assq mode mime-preview-following-method-alist))))
-         (if (functionp f)
-             (funcall f new-buf)
-           (message
-            (format
-             "Sorry, following method for %s is not implemented yet."
-             mode))
-           ))
-       ))))
+  (let* ((boundary-info (mime-preview-find-boundary-info t))
+        (p-beg (aref boundary-info 0))
+        (p-end (aref boundary-info 1))
+        (entity (aref boundary-info 2))
+        pb-beg)
+    (if (or (get-text-property p-beg 'mime-view-entity-body)
+           (null entity))
+       (setq pb-beg p-beg)
+      (setq pb-beg
+           (next-single-property-change
+            p-beg 'mime-view-entity-body nil
+            (or (next-single-property-change p-beg 'mime-view-entity)
+                p-end))))
+    (let* ((mode (mime-preview-original-major-mode 'recursive))
+          (entity-node-id (and entity (mime-entity-node-id entity)))
+          (new-name
+           (format "%s-%s" (buffer-name) (reverse entity-node-id)))
+          new-buf
+          (the-buf (current-buffer))
+          fields)
+      (save-excursion
+       (set-buffer (setq new-buf (get-buffer-create new-name)))
+       (erase-buffer)
+       (insert ?\n)
+       (insert-buffer-substring the-buf pb-beg p-end)
+       (goto-char (point-min))
+       (let ((current-entity
+              (if (and entity
+                       (eq (mime-entity-media-type entity) 'message)
+                       (eq (mime-entity-media-subtype entity) 'rfc822))
+                  (car (mime-entity-children entity))
+                entity)))
+         (while (and current-entity
+                     (if (and (eq (mime-entity-media-type
+                                   current-entity) 'message)
+                              (eq (mime-entity-media-subtype
+                                   current-entity) 'rfc822))
+                         nil
+                       (mime-insert-header current-entity fields)
+                       t))
+           (setq fields (std11-collect-field-names)
+                 current-entity (mime-entity-parent current-entity))))
+       (let ((rest mime-view-following-required-fields-list)
+             field-name ret)
+         (while rest
+           (setq field-name (car rest))
+           (or (std11-field-body field-name)
+               (progn
+                 (save-excursion
+                   (set-buffer the-buf)
+                   (let ((entity (when mime-mother-buffer
+                                   (set-buffer mime-mother-buffer)
+                                   (get-text-property (point)
+                                                      'mime-view-entity))))
+                     (while (and entity
+                                 (null (setq ret (mime-entity-fetch-field
+                                                  entity field-name))))
+                       (setq entity (mime-entity-parent entity)))))
+                 (if ret
+                     (insert (concat field-name ": " ret "\n")))))
+           (setq rest (cdr rest)))))
+      (let ((f (cdr (assq mode mime-preview-following-method-alist))))
+       (if (functionp f)
+           (funcall f new-buf)
+         (message
+          "Sorry, following method for %s is not implemented yet."
+           mode))))))
 
 
 ;;; @@ moving
@@ -1279,8 +1631,7 @@ If there is no upper entity, call function `mime-preview-quit'."
   (let (cinfo)
     (while (null (setq cinfo
                       (get-text-property (point) 'mime-view-entity)))
-      (backward-char)
-      )
+      (backward-char))
     (let ((r (mime-entity-parent cinfo))
          point)
       (catch 'tag
@@ -1297,11 +1648,8 @@ If there is no upper entity, call function `mime-preview-quit'."
                               (beginning-of-line)
                               (point)))))
                (recenter next-screen-context-lines))
-           (throw 'tag t)
-           )
-         )
-       (mime-preview-quit)
-       ))))
+           (throw 'tag t)))
+       (mime-preview-quit)))))
 
 (defun mime-preview-move-to-previous ()
   "Move to previous entity.
@@ -1310,8 +1658,7 @@ variable `mime-preview-over-to-previous-method-alist'."
   (interactive)
   (while (and (not (bobp))
              (null (get-text-property (point) 'mime-view-entity)))
-    (backward-char)
-    )
+    (backward-char))
   (let ((point (previous-single-property-change (point) 'mime-view-entity)))
     (if (and point
             (>= point (point-min)))
@@ -1328,14 +1675,11 @@ variable `mime-preview-over-to-previous-method-alist'."
                                  (point)))))
                        (recenter (* -1 next-screen-context-lines))))
          (goto-char (1- point))
-         (mime-preview-move-to-previous)
-         )
+         (mime-preview-move-to-previous))
       (let ((f (assq (mime-preview-original-major-mode)
                     mime-preview-over-to-previous-method-alist)))
        (if f
-           (funcall (cdr f))
-         ))
-      )))
+           (funcall (cdr f)))))))
 
 (defun mime-preview-move-to-next ()
   "Move to next entity.
@@ -1344,8 +1688,7 @@ variable `mime-preview-over-to-next-method-alist'."
   (interactive)
   (while (and (not (eobp))
              (null (get-text-property (point) 'mime-view-entity)))
-    (forward-char)
-    )
+    (forward-char))
   (let ((point (next-single-property-change (point) 'mime-view-entity)))
     (if (and point
             (<= point (point-max)))
@@ -1363,14 +1706,11 @@ variable `mime-preview-over-to-next-method-alist'."
                            (* -1 next-screen-context-lines))
                           (beginning-of-line)
                           (point)))))
-                (recenter next-screen-context-lines))
-           ))
+                (recenter next-screen-context-lines))))
       (let ((f (assq (mime-preview-original-major-mode)
                     mime-preview-over-to-next-method-alist)))
        (if f
-           (funcall (cdr f))
-         ))
-      )))
+           (funcall (cdr f)))))))
 
 (defun mime-preview-scroll-up-entity (&optional h)
   "Scroll up current entity.
@@ -1381,8 +1721,7 @@ If reached to (point-max), it calls function registered in variable
       (let ((f (assq (mime-preview-original-major-mode)
                     mime-preview-over-to-next-method-alist)))
        (if f
-           (funcall (cdr f))
-         ))
+           (funcall (cdr f))))
     (let ((point
           (or (next-single-property-change (point) 'mime-view-entity)
               (point-max)))
@@ -1394,8 +1733,7 @@ If reached to (point-max), it calls function registered in variable
        (condition-case nil
            (scroll-up h)
          (end-of-buffer
-          (goto-char (point-max)))))
-      )))
+          (goto-char (point-max))))))))
 
 (defun mime-preview-scroll-down-entity (&optional h)
   "Scroll down current entity.
@@ -1406,8 +1744,7 @@ If reached to (point-min), it calls function registered in variable
       (let ((f (assq (mime-preview-original-major-mode)
                     mime-preview-over-to-previous-method-alist)))
        (if f
-           (funcall (cdr f))
-         ))
+           (funcall (cdr f))))
     (let ((point
           (or (previous-single-property-change (point) 'mime-view-entity)
               (point-min)))
@@ -1419,23 +1756,130 @@ If reached to (point-min), it calls function registered in variable
        (condition-case nil
            (scroll-down h)
          (beginning-of-buffer
-          (goto-char (point-min)))))
-      )))
+          (goto-char (point-min))))))))
 
 (defun mime-preview-next-line-entity (&optional lines)
   "Scroll up one line (or prefix LINES lines).
 If LINES is negative, scroll down LINES lines."
   (interactive "p")
-  (mime-preview-scroll-up-entity (or lines 1))
-  )
+  (mime-preview-scroll-up-entity (or lines 1)))
 
 (defun mime-preview-previous-line-entity (&optional lines)
   "Scrroll down one line (or prefix LINES lines).
 If LINES is negative, scroll up LINES lines."
   (interactive "p")
-  (mime-preview-scroll-down-entity (or lines 1))
-  )
+  (mime-preview-scroll-down-entity (or lines 1)))
+
+
+;;; @@ display
+;;;
+
+(defun mime-view-guess-encoding (entity situation)
+  (or (cdr (assq '*encoding situation))
+      (cdr (assq 'encoding situation))
+      (mime-entity-encoding entity)
+      "7bit"))
+
+(defun mime-view-read-encoding (entity situation)
+  (let* ((default-encoding
+          (mime-view-guess-encoding entity situation))
+        (encoding
+         (completing-read
+          "Content Transfer Encoding: "
+          (mime-encoding-alist) nil t default-encoding)))
+    (unless (or (string= encoding "")
+               (string= encoding default-encoding))
+      encoding)))
+
+(defun mime-view-guess-charset (entity situation)
+  (or (static-if (fboundp 'coding-system-to-mime-charset)
+         ;; might be overridden by `universal-coding-system-argument'.
+         (and coding-system-for-read
+              (coding-system-to-mime-charset coding-system-for-read)))
+      (cdr (assq '*charset situation))
+      (cdr (assq 'charset situation))
+      (let ((charset (cdr (assoc "charset" (mime-entity-parameters entity)))))
+       (if charset
+           (intern (downcase charset))))
+      default-mime-charset))
+
+(defun mime-view-read-charset (entity situation)
+  (static-if (featurep 'mule)
+      (let* ((default-charset
+              (mime-view-guess-charset entity situation))
+            (charset
+             (intern (completing-read "MIME-charset: "
+                                      (mapcar
+                                       (lambda (sym)
+                                         (list (symbol-name sym)))
+                                       (mime-charset-list))
+                                      nil t
+                                      (symbol-name default-charset)))))
+       (unless (eq charset default-charset)
+         charset))
+    default-charset))
+
+(defun mime-preview-toggle-display (type &optional display)
+  (let ((situation (mime-preview-find-boundary-info t))
+       (sym (intern (concat "*" (symbol-name type))))
+       entity p-beg p-end encoding charset)
+    (setq p-beg (aref situation 0)
+         p-end (aref situation 1)
+         entity (aref situation 2)
+         situation (get-text-property p-beg 'mime-view-situation))
+    (cond ((eq display 'invisible)
+          (setq display nil))
+         (display)
+         (t
+          (setq display
+                (memq (cdr (or (assq sym situation)
+                               (assq type situation)))
+                      '(nil invisible)))))
+    (setq situation (put-alist sym (if display
+                                      'visible
+                                    'invisible)
+                              situation))
+    (when (and current-prefix-arg
+              (eq (cdr (assq sym situation)) 'visible))
+      (if (setq encoding (mime-view-read-encoding entity situation))
+         (setq situation (put-alist '*encoding encoding situation)))
+      (if (setq charset (mime-view-read-charset entity situation))
+         (setq situation (put-alist '*charset charset situation))))
+    (save-excursion
+      (let ((inhibit-read-only t))
+       (delete-region p-beg p-end)
+       (mime-display-entity entity situation)))
+    (let ((ret (assoc situation mime-preview-situation-example-list)))
+      (if ret
+         (setcdr ret (1+ (cdr ret)))
+       (add-to-list 'mime-preview-situation-example-list
+                    (cons situation 0))))))
+
+(defun mime-preview-toggle-header (&optional force-visible)
+  (interactive "P")
+  (mime-preview-toggle-display 'header force-visible))
 
+(defun mime-preview-toggle-content (&optional force-visible)
+  (interactive "P")
+  (mime-preview-toggle-display 'body force-visible))
+
+(defun mime-preview-show-header ()
+  (interactive)
+  (mime-preview-toggle-display 'header 'visible))
+
+(defun mime-preview-show-content ()
+  (interactive)
+  (mime-preview-toggle-display 'body 'visible))
+
+(defun mime-preview-hide-header ()
+  (interactive)
+  (mime-preview-toggle-display 'header 'invisible))
+
+(defun mime-preview-hide-content ()
+  (interactive)
+  (mime-preview-toggle-display 'body 'invisible))
+
+    
 ;;; @@ quitting
 ;;;
 
@@ -1447,13 +1891,11 @@ It calls function registered in variable
   (let ((r (assq (mime-preview-original-major-mode)
                 mime-preview-quitting-method-alist)))
     (if r
-       (funcall (cdr r))
-      )))
+       (funcall (cdr r)))))
 
 (defun mime-preview-kill-buffer ()
   (interactive)
-  (kill-buffer (current-buffer))
-  )
+  (kill-buffer (current-buffer)))
 
 
 ;;; @ end
@@ -1461,6 +1903,11 @@ It calls function registered in variable
 
 (provide 'mime-view)
 
-(run-hooks 'mime-view-load-hook)
+(eval-when-compile
+  (setq mime-situation-examples-file nil)
+  ;; to avoid to read situation-examples-file at compile time.
+  )
+
+(mime-view-read-situation-examples-file)
 
 ;;; mime-view.el ends here
index 6ce9927..168870e 100644 (file)
@@ -1,8 +1,8 @@
 ;;; mime-w3.el --- mime-view content filter for text
 
-;; Copyright (C) 1994,1995,1996,1997,1998,1999 Free Software Foundation, Inc.
+;; Copyright (C) 1994,95,96,97,98,99,2000 Free Software Foundation, Inc.
 
-;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Author: MORIOKA Tomohiko <tomo@m17n.org>
 ;; Keywords: HTML, MIME, multimedia, mail, news
 
 ;; This file is part of SEMI (Suite of Emacs MIME Interfaces).
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
-(require 'w3)
+(condition-case nil
+    (require 'w3)
+  (error nil))
 (require 'mime)
 
 (defmacro mime-put-keymap-region (start end keymap)
       `(let ((color (color-name (face-background 'default))))
         (prog1
             (progn ,@body)
-          (font-set-face-background 'default color (current-buffer))
-          ))
+          (font-set-face-background 'default color (current-buffer))))
     (cons 'progn body)))
 
 (defvar mime-w3-message-structure nil)
 
 (defun mime-preview-text/html (entity situation)
-  (setq mime-w3-message-structure
-       (with-current-buffer (mime-entity-buffer entity)
-         mime-message-structure))
+  (setq mime-w3-message-structure (mime-find-root-entity entity))
   (goto-char (point-max))
   (let ((p (point)))
     (insert "\n")
        (run-hooks 'mime-text-decode-hook)
        (condition-case err
           (w3-region p (point-max))
-        (error (message (format "%s" err))))
-       (mime-put-keymap-region p (point-max) w3-mode-map)
-       ))))
+        (error (message "%s" err)))
+       (mime-put-keymap-region p (point-max) w3-mode-map)))))
 
 (defun url-cid (url &optional proxy-info)
   (let ((entity
         (mime-find-entity-from-content-id (mime-uri-parse-cid url)
-                                          mime-w3-message-structure)))
+                                          mime-w3-message-structure))
+       buffer)
     (when entity
-      (mime-insert-entity-content entity)
-      (setq url-current-mime-type (mime-entity-type/subtype entity))
-      )))
-
-(url-register-protocol "cid"
-                      'url-cid
-                      'url-identity-expander)
+      (setq buffer (generate-new-buffer (format " *cid %s" url)))
+      (save-excursion
+       (set-buffer buffer)
+       (mime-insert-entity-content entity)
+       (if (boundp 'url-current-mime-type)
+           (setq url-current-mime-type (mime-entity-type/subtype entity)))))
+    buffer))
+
+(if (fboundp 'url-register-protocol)
+    (url-register-protocol "cid"
+                          'url-cid
+                          'url-identity-expander)
+  (provide 'url-cid))
 
 
 ;;; @ end
diff --git a/pgg-def.el b/pgg-def.el
new file mode 100644 (file)
index 0000000..c793816
--- /dev/null
@@ -0,0 +1,85 @@
+;;; pgg-def.el --- functions/macros for defining PGG functions
+
+;; Copyright (C) 1999 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Created: 1999/11/02
+;; Keywords: PGP, OpenPGP, GnuPG
+
+;; This file is part of SEMI (Secure Emacs MIME Interface).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+(require 'custom)
+
+(defgroup pgg ()
+  "Glue for the various PGP implementations."
+  :group 'mime)
+
+(defcustom pgg-default-scheme 'gpg
+  "Default PGP scheme."
+  :group 'pgg
+  :type '(choice (const :tag "GnuPG" gpg)
+                (const :tag "PGP 5" pgp5)
+                (const :tag "PGP" pgp)))
+
+(defcustom pgg-default-user-id (user-login-name)
+  "User ID of your default identity."
+  :group 'pgg
+  :type 'string)
+
+(defvar pgg-overriding-user-id nil
+  "User ID temporally bound during the command consequent upon
+`pgg-universal-user-id-argument'.")
+
+(defcustom pgg-default-keyserver-address "wwwkeys.pgp.net"
+  "Host name of keyserver."
+  :group 'pgg
+  :type 'string)
+
+(defcustom pgg-encrypt-for-me nil
+  "If t, encrypt all outgoing messages with user's public key."
+  :group 'pgg
+  :type 'boolean)
+
+(defcustom pgg-cache-passphrase t
+  "If t, cache passphrase."
+  :group 'pgg
+  :type 'boolean)
+
+(defvar pgg-messages-coding-system nil
+  "Coding system used when reading from a PGP external process.")
+
+(defvar pgg-messages-locale nil
+  "Locale set before running a PGP external process.")
+
+(defvar pgg-status-buffer " *PGG status*")
+(defvar pgg-errors-buffer " *PGG errors*")
+(defvar pgg-output-buffer " *PGG output*")
+
+(defvar pgg-echo-buffer "*PGG-echo*")
+
+(defvar pgg-scheme nil
+  "Current scheme of PGP implementation.")
+
+(defmacro pgg-truncate-key-identifier (key)
+  `(if (> (length ,key) 8) (substring ,key 8) ,key))
+
+(provide 'pgg-def)
+
+;;; pgg-def.el ends here
diff --git a/pgg-gpg.el b/pgg-gpg.el
new file mode 100644 (file)
index 0000000..104dad0
--- /dev/null
@@ -0,0 +1,252 @@
+;;; pgg-gpg.el --- GnuPG support for PGG.
+
+;; Copyright (C) 1999,2000 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Created: 1999/10/28
+;; Keywords: PGP, OpenPGP, GnuPG
+
+;; This file is part of SEMI (Secure Emacs MIME Interface).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+(require 'mel) ; binary-to-text-funcall
+(eval-when-compile (require 'pgg))
+
+(defgroup pgg-gpg ()
+  "GnuPG interface"
+  :group 'pgg)
+
+(defcustom pgg-gpg-program "gpg" 
+  "The GnuPG executable."
+  :group 'pgg-gpg
+  :type 'string)
+
+(defcustom pgg-gpg-extra-args nil
+  "Extra arguments for every GnuPG invocation."
+  :group 'pgg-gpg
+  :type 'string)
+
+(eval-and-compile
+  (luna-define-class pgg-scheme-gpg (pgg-scheme)))
+
+(defvar pgg-gpg-user-id nil
+  "GnuPG ID of your default identity.")
+
+(defvar pgg-gpg-messages-locale pgg-messages-locale
+  "Locale set before running a GnuPG external process.")
+
+(defvar pgg-scheme-gpg-instance nil)
+
+;;;###autoload
+(defun pgg-make-scheme-gpg ()
+  (or pgg-scheme-gpg-instance
+      (setq pgg-scheme-gpg-instance
+           (luna-make-entity 'pgg-scheme-gpg))))
+
+(defun pgg-gpg-process-region (start end passphrase program args)
+  (let* ((output-file-name (make-temp-file
+                           (expand-file-name "pgg-output"
+                                             temporary-file-directory)))
+        (args
+         `("--status-fd" "2"
+           ,@(if passphrase '("--passphrase-fd" "0"))
+           "--yes" ; overwrite
+           "--output" ,output-file-name
+           ,@pgg-gpg-extra-args ,@args))
+        (output-buffer pgg-output-buffer)
+        (errors-buffer pgg-errors-buffer)
+        (process-connection-type nil)
+        (process-environment process-environment)
+        process status exit-status)
+    (when pgg-gpg-messages-locale
+      (setq process-environment (copy-sequence process-environment))
+      (setenv "LC_ALL" pgg-gpg-messages-locale)
+      (setenv "LANGUAGE" pgg-gpg-messages-locale))
+    (with-current-buffer (get-buffer-create errors-buffer)
+      (buffer-disable-undo)
+      (erase-buffer))
+    (unwind-protect
+       (progn
+         (let ((coding-system-for-write 'binary))
+           (setq process
+                 (apply #'start-process "*GnuPG*" errors-buffer
+                        program args)))
+         (set-process-sentinel process #'ignore)
+         (when passphrase
+           (process-send-string process (concat passphrase "\n")))
+         (process-send-region process start end)
+         (process-send-eof process)
+         (while (eq 'run (process-status process))
+           (accept-process-output process 5))
+         (setq status (process-status process)
+               exit-status (process-exit-status process))
+         (delete-process process)
+         (with-current-buffer (get-buffer-create output-buffer)
+           (buffer-disable-undo)
+           (erase-buffer)
+           (if (file-exists-p output-file-name)
+               (let ((coding-system-for-read 'raw-text-dos))
+                 (insert-file-contents output-file-name)))
+           (set-buffer errors-buffer)
+           (if (memq status '(stop signal))
+               (error "%s exited abnormally: '%s'" program exit-status))
+           (if (= 127 exit-status)
+               (error "%s could not be found" program))))
+      (if (and process (eq 'run (process-status process)))
+         (interrupt-process process))
+      (if (file-exists-p output-file-name)
+         (delete-file output-file-name)))))
+
+(defun pgg-gpg-possibly-cache-passphrase (passphrase)
+  (if (and pgg-cache-passphrase
+          (progn
+            (goto-char (point-min))
+            (re-search-forward "^\\[GNUPG:] GOOD_PASSPHRASE\\>" nil t)))
+      (pgg-add-passphrase-cache
+       (progn
+        (goto-char (point-min))
+        (if (re-search-forward
+             "^\\[GNUPG:] NEED_PASSPHRASE \\w+ ?\\w*" nil t)
+            (substring (match-string 0) -8)))
+       passphrase)))
+
+(luna-define-method pgg-scheme-lookup-key ((scheme pgg-scheme-gpg)
+                                          string &optional type)
+  (let ((args (list "--with-colons" "--no-greeting" "--batch"
+                   (if type "--list-secret-keys" "--list-keys")
+                   string)))
+    (with-temp-buffer
+      (apply #'call-process pgg-gpg-program nil t nil args)
+      (goto-char (point-min))
+      (if (re-search-forward "^\\(sec\\|pub\\):[^:]*:[^:]*:[^:]*:\\([^:]*\\)"
+                            nil t)
+         (substring (match-string 2) 8)))))
+
+(luna-define-method pgg-scheme-encrypt-region ((scheme pgg-scheme-gpg)
+                                              start end recipients)
+  (let* ((user-id (or pgg-overriding-user-id pgg-gpg-user-id
+                     pgg-default-user-id))
+        (args
+         `("--batch" "--armor" "--always-trust" "--encrypt"
+           ,@(if recipients
+                 (apply #'nconc
+                        (mapcar (lambda (rcpt)
+                                  (list "--remote-user" rcpt))
+                                (append recipients
+                                        (if pgg-encrypt-for-me
+                                            (list user-id)))))))))
+    (pgg-as-lbt start end 'CRLF
+      (pgg-gpg-process-region start end nil pgg-gpg-program args))
+    (pgg-process-when-success)))
+
+(luna-define-method pgg-scheme-decrypt-region ((scheme pgg-scheme-gpg)
+                                              start end)
+  (let* ((user-id (or pgg-overriding-user-id pgg-gpg-user-id
+                     pgg-default-user-id))
+        (passphrase
+         (pgg-read-passphrase
+          (format "GnuPG passphrase for %s: " pgg-gpg-user-id)
+          (pgg-scheme-lookup-key scheme user-id 'encrypt)))
+        (args '("--batch" "--decrypt")))
+    (pgg-gpg-process-region start end passphrase pgg-gpg-program args)
+    (with-current-buffer pgg-errors-buffer
+      (pgg-gpg-possibly-cache-passphrase passphrase)
+      (goto-char (point-min))
+      (re-search-forward "^\\[GNUPG:] DECRYPTION_OKAY\\>" nil t))))
+
+(luna-define-method pgg-scheme-sign-region ((scheme pgg-scheme-gpg)
+                                           start end &optional cleartext)
+  (let* ((user-id (or pgg-overriding-user-id pgg-gpg-user-id
+                     pgg-default-user-id))
+        (passphrase
+         (pgg-read-passphrase
+          (format "GnuPG passphrase for %s: " user-id)
+          (pgg-scheme-lookup-key scheme user-id 'sign)))
+        (args
+         (list (if cleartext "--clearsign" "--detach-sign")
+               "--armor" "--batch" "--verbose"
+               "--local-user" user-id))
+        (inhibit-read-only t)
+        buffer-read-only)
+    (pgg-as-lbt start end 'CRLF
+      (pgg-gpg-process-region start end passphrase pgg-gpg-program args))
+    (with-current-buffer pgg-errors-buffer
+      (pgg-gpg-possibly-cache-passphrase passphrase))
+    (pgg-process-when-success)))
+
+(luna-define-method pgg-scheme-verify-region ((scheme pgg-scheme-gpg)
+                                             start end &optional signature)
+  (let ((args '("--batch" "--verify")))
+    (when (stringp signature)
+      (setq args (append args (list signature))))
+    (setq args (append args '("-")))
+    (pgg-gpg-process-region start end nil pgg-gpg-program args)
+    (with-current-buffer pgg-errors-buffer
+      (goto-char (point-min))
+      (while (re-search-forward "^gpg: " nil t)
+       (replace-match ""))
+      (goto-char (point-min))
+      (prog1 (re-search-forward "^\\[GNUPG:] GOODSIG\\>" nil t)
+       (goto-char (point-min))
+       (delete-matching-lines "^\\[GNUPG:] ")
+       ;; XXX: copy contents of pgg-errors-buffer into
+       ;; pgg-output-buffer for backward compatibility.
+       (with-current-buffer pgg-output-buffer
+         (set-buffer-multibyte t)
+         (insert-buffer-substring pgg-errors-buffer))))))
+
+(luna-define-method pgg-scheme-insert-key ((scheme pgg-scheme-gpg))
+  (let* ((user-id (or pgg-overriding-user-id pgg-gpg-user-id
+                     pgg-default-user-id))
+        (args (list "--batch" "--export" "--armor" user-id)))
+    (pgg-gpg-process-region (point)(point) nil pgg-gpg-program args)
+    (insert-buffer-substring pgg-output-buffer)))
+
+(luna-define-method pgg-scheme-snarf-keys-region ((scheme pgg-scheme-gpg)
+                                                 start end)
+  (let ((args '("--import" "--batch" "-")) status)
+    (pgg-gpg-process-region start end nil pgg-gpg-program args)
+    (set-buffer pgg-errors-buffer)
+    (goto-char (point-min))
+    (when (re-search-forward "^\\[GNUPG:] IMPORT_RES\\>" nil t)
+      (setq status (buffer-substring (match-end 0)
+                                    (progn (end-of-line)(point)))
+           status (vconcat (mapcar #'string-to-int (split-string status))))
+      (erase-buffer)
+      (insert (format "Imported %d key(s).
+\tArmor contains %d key(s) [%d bad, %d old].\n"
+                     (+ (aref status 2)
+                        (aref status 10))
+                     (aref status 0)
+                     (aref status 1)
+                     (+ (aref status 4)
+                        (aref status 11)))
+             (if (zerop (aref status 9))
+                 ""
+               "\tSecret keys are imported.\n"))
+      ;; XXX: copy contents of pgg-errors-buffer into
+      ;; pgg-output-buffer for backward compatibility.
+      (with-current-buffer pgg-output-buffer
+       (set-buffer-multibyte t)
+       (insert-buffer-substring pgg-errors-buffer))
+      t)))
+
+(provide 'pgg-gpg)
+
+;;; pgg-gpg.el ends here
diff --git a/pgg-parse.el b/pgg-parse.el
new file mode 100644 (file)
index 0000000..bc5fec1
--- /dev/null
@@ -0,0 +1,500 @@
+;;; pgg-parse.el --- OpenPGP packet parsing
+
+;; Copyright (C) 1999 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Created: 1999/10/28
+;; Keywords: PGP, OpenPGP, GnuPG
+
+;; This file is part of SEMI (Secure Emacs MIME Interface).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;    This module is based on
+
+;;     [OpenPGP] RFC 2440: "OpenPGP Message Format"
+;;         by John W. Noerenberg, II <jwn2@qualcomm.com>,
+;;          Jon Callas <jon@pgp.com>, Lutz Donnerhacke <lutz@iks-jena.de>,
+;;          Hal Finney <hal@pgp.com> and Rodney Thayer <rodney@unitran.com>
+;;         (1998/11)
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(eval-when-compile (require 'static))
+
+(require 'pccl)
+(require 'custom)
+(require 'mel)
+
+(defgroup pgg-parse ()
+  "OpenPGP packet parsing"
+  :group 'pgg)
+
+(defcustom pgg-parse-public-key-algorithm-alist
+  '((1 . RSA) (2 . RSA-E) (3 . RSA-S) (16 . ELG-E) (17 . DSA) (20 . ELG))
+  "Alist of the assigned number to the public key algorithm."
+  :group 'pgg-parse
+  :type 'alist)
+
+(defcustom pgg-parse-symmetric-key-algorithm-alist
+  '((1 . IDEA) (2 . 3DES) (4 . CAST5) (5 . SAFER-SK128))
+  "Alist of the assigned number to the simmetric key algorithm."
+  :group 'pgg-parse
+  :type 'alist)
+
+(defcustom pgg-parse-hash-algorithm-alist
+  '((1 . MD5) (2 . SHA1) (3 . RIPEMD160) (5 . MD2))
+  "Alist of the assigned number to the cryptographic hash algorithm."
+  :group 'pgg-parse
+  :type 'alist)
+
+(defcustom pgg-parse-compression-algorithm-alist
+  '((0 . nil); Uncompressed
+    (1 . ZIP)
+    (2 . ZLIB))
+  "Alist of the assigned number to the compression algorithm."
+  :group 'pgg-parse
+  :type 'alist)
+
+(defcustom pgg-parse-signature-type-alist
+  '((0 . "Signature of a binary document")
+    (1 . "Signature of a canonical text document")
+    (2 . "Standalone signature")
+    (16 . "Generic certification of a User ID and Public Key packet")
+    (17 . "Persona certification of a User ID and Public Key packet")
+    (18 . "Casual certification of a User ID and Public Key packet")
+    (19 . "Positive certification of a User ID and Public Key packet")
+    (24 . "Subkey Binding Signature")
+    (31 . "Signature directly on a key")
+    (32 . "Key revocation signature")
+    (40 . "Subkey revocation signature")
+    (48 . "Certification revocation signature")
+    (64 . "Timestamp signature."))
+  "Alist of the assigned number to the signature type."
+  :group 'pgg-parse
+  :type 'alist)
+
+(defcustom pgg-ignore-packet-checksum t; XXX
+  "If non-nil checksum of each ascii armored packet will be ignored."
+  :group 'pgg-parse
+  :type 'boolean)
+
+(defvar pgg-armor-header-lines
+  '("^-----BEGIN PGP MESSAGE\\(, PART [0-9]+\\(/[0-9]+\\)?\\)?-----\r?$"
+    "^-----BEGIN PGP PUBLIC KEY BLOCK-----\r?$"
+    "^-----BEGIN PGP PRIVATE KEY BLOCK-----\r?$"
+    "^-----BEGIN PGP SIGNATURE-----\r?$")
+  "Armor headers.")
+
+(defmacro pgg-format-key-identifier (string)
+  `(mapconcat (lambda (c) (format "%02X" (char-int c)))
+             ,string "")
+  ;; `(upcase (apply #'format "%02x%02x%02x%02x%02x%02x%02x%02x"
+  ;;                 (string-to-int-list ,string)))
+  )
+
+(defmacro pgg-parse-time-field (bytes)
+  `(list (logior (lsh (car ,bytes) 8)
+                (nth 1 ,bytes))
+        (logior (lsh (nth 2 ,bytes) 8)
+                (nth 3 ,bytes))
+        0))
+
+(defmacro pgg-byte-after (&optional pos)
+  `(char-int (char-after ,(or pos `(point)))))
+
+(defmacro pgg-read-byte ()
+  `(char-int (char-after (prog1 (point) (forward-char)))))
+
+(defmacro pgg-read-bytes-string (nbytes)
+  `(buffer-substring
+    (point) (prog1 (+ ,nbytes (point))
+             (forward-char ,nbytes))))
+
+(defmacro pgg-read-bytes (nbytes)
+  `(mapcar #'char-int (pgg-read-bytes-string ,nbytes))
+  ;; `(string-to-int-list (pgg-read-bytes-string ,nbytes))
+  )
+
+(defmacro pgg-read-body-string (ptag)
+  `(if (nth 1 ,ptag)
+       (pgg-read-bytes-string (nth 1 ,ptag))
+     (pgg-read-bytes-string (- (point-max) (point)))))
+
+(defmacro pgg-read-body (ptag)
+  `(mapcar #'char-int (pgg-read-body-string ,ptag))
+  ;; `(string-to-int-list (pgg-read-body-string ,ptag))
+  )
+
+(defalias 'pgg-skip-bytes 'forward-char)
+
+(defmacro pgg-skip-header (ptag)
+  `(pgg-skip-bytes (nth 2 ,ptag)))
+
+(defmacro pgg-skip-body (ptag)
+  `(pgg-skip-bytes (nth 1 ,ptag)))
+
+(defmacro pgg-set-alist (alist key value)
+  `(setq ,alist (nconc ,alist (list (cons ,key ,value)))))
+
+(unless-broken ccl-usable
+  (define-ccl-program pgg-parse-crc24
+    '(1
+      ((loop
+       (read r0) (r1 ^= r0) (r2 ^= 0)
+       (r5 = 0)
+       (loop
+        (r1 <<= 1)
+        (r1 += ((r2 >> 15) & 1))
+        (r2 <<= 1)
+        (if (r1 & 256)
+            ((r1 ^= 390) (r2 ^= 19707)))
+        (if (r5 < 7)
+            ((r5 += 1)
+             (repeat))))
+       (repeat)))))
+
+  (defun pgg-parse-crc24-string (string)
+    (let ((h (vector nil 183 1230 nil nil nil nil nil nil)))
+      (ccl-execute-on-string pgg-parse-crc24 h string)
+      (format "%c%c%c"
+             (logand (aref h 1) 255)
+             (logand (lsh (aref h 2) -8) 255)
+             (logand (aref h 2) 255)))))
+
+(defmacro pgg-parse-length-type (c)
+  `(cond
+    ((< ,c 192) (cons ,c 1))
+    ((< ,c 224)
+     (cons (+ (lsh (- ,c 192) 8)
+             (pgg-byte-after (+ 2 (point)))
+             192)
+          2))
+    ((= ,c 255)
+     (cons (cons (logior (lsh (pgg-byte-after (+ 2 (point))) 8)
+                        (pgg-byte-after (+ 3 (point))))
+                (logior (lsh (pgg-byte-after (+ 4 (point))) 8)
+                        (pgg-byte-after (+ 5 (point)))))
+          5))
+    (t;partial body length
+     '(0 . 0))))
+
+(defun pgg-parse-packet-header ()
+  (let ((ptag (pgg-byte-after))
+       length-type content-tag packet-bytes header-bytes)
+    (if (zerop (logand 64 ptag));Old format
+       (progn
+         (setq length-type (logand ptag 3)
+               length-type (if (= 3 length-type) 0 (lsh 1 length-type))
+               content-tag (logand 15 (lsh ptag -2))
+               packet-bytes 0
+               header-bytes (1+ length-type))
+         (dotimes (i length-type)
+           (setq packet-bytes
+                 (logior (lsh packet-bytes 8)
+                         (pgg-byte-after (+ 1 i (point)))))))
+      (setq content-tag (logand 63 ptag)
+           length-type (pgg-parse-length-type
+                        (pgg-byte-after (1+ (point))))
+           packet-bytes (car length-type)
+           header-bytes (1+ (cdr length-type))))
+    (list content-tag packet-bytes header-bytes)))
+
+(defun pgg-parse-packet (ptag)
+  (case (car ptag)
+    (1 ;Public-Key Encrypted Session Key Packet
+     (pgg-parse-public-key-encrypted-session-key-packet ptag))
+    (2 ;Signature Packet
+     (pgg-parse-signature-packet ptag))
+    (3 ;Symmetric-Key Encrypted Session Key Packet
+     (pgg-parse-symmetric-key-encrypted-session-key-packet ptag))
+    ;; 4        -- One-Pass Signature Packet
+    ;; 5        -- Secret Key Packet
+    (6 ;Public Key Packet
+     (pgg-parse-public-key-packet ptag))
+    ;; 7        -- Secret Subkey Packet
+    ;; 8        -- Compressed Data Packet
+    (9 ;Symmetrically Encrypted Data Packet
+     (pgg-read-body-string ptag))
+    (10 ;Marker Packet
+     (pgg-read-body-string ptag))
+    (11 ;Literal Data Packet
+     (pgg-read-body-string ptag))
+    ;; 12       -- Trust Packet
+    (13 ;User ID Packet
+     (pgg-read-body-string ptag))
+    ;; 14       -- Public Subkey Packet
+    ;; 60 .. 63 -- Private or Experimental Values
+    ))
+
+(defun pgg-parse-packets (&optional header-parser body-parser)
+  (let ((header-parser
+        (or header-parser
+            (function pgg-parse-packet-header)))
+       (body-parser
+        (or body-parser
+            (function pgg-parse-packet)))
+       result ptag)
+    (while (> (point-max) (1+ (point)))
+      (setq ptag (funcall header-parser))
+      (pgg-skip-header ptag)
+      (push (cons (car ptag)
+                 (save-excursion
+                   (funcall body-parser ptag)))
+           result)
+      (if (zerop (nth 1 ptag))
+         (goto-char (point-max))
+       (forward-char (nth 1 ptag))))
+    result))
+
+(defun pgg-parse-signature-subpacket-header ()
+  (let ((length-type (pgg-parse-length-type (pgg-byte-after))))
+    (list (pgg-byte-after (+ (cdr length-type) (point)))
+         (1- (car length-type))
+         (1+ (cdr length-type)))))
+       
+(defun pgg-parse-signature-subpacket (ptag)
+  (case (car ptag)
+    (2 ;signature creation time
+     (cons 'creation-time
+          (let ((bytes (pgg-read-bytes 4)))
+            (pgg-parse-time-field bytes))))
+    (3 ;signature expiration time
+     (cons 'signature-expiry
+          (let ((bytes (pgg-read-bytes 4)))
+            (pgg-parse-time-field bytes))))
+    (4 ;exportable certification
+     (cons 'exportability (pgg-read-byte)))
+    (5 ;trust signature
+     (cons 'trust-level (pgg-read-byte)))
+    (6 ;regular expression
+     (cons 'regular-expression
+          (pgg-read-body-string ptag)))
+    (7 ;revocable
+     (cons 'revocability (pgg-read-byte)))
+    (9 ;key expiration time
+     (cons 'key-expiry
+          (let ((bytes (pgg-read-bytes 4)))
+            (pgg-parse-time-field bytes))))
+    ;; 10 = placeholder for backward compatibility
+    (11 ;preferred symmetric algorithms
+     (cons 'preferred-symmetric-key-algorithm
+          (cdr (assq (pgg-read-byte)
+                     pgg-parse-symmetric-key-algorithm-alist))))
+    (12 ;revocation key
+     )
+    (16 ;issuer key ID
+     (cons 'key-identifier
+          (pgg-format-key-identifier (pgg-read-body-string ptag))))
+    (20 ;notation data
+     (pgg-skip-bytes 4)
+     (cons 'notation
+          (let ((name-bytes (pgg-read-bytes 2))
+                (value-bytes (pgg-read-bytes 2)))
+            (cons (pgg-read-bytes-string
+                   (logior (lsh (car name-bytes) 8)
+                           (nth 1 name-bytes)))
+                  (pgg-read-bytes-string
+                   (logior (lsh (car value-bytes) 8)
+                           (nth 1 value-bytes)))))))
+    (21 ;preferred hash algorithms
+     (cons 'preferred-hash-algorithm
+          (cdr (assq (pgg-read-byte)
+                     pgg-parse-hash-algorithm-alist))))
+    (22 ;preferred compression algorithms
+     (cons 'preferred-compression-algorithm
+          (cdr (assq (pgg-read-byte)
+                     pgg-parse-compression-algorithm-alist))))
+    (23 ;key server preferences
+     (cons 'key-server-preferences
+          (pgg-read-body ptag)))
+    (24 ;preferred key server
+     (cons 'preferred-key-server
+          (pgg-read-body-string ptag)))
+    ;; 25 = primary user id
+    (26 ;policy URL
+     (cons 'policy-url (pgg-read-body-string ptag)))
+    ;; 27 = key flags
+    ;; 28 = signer's user id
+    ;; 29 = reason for revocation
+    ;; 100 to 110 = internal or user-defined
+    ))
+
+(defun pgg-parse-signature-packet (ptag)
+  (let* ((signature-version (pgg-byte-after))
+        (result (list (cons 'version signature-version)))
+        hashed-material field n)
+    (cond
+     ((= signature-version 3)
+      (pgg-skip-bytes 2)
+      (setq hashed-material (pgg-read-bytes 5))
+      (pgg-set-alist result
+                    'signature-type
+                    (cdr (assq (pop hashed-material)
+                               pgg-parse-signature-type-alist)))
+      (pgg-set-alist result
+                    'creation-time
+                    (pgg-parse-time-field hashed-material))
+      (pgg-set-alist result
+                    'key-identifier
+                    (pgg-format-key-identifier
+                     (pgg-read-bytes-string 8)))
+      (pgg-set-alist result
+                    'public-key-algorithm (pgg-read-byte))
+      (pgg-set-alist result
+                    'hash-algorithm (pgg-read-byte)))
+     ((= signature-version 4)
+      (pgg-skip-bytes 1)
+      (pgg-set-alist result
+                    'signature-type
+                    (cdr (assq (pgg-read-byte)
+                               pgg-parse-signature-type-alist)))
+      (pgg-set-alist result
+                    'public-key-algorithm
+                    (pgg-read-byte))
+      (pgg-set-alist result
+                    'hash-algorithm (pgg-read-byte))
+      (when (>= 10000 (setq n (pgg-read-bytes 2)
+                           n (logior (lsh (car n) 8)
+                                     (nth 1 n))))
+       (save-restriction
+         (narrow-to-region (point)(+ n (point)))
+         (nconc result
+                (mapcar (function cdr) ;remove packet types
+                        (pgg-parse-packets
+                         #'pgg-parse-signature-subpacket-header
+                         #'pgg-parse-signature-subpacket)))
+         (goto-char (point-max))))
+      (when (>= 10000 (setq n (pgg-read-bytes 2)
+                           n (logior (lsh (car n) 8)
+                                     (nth 1 n))))
+       (save-restriction
+         (narrow-to-region (point)(+ n (point)))
+         (nconc result
+                (mapcar (function cdr) ;remove packet types
+                        (pgg-parse-packets
+                         #'pgg-parse-signature-subpacket-header
+                         #'pgg-parse-signature-subpacket)))))))
+
+    (setcdr (setq field (assq 'public-key-algorithm
+                             result))
+           (cdr (assq (cdr field)
+                      pgg-parse-public-key-algorithm-alist)))
+    (setcdr (setq field (assq 'hash-algorithm
+                             result))
+           (cdr (assq (cdr field)
+                      pgg-parse-hash-algorithm-alist)))
+    result))
+
+(defun pgg-parse-public-key-encrypted-session-key-packet (ptag)
+  (let (result)
+    (pgg-set-alist result
+                  'version (pgg-read-byte))
+    (pgg-set-alist result
+                  'key-identifier
+                  (pgg-format-key-identifier
+                   (pgg-read-bytes-string 8)))
+    (pgg-set-alist result
+                  'public-key-algorithm
+                  (cdr (assq (pgg-read-byte)
+                             pgg-parse-public-key-algorithm-alist)))
+    result))
+
+(defun pgg-parse-symmetric-key-encrypted-session-key-packet (ptag)
+  (let (result)
+    (pgg-set-alist result
+                  'version
+                  (pgg-read-byte))
+    (pgg-set-alist result
+                  'symmetric-key-algorithm
+                  (cdr (assq (pgg-read-byte)
+                             pgg-parse-symmetric-key-algorithm-alist)))
+    result))
+
+(defun pgg-parse-public-key-packet (ptag)
+  (let* ((key-version (pgg-read-byte))
+        (result (list (cons 'version key-version)))
+        field)
+    (cond
+     ((= 3 key-version)
+      (pgg-set-alist result
+                    'creation-time
+                    (let ((bytes (pgg-read-bytes 4)))
+                      (pgg-parse-time-field bytes)))
+      (pgg-set-alist result
+                    'key-expiry (pgg-read-bytes 2))
+      (pgg-set-alist result
+                    'public-key-algorithm (pgg-read-byte)))
+     ((= 4 key-version)
+      (pgg-set-alist result
+                    'creation-time
+                    (let ((bytes (pgg-read-bytes 4)))
+                      (pgg-parse-time-field bytes)))
+      (pgg-set-alist result
+                    'public-key-algorithm (pgg-read-byte))))
+
+    (setcdr (setq field (assq 'public-key-algorithm
+                             result))
+           (cdr (assq (cdr field)
+                      pgg-parse-public-key-algorithm-alist)))
+    result))
+     
+(defun pgg-decode-packets ()
+  (let* ((marker
+         (set-marker (make-marker)
+                     (and (re-search-forward "^=")
+                          (match-beginning 0))))
+        (checksum (buffer-substring (point) (+ 4 (point)))))
+    (delete-region marker (point-max))
+    (mime-decode-region (point-min) marker "base64")
+    (static-when (fboundp 'pgg-parse-crc24-string )
+      (or pgg-ignore-packet-checksum
+         (string-equal
+          (funcall (mel-find-function 'mime-encode-string "base64")
+                   (pgg-parse-crc24-string
+                    (buffer-string)))
+          checksum)
+         (error "PGP packet checksum does not match")))))
+
+(defun pgg-decode-armor-region (start end)
+  (save-restriction
+    (narrow-to-region start end)
+    (goto-char (point-min))
+    (re-search-forward "^-+BEGIN PGP" nil t)
+    (delete-region (point-min)
+                  (and (search-forward "\n\n")
+                       (match-end 0)))
+    (pgg-decode-packets)
+    (goto-char (point-min))
+    (pgg-parse-packets)))
+
+(defun pgg-parse-armor (string)
+  (with-temp-buffer
+    (buffer-disable-undo)
+    (set-buffer-multibyte nil)
+    (insert string)
+    (pgg-decode-armor-region (point-min)(point))))
+
+(defun pgg-parse-armor-region (start end)
+  (pgg-parse-armor (string-as-unibyte (buffer-substring start end))))
+
+(provide 'pgg-parse)
+
+;;; pgg-parse.el ends here
diff --git a/pgg-pgp.el b/pgg-pgp.el
new file mode 100644 (file)
index 0000000..8715caa
--- /dev/null
@@ -0,0 +1,242 @@
+;;; pgg-pgp.el --- PGP 2.* and 6.* support for PGG.
+
+;; Copyright (C) 1999,2000 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Created: 1999/11/02
+;; Keywords: PGP, OpenPGP
+
+;; This file is part of SEMI (Secure Emacs MIME Interface).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+(require 'mel) ; binary-to-text-funcall, binary-write-decoded-region
+(eval-when-compile (require 'pgg))
+
+(defgroup pgg-pgp ()
+  "PGP 2.* and 6.* interface"
+  :group 'pgg)
+
+(defcustom pgg-pgp-program "pgp"
+  "PGP 2.* and 6.* executable."
+  :group 'pgg-pgp
+  :type 'string)
+
+(defcustom pgg-pgp-shell-file-name "/bin/sh"
+  "File name to load inferior shells from.
+Bourne shell or its equivalent \(not tcsh) is needed for \"2>\"."
+  :group 'pgg-pgp
+  :type 'string)
+
+(defcustom pgg-pgp-shell-command-switch "-c"
+  "Switch used to have the shell execute its command line argument."
+  :group 'pgg-pgp
+  :type 'string)
+
+(defcustom pgg-pgp-extra-args nil
+  "Extra arguments for every PGP invocation."
+  :group 'pgg-pgp
+  :type 'string)
+
+(eval-and-compile
+  (luna-define-class pgg-scheme-pgp (pgg-scheme)))
+
+(defvar pgg-pgp-user-id nil
+  "PGP ID of your default identity.")
+
+(defvar pgg-scheme-pgp-instance nil)
+
+;;;###autoload
+(defun pgg-make-scheme-pgp ()
+  (or pgg-scheme-pgp-instance
+      (setq pgg-scheme-pgp-instance
+           (luna-make-entity 'pgg-scheme-pgp))))
+
+(defun pgg-pgp-process-region (start end passphrase program args)
+  (let* ((errors-file-name (make-temp-file "pgg-errors"))
+        (args
+         (append args
+                 pgg-pgp-extra-args
+                 (list (concat "2>" errors-file-name))))
+        (shell-file-name pgg-pgp-shell-file-name)
+        (shell-command-switch pgg-pgp-shell-command-switch)
+        (process-environment process-environment)
+        (output-buffer pgg-output-buffer)
+        (errors-buffer pgg-errors-buffer)
+        (process-connection-type nil)
+        process status exit-status)
+    (with-current-buffer (get-buffer-create output-buffer)
+      (buffer-disable-undo)
+      (erase-buffer))
+    (when passphrase
+      (setenv "PGPPASSFD" "0"))
+    (unwind-protect
+       (progn
+         (setq process
+               (apply #'binary-funcall
+                      #'start-process-shell-command "*PGP*" output-buffer
+                      program args))
+         (set-process-sentinel process #'ignore)
+         (when passphrase
+           (process-send-string process (concat passphrase "\n")))
+         (process-send-region process start end)
+         (process-send-eof process)
+         (while (eq 'run (process-status process))
+           (accept-process-output process 5))
+         (setq status (process-status process)
+               exit-status (process-exit-status process))
+         (delete-process process)
+         (with-current-buffer output-buffer
+           (pgg-convert-lbt-region (point-min)(point-max) 'LF)
+
+           (if (memq status '(stop signal))
+               (error "%s exited abnormally: '%s'" program exit-status))
+           (if (= 127 exit-status)
+               (error "%s could not be found" program))
+
+           (set-buffer (get-buffer-create errors-buffer))
+           (buffer-disable-undo)
+           (erase-buffer)
+           (insert-file-contents errors-file-name)))
+      (if (and process (eq 'run (process-status process)))
+         (interrupt-process process))
+      (condition-case nil
+         (delete-file errors-file-name)
+       (file-error nil)))))
+
+(luna-define-method pgg-scheme-lookup-key ((scheme pgg-scheme-pgp)
+                                                 string &optional type)
+  (let ((args (list "+batchmode" "+language=en" "-kv" string)))
+    (with-current-buffer (get-buffer-create pgg-output-buffer)
+      (buffer-disable-undo)
+      (erase-buffer)
+      (apply #'call-process pgg-pgp-program nil t nil args)
+      (goto-char (point-min))
+      (cond
+       ((re-search-forward "^pub\\s +[0-9]+/" nil t);PGP 2.*
+       (buffer-substring (point)(+ 8 (point))))
+       ((re-search-forward "^Type" nil t);PGP 6.*
+       (beginning-of-line 2)
+       (substring
+        (nth 2 (split-string
+                (buffer-substring (point)(progn (end-of-line) (point)))))
+        2))))))
+
+(luna-define-method pgg-scheme-encrypt-region ((scheme pgg-scheme-pgp)
+                                              start end recipients)
+  (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
+        (args
+         `("+encrypttoself=off +verbose=1" "+batchmode"
+           "+language=us" "-fate"
+           ,@(if recipients
+                 (mapcar (lambda (rcpt) (concat "\"" rcpt "\""))
+                         (append recipients
+                                 (if pgg-encrypt-for-me
+                                     (list pgg-pgp-user-id))))))))
+    (pgg-pgp-process-region start end nil pgg-pgp-program args)
+    (pgg-process-when-success nil)))
+
+(luna-define-method pgg-scheme-decrypt-region ((scheme pgg-scheme-pgp)
+                                              start end)
+  (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
+        (passphrase
+         (pgg-read-passphrase
+          (format "PGP passphrase for %s: " pgg-pgp-user-id)
+          (pgg-scheme-lookup-key scheme pgg-pgp-user-id 'encrypt)))
+        (args
+         '("+verbose=1" "+batchmode" "+language=us" "-f")))
+    (pgg-pgp-process-region start end passphrase pgg-pgp-program args)
+    (pgg-process-when-success nil)))
+
+(luna-define-method pgg-scheme-sign-region ((scheme pgg-scheme-pgp)
+                                           start end &optional clearsign)
+  (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
+        (passphrase
+         (pgg-read-passphrase
+          (format "PGP passphrase for %s: " pgg-pgp-user-id)
+          (pgg-scheme-lookup-key scheme pgg-pgp-user-id 'sign)))
+        (args
+         (list (if clearsign "-fast" "-fbast")
+               "+verbose=1" "+language=us" "+batchmode"
+               "-u" pgg-pgp-user-id)))
+    (pgg-pgp-process-region start end passphrase pgg-pgp-program args)
+    (pgg-process-when-success
+      (goto-char (point-min))
+      (when (re-search-forward "^-+BEGIN PGP" nil t);XXX
+       (let ((packet
+              (cdr (assq 2 (pgg-parse-armor-region
+                            (progn (beginning-of-line 2)
+                                   (point))
+                            (point-max))))))
+         (if pgg-cache-passphrase
+             (pgg-add-passphrase-cache
+              (cdr (assq 'key-identifier packet))
+              passphrase)))))))
+
+(luna-define-method pgg-scheme-verify-region ((scheme pgg-scheme-pgp)
+                                             start end &optional signature)
+  (let ((orig-file (make-temp-file "pgg"))
+       (args '("+verbose=1" "+batchmode" "+language=us"))
+       (orig-mode (default-file-modes)))
+    (unwind-protect
+       (progn
+         (set-default-file-modes 448)
+         (binary-write-decoded-region start end orig-file))
+      (set-default-file-modes orig-mode))
+    (when (stringp signature)
+      (copy-file signature (setq signature (concat orig-file ".asc")))
+      (setq args (append args (list signature orig-file))))
+    (pgg-pgp-process-region (point)(point) nil pgg-pgp-program args)
+    (delete-file orig-file)
+    (if signature (delete-file signature))
+    (pgg-process-when-success
+      (goto-char (point-min))
+      (let ((case-fold-search t))
+       (while (re-search-forward "^warning: " nil t)
+         (delete-region (match-beginning 0)
+                        (progn (beginning-of-line 2) (point)))))
+      (goto-char (point-min))
+      (when (re-search-forward "^\\.$" nil t)
+       (delete-region (point-min)
+                      (progn (beginning-of-line 2)
+                             (point)))))))
+
+(luna-define-method pgg-scheme-insert-key ((scheme pgg-scheme-pgp))
+  (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
+        (args
+         (list "+verbose=1" "+batchmode" "+language=us" "-kxaf"
+               (concat "\"" pgg-pgp-user-id "\""))))
+    (pgg-pgp-process-region (point)(point) nil pgg-pgp-program args)
+    (insert-buffer-substring pgg-output-buffer)))
+
+(luna-define-method pgg-scheme-snarf-keys-region ((scheme pgg-scheme-pgp)
+                                                 start end)
+  (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
+        (key-file (make-temp-file "pgg"))
+        (args
+         (list "+verbose=1" "+batchmode" "+language=us" "-kaf"
+               key-file)))
+    (let ((coding-system-for-write 'raw-text-dos))
+      (write-region start end key-file))
+    (pgg-pgp-process-region start end nil pgg-pgp-program args)
+    (delete-file key-file)
+    (pgg-process-when-success nil)))
+
+(provide 'pgg-pgp)
+
+;;; pgg-pgp.el ends here
diff --git a/pgg-pgp5.el b/pgg-pgp5.el
new file mode 100644 (file)
index 0000000..c6438f6
--- /dev/null
@@ -0,0 +1,251 @@
+;;; pgg-pgp5.el --- PGP 5.* support for PGG.
+
+;; Copyright (C) 1999,2000 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Created: 1999/11/02
+;; Keywords: PGP, OpenPGP
+
+;; This file is part of SEMI (Secure Emacs MIME Interface).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+(require 'mel) ; binary-to-text-funcall, binary-write-decoded-region
+(eval-when-compile (require 'pgg))
+
+(defgroup pgg-pgp5 ()
+  "PGP 5.* interface"
+  :group 'pgg)
+
+(defcustom pgg-pgp5-pgpe-program "pgpe"
+  "PGP 5.* 'pgpe' executable."
+  :group 'pgg-pgp5
+  :type 'string)
+
+(defcustom pgg-pgp5-pgps-program "pgps"
+  "PGP 5.* 'pgps' executable."
+  :group 'pgg-pgp5
+  :type 'string)
+
+(defcustom pgg-pgp5-pgpk-program "pgpk"
+  "PGP 5.* 'pgpk' executable."
+  :group 'pgg-pgp5
+  :type 'string)
+
+(defcustom pgg-pgp5-pgpv-program "pgpv"
+  "PGP 5.* 'pgpv' executable."
+  :group 'pgg-pgp5
+  :type 'string)
+
+(defcustom pgg-pgp5-shell-file-name "/bin/sh"
+  "File name to load inferior shells from.
+Bourne shell or its equivalent \(not tcsh) is needed for \"2>\"."
+  :group 'pgg-pgp5
+  :type 'string)
+
+(defcustom pgg-pgp5-shell-command-switch "-c"
+  "Switch used to have the shell execute its command line argument."
+  :group 'pgg-pgp5
+  :type 'string)
+
+(defcustom pgg-pgp5-extra-args nil
+  "Extra arguments for every PGP 5.* invocation."
+  :group 'pgg-pgp5
+  :type 'string)
+
+(eval-and-compile
+  (luna-define-class pgg-scheme-pgp5 (pgg-scheme)))
+
+(defvar pgg-pgp5-user-id nil
+  "PGP 5.* ID of your default identity.")
+
+(defvar pgg-scheme-pgp5-instance nil)
+
+;;;###autoload
+(defun pgg-make-scheme-pgp5 ()
+  (or pgg-scheme-pgp5-instance
+      (setq pgg-scheme-pgp5-instance
+           (luna-make-entity 'pgg-scheme-pgp5))))
+
+(defun pgg-pgp5-process-region (start end passphrase program args)
+  (let* ((errors-file-name (make-temp-file "pgg-errors"))
+        (args
+         (append args
+                 pgg-pgp5-extra-args
+                 (list (concat "2>" errors-file-name))))
+        (shell-file-name pgg-pgp5-shell-file-name)
+        (shell-command-switch pgg-pgp5-shell-command-switch)
+        (process-environment process-environment)
+        (output-buffer pgg-output-buffer)
+        (errors-buffer pgg-errors-buffer)
+        (process-connection-type nil)
+        process status exit-status)
+    (with-current-buffer (get-buffer-create output-buffer)
+      (buffer-disable-undo)
+      (erase-buffer))
+    (when passphrase
+      (setenv "PGPPASSFD" "0"))
+    (unwind-protect
+       (progn
+         (setq process
+               (apply #'binary-funcall
+                      #'start-process-shell-command "*PGP*" output-buffer
+                      program args))
+         (set-process-sentinel process #'ignore)
+         (when passphrase
+           (process-send-string process (concat passphrase "\n")))
+         (process-send-region process start end)
+         (process-send-eof process)
+         (while (eq 'run (process-status process))
+           (accept-process-output process 5))
+         (setq status (process-status process)
+               exit-status (process-exit-status process))
+         (delete-process process)
+         (with-current-buffer output-buffer
+           (pgg-convert-lbt-region (point-min)(point-max) 'LF)
+
+           (if (memq status '(stop signal))
+               (error "%s exited abnormally: '%s'" program exit-status))
+           (if (= 127 exit-status)
+               (error "%s could not be found" program))
+
+           (set-buffer (get-buffer-create errors-buffer))
+           (buffer-disable-undo)
+           (erase-buffer)
+           (insert-file-contents errors-file-name)))
+      (if (and process (eq 'run (process-status process)))
+         (interrupt-process process))
+      (condition-case nil
+         (delete-file errors-file-name)
+       (file-error nil)))))
+
+(luna-define-method pgg-scheme-lookup-key ((scheme pgg-scheme-pgp5)
+                                                 string &optional type)
+  (let ((args (list "+language=en" "-l" string)))
+    (with-current-buffer (get-buffer-create pgg-output-buffer)
+      (buffer-disable-undo)
+      (erase-buffer)
+      (apply #'call-process pgg-pgp5-pgpk-program nil t nil args)
+      (goto-char (point-min))
+      (when (re-search-forward "^sec" nil t)
+       (substring
+        (nth 2 (split-string
+                (buffer-substring (match-end 0)(progn (end-of-line)(point)))))
+        2)))))
+
+(luna-define-method pgg-scheme-encrypt-region ((scheme pgg-scheme-pgp5)
+                                              start end recipients)
+  (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
+        (args
+         `("+NoBatchInvalidKeys=off" "-fat" "+batchmode=1"
+           ,@(if recipients
+                 (apply #'append
+                        (mapcar (lambda (rcpt)
+                                  (list "-r"
+                                        (concat "\"" rcpt "\"")))
+                                (append recipients
+                                        (if pgg-encrypt-for-me
+                                            (list pgg-pgp5-user-id)))))))))
+    (pgg-pgp5-process-region start end nil pgg-pgp5-pgpe-program args)
+    (pgg-process-when-success nil)))
+
+(luna-define-method pgg-scheme-decrypt-region ((scheme pgg-scheme-pgp5)
+                                              start end)
+  (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
+        (passphrase
+         (pgg-read-passphrase
+          (format "PGP passphrase for %s: " pgg-pgp5-user-id)
+          (pgg-scheme-lookup-key scheme pgg-pgp5-user-id 'encrypt)))
+        (args
+         '("+verbose=1" "+batchmode=1" "+language=us" "-f")))
+    (pgg-pgp5-process-region start end passphrase pgg-pgp5-pgpv-program args)
+    (pgg-process-when-success nil)))
+
+(luna-define-method pgg-scheme-sign-region ((scheme pgg-scheme-pgp5)
+                                           start end &optional clearsign)
+  (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
+        (passphrase
+         (pgg-read-passphrase
+          (format "PGP passphrase for %s: " pgg-pgp5-user-id)
+          (pgg-scheme-lookup-key scheme pgg-pgp5-user-id 'sign)))
+        (args
+         (list (if clearsign "-fat" "-fbat")
+               "+verbose=1" "+language=us" "+batchmode=1"
+               "-u" pgg-pgp5-user-id)))
+    (pgg-pgp5-process-region start end passphrase pgg-pgp5-pgps-program args)
+    (pgg-process-when-success
+      (when (re-search-forward "^-+BEGIN PGP SIGNATURE" nil t);XXX
+       (let ((packet
+              (cdr (assq 2 (pgg-parse-armor-region
+                            (progn (beginning-of-line 2)
+                                   (point))
+                            (point-max))))))
+         (if pgg-cache-passphrase
+             (pgg-add-passphrase-cache
+              (cdr (assq 'key-identifier packet))
+              passphrase)))))))
+
+(luna-define-method pgg-scheme-verify-region ((scheme pgg-scheme-pgp5)
+                                             start end &optional signature)
+  (let ((orig-file (make-temp-file "pgg"))
+       (args '("+verbose=1" "+batchmode=1" "+language=us"))
+       (orig-mode (default-file-modes)))
+    (unwind-protect
+       (progn
+         (set-default-file-modes 448)
+         (binary-write-decoded-region start end orig-file))
+      (set-default-file-modes orig-mode))
+    (when (stringp signature)
+      (copy-file signature (setq signature (concat orig-file ".asc")))
+      (setq args (append args (list signature))))
+    (pgg-pgp5-process-region (point)(point) nil pgg-pgp5-pgpv-program args)
+    (delete-file orig-file)
+    (if signature (delete-file signature))
+    (with-current-buffer pgg-errors-buffer
+      (goto-char (point-min))
+      (if (re-search-forward "^Good signature" nil t)
+         (progn
+           (set-buffer pgg-output-buffer)
+           (insert-buffer-substring pgg-errors-buffer)
+           t)
+       nil))))
+
+(luna-define-method pgg-scheme-insert-key ((scheme pgg-scheme-pgp5))
+  (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
+        (args
+         (list "+verbose=1" "+batchmode=1" "+language=us" "-x"
+               (concat "\"" pgg-pgp5-user-id "\""))))
+    (pgg-pgp5-process-region (point)(point) nil pgg-pgp5-pgpk-program args)
+    (insert-buffer-substring pgg-output-buffer)))
+
+(luna-define-method pgg-scheme-snarf-keys-region ((scheme pgg-scheme-pgp5)
+                                                 start end)
+  (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
+        (key-file (make-temp-file "pgg"))
+        (args
+         (list "+verbose=1" "+batchmode=1" "+language=us" "-a"
+               key-file)))
+    (let ((coding-system-for-write 'raw-text-dos))
+      (write-region start end key-file))
+    (pgg-pgp5-process-region start end nil pgg-pgp5-pgpk-program args)
+    (delete-file key-file)
+    (pgg-process-when-success nil)))
+
+(provide 'pgg-pgp5)
+
+;;; pgg-pgp5.el ends here
diff --git a/pgg.el b/pgg.el
new file mode 100644 (file)
index 0000000..ad7ae22
--- /dev/null
+++ b/pgg.el
@@ -0,0 +1,431 @@
+;;; pgg.el --- glue for the various PGP implementations.
+
+;; Copyright (C) 1999,2000 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Created: 1999/10/28
+;; Keywords: PGP
+
+;; This file is part of SEMI (Secure Emacs MIME Interface).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+
+;;; Commentary:
+;; 
+
+;;; Code:
+
+(require 'calist)
+
+(eval-and-compile (require 'luna))
+
+(require 'pgg-def)
+(require 'pgg-parse)
+
+(eval-when-compile
+  (ignore-errors
+    (require 'w3)
+    (require 'url)))
+
+(in-calist-package 'pgg)
+
+(defun pgg-field-match-method-with-containment
+  (calist field-type field-value)
+  (let ((s-field (assq field-type calist)))
+    (cond ((null s-field)
+          (cons (cons field-type field-value) calist))
+         ((memq (cdr s-field) field-value)
+          calist))))
+
+(define-calist-field-match-method 'signature-version
+  #'pgg-field-match-method-with-containment)
+
+(define-calist-field-match-method 'symmetric-key-algorithm
+  #'pgg-field-match-method-with-containment)
+
+(define-calist-field-match-method 'public-key-algorithm
+  #'pgg-field-match-method-with-containment)
+
+(define-calist-field-match-method 'hash-algorithm
+  #'pgg-field-match-method-with-containment)
+
+(defvar pgg-verify-condition nil
+  "Condition-tree about which PGP implementation is used for verifying.")
+
+(defvar pgg-decrypt-condition nil
+  "Condition-tree about which PGP implementation is used for decrypting.")
+
+(ctree-set-calist-strictly
+ 'pgg-verify-condition
+ '((signature-version 3)(public-key-algorithm RSA)(hash-algorithm MD5)
+   (scheme . pgp)))
+
+(ctree-set-calist-strictly
+ 'pgg-decrypt-condition
+ '((public-key-algorithm RSA)(symmetric-key-algorithm IDEA)
+   (scheme . pgp)))
+
+(ctree-set-calist-strictly
+ 'pgg-verify-condition
+ '((signature-version 3 4)
+   (public-key-algorithm RSA ELG DSA)
+   (hash-algorithm MD5 SHA1 RIPEMD160)
+   (scheme . pgp5)))
+
+(ctree-set-calist-strictly
+ 'pgg-decrypt-condition
+ '((public-key-algorithm RSA ELG DSA)
+   (symmetric-key-algorithm 3DES CAST5 IDEA)
+   (scheme . pgp5)))
+
+(ctree-set-calist-strictly
+ 'pgg-verify-condition
+ '((signature-version 3 4)
+   (public-key-algorithm ELG-E DSA ELG)
+   (hash-algorithm MD5 SHA1 RIPEMD160)
+   (scheme . gpg)))
+
+(ctree-set-calist-strictly
+ 'pgg-decrypt-condition
+ '((public-key-algorithm ELG-E DSA ELG)
+   (symmetric-key-algorithm
+    3DES CAST5 BLOWFISH RIJNDAEL RIJNDAEL192 RIJNDAEL256 TWOFISH)
+   (scheme . gpg)))
+
+;;; @ definition of the implementation scheme
+;;;
+
+(eval-and-compile
+  (luna-define-class pgg-scheme ())
+
+  (luna-define-internal-accessors 'pgg-scheme))
+
+(luna-define-generic pgg-scheme-lookup-key (scheme string &optional type)
+  "Search keys associated with STRING.")
+
+(luna-define-generic pgg-scheme-encrypt-region (scheme start end recipients)
+  "Encrypt the current region between START and END.")
+
+(luna-define-generic pgg-scheme-decrypt-region (scheme start end)
+  "Decrypt the current region between START and END.")
+
+(luna-define-generic pgg-scheme-sign-region
+  (scheme start end &optional cleartext)
+  "Make detached signature from text between START and END.")
+
+(luna-define-generic pgg-scheme-verify-region
+  (scheme start end &optional signature)
+  "Verify region between START and END as the detached signature SIGNATURE.")
+
+(luna-define-generic pgg-scheme-insert-key (scheme)
+  "Insert public key at point.")
+
+(luna-define-generic pgg-scheme-snarf-keys-region (scheme start end)
+  "Add all public keys in region between START and END to the keyring.")
+
+;;; @ utility functions
+;;;
+
+(defvar pgg-fetch-key-function (function pgg-fetch-key-with-w3))
+
+(defmacro pgg-make-scheme (scheme)
+  `(progn
+     (require (intern (format "pgg-%s" ,scheme)))
+     (funcall (intern (format "pgg-make-scheme-%s"
+                             ,scheme)))))
+
+(put 'pgg-save-coding-system 'lisp-indent-function 2)
+
+(defmacro pgg-save-coding-system (start end &rest body)
+  `(if (interactive-p)
+       (let ((buffer (current-buffer)))
+        (with-temp-buffer
+          (let (buffer-undo-list)
+            (insert-buffer-substring buffer ,start ,end)
+            (encode-coding-region (point-min)(point-max)
+                                  buffer-file-coding-system)
+            (prog1 (save-excursion ,@body)
+              (push nil buffer-undo-list)
+              (ignore-errors (undo))))))
+     (save-restriction
+       (narrow-to-region ,start ,end)
+       ,@body)))
+
+(defun pgg-temp-buffer-show-function (buffer)
+  (let ((window (split-window-vertically)))
+    (set-window-buffer window buffer)
+    (shrink-window-if-larger-than-buffer window)))
+
+(defun pgg-display-output-buffer (start end status)
+  (if status
+      (progn
+       (delete-region start end)
+       (insert-buffer-substring pgg-output-buffer)
+       (decode-coding-region start (point) buffer-file-coding-system))
+    (let ((temp-buffer-show-function
+          (function pgg-temp-buffer-show-function)))
+      (with-output-to-temp-buffer pgg-echo-buffer
+       (set-buffer standard-output)
+       (insert-buffer-substring pgg-errors-buffer)))))
+
+(defvar pgg-passphrase-cache-expiry 16)
+(defvar pgg-passphrase-cache (make-vector 7 0))
+
+(defvar pgg-read-passphrase nil)
+(defun pgg-read-passphrase (prompt &optional key)
+  (if (not pgg-read-passphrase)
+      (if (functionp 'read-passwd)
+         (setq pgg-read-passphrase 'read-passwd)
+       (if (load "passwd" t)
+           (setq pgg-read-passphrase 'read-passwd)
+         (autoload 'ange-ftp-read-passwd "ange-ftp")
+         (setq pgg-read-passphrase 'ange-ftp-read-passwd))))
+  (or (and pgg-cache-passphrase
+          key (setq key (pgg-truncate-key-identifier key))
+          (symbol-value (intern-soft key pgg-passphrase-cache)))
+      (funcall pgg-read-passphrase prompt)))
+
+(defun pgg-add-passphrase-cache (key passphrase)
+  (setq key (pgg-truncate-key-identifier key))
+  (set (intern key pgg-passphrase-cache)
+       passphrase)
+  (run-at-time pgg-passphrase-cache-expiry nil
+              #'pgg-remove-passphrase-cache
+              key))
+
+(defun pgg-remove-passphrase-cache (key)
+  (let ((passphrase (symbol-value (intern-soft key pgg-passphrase-cache))))
+    (when passphrase
+      (fillarray passphrase ?_)
+      (unintern key pgg-passphrase-cache))))
+
+(defmacro pgg-convert-lbt-region (start end lbt)
+  `(let ((pgg-conversion-end (set-marker (make-marker) ,end)))
+     (goto-char ,start)
+     (case ,lbt
+       (CRLF
+       (while (progn
+                (end-of-line)
+                (> (marker-position pgg-conversion-end) (point)))
+         (insert "\r")
+         (forward-line 1)))
+       (LF
+       (while (re-search-forward "\r$" pgg-conversion-end t)
+         (replace-match ""))))))
+
+(put 'pgg-as-lbt 'lisp-indent-function 3)
+
+(defmacro pgg-as-lbt (start end lbt &rest body)
+  `(let ((inhibit-read-only t)
+        buffer-read-only
+        buffer-undo-list)
+     (pgg-convert-lbt-region ,start ,end ,lbt)
+     (let ((,end (point)))
+       ,@body)
+     (push nil buffer-undo-list)
+     (ignore-errors (undo))))
+
+(put 'pgg-process-when-success 'lisp-indent-function 0)
+
+(defmacro pgg-process-when-success (&rest body)
+  `(with-current-buffer pgg-output-buffer
+     (if (zerop (buffer-size)) nil ,@body t)))
+
+
+;;; @ interface functions
+;;;
+
+;;;###autoload
+(defun pgg-encrypt-region (start end rcpts)
+  "Encrypt the current region between START and END for RCPTS."
+  (interactive
+   (list (region-beginning)(region-end)
+        (split-string (read-string "Recipients: ") "[ \t,]+")))
+  (let* ((entity (pgg-make-scheme pgg-default-scheme))
+        (status
+         (pgg-save-coding-system start end
+           (pgg-scheme-encrypt-region entity (point-min)(point-max) rcpts))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-decrypt-region (start end)
+  "Decrypt the current region between START and END."
+  (interactive "r")
+  (let* ((packet (cdr (assq 1 (pgg-parse-armor-region start end))))
+        (scheme
+         (or pgg-scheme
+             (cdr (assq 'scheme
+                        (progn
+                          (in-calist-package 'pgg)
+                          (ctree-match-calist pgg-decrypt-condition
+                                              packet))))
+             pgg-default-scheme))
+        (entity (pgg-make-scheme scheme))
+        (status
+         (pgg-save-coding-system start end
+           (pgg-scheme-decrypt-region entity (point-min)(point-max)))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-sign-region (start end &optional cleartext)
+  "Make the signature from text between START and END.
+If the optional 3rd argument CLEARTEXT is non-nil, it does not create
+a detached signature."
+  (interactive "r")
+  (let* ((entity (pgg-make-scheme pgg-default-scheme))
+        (status (pgg-save-coding-system start end
+                  (pgg-scheme-sign-region entity (point-min)(point-max)
+                                          (or (interactive-p) cleartext)))))
+    (when (interactive-p)
+      (pgg-display-output-buffer start end status))
+    status))
+
+;;;###autoload
+(defun pgg-verify-region (start end &optional signature fetch)
+  "Verify the current region between START and END.
+If the optional 3rd argument SIGNATURE is non-nil, it is treated as
+the detached signature of the current region.
+
+If the optional 4th argument FETCH is non-nil, we attempt to fetch the
+signer's public key from `pgg-default-keyserver-address'."
+  (interactive "r")
+  (let* ((packet
+         (if (null signature) nil
+           (with-temp-buffer
+             (buffer-disable-undo)
+             (set-buffer-multibyte nil)
+             (insert-file-contents signature)
+             (cdr (assq 2 (pgg-decode-armor-region
+                           (point-min)(point-max)))))))
+        (scheme
+         (or pgg-scheme
+             (cdr (assq 'scheme
+                        (progn
+                          (in-calist-package 'pgg)
+                          (ctree-match-calist pgg-verify-condition
+                                              packet))))
+             pgg-default-scheme))
+        (entity (pgg-make-scheme scheme))
+        (key (cdr (assq 'key-identifier packet)))
+        status keyserver)
+    (and (stringp key)
+        (setq key (concat "0x" (pgg-truncate-key-identifier key)))
+        (null (let ((pgg-scheme scheme))
+                (pgg-lookup-key key)))
+        (or fetch (interactive-p))
+        (y-or-n-p (format "Key %s not found; attempt to fetch? " key))
+        (setq keyserver
+              (or (cdr (assq 'preferred-key-server packet))
+                  pgg-default-keyserver-address))
+        (pgg-fetch-key keyserver key))
+    (setq status (pgg-save-coding-system start end
+                  (pgg-scheme-verify-region entity (point-min)(point-max)
+                                            signature)))
+    (when (interactive-p)
+      (let ((temp-buffer-show-function
+            (function pgg-temp-buffer-show-function)))
+       (with-output-to-temp-buffer pgg-echo-buffer
+         (set-buffer standard-output)
+         (insert-buffer-substring (if status pgg-output-buffer
+                                    pgg-errors-buffer)))))
+    status))
+
+;;;###autoload
+(defun pgg-insert-key ()
+  "Insert the ASCII armored public key."
+  (interactive)
+  (let ((entity (pgg-make-scheme (or pgg-scheme pgg-default-scheme))))
+    (pgg-scheme-insert-key entity)))
+
+;;;###autoload
+(defun pgg-snarf-keys-region (start end)
+  "Import public keys in the current region between START and END."
+  (interactive "r")
+  (let ((entity (pgg-make-scheme (or pgg-scheme pgg-default-scheme))))
+    (pgg-save-coding-system start end
+      (pgg-scheme-snarf-keys-region entity start end))))
+
+(defun pgg-lookup-key (string &optional type)
+  (let ((entity (pgg-make-scheme (or pgg-scheme pgg-default-scheme))))
+    (pgg-scheme-lookup-key entity string type)))
+
+(defvar pgg-insert-url-function  (function pgg-insert-url-with-w3))
+
+(defun pgg-insert-url-with-w3 (url)
+  (require 'w3)
+  (require 'url)
+  (let (buffer-file-name)
+    (url-insert-file-contents url)))
+
+(defvar pgg-insert-url-extra-arguments nil)
+(defvar pgg-insert-url-program nil)
+
+(defun pgg-insert-url-with-program (url)
+  (let ((args (copy-sequence pgg-insert-url-extra-arguments))
+       process)
+    (insert
+     (with-temp-buffer
+       (setq process
+            (apply #'start-process " *PGG url*" (current-buffer)
+                   pgg-insert-url-program (nconc args (list url))))
+       (set-process-sentinel process #'ignore)
+       (while (eq 'run (process-status process))
+        (accept-process-output process 5))
+       (delete-process process)
+       (if (and process (eq 'run (process-status process)))
+          (interrupt-process process))
+       (buffer-string)))))
+
+(defun pgg-fetch-key (keyserver key)
+  "Attempt to fetch a KEY from KEYSERVER for addition to PGP or GnuPG keyring."
+  (with-current-buffer (get-buffer-create pgg-output-buffer)
+    (buffer-disable-undo)
+    (erase-buffer)
+    (let ((proto (if (string-match "^[a-zA-Z\\+\\.\\\\-]+:" keyserver)
+                    (substring keyserver 0 (1- (match-end 0))))))
+      (save-excursion
+       (funcall pgg-insert-url-function
+                (if proto keyserver
+                  (format "http://%s:11371/pks/lookup?op=get&search=%s"
+                          keyserver key))))
+      (when (re-search-forward "^-+BEGIN" nil 'last)
+       (delete-region (point-min) (match-beginning 0))
+       (when (re-search-forward "^-+END" nil t)
+         (delete-region (progn (end-of-line) (point))
+                        (point-max)))
+       (insert "\n")
+       (with-temp-buffer
+         (insert-buffer-substring pgg-output-buffer)
+         (pgg-snarf-keys-region (point-min)(point-max)))))))
+
+;;;###autoload
+(defun pgg-universal-user-id-argument ()
+  (interactive)
+  (let* ((pgg-overriding-user-id (read-string "User ID: "))
+        (command (key-binding (read-key-sequence
+                               (format "Command to execute on \"%s\":"
+                                       pgg-overriding-user-id)))))
+    (message "")
+    (call-interactively command)))
+
+(provide 'pgg)
+
+;;; pgg.el ends here
diff --git a/pgg.texi b/pgg.texi
new file mode 100644 (file)
index 0000000..cbb305a
--- /dev/null
+++ b/pgg.texi
@@ -0,0 +1,414 @@
+\input texinfo                  @c -*-texinfo-*-
+
+@setfilename pgg.info
+
+@set VERSION 0.1
+
+@direntry
+* PGG: (pgg).   Emacs interface to various PGP implementations.
+@end direntry
+
+@settitle PGG @value{VERSION}
+
+@ifinfo
+This file describes the PGG.
+
+Copyright (C) 2001 Daiki Ueno.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
+Texts.  A copy of the license is included in the section entitled "GNU
+Free Documentation License".
+@end ifinfo
+
+@tex
+
+@titlepage
+@title PGG
+
+@author by Daiki Ueno
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 2001 Daiki Ueno.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
+Texts.  A copy of the license is included in the section entitled "GNU
+Free Documentation License".
+@end titlepage
+@page
+
+@end tex
+
+@node Top
+@top PGG
+This manual describes PGG.  PGG is an interface library between Emacs
+and various tools for secure communication.  PGG also provides a simple
+user interface to encrypt, decrypt, sign, and verify MIME messages.
+
+@menu
+* Overview::                    What PGG is.
+* Prerequisites::               Complicated stuff you may have to do.
+* How to use::                  Getting started quickly.
+* Architecture::                
+* Parsing OpenPGP packets::     
+* Function Index::              
+* Variable Index::              
+@end menu
+
+@node Overview
+@chapter Overview
+
+PGG is an interface library between Emacs and various tools for secure
+communication.  Even though Mailcrypt has similar feature, it does not
+deal with detached PGP messages, normally used in PGP/MIME
+infrastructure.  This was the main reason why I wrote the new library.
+
+PGP/MIME is an application of MIME Object Security Services (RFC1848).
+The standard is documented in RFC2015.
+
+@node Prerequisites
+@chapter Prerequisites
+
+PGG requires at least one implementation of privacy guard system.
+This document assumes that you have already obtained and installed them
+and that you are familiar with its basic functions.
+
+By default, PGG uses GnuPG, but Pretty Good Privacy version 2 or version
+5 are also supported.  If you are new to such a system, I recomend that
+you should look over the GNU Privacy Handbook (GPH) which is available
+at @uref{http://www.gnupg.org/gph/}.
+
+@node How to use
+@chapter How to use
+
+The toplevel interface of this library is quite simple, and only
+intended to use with public-key cryptographic operation.
+
+To use PGG, evaluate following expression at the beginning of your
+application program.
+
+@lisp
+(require 'pgg)
+@end lisp
+
+If you want to check existence of pgg.el at runtime, instead you can
+list autoload setting for desired functions as follows.
+
+@lisp
+(autoload 'pgg-encrypt-region "pgg"
+  "Encrypt the current region." t)
+(autoload 'pgg-decrypt-region "pgg"
+  "Decrypt the current region." t)
+(autoload 'pgg-sign-region "pgg"
+  "Sign the current region." t)
+(autoload 'pgg-verify-region "pgg"
+  "Verify the current region." t)
+(autoload 'pgg-insert-key "pgg"
+  "Insert the ASCII armored public key." t)
+(autoload 'pgg-snarf-keys-region "pgg"
+  "Import public keys in the current region." t)
+@end lisp
+
+@menu
+* User Commands::               
+* Selecting an implementation::  
+* Caching passphrase::          
+@end menu
+
+@node User Commands
+@section User Commands
+
+At this time you can use some cryptographic commands.  The behavior of
+these commands relies on a fashion of invocation because they are also
+intended to be used as library functions.  In case you don't have the
+signer's public key, for example, the function @code{pgg-verify-region}
+fails immediately, but if the function had been called interactively, it
+would ask you to retrieve the signer's public key from the server.
+
+@deffn Command pgg-encrypt-region start end recipients
+Encrypt the current region between @var{start} and @var{end} for
+@var{recipients}.  When the function were called interactively, you
+would be asked about the recipients.
+
+If encryption is successful, it replaces the current region contents (in
+the accessible portion) with the resulting data.
+@end deffn
+
+@deffn Command pgg-decrypt-region start end
+Decrypt the current region between @var{start} and @var{end}.  If
+decryption is successful, it replaces the current region contents (in
+the accessible portion) with the resulting data.
+@end deffn
+
+@deffn Command pgg-sign-region start end &optional cleartext
+Make the signature from text between @var{start} and @var{end}.  If the
+optional third argument @var{cleartext} is non-@code{nil}, or the
+function is called interactively, it does not create a detached
+signature.  In such a case, it replaces the current region contents (in
+the accessible portion) with the resulting data.
+@end deffn
+
+@deffn Command pgg-verify-region start end &optional signature fetch
+Verify the current region between @var{start} and @var{end}.  If the
+optional third argument @var{signature} is non-@code{nil}, or the function
+is called interactively, it is treated as the detached signature of the
+current region.
+
+If the optional 4th argument @var{fetch} is non-@code{nil}, or the
+function is called interactively, we attempt to fetch the signer's
+public key from the key server.
+@end deffn
+
+@deffn Command pgg-insert-key
+Retrieve the user's public key and insert it as ASCII-armored format.
+@end deffn
+
+@deffn Command pgg-snarf-keys-region start end
+Collect public keys in the current region between @var{start} and
+@var{end}, and add them into the user's keyring.
+@end deffn
+
+@node Selecting an implementation
+@section Selecting an implementation
+
+Since PGP has a long history and there are a number of PGP
+implementations available today, the function which each one has differs
+considerably.  For example, if you are using GnuPG, you know you can
+select cipher algorithm from 3DES, CAST5, BLOWFISH, and so on, but on
+the other hand the version 2 of PGP only supports IDEA.
+
+By default, if the variable @var{pgg-scheme} is not set, PGG searches the
+registered scheme for an implementation of the requested service
+associated with the named algorithm.  If there are no match, PGG uses
+@var{pgg-default-scheme}.  In other words, there are two options to
+control which command is used to process the incoming PGP armors.  One
+is for encrypting and signing, the other is for decrypting and
+verifying.
+
+@defvar pgg-scheme
+Force specify the scheme of PGP implementation for decrypting and verifying.
+The value can be @code{gpg}, @code{pgp}, and @code{pgp5}.
+@end defvar
+
+@defvar pgg-default-scheme
+Force specify the scheme of PGP implementation for encrypting and signing.
+The value can be @code{gpg}, @code{pgp}, and @code{pgp5}.
+@end defvar
+
+@node Caching passphrase
+@section Caching passphrase
+
+PGG provides a simple passphrase caching mechanism.  If you want to
+arrange the interaction, set the variable @var{pgg-read-passphrase}.
+
+@defvar pgg-cache-passphrase
+If non-@code{nil}, store passphrases.  The default value of this
+variable is @code{t}.  If you were worry about security issue, however,
+you could stop caching with setting it @code{nil}.
+@end defvar
+
+@defvar pgg-passphrase-cache-expiry
+Elapsed time for expiration in seconds.
+@end defvar
+
+@node Architecture
+@chapter Architecture
+
+PGG introduces the notion of a "scheme of PGP implementation" (used
+interchangeably with "scheme" in this document).  This term refers to a
+singleton object wrapped with the luna object system.
+
+Since PGG was designed for accessing and developing PGP functionality,
+the architecture had to be designed not just for interoperablity but
+also for extensiblity.  In this chapter we explore the architecture
+while finding out how to write the PGG backend.
+
+@menu
+* Initializing::                
+* Backend methods::             
+* Getting output::              
+* Registering backend::         
+@end menu
+
+@node Initializing
+@section Initializing
+
+A scheme must be initialized before it is used.
+It had better guarantee to keep only one instance of a scheme.
+
+The following code is snipped out of @file{pgg-gpg.el}.  Once an
+instance of @code{pgg-gpg} scheme is initialized, it's stored to the
+variable @var{pgg-scheme-gpg-instance} and will be reused from now on.
+
+@lisp
+(defvar pgg-scheme-gpg-instance nil)
+
+(defun pgg-make-scheme-gpg ()
+  (or pgg-scheme-gpg-instance
+      (setq pgg-scheme-gpg-instance
+           (luna-make-entity 'pgg-scheme-gpg))))
+@end lisp
+
+The name of the function must follow the
+regulation---@code{pgg-make-scheme-} follows the backend name.
+
+@node Backend methods
+@section Backend methods
+
+In each backend, these methods must be present.  The output of these
+methods is stored in special buffers (@ref{Getting output}), so that
+these methods must tell the status of the execution.
+
+@deffn Method pgg-scheme-lookup-key scheme string &optional type
+Return keys associated with @var{string}.  If the optional third
+argument @var{type} is non-@code{nil}, it searches from the secret
+keyrings.
+@end deffn
+
+@deffn Method pgg-scheme-encrypt-region scheme start end recipients
+Encrypt the current region between @var{start} and @var{end} for
+@var{recipients}.  If encryption is successful, it returns @code{t},
+otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-decrypt-region scheme start end
+Decrypt the current region between @var{start} and @var{end}.  If
+decryption is successful, it returns @code{t}, otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-sign-region scheme start end &optional cleartext
+Make the signature from text between @var{start} and @var{end}.  If the
+optional third argument @var{cleartext} is non-@code{nil}, it does not
+create a detached signature.  If signing is successful, it returns
+@code{t}, otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-verify-region scheme start end &optional signature
+Verify the current region between @var{start} and @var{end}.  If the
+optional third argument @var{signature} is non-@code{nil}, it is treated
+as the detached signature of the current region.  If the signature is
+successflly verified, it returns @code{t}, otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-insert-key scheme
+Retrieve the user's public key and insert it as ASCII-armored format.
+On success, it returns @code{t}, otherwise @code{nil}.
+@end deffn
+
+@deffn Method pgg-scheme-snarf-keys-region scheme start end
+Collect public keys in the current region between @var{start} and
+@var{end}, and add them into the user's keyring.
+On success, it returns @code{t}, otherwise @code{nil}.
+@end deffn
+
+@node Getting output
+@section Getting output
+
+The output of the backend methods (@ref{Backend methods}) is stored in
+special buffers, so that these methods must tell the status of the
+execution.
+
+@defvar pgg-errors-buffer
+The standard error output of the execution of the PGP command is stored
+here.
+@end defvar
+
+@defvar pgg-output-buffer
+The standard output of the execution of the PGP command is stored here.
+@end defvar
+
+@defvar pgg-status-buffer
+The rest of status information of the execution of the PGP command is
+stored here.
+@end defvar
+
+@node Registering backend
+@section Registering backend
+
+When decrypting and verifying PGG searches the registered scheme for an
+implementation from @var{pgg-verify-condition} and
+@var{pgg-decrypt-condition}.  These variable hold capability information
+of backend implementations.
+
+The @code{gpg} backend, for example, is registered as below:
+
+@lisp
+(ctree-set-calist-strictly
+ 'pgg-verify-condition
+ '((signature-version 3 4)
+   (public-key-algorithm ELG-E DSA ELG)
+   (hash-algorithm MD5 SHA1 RIPEMD160)
+   (scheme . gpg)))
+
+(ctree-set-calist-strictly
+ 'pgg-decrypt-condition
+ '((public-key-algorithm ELG-E DSA ELG)
+   (symmetric-key-algorithm 3DES CAST5 BLOWFISH TWOFISH)
+   (scheme . gpg)))
+@end lisp
+
+The former expression says:
+
+@itemize
+@item
+the backend @code{gpg} supports version 3 and 4 of the signature format
+@item
+the backend @code{gpg} supports ELG-E, DSA, and ELG as public-key
+algorithm for signing
+@item
+the backend @code{gpg} supports MD5, SHA1, and RIPEMD160 as hash
+algorithm for signing
+@end itemize
+
+And the latter expression says:
+
+@itemize
+@item
+the backend @code{gpg} supports ELG-E, DSA, and ELG as public-key
+algorithm for decrypting
+@item
+the backend @code{gpg} supports 3DES, CAST5, BLOWFISH, and TWOFISH as
+cipher algorithm for decrypting.
+@end itemize
+
+@node Parsing OpenPGP packets
+@chapter Parsing OpenPGP packets
+
+The format of OpenPGP messages is maintained in order to publish all
+necessary information needed to develop interoperable applications.
+The standard is documented in RFC 2440.
+
+PGG has its own parser for the OpenPGP packets.
+
+@defun pgg-parse-armor string
+List the sequence of packets in @var{string}.
+@end defun
+
+@defun pgg-parse-armor-region start end
+List the sequence of packets in the current region between @var{start}
+and @var{end}.
+@end defun
+
+@defvar pgg-ignore-packet-checksum
+If non-@code{nil}, don't check the checksum of the packets.
+@end defvar
+
+@node Function Index
+@chapter Function Index
+@printindex fn
+
+@node Variable Index
+@chapter Variable Index
+@printindex vr
+
+@summarycontents
+@contents
+@bye
+
+@c End:
diff --git a/postpet.el b/postpet.el
new file mode 100644 (file)
index 0000000..a88ebb7
--- /dev/null
@@ -0,0 +1,153 @@
+;;; postpet.el --- Postpet support for GNU Emacs
+
+;; Copyright (C) 1999,2000 Free Software Foundation, Inc.
+
+;; Author: Tanaka Akira  <akr@jaist.ac.jp>
+;; Keywords: Postpet, MIME, multimedia, mail, news
+
+;; This file is part of SEMI (Sample of Elastic MIME Interfaces).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+(require 'mime)
+(require 'alist)
+
+(put 'unpack 'lisp-indent-function 1)
+(defmacro unpack (string &rest body)
+  `(let* ((*unpack*string* (string-as-unibyte ,string))
+         (*unpack*index* 0))
+     ,@body))
+
+(defun unpack-skip (len)
+  (setq *unpack*index* (+ len *unpack*index*)))
+
+(defun unpack-fixed (len)
+  (prog1
+      (substring *unpack*string* *unpack*index* (+ *unpack*index* len))
+    (unpack-skip len)))
+
+(defun unpack-byte ()
+  (char-int (aref (unpack-fixed 1) 0)))
+
+(defun unpack-short ()
+  (let* ((b0 (unpack-byte))
+        (b1 (unpack-byte)))
+    (+ (* 256 b0) b1)))
+
+(defun unpack-long ()
+  (let* ((s0 (unpack-short))
+        (s1 (unpack-short)))
+    (+ (* 65536 s0) s1)))
+
+(defun unpack-string ()
+  (let ((len (unpack-byte)))
+    (unpack-fixed len)))
+
+(defun unpack-string-sjis ()
+  (decode-mime-charset-string (unpack-string) 'shift_jis))
+
+;;;###autoload
+(defun postpet-decode (string)
+  (condition-case nil
+      (unpack string
+       (let (res)
+         (unpack-skip 4)
+         (set-alist 'res 'carryingcount (unpack-long))
+         (unpack-skip 8)
+         (set-alist 'res 'sentyear (unpack-short))
+         (set-alist 'res 'sentmonth (unpack-short))
+         (set-alist 'res 'sentday (unpack-short))
+         (unpack-skip 8)
+         (set-alist 'res 'petname (unpack-string-sjis))
+         (set-alist 'res 'owner (unpack-string-sjis))
+         (set-alist 'res 'pettype (unpack-fixed 4))
+         (set-alist 'res 'health (unpack-short))
+         (unpack-skip 2)
+         (set-alist 'res 'sex (unpack-long))
+         (unpack-skip 1)
+         (set-alist 'res 'brain (unpack-byte))
+         (unpack-skip 39)
+         (set-alist 'res 'happiness (unpack-byte))
+         (unpack-skip 14)
+         (set-alist 'res 'petbirthyear (unpack-short))
+         (set-alist 'res 'petbirthmonth (unpack-short))
+         (set-alist 'res 'petbirthday (unpack-short))
+         (unpack-skip 8)
+         (set-alist 'res 'from (unpack-string))
+         (unpack-skip 5)
+         (unpack-skip 160)
+         (unpack-skip 4)
+         (unpack-skip 8)
+         (unpack-skip 8)
+         (unpack-skip 26)
+         (set-alist 'res 'treasure (unpack-short))
+         (set-alist 'res 'money (unpack-long))
+         res))
+    (error nil)))
+
+;;;###autoload
+(defun mime-display-application/x-postpet (entity situation)
+  (save-restriction
+    (narrow-to-region (point-max)(point-max))
+    (let ((pet (postpet-decode (mime-entity-content entity))))
+      (if pet
+         (insert
+          "Petname: " (cdr (assq 'petname pet))
+          "\n"
+          "Owner: " (cdr (assq 'owner pet))
+          "\n"
+          "Pettype: " (cdr (assq 'pettype pet))
+          "\n"
+          "From: " (cdr (assq 'from pet))
+          "\n"
+          "CarryingCount: " (int-to-string (cdr (assq 'carryingcount pet)))
+          "\n"
+          "SentYear: " (int-to-string (cdr (assq 'sentyear pet)))
+          "\n"
+          "SentMonth: " (int-to-string (cdr (assq 'sentmonth pet)))
+          "\n"
+          "SentDay: " (int-to-string (cdr (assq 'sentday pet)))
+          "\n"
+          "PetbirthYear: " (int-to-string (cdr (assq 'petbirthyear pet)))
+          "\n"
+          "PetbirthMonth: " (int-to-string (cdr (assq 'petbirthmonth pet)))
+          "\n"
+          "PetbirthDay: " (int-to-string (cdr (assq 'petbirthday pet)))
+          "\n"
+          "Health: " (int-to-string (cdr (assq 'health pet)))
+          "\n"
+          "Sex: " (int-to-string (cdr (assq 'sex pet)))
+          "\n"
+          "Brain: " (int-to-string (cdr (assq 'brain pet)))
+          "\n"
+          "Happiness: " (int-to-string (cdr (assq 'happiness pet)))
+          "\n"
+          "Treasure: " (int-to-string (cdr (assq 'treasure pet)))
+          "\n"
+          "Money: " (int-to-string (cdr (assq 'money pet)))
+          "\n")
+       (insert "Invalid format\n"))
+      (run-hooks 'mime-display-application/x-postpet-hook))))
+
+
+;;; @ end
+;;;
+
+(provide 'postpet)
+
+;;; postpet.el ends here
index 62baefd..d4b13e7 100644 (file)
@@ -1,6 +1,6 @@
 ;;; semi-def.el --- definition module for SEMI -*- coding: iso-8859-4; -*-
 
-;; Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
+;; Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
 
 ;; Author: MORIOKA Tomohiko <tomo@m17n.org>
 ;; Keywords: definition, MIME, multimedia, mail, news
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
-(require 'poe)
-
 (eval-when-compile (require 'cl))
 
 (require 'custom)
 
-(defconst mime-user-interface-product ["SEMI" (1 13 7) "Awazu"]
+(defconst mime-user-interface-product ["EMIKO" (1 14 1) "Choanoflagellata"]
   "Product name, version number and code name of MIME-kernel package.")
 
 (autoload 'mule-caesar-region "mule-caesar"
   "Caesar rotation of current region." t)
 
+(autoload 'widget-convert-button "wid-edit")
 
 ;;; @ constants
 ;;;
 ;;; @ button
 ;;;
 
-(defcustom mime-button-face 'bold
-  "Face used for content-button or URL-button of MIME-Preview buffer."
-  :group 'mime
-  :type 'face)
-
-(defcustom mime-button-mouse-face 'highlight
-  "Face used for MIME-preview buffer mouse highlighting."
-  :group 'mime
-  :type 'face)
-
-(defsubst mime-add-button (from to function &optional data)
-  "Create a button between FROM and TO with callback FUNCTION and DATA."
-  (let ((overlay (make-overlay from to)))
-    (and mime-button-face
-        (overlay-put overlay 'face mime-button-face))
-    (and mime-button-mouse-face
-        (overlay-put overlay 'mouse-face mime-button-mouse-face))
-    (add-text-properties from to (list 'mime-button-callback function))
-    (and data
-        (add-text-properties from to (list 'mime-button-data data)))
-    ))
+(define-widget 'mime-button 'link
+  "Widget for MIME button."
+  :action 'mime-button-action)
 
+(defun mime-button-action (widget &optional event)
+  (let ((function (widget-get widget :mime-button-callback))
+       (data (widget-get widget :mime-button-data)))
+    (when function
+      (funcall function data))))
+    
 (defsubst mime-insert-button (string function &optional data)
   "Insert STRING as button with callback FUNCTION and DATA."
   (save-restriction
     (narrow-to-region (point)(point))
-    (insert (concat "[" string "]\n"))
-    (mime-add-button (point-min)(point-max) function data)
-    ))
-
-(defvar mime-button-mother-dispatcher nil)
-
-(defun mime-button-dispatcher (event)
-  "Select the button under point."
-  (interactive "e")
-  (let (buf point func data)
-    (save-window-excursion
-      (mouse-set-point event)
-      (setq buf (current-buffer)
-           point (point)
-           func (get-text-property (point) 'mime-button-callback)
-           data (get-text-property (point) 'mime-button-data)
-           ))
-    (save-excursion
-      (set-buffer buf)
-      (goto-char point)
-      (if func
-         (apply func data)
-       (if (fboundp mime-button-mother-dispatcher)
-           (funcall mime-button-mother-dispatcher event)
-         )))))
+    ;; Maybe we should introduce button formatter such as
+    ;; `gnus-mime-button-line-format'.
+    (insert "[" string "]")
+    ;; XEmacs -- when `widget-glyph-enable' is non nil, widget values are not
+    ;; guaranteed to be underlain.
+    (widget-convert-button 'mime-button (point-min)(point-max)
+                          :mime-button-callback function
+                          :mime-button-data data)
+    (insert "\n")))
 
 
 ;;; @ for URL
 ;;;
 
 (defcustom mime-browse-url-regexp
-  (concat "\\(http\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):"
+  (concat "\\(https?\\|ftps?\\|file\\|gopher\\|news\\|nntps?\\|telnets?\\|wais\\|mailto\\):"
          "\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?"
-         "[-a-zA-Z0-9_=?#$@~`%&*+|\\/.,]*[-a-zA-Z0-9_=#$@~`%&*+|\\/]")
-  "*Regexp to match URL in text body."
+         "[-a-zA-Z0-9_=?#$@~`%&*+|\\/.,;]*[-a-zA-Z0-9_=#$@~`%&*+|\\/;]")
+  "Regexp to match URL in text body."
   :group 'mime
   :type 'regexp)
 
 (defcustom mime-browse-url-function (function browse-url)
-  "*Function to browse URL."
+  "Function to browse URL."
   :group 'mime
   :type 'function)
 
+(define-widget 'mime-url-link 'url-link
+  "A link to an www page.")
+
 (defsubst mime-add-url-buttons ()
   "Add URL-buttons for text body."
   (goto-char (point-min))
   (while (re-search-forward mime-browse-url-regexp nil t)
-    (let ((beg (match-beginning 0))
-         (end (match-end 0)))
-      (mime-add-button beg end mime-browse-url-function
-                      (list (buffer-substring beg end))))))
+    (widget-convert-button 'mime-url-link (match-beginning 0)(match-end 0)
+                          (match-string-no-properties 0))))
 
 
 ;;; @ menu
 ;;;
 
-(if window-system
-    (if (featurep 'xemacs)
-       (defun select-menu-alist (title menu-alist)
-         (let (ret)
-           (popup-menu
-            (list* title
-                   "---"
-                   (mapcar (function
-                            (lambda (cell)
-                              (vector (car cell)
-                                      `(progn
-                                         (setq ret ',(cdr cell))
-                                         (throw 'exit nil)
-                                         )
-                                      t)
-                              ))
-                           menu-alist)
-                   ))
-           (recursive-edit)
-           ret))
-      (defun select-menu-alist (title menu-alist)
-       (x-popup-menu
-        (list '(1 1) (selected-window))
-        (list title (cons title menu-alist))
-        ))
-      )
-  (defun select-menu-alist (title menu-alist)
-    (cdr
-     (assoc (completing-read (concat title " : ") menu-alist)
-           menu-alist)
-     ))
-  )
-
-
-;;; @ PGP
-;;;
-
-(defvar pgp-function-alist
-  '(
-    ;; for mime-pgp
-    (verify            mc-verify                       "mc-toplev")
-    (decrypt           mc-decrypt                      "mc-toplev")
-    (fetch-key         mc-pgp-fetch-key                "mc-pgp")
-    (snarf-keys                mc-snarf-keys                   "mc-toplev")
-    ;; for mime-edit
-    (mime-sign         mime-mc-pgp-sign-region         "mime-mc")
-    (traditional-sign  mc-pgp-sign-region              "mc-pgp")
-    (encrypt           mime-mc-pgp-encrypt-region      "mime-mc")
-    (insert-key                mc-insert-public-key            "mc-toplev")
-    )
-  "Alist of service names vs. corresponding functions and its filenames.
-Each element looks like (SERVICE FUNCTION FILE).
-
-SERVICE is a symbol of PGP processing.  It allows `verify', `decrypt',
-`fetch-key', `snarf-keys', `mime-sign', `traditional-sign', `encrypt'
-or `insert-key'.
-
-Function is a symbol of function to do specified SERVICE.
-
-FILE is string of filename which has definition of corresponding
-FUNCTION.")
-
-(defmacro pgp-function (method)
-  "Return function to do service METHOD."
-  `(cadr (assq ,method (symbol-value 'pgp-function-alist))))
-
-(mapcar (function
-        (lambda (method)
-          (autoload (cadr method)(nth 2 method))
-          ))
-       pgp-function-alist)
+(defmacro mime-popup-menu-bogus-filter-constructor (menu)
+  ;; #### Kludge for FSF Emacs-style menu.
+  (let ((bogus-menu (make-symbol "bogus-menu")))
+    `(let (,bogus-menu selection function)
+       (easy-menu-define ,bogus-menu nil nil ,menu)
+       (setq selection (x-popup-menu t ,bogus-menu))
+       (when selection
+        (setq function (lookup-key ,bogus-menu (apply #'vector selection)))
+        ;; If a callback entry has no name, easy-menu wraps its value.
+        ;; See `easy-menu-make-symbol'.
+        (if (eq t (compare-strings "menu-function-" 0 nil
+                                   (symbol-name function) 0 14))
+            (car (last (symbol-function function)))
+          function)))))
+
+;;; While XEmacs can have both X and tty frames at the same time with
+;;; gnuclient, we shouldn't emulate in text-mode here.
+
+(static-if (featurep 'xemacs)
+    (defalias 'mime-popup-menu-popup 'popup-menu)
+  (defun mime-popup-menu-popup (menu &optional event)
+    (let ((function (mime-popup-menu-bogus-filter-constructor menu)))
+      (when (symbolp function)
+       (funcall function)))))
+
+(static-if (featurep 'xemacs)
+    (defun mime-popup-menu-select (menu &optional event)
+      (let ((selection (get-popup-menu-response menu event)))
+       (event-object selection)))
+  (defun mime-popup-menu-select (menu &optional event)
+    (mime-popup-menu-bogus-filter-constructor menu)))
+
+(static-if (featurep 'xemacs)
+    (defun mime-should-use-popup-menu ()
+      (mouse-event-p last-command-event))
+  (defun mime-should-use-popup-menu ()
+    (memq (event-basic-type last-command-event) '(mouse-1 mouse-2 mouse-3))))
+
+(defun mime-menu-select (prompt menu &optional event)
+  (if (mime-should-use-popup-menu)
+      (mime-popup-menu-select menu event)
+    (let ((rest (cdr menu)))
+      (while rest
+       (setcar rest (append (car rest) nil))
+       (setq rest (cdr rest)))
+      (nth 1 (assoc (completing-read prompt (cdr menu)) (cdr menu))))))
 
 
 ;;; @ Other Utility
@@ -233,13 +180,9 @@ activate."
                (funcall func sym condition)
                (if file
                    (let ((method (cdr (assq 'method condition))))
-                     (autoload method file)
-                     ))
-               )
-           (error "Function for mode `%s' is not found." mode)
-           ))
-      (error "Variable for target-type `%s' is not found." target-type)
-      )))
+                     (autoload method file))))
+           (error "Function for mode `%s' is not found." mode)))
+      (error "Variable for target-type `%s' is not found." target-type))))
 
 
 ;;; @ end
index 9928d1e..7a3aa11 100644 (file)
@@ -1,8 +1,8 @@
 ;;; semi-setup.el --- setup file for MIME-View.
 
-;; Copyright (C) 1994,1995,1996,1997,1998 Free Software Foundation, Inc.
+;; Copyright (C) 1994,95,96,97,98,99,2000 Free Software Foundation, Inc.
 
-;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Author: MORIOKA Tomohiko <tomo@m17n.org>
 ;; Keywords: mail, news, MIME, multimedia, multilingual, encoded-word
 
 ;; This file is part of SEMI (Setting for Emacs MIME Interfaces).
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code:
 
 (require 'semi-def)
-(require 'path-util)
-
-(defun call-after-loaded (module func &optional hook-name)
-  "If MODULE is provided, then FUNC is called.
-Otherwise func is set to MODULE-load-hook.
-If optional argument HOOK-NAME is specified,
-it is used as hook to set."
-  (if (featurep module)
-      (funcall func)
-    (or hook-name
-       (setq hook-name (intern (concat (symbol-name module) "-load-hook")))
-       )
-    (add-hook hook-name func)
-    ))
-
-
-;; for image/* and X-Face
+
+;; for image/*
 (defvar mime-setup-enable-inline-image
-  (and window-system
-       (or (featurep 'xemacs)
-          (and (featurep 'mule)(module-installed-p 'bitmap))
-          ))
+  (if (featurep 'xemacs)
+      (console-on-window-system-p)
+    window-system)
   "*If it is non-nil, semi-setup sets up to use mime-image.")
 
-(if mime-setup-enable-inline-image
-    (call-after-loaded 'mime-view
-                      (function
-                       (lambda ()
-                         (require 'mime-image)
-                         )))
-  )
-
+(eval-after-load "mime-view"
+  '(if mime-setup-enable-inline-image
+       (require 'mime-image)))
 
 ;; for text/html
 (defvar mime-setup-enable-inline-html
-  (module-installed-p 'w3)
+  (locate-library "w3")
   "*If it is non-nil, semi-setup sets up to use mime-w3.")
 
-(if mime-setup-enable-inline-html
-    (call-after-loaded
-     'mime-view
-     (function
-      (lambda ()
-       (autoload 'mime-preview-text/html "mime-w3")
-       
-       (ctree-set-calist-strictly
-        'mime-preview-condition
-        '((type . text)(subtype . html)
-          (body . visible)
-          (body-presentation-method . mime-preview-text/html)))
-       
-       (set-alist 'mime-view-type-subtype-score-alist
-                  '(text . html) 3)
-       )))
-  )
+(eval-after-load "mime-view"
+  '(when mime-setup-enable-inline-html
+     (autoload 'mime-preview-text/html "mime-w3")
+     (ctree-set-calist-strictly
+      'mime-preview-condition
+      '((type . text)(subtype . html)
+       (body . visible)
+       (body-presentation-method . mime-preview-text/html)))
+        
+     (set-alist 'mime-view-type-subtype-score-alist
+               '(text . html) 3)))
 
+;; for text/x-vcard
+(defvar mime-setup-enable-vcard
+  (locate-library "vcard")
+  "*If it is non-nil, semi-setup sets uf to use mime-vcard.")
+
+(eval-after-load "mime-view"
+  '(when mime-setup-enable-vcard
+     (autoload 'mime-display-text/x-vcard "mime-vcard")
+
+     (mime-add-condition
+      'preview 
+      '((type . text)(subtype . x-vcard)
+       (body . visible)
+       (body-presentation-method . mime-display-text/x-vcard))
+      'strict)
+
+     (set-alist 'mime-view-type-subtype-score-alist
+               '(text . x-vcard) 3)))
 
 ;; for PGP
-(defvar mime-setup-enable-pgp
-  (module-installed-p 'mailcrypt)
+(defvar mime-setup-enable-pgp t
   "*If it is non-nil, semi-setup sets uf to use mime-pgp.")
 
-(if mime-setup-enable-pgp
-    (eval-after-load "mime-view"
-      '(progn
-        (mime-add-condition
-         'preview '((type . application)(subtype . pgp)
-                    (message-button . visible)))
-        (mime-add-condition
-         'action '((type . application)(subtype . pgp)
-                   (method . mime-view-application/pgp))
-         'strict "mime-pgp")
-        (mime-add-condition
-         'action '((type . text)(subtype . x-pgp)
-                   (method . mime-view-application/pgp)))
+(eval-after-load "mime-view"
+  '(when mime-setup-enable-pgp
+     (mime-add-condition
+      'preview '((type . application)(subtype . pgp)
+                (message-button . visible)))
+     (mime-add-condition
+      'action '((type . application)(subtype . pgp)
+               (method . mime-view-application/pgp))
+      'strict "mime-pgp")
+     (mime-add-condition
+      'action '((type . text)(subtype . x-pgp)
+               (method . mime-view-application/pgp)))
         
-        (mime-add-condition
-         'action '((type . multipart)(subtype . signed)
-                   (method . mime-verify-multipart/signed))
-         'strict "mime-pgp")
+     (mime-add-condition
+      'action '((type . multipart)(subtype . signed)
+               (method . mime-verify-multipart/signed))
+      'strict "mime-pgp")
         
-        (mime-add-condition
-         'action
-         '((type . application)(subtype . pgp-signature)
-           (method . mime-verify-application/pgp-signature))
-         'strict "mime-pgp")
+     (mime-add-condition
+      'action
+      '((type . application)(subtype . pgp-signature)
+       (method . mime-verify-application/pgp-signature))
+      'strict "mime-pgp")
         
-        (mime-add-condition
-         'action
-         '((type . application)(subtype . pgp-encrypted)
-           (method . mime-decrypt-application/pgp-encrypted))
-         'strict "mime-pgp")
+     (mime-add-condition
+      'action
+      '((type . application)(subtype . pgp-encrypted)
+       (method . mime-decrypt-application/pgp-encrypted))
+      'strict "mime-pgp")
         
-        (mime-add-condition
-         'action
-         '((type . application)(subtype . pgp-keys)
-           (method . mime-add-application/pgp-keys))
-         'strict "mime-pgp")
-        ))
-  )
+     (mime-add-condition
+      'action
+      '((type . application)(subtype . pgp-keys)
+       (method . mime-add-application/pgp-keys))
+      'strict "mime-pgp")
+
+     (mime-add-condition
+      'action
+      '((type . application)(subtype . pkcs7-signature)
+       (method . mime-verify-application/pkcs7-signature))
+      'strict "mime-pgp")
+
+     (mime-add-condition
+      'action
+      '((type . application)(subtype . x-pkcs7-signature)
+       (method . mime-verify-application/pkcs7-signature))
+      'strict "mime-pgp")
+
+     (mime-add-condition
+      'action
+      '((type . application)(subtype . pkcs7-mime)
+       (method . mime-view-application/pkcs7-mime))
+      'strict "mime-pgp")
+
+     (mime-add-condition
+      'action
+      '((type . application)(subtype . x-pkcs7-mime)
+       (method . mime-view-application/pkcs7-mime))
+      'strict "mime-pgp")))
 
 
 ;;; @ for mime-edit
 ;;;
 
-(defun mime-setup-decode-message-header ()
-  (save-excursion
-    (save-restriction
-      (goto-char (point-min))
-      (narrow-to-region
-       (point-min)
-       (if (re-search-forward
-           (concat "^" (regexp-quote mail-header-separator) "$")
-           nil t)
-          (match-beginning 0)
-        (point-max)
-        ))
-      (mime-decode-header-in-buffer)
-      (set-buffer-modified-p nil)
-      )))
-
-(add-hook 'mime-edit-mode-hook 'mime-setup-decode-message-header)
+;; (defun mime-setup-decode-message-header ()
+;;   (save-excursion
+;;     (save-restriction
+;;       (goto-char (point-min))
+;;       (narrow-to-region
+;;        (point-min)
+;;        (if (re-search-forward
+;;             (concat "^" (regexp-quote mail-header-separator) "$")
+;;             nil t)
+;;            (match-beginning 0)
+;;          (point-max)
+;;          ))
+;;       (mime-decode-header-in-buffer)
+;;       (set-buffer-modified-p nil)
+;;       )))
+
+;; (add-hook 'mime-edit-mode-hook 'mime-setup-decode-message-header)
 
 
 ;;; @@ variables
@@ -171,8 +182,7 @@ it is used as hook to set."
        (let ((key
               (or (cdr (assq major-mode mime-setup-signature-key-alist))
                   mime-setup-default-signature-key)))
-         (define-key keymap key (function insert-signature))
-         ))))
+         (define-key keymap key (function insert-signature))))))
 
 (when mime-setup-use-signature
   (autoload 'insert-signature "signature" "Insert signature" t)
@@ -184,7 +194,7 @@ it is used as hook to set."
 ;;; @ for mu-cite
 ;;;
 
-(add-hook 'mu-cite/pre-cite-hook 'eword-decode-header)
+;; (add-hook 'mu-cite/pre-cite-hook 'eword-decode-header)
 
 
 ;;; @ end
index f06f53c..3a21aeb 100644 (file)
@@ -1,13 +1,12 @@
 ;;; signature.el --- a signature utility for GNU Emacs
 
-;; Copyright (C) 1994,1995,1996,1997 Free Software Foundation, Inc.
+;; Copyright (C) 1994,1995,1996,1997,2000 Free Software Foundation, Inc.
 
-;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Author: MORIOKA Tomohiko <tomo@m17n.org>
 ;;         OKABE Yasuo <okabe@kudpc.kyoto-u.ac.jp>
-;;         Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
-;; Maintainer: Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
+;;         Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Maintainer: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
 ;; Created: 1994/7/11
-;; Version: $Id: signature.el,v 7.16 1997/09/24 23:17:38 shuhei-k Exp $
 ;; Keywords: mail, news, signature
 
 ;; This file is part of SEMI (SEMI is Emacs MIME Interfaces).
@@ -24,8 +23,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Code: