🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.emacs.sources
Article #356

Improved Emacs MIME tools: mime.el (part 2/2)

#356
From: Masanobu UMEDA
Date: Sat, 21 Aug 1993 12:24
551 lines
20732 bytes
---- Cut Here and unpack ----
#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file mime.el continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> mime.el
X		(stringp encoding))
X	   (setq string
X		 (if qp (concat string "\n") string))
X	   (let ((encoded (funcall mime-string-encoder method string)))
X	     (setq encoded
X		   (substring encoded 0 (1- (length encoded))))
X	     (if (string-equal string encoded)
X		 string
X	       (concat "=?" charset "?" encoding "?" encoded "?="))))
X	  ;; Return string without any encoding.
X	  (t string)
X	  )))
X
X(defun mime-search-for-code-boundary ()
X  "Search for code boundary starting from current point and return points."
X  (let ((repeat t)
X	(lastwhite nil)
X	(poslist nil)			;possible boundary points
X	(encoding (and (not (eobp))
X		       (funcall mime-header-charset-chooser
X				(point)
X				(save-excursion
X				  (forward-char 1) (point))))))
X    (while repeat
X      (while (and (not (eobp))
X		  (equal encoding
X			 (funcall mime-header-charset-chooser
X				  (point)
X				  (save-excursion
X				    (forward-char 1) (point)))))
X	(setq lastwhite nil)
X	(forward-char 1))
X      ;; Remember the candidate.
X      (if (not lastwhite)
X	  (setq poslist (cons (point) poslist)))
X      ;; Iterate if the next of the next whitespace is the same.
X      (if (looking-at "[ \t]")
X	  (skip-chars-forward " \t")
X	(setq repeat nil))
X      (setq lastwhite t)
X      )
X    ;; Goto the last point.
X    (goto-char (car poslist))
X    poslist
X    ))
X
X(defun mime-translate-body ()
X  "Encode the tagged MIME body in current buffer in MIME compliant message."
X  (interactive)
X  (save-excursion
X    (let ((boundary
X	   (concat mime-multipart-boundary " " (current-time-string)))
X	  (tag nil)			;MIME tag
X	  (contype nil)			;Content-Type
X	  (encoding nil)		;Content-Transfer-Encoding
X	  (nparts 0))			;Number of body parts
X      (save-restriction
X	;; We are interested in message body.
X	(let* ((beg
X		(progn
X		  (goto-char (point-min))
X		  (re-search-forward
X		   (concat "\n" mail-header-separator
X			   (if mime-ignore-preceding-spaces
X			       "[ \t\n]*\n" "\n")) nil 'move)
X		  (point)))
X	       (end
X		(progn
X		  (goto-char (point-max))
X		  (and mime-ignore-trailing-spaces
X		       (re-search-backward "[^ \t\n]\n" beg t)
X		       (forward-char 1))
X		  (point))))
X	  (narrow-to-region beg end))
X	;; Normalize the body part by inserting appropriate message
X	;; tags for every message contents.
X	(mime-normalize-body)
X	;; Counting the number of Content-Type.
X	(goto-char (point-min))
X	(while (re-search-forward mime-tag-regexp nil t)
X	  (setq nparts (1+ nparts)))
X	;; Begin translation.
X	(cond ((<= nparts 1)
X	       ;; It's a singular message.
X	       (goto-char (point-min))
X	       (while (re-search-forward mime-tag-regexp nil t)
X		 (setq tag
X		       (buffer-substring (match-beginning 0) (match-end 0)))
X		 (delete-region (match-beginning 0) (1+ (match-end 0)))
X		 (setq contype (mime-get-contype tag))
X		 (setq encoding (mime-get-encoding tag))
X		 ))
X	      (t
X	       ;; It's a multipart message.
X	       (goto-char (point-min))
X	       (while (re-search-forward mime-tag-regexp nil t)
X		 (setq tag
X		       (buffer-substring (match-beginning 0) (match-end 0)))
X		 (delete-region (match-beginning 0) (match-end 0))
X		 (setq contype (mime-get-contype tag))
X		 (setq encoding (mime-get-encoding tag))
X		 (insert "--" boundary "\n")
X		 (insert "Content-Type: " contype "\n")
X		 (if encoding
X		     (insert "Content-Transfer-Encoding: " encoding "\n"))
X		 )
X	       ;; Define Content-Type as "multipart/mixed".
X	       (setq contype
X		     (concat "multipart/mixed; boundary=\"" boundary "\""))
X	       ;; Content-Transfer-Encoding must be "7bit".
X	       ;; The following encoding can be `nil', but is
X	       ;; specified as is since there is no way that a user
X	       ;; specifies it.
X	       (setq encoding "7bit")
X	       ;; Insert the trailer.
X	       (goto-char (point-max))
X	       (if (not (= (preceding-char) ?\n))
X		   ;; Boundary must start with a newline.
X		   (insert "\n"))
X	       (insert "--" boundary "--\n")))
X	)
X      ;; Make primary MIME headers.
X      (or (mail-position-on-field "Mime-Version")
X	  (insert mime-version-number))
X      ;; Remove old Content-Type and other fields.
X      (save-restriction
X	(goto-char (point-min))
X	(search-forward (concat "\n" mail-header-separator "\n") nil t)
X	(narrow-to-region (point-min) (point))
X	(goto-char (point-min))
X	(mime-delete-field "Content-Type")
X	(mime-delete-field "Content-Transfer-Encoding"))
X      ;; Then, insert Content-Type and Content-Transfer-Encoding fields.
X      (mail-position-on-field "Content-Type")
X      (insert contype)
X      (if encoding
X	  (progn
X	    (mail-position-on-field "Content-Transfer-Encoding")
X	    (insert encoding)))
X      )))
X
X(defun mime-normalize-body ()
X  "Normalize the body part by inserting appropriate message tags."
X  ;; Insert the first MIME tags if necessary.
X  (goto-char (point-min))
X  (if (not (looking-at mime-tag-regexp))
X      (insert (mime-make-text-tag) "\n"))
X  ;; Check each tag, and add new tag or correct it if necessary.
X  (goto-char (point-min))
X  (while (re-search-forward mime-tag-regexp nil t)
X    (let* ((tag (buffer-substring (match-beginning 0) (match-end 0)))
X	   (contype (mime-get-contype tag))
X	   (charset (mime-get-parameter contype "charset"))
X	   (encoding (mime-get-encoding tag)))
X      ;; Remove extra whitespaces after the tag.
X      (if (looking-at "[ \t]+$")
X	  (delete-region (match-beginning 0) (match-end 0)))
X      (cond ((= (following-char) ?\^M)
X	     ;; It must be image, audio or video.
X	     (let ((beg (point))
X		   (end (mime-content-end)))
X	       ;; Insert explicit MIME tags after hidden messages.
X	       (forward-line 1)
X	       (if (and (not (eobp))
X			(not (looking-at mime-tag-regexp)))
X		   (progn
X		     (insert (mime-make-text-tag) "\n")
X		     (forward-line -1)	;Process it again as text.
X		     ))
X	       ;; Show a hidden message.  The point is not altered
X	       ;; after the conversion.
X	       (mime-flag-region beg end ?\n)))
X	    ((mime-test-content-type contype "message")
X	     ;; Content-type "message" should be sent as is.
X	     (forward-line 1))
X	    ((mime-test-content-type contype "text")
X	     ;; Define charset for text if necessary.
X	     (setq charset (or charset (mime-choose-charset)))
X	     (mime-define-charset charset)
X	     ;; Point is now on current tag.
X	     ;; Define encoding and encode text if necessary.
X	     (if (null encoding)	;Encoding is not specified.
X		 (let* ((encoding (mime-choose-encoding))
X			(beg (mime-content-beginning))
X			(end (mime-content-end))
X			(body (buffer-substring beg end))
X			(encoded (funcall mime-string-encoder
X					  (cons charset encoding) body)))
X		   (if (not (string-equal body encoded))
X		       (progn
X			 (goto-char beg)
X			 (delete-region beg end)
X			 (insert encoded)
X			 (goto-char beg)))
X		   (mime-define-encoding encoding)))
X	     (forward-line 1))
X	    ((null encoding)		;Encoding is not specified.
X	     ;; Application, image, audio, video, and any other
X	     ;; unknown content-type without encoding should be
X	     ;; encoded.
X	     (let* ((encoding "base64")	;Encode in BASE64 by default.
X		    (beg (mime-content-beginning))
X		    (end (mime-content-end))
X		    (body (buffer-substring beg end))
X		    (encoded (funcall mime-string-encoder
X				      (cons nil encoding) body)))
X	       (if (not (string-equal body encoded))
X		   (progn
X		     (goto-char beg)
X		     (delete-region beg end)
X		     (insert encoded)
X		     (goto-char beg)))
X	       (mime-define-encoding encoding))
X	     (forward-line 1))
X	    )
X      )))
X
X(defun mime-delete-field (field)
X  "Delete header FIELD."
X  (let ((regexp (format "^%s:[ \t]*" field)))
X    (goto-char (point-min))
X    (while (re-search-forward regexp nil t)
X      (delete-region (match-beginning 0)
X		     (progn (forward-line 1) (point)))
X      )))
X
X
X;;;
X;;; Platform dependent functions
X;;;
X
X;; Emacs 18 implementations
X
X(defun mime-header-charset-chooser-for-emacs18 (begin end)
X  "Return a cons of charset and header encoding for a given header region.
XEncoding name must be a short name, such as `B' or `Q'."
X  nil					;No encoding is necessary.
X  )
X
X(defun mime-body-charset-chooser-for-emacs18 (begin end)
X  "Return a cons of charset and encoding of a message in a given region.
XEncoding name must be a canonical name, such as `base64'."
X  '("US-ASCII" . nil)			;Default charset of MIME.
X  )
X
X(defun mime-string-encoder-for-emacs18 (method string)
X  "For given METHOD that is a cons of charset and encoding, encode a STRING."
X  (let ((charset (car method))
X	(encoding (cdr method)))
X    (cond ((stringp encoding)
X	   (mime-encode-string encoding string))
X	  ;; Return string without any encoding.
X	  (t string)
X	  )))
X
X
X;; Emacs 19 implementations
X
X(defun mime-header-charset-chooser-for-emacs19 (begin end)
X  "Return a cons of charset and header encoding for a given header region.
XEncoding name must be a short name, such as `B' or `Q'.
XUS-ASCII and ISO-8859-1 are supported on Emacs 19."
X  (cond ((save-excursion
X	   (goto-char begin)
X	   (re-search-forward "[\200-\377]" end t))
X	 '("ISO-8859-1" . "Q"))
X	(t nil)				;No encoding is necessary.
X	))
X
X(defun mime-body-charset-chooser-for-emacs19 (begin end)
X  "Return a cons of charset and encoding of a message in a given region.
XEncoding name must be a canonical name, such as `base64'.
XUS-ASCII and ISO-8859-1 are supported on Emacs 19."
X  (cond ((save-excursion
X	   (goto-char begin)
X	   (re-search-forward "[\200-\377]" end t))
X	 '("ISO-8859-1" . "quoted-printable"))
X	(t
X	 '("US-ASCII" . nil))		;Default charset of MIME.
X	))
X
X(defun mime-string-encoder-for-emacs19 (method string)
X  "For given METHOD that is a cons of charset and encoding, encode a STRING."
X  (let ((charset (car method))
X	(encoding (cdr method)))
X    (cond ((stringp encoding)
X	   (mime-encode-string encoding string))
X	  ;; Return string without any encoding.
X	  (t string)
X	  )))
X
X
X;; NEmacs implementations
X
X(defun mime-header-charset-chooser-for-nemacs (begin end)
X  "Return a cons of charset and header encoding for a given header region.
XEncoding name must be a short name, such as `B' or `Q'.
XUS-ASCII and ISO-2022-JP are supported on NEmacs."
X  (cond ((check-region-kanji-code begin end)
X	 '("ISO-2022-JP" . "B"))
X	(t nil)				;No encoding is necessary.
X	))
X
X(defun mime-body-charset-chooser-for-nemacs (begin end)
X  "Return a cons of charset and encoding of a message in a given region.
XEncoding name must be a canonical name, such as `base64'.
XUS-ASCII and ISO-2022-JP are supported on NEmacs."
X  (cond ((check-region-kanji-code begin end)
X	 ;; The following are safe encoding methods for use in
X	 ;; USENET News systems that strip off all ESCs.
X	 ;; '("ISO-2022-JP" . "quoted-printable")
X	 ;; '("ISO-2022-JP" . "base64")
X	 ;; The following expects transport systems are all MIME
X	 ;; compliants.  For instance, ESCs are never stripped off.
X	 '("ISO-2022-JP" . nil))
X	(t
X	 '("US-ASCII" . nil))		;Default charset of MIME.
X	))
X
X(defun mime-string-encoder-for-nemacs (method string)
X  "For given METHOD that is a cons of charset and encoding, encode a STRING.
XUS-ASCII and ISO-2022-JP are supported on NEmacs."
X  (let ((charset (car method))
X	(encoding (cdr method)))
X    (cond ((stringp encoding)
X	   (mime-encode-string encoding
X			       ;; Convert internal (EUC) to JIS code.
X			       (convert-string-kanji-code string 3 2)
X			       ))
X	  ;; NEmacs can convert into ISO-2022-JP automatically,
X	  ;; but can do it myself as follows:
X	  ;;(t (convert-string-kanji-code string 3 2))
X
X	  ;; Return string without any encoding.
X	  (t string)
X	  )))
X
X
X;; Mule implementations
X;; Thanks to contributions by wkenji@flab.fujitsu.co.jp (Kenji
X;; WAKAMIYA) and handa@etl.go.jp (Kenichi Handa).
X
X(defun mime-header-charset-chooser-for-mule (begin end)
X  "Return cons of charset and header encoding for a given header region.
XEncoding name must be a short name, such as `B' or `Q'.  US-ASCII,
XISO-8859-* (except for ISO-8859-6), ISO-2022-JP and X-ISO-2022-JP-2
Xare supported on Mule."
X  (let ((lclist (find-charset-region begin end)))
X    (cond ((null lclist) nil)		;US-ASCII requres no encoding.
X	  ((memq lc-ltn1 lclist)
X	   '("ISO-8859-1" . "Q"))
X	  ((memq lc-ltn2 lclist)
X	   '("ISO-8859-2" . "Q"))
X	  ((memq lc-ltn3 lclist)
X	   '("ISO-8859-3" . "Q"))
X	  ((memq lc-ltn4 lclist)
X	   '("ISO-8859-4" . "Q"))
X	  ((memq lc-crl lclist)
X	   '("ISO-8859-5" . "Q"))
X	  ;;((memq lc-arb lclist)
X	  ;; '("ISO-8859-6" . "Q"))
X	  ((memq lc-grk lclist)
X	   '("ISO-8859-7" . "Q"))
X	  ((memq lc-hbw lclist)
X	   '("ISO-8859-8" . "Q"))
X	  ((memq lc-ltn5 lclist)
X	   '("ISO-8859-9" . "Q"))
X	  ((memq lc-jp lclist)
X	   '("ISO-2022-JP" . "B"))
X	  (t				;Unknown charset.  It must be Mule!
X	   '("X-ISO-2022-JP-2" . "B"))
X	  )))
X
X(defun mime-body-charset-chooser-for-mule (begin end)
X  "Return a cons of charset and encoding of a message in a given region.
XEncoding name must be a canonical name, such as `base64'.  US-ASCII,
XISO-8859-* (except for ISO-8859-6), ISO-2022-JP and X-ISO-2022-JP-2
Xare supported on Mule.  Charset X-ISO-2022-JP-2 is used for
Xmultilingual text, and it is expected to be encoded in Mule style."
X  (let ((lclist (find-charset-region begin end)))
X    (cond ((null lclist)
X	   '("US-ASCII" . nil))		;Default charset of MIME.
X	  ((> (length lclist) 1)	;Requre multilingual capability
X	   '("X-ISO-2022-JP-2" . nil))
X	  ((memq lc-ltn1 lclist)
X	   '("ISO-8859-1" . "quoted-printable"))
X	  ((memq lc-ltn2 lclist)
X	   '("ISO-8859-2" . "quoted-printable"))
X	  ((memq lc-ltn3 lclist)
X	   '("ISO-8859-3" . "quoted-printable"))
X	  ((memq lc-ltn4 lclist)
X	   '("ISO-8859-4" . "quoted-printable"))
X	  ((memq lc-crl lclist)
X	   '("ISO-8859-5" . "quoted-printable"))
X	  ;;((memq lc-arb lclist)
X	  ;; '("ISO-8859-6" . "quoted-printable"))
X	  ((memq lc-grk lclist)
X	   '("ISO-8859-7" . "quoted-printable"))
X	  ((memq lc-hbw lclist)
X	   '("ISO-8859-8" . "quoted-printable"))
X	  ((memq lc-ltn5 lclist)
X	   '("ISO-8859-9" . "quoted-printable"))
X	  ((memq lc-jp lclist)
X	   '("ISO-2022-JP" . nil))
X	  (t				;Unknown charset.  It must be Mule!
X	   '("X-ISO-2022-JP-2" . nil))
X	  )))
X
X(defun mime-string-encoder-for-mule (method string)
X  "For given METHOD that is a cons of charset and encoding, encode a STRING.
XUS-ASCII, ISO-8859-* (except for ISO-8859-6), ISO-2022-JP and
XX-ISO-2022-JP-2 are supported on Mule.  Charset X-ISO-2022-JP-2 used
Xfor multilingual text is encoded in Mule style."
X  (let* ((charset (car method))
X	 (encoding (cdr method))
X	 (coding-system
X	  (cdr (assoc (and (stringp charset) (upcase charset))
X		      '(("ISO-8859-1" . *ctext*)
X			("ISO-8859-2" . *iso-8859-2*)
X			("ISO-8859-3" . *iso-8859-3*)
X			("ISO-8859-4" . *iso-8859-4*)
X			("ISO-8859-5" . *iso-8859-5*)
X			;;("ISO-8859-6" . *iso-8859-6*)
X			("ISO-8859-7" . *iso-8859-7*)
X			("ISO-8859-8" . *iso-8859-8*)
X			("ISO-8859-9" . *iso-8859-9*)
X			("ISO-2022-JP" . *junet*)
X			("X-ISO-2022-JP-2" . *iso-2022-ss2-7*))))))
X    ;; In bilingual environment it may be unnecessary to convert the
X    ;; coding system of the string unless transfer encoding is
X    ;; required since such conversion may be performed by mule
X    ;; automatically.
X    (if (not (null coding-system))
X	(setq string (code-convert-string string *internal* coding-system)))
X    (if (stringp encoding)
X	(setq string (mime-encode-string encoding string)))
X    string
X    ))
X
X
X;; Sun implementations
X
X(defun mime-voice-recorder-for-sun ()
X  "Record voice in a buffer using Sun audio device, and return the buffer."
X  (let ((buffer (get-buffer-create " *MIME audio*")))
X    (message "Type C-g to finish recording...")
X    (save-excursion
X      (set-buffer buffer)
X      (erase-buffer)
X      (condition-case errorcode
X	  (let ((selective-display nil) ;Disable ^M to nl translation.
X		(mc-flag nil)		;Mule
X		(kanji-flag nil))	;NEmacs
X	    ;; Disable automatic conversion of coding system if Mule.
X	    (if (featurep 'mule)
X		(define-program-coding-system nil "cat" *noconv*))
X	    (call-process "cat"
X			  "/dev/audio"
X			  buffer
X			  nil
X			  ))
X	(quit (message "Type C-g to finish recording... done.")
X	      buffer			;Return the buffer
X	      )))))
X
X
X;;;
X;;; Other useful commands.
X;;;
X
X;; Message forwarding commands as content-type "message/rfc822".
X
X;;;###autoload
X(defun mime-forward-from-rmail-using-mail ()
X  "Forward current message in message/rfc822 content-type message from rmail."
X  (interactive)
X  ;;>> this gets set even if we abort. Can't do anything about it, though.
X  (rmail-set-attribute "forwarded" t)
X  (let ((forward-buffer (current-buffer))
X	(subject (concat "["
X			 (mail-strip-quoted-names (mail-fetch-field "From"))
X			 ": " (or (mail-fetch-field "Subject") "") "]")))
X    ;; If only one window, use it for the mail buffer.
X    ;; Otherwise, use another window for the mail buffer
X    ;; so that the Rmail buffer remains visible
X    ;; and sending the mail will get back to it.
X    (if (if (one-window-p t)
X	    (mail nil nil subject)
X	  (mail-other-window nil nil subject))
X	(save-excursion
X	  (goto-char (point-max))
X	  (forward-line 1)
X	  (mime-insert-tag "message" "rfc822")
X	  (insert-buffer forward-buffer)))))
X
X;;;###autoload
X(defun mime-forward-from-gnus-using-mail ()
X  "Forward current article in message/rfc822 content-type message from GNUS."
X  (let ((forward-buffer (current-buffer))
X	(subject
X	 (concat "[" gnus-newsgroup-name "] "
X		 ;;(mail-strip-quoted-names (gnus-fetch-field "From")) ": "
X		 (or (gnus-fetch-field "Subject") ""))))
X    ;; If only one window, use it for the mail buffer.
X    ;; Otherwise, use another window for the mail buffer
X    ;; so that the Rmail buffer remains visible
X    ;; and sending the mail will get back to it.
X    (if (if (one-window-p t)
X	    (mail nil nil subject)
X	  (mail-other-window nil nil subject))
X	(save-excursion
X	  (goto-char (point-max))
X	  (mime-insert-tag "message" "rfc822")
X	  (insert-buffer forward-buffer)
X	  ;; You have a chance to arrange the message.
X	  (run-hooks 'gnus-mail-forward-hook)
X	  ))))
X
X(provide 'mime)
X
X;;; mime.el ends here
SHAR_EOF
chmod 0644 mime.el || echo "restore of mime.el fails"
set `wc -c mime.el`;Sum=$1
if test "$Sum" != "64778"
then echo original size 64778, current size $Sum;fi
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0
--
Masanobu UMEDA
umerin@mse.kyutech.ac.jp
Faculty of Computer Science and System Engineering
Kyushu Institute of Technology
Technical Details
Message-ID: <UMERIN.93Aug21212436@orchid.mse.kyutech.ac.jp>
Path: arc1-ca.pugleaf.net!gmd.de!newsserver.jvnc.net!howland.reston.ans.net!europa.eng.gtefsd.com!uunet!ccut!news.u-tokyo.ac.jp!wnoc-tyo-news!sh.wide!wnoc-kyo!kyu-cs!wnoc-fukuoka-news!shiwasu!shiwasu!umerin
References: <UMERIN.93Aug21210519@orchid.mse.kyutech.ac.jp>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 10160c,f5577f01abaf7e4e,start
X-Google-Attributes: gid10160c,public
X-Google-Thread: 107729,de723f7325371838
X-Google-Attributes: gid107729,public
X-Google-ArrivalTime: 1993-08-21 06:05:16 PST
Newsgroups: gnu.emacs.sources,fj.sources
Path: arc1-ca.pugleaf.net!gmd.de!newsserver.jvnc.net!howland.reston.ans.net!europa.eng.gtefsd.com!uunet!ccut!news.u-tokyo.ac.jp!wnoc-tyo-news!sh.wide!wnoc-kyo!kyu-cs!wnoc-fukuoka-news!shiwasu!shiwasu!umerin
From: umerin@mse.kyutech.ac.jp (Masanobu UMEDA)
Subject: Improved Emacs MIME tools: mime.el (part 2/2)
Content-Type: text/plain; charset=US-ASCII
References: <UMERIN.93Aug21210519@orchid.mse.kyutech.ac.jp>
Sender: news@shiwasu.isci.kyutech.ac.jp
Mime-Version: 1.0
Organization: Department of Mechanical System Engineering, Kyutech, Japan
Date: Sat, 21 Aug 1993 12:24:36 GMT
Message-ID: <UMERIN.93Aug21212436@orchid.mse.kyutech.ac.jp>
Reply-To: umerin@mse.kyutech.ac.jp
Lines: 551