+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.
# 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
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:
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'
* 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
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
=============
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
(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)
(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)
(expand-file-name SEMI_PREFIX
(expand-file-name "lisp"
PACKAGEDIR)))
+ (delete-file "./auto-autoloads.el")
+ (delete-file "./custom-load.el")
)
;;; SEMI-MK ends here
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
------- 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.]
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;
;;; 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
;; 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
;; 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:
"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
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
(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
(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
(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
(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
(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
"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."
(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
;;; 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
;; 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
("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"
("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
("\\.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
("\\.\\(rc\\|lst\\|log\\|sql\\|mak\\)$\\|\\..*rc$"
"text" "plain" nil
nil
- "attachment" (("filename" . file))
- )
+ "attachment" (("filename" . file)))
("\\.html$"
"text" "html" nil
("\\.diff$\\|\\.patch$"
"application" "octet-stream" (("type" . "patch"))
nil
- "attachment" (("filename" . file))
- )
+ "attachment" (("filename" . file)))
("\\.signature"
"text" "plain" nil nil nil nil)
;; 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
;; primary-type
(choice :tag "Primary-Type"
,@(nconc (mapcar (lambda (cell)
- (list 'item (car cell))
- )
+ (list 'item (car cell)))
mime-content-types)
'(string)))
;; subtype
(apply #'nconc
(mapcar (lambda (cell)
(mapcar (lambda (cell)
- (list 'item (car cell))
- )
+ (list 'item (car cell)))
(cdr cell)))
mime-content-types))
'(string)))
,@(cons
'(const nil)
(mapcar (lambda (cell)
- (list 'item cell)
- )
+ (list 'item cell))
(mime-encoding-list))))
;; disposition-type
(choice :tag "Disposition-Type"
string)
;; parameters
(repeat :tag "Parameters of Content-Disposition field"
- (cons string (choice string symbol)))
- ))
+ (cons string (choice string symbol)))))
:group 'mime-edit)
(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")
(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.")
(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
" ("
(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"
;; 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)
(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 ")")))))
(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.")
(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)
(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])
(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
(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
(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)
'((" 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
;; 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
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
(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)
(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."
(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."
(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 "")
(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
(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."
(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."
(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.
(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)))
(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
;; Restore previous point.
(goto-char current)
nil ;Nothing is created.
- )
- ))
+ )))
(defun mime-edit-insert-binary-file (file &optional encoding)
"Insert binary FILE at point.
(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.
(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."
(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."
(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."
(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.
(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."
(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]*\\("
;; 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)
)))
(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."
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)
(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
(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)
(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)
(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)
;; 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."
(setq encoding
(completing-read
"What transfer encoding: "
- (mime-encoding-alist) nil t default)
- )
+ (mime-encoding-alist) nil t default))
""))
encoding))
(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))
(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))
(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
(insert
(format "--[[multipart/%s;
boundary=\"%s\"][7bit]]\n"
- type boundary))
- ))
+ type boundary))))
boundary))))
(defun mime-edit-enquote-region (beg end)
(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
(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"))
(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\";
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
(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
(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
(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."
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
(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
;; 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))
(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."
(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)
(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))
(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."
(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
(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)
;; (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.
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
(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."
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.
(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)
(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
;; 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
(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
(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.
(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
(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
(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*"))
(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
(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
(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)
(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)
(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."
(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
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)
(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))
(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)
(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)
(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
(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)
(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
;; 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
;; 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
;;;
;; 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:
(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)
" 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
(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
(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
--[[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)))
'never)))
(mc-pgp-encrypt-region
(mc-split "\\([ \t\n]*,[ \t\n]*\\)+" recipients)
- start end id nil)
- ))
+ start end id nil)))
;;; @ end
;; 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:
(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))
(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
;;; 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
;; 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."
(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))
(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
;;;
;;; 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
;; 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
(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)
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
(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)
(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.
(- (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
(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
("^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
(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)))
(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
(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"))
(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")))
(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))
(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))
(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
(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)))
(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
(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
;; 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
<!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
<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]
</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
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.
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> ==============
</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>
</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>
<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
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
\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
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
@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
@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]
@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
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.
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
@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
@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.)
@menu
-* PGP::
+* PGP:: Encryption, Sign
* Buttons:: Mouse button
* Acting-condition configuration:: Utility for configuration
@end menu
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
<!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
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
<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
<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
<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>
\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
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
@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
@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
@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
(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
@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
--- /dev/null
+;;; 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
;;; 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)
(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)
;;;
(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)
;;;
(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))
(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)
(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))
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
;;; @@@ 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
;;;
(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))
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))
""))))
(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
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
'((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)
(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)
(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
(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))
(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)
(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
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
(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
(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
(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
(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
"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
(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."
(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
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")
(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)
(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))
(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
(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
\"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).
\"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
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
(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
(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.
(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)))
(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.
(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)))
(* -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.
(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)))
(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.
(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)))
(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
;;;
(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
(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
;;; 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
--- /dev/null
+;;; 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
--- /dev/null
+;;; 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
--- /dev/null
+;;; 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
--- /dev/null
+;;; 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
--- /dev/null
+;;; 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
--- /dev/null
+;;; 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
--- /dev/null
+\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:
--- /dev/null
+;;; 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
;;; 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
(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
;;; 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
(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)
;;; @ for mu-cite
;;;
-(add-hook 'mu-cite/pre-cite-hook 'eword-decode-header)
+;; (add-hook 'mu-cite/pre-cite-hook 'eword-decode-header)
;;; @ end
;;; 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).
;; 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: