mm-uu.el 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. ;;; mm-uu.el --- Return uu stuff as mm handles
  2. ;; Copyright (C) 1998-2012 Free Software Foundation, Inc.
  3. ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
  4. ;; Keywords: postscript uudecode binhex shar forward gnatsweb pgp
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;; Code:
  18. (eval-when-compile (require 'cl))
  19. (require 'mail-parse)
  20. (require 'nnheader)
  21. (require 'mm-decode)
  22. (require 'mailcap)
  23. (require 'mml2015)
  24. (autoload 'uudecode-decode-region "uudecode")
  25. (autoload 'uudecode-decode-region-external "uudecode")
  26. (autoload 'uudecode-decode-region-internal "uudecode")
  27. (autoload 'binhex-decode-region "binhex")
  28. (autoload 'binhex-decode-region-external "binhex")
  29. (autoload 'binhex-decode-region-internal "binhex")
  30. (autoload 'yenc-decode-region "yenc")
  31. (autoload 'yenc-extract-filename "yenc")
  32. (defcustom mm-uu-decode-function 'uudecode-decode-region
  33. "*Function to uudecode.
  34. Internal function is done in Lisp by default, therefore decoding may
  35. appear to be horribly slow. You can make Gnus use an external
  36. decoder, such as uudecode."
  37. :type '(choice
  38. (function-item :tag "Auto detect" uudecode-decode-region)
  39. (function-item :tag "Internal" uudecode-decode-region-internal)
  40. (function-item :tag "External" uudecode-decode-region-external))
  41. :group 'gnus-article-mime)
  42. (defcustom mm-uu-binhex-decode-function 'binhex-decode-region
  43. "*Function to binhex decode.
  44. Internal function is done in elisp by default, therefore decoding may
  45. appear to be horribly slow . You can make Gnus use the external Unix
  46. decoder, such as hexbin."
  47. :type '(choice (function-item :tag "Auto detect" binhex-decode-region)
  48. (function-item :tag "Internal" binhex-decode-region-internal)
  49. (function-item :tag "External" binhex-decode-region-external))
  50. :group 'gnus-article-mime)
  51. (defvar mm-uu-yenc-decode-function 'yenc-decode-region)
  52. (defvar mm-uu-beginning-regexp nil)
  53. (defvar mm-dissect-disposition "inline"
  54. "The default disposition of uu parts.
  55. This can be either \"inline\" or \"attachment\".")
  56. (defcustom mm-uu-emacs-sources-regexp "\\.emacs\\.sources"
  57. "The regexp of Emacs sources groups."
  58. :version "22.1"
  59. :type 'regexp
  60. :group 'gnus-article-mime)
  61. (defcustom mm-uu-diff-groups-regexp
  62. "\\(gmane\\|gnu\\)\\..*\\(diff\\|commit\\|cvs\\|bug\\|devel\\)"
  63. "Regexp matching diff groups."
  64. :version "22.1"
  65. :type 'regexp
  66. :group 'gnus-article-mime)
  67. (defcustom mm-uu-tex-groups-regexp "\\.tex\\>"
  68. "*Regexp matching TeX groups."
  69. :version "23.1"
  70. :type 'regexp
  71. :group 'gnus-article-mime)
  72. (defvar mm-uu-type-alist
  73. '((postscript
  74. "^%!PS-"
  75. "^%%EOF$"
  76. mm-uu-postscript-extract
  77. nil)
  78. (uu ;; Maybe we should have a more strict test here.
  79. "^begin[ \t]+0?[0-7][0-7][0-7][ \t]+"
  80. "^end[ \t]*$"
  81. mm-uu-uu-extract
  82. mm-uu-uu-filename)
  83. (binhex
  84. "^:.\\{63,63\\}$"
  85. ":$"
  86. mm-uu-binhex-extract
  87. nil
  88. mm-uu-binhex-filename)
  89. (yenc
  90. "^=ybegin.*size=[0-9]+.*name=.*$"
  91. "^=yend.*size=[0-9]+"
  92. mm-uu-yenc-extract
  93. mm-uu-yenc-filename)
  94. (shar
  95. "^#! */bin/sh"
  96. "^exit 0$"
  97. mm-uu-shar-extract)
  98. (forward
  99. ;; Thanks to Edward J. Sabol <sabol@alderaan.gsfc.nasa.gov> and
  100. ;; Peter von der Ah\'e <pahe@daimi.au.dk>
  101. "^-+ \\(Start of \\)?Forwarded message"
  102. "^-+ End \\(of \\)?forwarded message"
  103. mm-uu-forward-extract
  104. nil
  105. mm-uu-forward-test)
  106. (gnatsweb
  107. "^----gnatsweb-attachment----"
  108. nil
  109. mm-uu-gnatsweb-extract)
  110. (pgp-signed
  111. "^-----BEGIN PGP SIGNED MESSAGE-----"
  112. "^-----END PGP SIGNATURE-----"
  113. mm-uu-pgp-signed-extract
  114. nil
  115. nil)
  116. (pgp-encrypted
  117. "^-----BEGIN PGP MESSAGE-----"
  118. "^-----END PGP MESSAGE-----"
  119. mm-uu-pgp-encrypted-extract
  120. nil
  121. nil)
  122. (pgp-key
  123. "^-----BEGIN PGP PUBLIC KEY BLOCK-----"
  124. "^-----END PGP PUBLIC KEY BLOCK-----"
  125. mm-uu-pgp-key-extract
  126. mm-uu-gpg-key-skip-to-last
  127. nil)
  128. (emacs-sources
  129. "^;;;?[ \t]*[^ \t]+\\.el[ \t]*--"
  130. "^;;;?[ \t]*\\([^ \t]+\\.el\\)[ \t]+ends here"
  131. mm-uu-emacs-sources-extract
  132. nil
  133. mm-uu-emacs-sources-test)
  134. (diff
  135. "^Index: "
  136. nil
  137. mm-uu-diff-extract
  138. nil
  139. mm-uu-diff-test)
  140. (diff
  141. "^=== modified file "
  142. nil
  143. mm-uu-diff-extract
  144. nil
  145. mm-uu-diff-test)
  146. (git-format-patch
  147. "^diff --git "
  148. "^-- "
  149. mm-uu-diff-extract
  150. nil
  151. mm-uu-diff-test)
  152. (message-marks
  153. ;; Text enclosed with tags similar to `message-mark-insert-begin' and
  154. ;; `message-mark-insert-end'. Don't use those variables to avoid
  155. ;; dependency on `message.el'.
  156. "^-+[8<>]*-\\{9,\\}[a-z ]+-\\{9,\\}[a-z ]+-\\{9,\\}[8<>]*-+$"
  157. "^-+[8<>]*-\\{9,\\}[a-z ]+-\\{9,\\}[a-z ]+-\\{9,\\}[8<>]*-+$"
  158. (lambda () (mm-uu-verbatim-marks-extract 0 0 1 -1))
  159. nil)
  160. ;; Omitting [a-z8<] leads to false positives (bogus signature separators
  161. ;; and mailing list banners).
  162. (insert-marks
  163. "^ *\\(-\\|_\\)\\{30,\\}.*[a-z8<].*\\(-\\|_\\)\\{30,\\} *$"
  164. "^ *\\(-\\|_\\)\\{30,\\}.*[a-z8<].*\\(-\\|_\\)\\{30,\\} *$"
  165. (lambda () (mm-uu-verbatim-marks-extract 0 0 1 -1))
  166. nil)
  167. (verbatim-marks
  168. ;; slrn-style verbatim marks, see
  169. ;; http://slrn.sourceforge.net/docs/slrn-manual-6.html#process_verbatim_marks
  170. "^#v\\+"
  171. "^#v\\-$"
  172. (lambda () (mm-uu-verbatim-marks-extract 0 0))
  173. nil)
  174. (LaTeX
  175. "^\\([\\\\%][^\n]+\n\\)*\\\\documentclass.*[[{%]"
  176. "^\\\\end{document}"
  177. mm-uu-latex-extract
  178. nil
  179. mm-uu-latex-test)
  180. (org-src-code-block
  181. "^[ \t]*#\\+begin_"
  182. "^[ \t]*#\\+end_"
  183. mm-uu-org-src-code-block-extract)
  184. (org-meta-line
  185. "^[ \t]*#\\+[[:alpha:]]+: "
  186. "$"
  187. mm-uu-org-src-code-block-extract))
  188. "A list of specifications for non-MIME attachments.
  189. Each element consist of the following entries: label,
  190. start-regexp, end-regexp, extract-function, test-function.
  191. After modifying this list you must run \\[mm-uu-configure].
  192. You can disable elements from this list by customizing
  193. `mm-uu-configure-list'.")
  194. (defcustom mm-uu-configure-list '((shar . disabled))
  195. "A list of mm-uu configuration.
  196. To disable dissecting shar codes, for instance, add
  197. `(shar . disabled)' to this list."
  198. :type 'alist
  199. :options (mapcar (lambda (entry)
  200. (list (car entry) '(const disabled)))
  201. mm-uu-type-alist)
  202. :group 'gnus-article-mime)
  203. (defvar mm-uu-text-plain-type '("text/plain" (charset . gnus-decoded))
  204. "MIME type and parameters for text/plain parts.
  205. `gnus-decoded' is a fake charset, which means no further decoding.")
  206. ;; functions
  207. (defsubst mm-uu-type (entry)
  208. (car entry))
  209. (defsubst mm-uu-beginning-regexp (entry)
  210. (nth 1 entry))
  211. (defsubst mm-uu-end-regexp (entry)
  212. (nth 2 entry))
  213. (defsubst mm-uu-function-extract (entry)
  214. (nth 3 entry))
  215. (defsubst mm-uu-function-1 (entry)
  216. (nth 4 entry))
  217. (defsubst mm-uu-function-2 (entry)
  218. (nth 5 entry))
  219. ;; In Emacs 22, we could use `min-colors' in the face definition. But Emacs
  220. ;; 21 and XEmacs don't support it.
  221. (defcustom mm-uu-hide-markers
  222. (< 16 (or (and (fboundp 'defined-colors)
  223. (length (defined-colors)))
  224. (and (fboundp 'device-color-cells)
  225. (device-color-cells))
  226. 0))
  227. "If non-nil, hide verbatim markers.
  228. The value should be nil on displays where the face
  229. `mm-uu-extract' isn't distinguishable to the face `default'."
  230. :type '(choice (const :tag "Hide" t)
  231. (const :tag "Don't hide" nil))
  232. :version "23.1" ;; No Gnus
  233. :group 'gnus-article-mime)
  234. (defface mm-uu-extract '(;; Inspired by `gnus-cite-3'
  235. (((type tty)
  236. (class color)
  237. (background dark))
  238. (:background "dark blue"))
  239. (((class color)
  240. (background dark))
  241. (:foreground "light yellow"
  242. :background "dark green"))
  243. (((type tty)
  244. (class color)
  245. (background light))
  246. (:foreground "dark blue"))
  247. (((class color)
  248. (background light))
  249. (:foreground "dark green"
  250. :background "light yellow"))
  251. (t
  252. ()))
  253. "Face for extracted buffers."
  254. ;; See `mm-uu-verbatim-marks-extract'.
  255. :version "23.1" ;; No Gnus
  256. :group 'gnus-article-mime)
  257. (defun mm-uu-copy-to-buffer (&optional from to properties)
  258. "Copy the contents of the current buffer to a fresh buffer.
  259. Return that buffer.
  260. If PROPERTIES is non-nil, PROPERTIES are applied to the buffer,
  261. see `set-text-properties'. If PROPERTIES equals t, this means to
  262. apply the face `mm-uu-extract'."
  263. (let ((obuf (current-buffer))
  264. (multi (and (boundp 'enable-multibyte-characters)
  265. enable-multibyte-characters))
  266. (coding-system
  267. ;; Might not exist in non-MULE XEmacs
  268. (when (boundp 'buffer-file-coding-system)
  269. buffer-file-coding-system)))
  270. (with-current-buffer (generate-new-buffer " *mm-uu*")
  271. (if multi (mm-enable-multibyte) (mm-disable-multibyte))
  272. (setq buffer-file-coding-system coding-system)
  273. (insert-buffer-substring obuf from to)
  274. (cond ((eq properties t)
  275. (set-text-properties (point-min) (point-max)
  276. '(face mm-uu-extract)))
  277. (properties
  278. (set-text-properties (point-min) (point-max) properties)))
  279. (current-buffer))))
  280. (defun mm-uu-configure-p (key val)
  281. (member (cons key val) mm-uu-configure-list))
  282. (defun mm-uu-configure (&optional symbol value)
  283. "Configure detection of non-MIME attachments."
  284. (interactive)
  285. (if symbol (set-default symbol value))
  286. (setq mm-uu-beginning-regexp nil)
  287. (mapcar (lambda (entry)
  288. (if (mm-uu-configure-p (mm-uu-type entry) 'disabled)
  289. nil
  290. (setq mm-uu-beginning-regexp
  291. (concat mm-uu-beginning-regexp
  292. (if mm-uu-beginning-regexp "\\|")
  293. (mm-uu-beginning-regexp entry)))))
  294. mm-uu-type-alist))
  295. (mm-uu-configure)
  296. (defvar file-name)
  297. (defvar start-point)
  298. (defvar end-point)
  299. (defvar entry)
  300. (defun mm-uu-uu-filename ()
  301. (if (looking-at ".+")
  302. (setq file-name
  303. (let ((nnheader-file-name-translation-alist
  304. '((?/ . ?,) (?\ . ?_) (?* . ?_) (?$ . ?_))))
  305. (nnheader-translate-file-chars (match-string 0))))))
  306. (defun mm-uu-binhex-filename ()
  307. (setq file-name
  308. (ignore-errors
  309. (binhex-decode-region start-point end-point t))))
  310. (defun mm-uu-yenc-filename ()
  311. (goto-char start-point)
  312. (setq file-name
  313. (ignore-errors
  314. (yenc-extract-filename))))
  315. (defun mm-uu-forward-test ()
  316. (save-excursion
  317. (goto-char start-point)
  318. (forward-line)
  319. (looking-at "[\r\n]*[a-zA-Z][a-zA-Z0-9-]*:")))
  320. (defun mm-uu-postscript-extract ()
  321. (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
  322. '("application/postscript")))
  323. (defun mm-uu-verbatim-marks-extract (start-offset end-offset
  324. &optional
  325. start-hide
  326. end-hide)
  327. (let ((start (or (and mm-uu-hide-markers
  328. start-hide)
  329. start-offset
  330. 1))
  331. (end (or (and mm-uu-hide-markers
  332. end-hide)
  333. end-offset
  334. -1)))
  335. (mm-make-handle
  336. (mm-uu-copy-to-buffer
  337. (progn (goto-char start-point)
  338. (forward-line start)
  339. (point))
  340. (progn (goto-char end-point)
  341. (forward-line end)
  342. (point))
  343. t)
  344. '("text/x-verbatim" (charset . gnus-decoded)))))
  345. (defun mm-uu-latex-extract ()
  346. (mm-make-handle
  347. (mm-uu-copy-to-buffer start-point end-point t)
  348. ;; application/x-tex?
  349. '("text/x-verbatim" (charset . gnus-decoded))))
  350. (defun mm-uu-emacs-sources-extract ()
  351. (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
  352. '("application/emacs-lisp" (charset . gnus-decoded))
  353. nil nil
  354. (list mm-dissect-disposition
  355. (cons 'filename file-name))))
  356. (defun mm-uu-org-src-code-block-extract ()
  357. (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
  358. '("text/x-org")))
  359. (defvar gnus-newsgroup-name)
  360. (defun mm-uu-emacs-sources-test ()
  361. (setq file-name (match-string 1))
  362. (and gnus-newsgroup-name
  363. mm-uu-emacs-sources-regexp
  364. (string-match mm-uu-emacs-sources-regexp gnus-newsgroup-name)))
  365. (defun mm-uu-diff-extract ()
  366. (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
  367. '("text/x-patch" (charset . gnus-decoded))))
  368. (defun mm-uu-diff-test ()
  369. (and gnus-newsgroup-name
  370. mm-uu-diff-groups-regexp
  371. (string-match mm-uu-diff-groups-regexp gnus-newsgroup-name)))
  372. (defun mm-uu-latex-test ()
  373. (and gnus-newsgroup-name
  374. mm-uu-tex-groups-regexp
  375. (string-match mm-uu-tex-groups-regexp gnus-newsgroup-name)))
  376. (defun mm-uu-forward-extract ()
  377. (mm-make-handle (mm-uu-copy-to-buffer
  378. (progn
  379. (goto-char start-point)
  380. (forward-line)
  381. (skip-chars-forward "\n")
  382. (point))
  383. (progn (goto-char end-point) (forward-line -1) (point)))
  384. '("message/rfc822" (charset . gnus-decoded))))
  385. (defun mm-uu-uu-extract ()
  386. (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
  387. (list (or (and file-name
  388. (string-match "\\.[^\\.]+$"
  389. file-name)
  390. (mailcap-extension-to-mime
  391. (match-string 0 file-name)))
  392. "application/octet-stream"))
  393. 'x-uuencode nil
  394. (if (and file-name (not (equal file-name "")))
  395. (list mm-dissect-disposition
  396. (cons 'filename file-name)))))
  397. (defun mm-uu-binhex-extract ()
  398. (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
  399. (list (or (and file-name
  400. (string-match "\\.[^\\.]+$" file-name)
  401. (mailcap-extension-to-mime
  402. (match-string 0 file-name)))
  403. "application/octet-stream"))
  404. 'x-binhex nil
  405. (if (and file-name (not (equal file-name "")))
  406. (list mm-dissect-disposition
  407. (cons 'filename file-name)))))
  408. (defvar gnus-original-article-buffer) ; gnus.el
  409. (defun mm-uu-yenc-extract ()
  410. ;; This might not be exactly correct, but we sure can't get the
  411. ;; binary data from the article buffer, since that's already in a
  412. ;; non-binary charset. So get it from the original article buffer.
  413. (mm-make-handle (with-current-buffer gnus-original-article-buffer
  414. (mm-uu-copy-to-buffer start-point end-point))
  415. (list (or (and file-name
  416. (string-match "\\.[^\\.]+$" file-name)
  417. (mailcap-extension-to-mime
  418. (match-string 0 file-name)))
  419. "application/octet-stream"))
  420. 'x-yenc nil
  421. (if (and file-name (not (equal file-name "")))
  422. (list mm-dissect-disposition
  423. (cons 'filename file-name)))))
  424. (defun mm-uu-shar-extract ()
  425. (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
  426. '("application/x-shar")))
  427. (defun mm-uu-gnatsweb-extract ()
  428. (save-restriction
  429. (goto-char start-point)
  430. (forward-line)
  431. (narrow-to-region (point) end-point)
  432. (mm-dissect-buffer t)))
  433. (defun mm-uu-pgp-signed-test (&rest rest)
  434. (and
  435. mml2015-use
  436. (mml2015-clear-verify-function)
  437. (cond
  438. ((eq mm-verify-option 'never) nil)
  439. ((eq mm-verify-option 'always) t)
  440. ((eq mm-verify-option 'known) t)
  441. (t (prog1
  442. (y-or-n-p "Verify pgp signed part? ")
  443. (message ""))))))
  444. (defvar gnus-newsgroup-charset)
  445. (defun mm-uu-pgp-signed-extract-1 (handles ctl)
  446. (let ((buf (mm-uu-copy-to-buffer (point-min) (point-max))))
  447. (with-current-buffer buf
  448. (if (mm-uu-pgp-signed-test)
  449. (progn
  450. (mml2015-clean-buffer)
  451. (let ((coding-system-for-write (or buffer-file-coding-system
  452. gnus-newsgroup-charset
  453. 'iso-8859-1))
  454. (coding-system-for-read (or buffer-file-coding-system
  455. gnus-newsgroup-charset
  456. 'iso-8859-1)))
  457. (funcall (mml2015-clear-verify-function))))
  458. (when (and mml2015-use (null (mml2015-clear-verify-function)))
  459. (mm-set-handle-multipart-parameter
  460. mm-security-handle 'gnus-details
  461. (format "Clear verification not supported by `%s'.\n" mml2015-use)))
  462. (mml2015-extract-cleartext-signature))
  463. (list (mm-make-handle buf mm-uu-text-plain-type)))))
  464. (defun mm-uu-pgp-signed-extract ()
  465. (let ((mm-security-handle (list (format "multipart/signed"))))
  466. (mm-set-handle-multipart-parameter
  467. mm-security-handle 'protocol "application/x-gnus-pgp-signature")
  468. (save-restriction
  469. (narrow-to-region start-point end-point)
  470. (add-text-properties 0 (length (car mm-security-handle))
  471. (list 'buffer (mm-uu-copy-to-buffer))
  472. (car mm-security-handle))
  473. (setcdr mm-security-handle
  474. (mm-uu-pgp-signed-extract-1 nil
  475. mm-security-handle)))
  476. mm-security-handle))
  477. (defun mm-uu-pgp-encrypted-test (&rest rest)
  478. (and
  479. mml2015-use
  480. (mml2015-clear-decrypt-function)
  481. (cond
  482. ((eq mm-decrypt-option 'never) nil)
  483. ((eq mm-decrypt-option 'always) t)
  484. ((eq mm-decrypt-option 'known) t)
  485. (t (prog1
  486. (y-or-n-p "Decrypt pgp encrypted part? ")
  487. (message ""))))))
  488. (defun mm-uu-pgp-encrypted-extract-1 (handles ctl)
  489. (let ((buf (mm-uu-copy-to-buffer (point-min) (point-max)))
  490. (first t)
  491. charset)
  492. ;; Make sure there's a blank line between header and body.
  493. (with-current-buffer buf
  494. (goto-char (point-min))
  495. (while (prog2
  496. (forward-line 1)
  497. (if first
  498. (looking-at "[^\t\n ]+:")
  499. (looking-at "[^\t\n ]+:\\|[\t ]"))
  500. (setq first nil)))
  501. (unless (memq (char-after) '(?\n nil))
  502. (insert "\n"))
  503. (save-restriction
  504. (narrow-to-region (point-min) (point))
  505. (setq charset (mail-fetch-field "charset")))
  506. (if (and (mm-uu-pgp-encrypted-test)
  507. (progn
  508. (mml2015-clean-buffer)
  509. (funcall (mml2015-clear-decrypt-function))
  510. (equal (mm-handle-multipart-ctl-parameter mm-security-handle
  511. 'gnus-info)
  512. "OK")))
  513. (progn
  514. ;; Decode charset.
  515. (if (and (or charset
  516. (setq charset gnus-newsgroup-charset))
  517. (setq charset (mm-charset-to-coding-system charset))
  518. (not (eq charset 'ascii)))
  519. ;; Assume that buffer's multibyteness is turned off.
  520. ;; See `mml2015-pgg-clear-decrypt'.
  521. (insert (mm-decode-coding-string (prog1
  522. (buffer-string)
  523. (erase-buffer)
  524. (mm-enable-multibyte))
  525. charset))
  526. (mm-enable-multibyte))
  527. (list (mm-make-handle buf mm-uu-text-plain-type)))
  528. (list (mm-make-handle buf '("application/pgp-encrypted")))))))
  529. (defun mm-uu-pgp-encrypted-extract ()
  530. (let ((mm-security-handle (list (format "multipart/encrypted"))))
  531. (mm-set-handle-multipart-parameter
  532. mm-security-handle 'protocol "application/x-gnus-pgp-encrypted")
  533. (save-restriction
  534. (narrow-to-region start-point end-point)
  535. (add-text-properties 0 (length (car mm-security-handle))
  536. (list 'buffer (mm-uu-copy-to-buffer))
  537. (car mm-security-handle))
  538. (setcdr mm-security-handle
  539. (mm-uu-pgp-encrypted-extract-1 nil
  540. mm-security-handle)))
  541. mm-security-handle))
  542. (defun mm-uu-gpg-key-skip-to-last ()
  543. (let ((point (point))
  544. (end-regexp (mm-uu-end-regexp entry))
  545. (beginning-regexp (mm-uu-beginning-regexp entry)))
  546. (when (and end-regexp
  547. (not (mm-uu-configure-p (mm-uu-type entry) 'disabled)))
  548. (while (re-search-forward end-regexp nil t)
  549. (skip-chars-forward " \t\n\r")
  550. (if (looking-at beginning-regexp)
  551. (setq point (match-end 0)))))
  552. (goto-char point)))
  553. (defun mm-uu-pgp-key-extract ()
  554. (let ((buf (mm-uu-copy-to-buffer start-point end-point)))
  555. (mm-make-handle buf
  556. '("application/pgp-keys"))))
  557. ;;;###autoload
  558. (defun mm-uu-dissect (&optional noheader mime-type)
  559. "Dissect the current buffer and return a list of uu handles.
  560. The optional NOHEADER means there's no header in the buffer.
  561. MIME-TYPE specifies a MIME type and parameters, which defaults to the
  562. value of `mm-uu-text-plain-type'."
  563. (let ((case-fold-search t)
  564. (mm-uu-text-plain-type (or mime-type mm-uu-text-plain-type))
  565. text-start start-point end-point file-name result entry func)
  566. (save-excursion
  567. (goto-char (point-min))
  568. (cond
  569. (noheader)
  570. ((looking-at "\n")
  571. (forward-line))
  572. ((search-forward "\n\n" nil t)
  573. t)
  574. (t (goto-char (point-max))))
  575. (setq text-start (point))
  576. (while (re-search-forward mm-uu-beginning-regexp nil t)
  577. (setq start-point (match-beginning 0)
  578. entry nil)
  579. (let ((alist mm-uu-type-alist)
  580. (beginning-regexp (match-string 0)))
  581. (while (not entry)
  582. (if (string-match (mm-uu-beginning-regexp (car alist))
  583. beginning-regexp)
  584. (setq entry (car alist))
  585. (pop alist))))
  586. (if (setq func (mm-uu-function-1 entry))
  587. (funcall func))
  588. (forward-line);; in case of failure
  589. (when (and (not (mm-uu-configure-p (mm-uu-type entry) 'disabled))
  590. (let ((end-regexp (mm-uu-end-regexp entry)))
  591. (if (not end-regexp)
  592. (or (setq end-point (point-max)) t)
  593. (prog1
  594. (re-search-forward end-regexp nil t)
  595. (forward-line)
  596. (setq end-point (point)))))
  597. (or (not (setq func (mm-uu-function-2 entry)))
  598. (funcall func)))
  599. (if (and (> start-point text-start)
  600. (progn
  601. (goto-char text-start)
  602. (re-search-forward "." start-point t)))
  603. (push
  604. (mm-make-handle (mm-uu-copy-to-buffer text-start start-point)
  605. mm-uu-text-plain-type)
  606. result))
  607. (push
  608. (funcall (mm-uu-function-extract entry))
  609. result)
  610. (goto-char (setq text-start end-point))))
  611. (when result
  612. (if (and (> (point-max) (1+ text-start))
  613. (save-excursion
  614. (goto-char text-start)
  615. (re-search-forward "." nil t)))
  616. (push
  617. (mm-make-handle (mm-uu-copy-to-buffer text-start (point-max))
  618. mm-uu-text-plain-type)
  619. result))
  620. (setq result (cons "multipart/mixed" (nreverse result))))
  621. result)))
  622. ;;;###autoload
  623. (defun mm-uu-dissect-text-parts (handle &optional decoded)
  624. "Dissect text parts and put uu handles into HANDLE.
  625. Assume text has been decoded if DECODED is non-nil."
  626. (let ((buffer (mm-handle-buffer handle)))
  627. (cond ((stringp buffer)
  628. (dolist (elem (cdr handle))
  629. (mm-uu-dissect-text-parts elem decoded)))
  630. ((bufferp buffer)
  631. (let ((type (mm-handle-media-type handle))
  632. (case-fold-search t) ;; string-match
  633. children charset encoding)
  634. (when (and
  635. (stringp type)
  636. ;; Mutt still uses application/pgp even though
  637. ;; it has already been withdrawn.
  638. (string-match "\\`text/\\|\\`application/pgp\\'" type)
  639. (equal (car (mm-handle-disposition handle))
  640. "inline")
  641. (setq
  642. children
  643. (with-current-buffer buffer
  644. (cond
  645. ((or decoded
  646. (eq (setq charset (mail-content-type-get
  647. (mm-handle-type handle)
  648. 'charset))
  649. 'gnus-decoded))
  650. (setq decoded t)
  651. (mm-uu-dissect
  652. t (cons type '((charset . gnus-decoded)))))
  653. (charset
  654. (setq decoded t)
  655. (mm-with-multibyte-buffer
  656. (insert (mm-decode-string (mm-get-part handle)
  657. charset))
  658. (mm-uu-dissect
  659. t (cons type '((charset . gnus-decoded))))))
  660. ((setq encoding (mm-handle-encoding handle))
  661. (setq decoded nil)
  662. ;; Inherit the multibyteness of the `buffer'.
  663. (with-temp-buffer
  664. (insert-buffer-substring buffer)
  665. (mm-decode-content-transfer-encoding
  666. encoding type)
  667. (mm-uu-dissect t (list type))))
  668. (t
  669. (setq decoded nil)
  670. (mm-uu-dissect t (list type)))))))
  671. ;; Ignore it if a given part is dissected into a single
  672. ;; part of which the type is the same as the given one.
  673. (if (and (<= (length children) 2)
  674. (string-equal (mm-handle-media-type (cadr children))
  675. type))
  676. (kill-buffer (mm-handle-buffer (cadr children)))
  677. (kill-buffer buffer)
  678. (setcdr handle (cdr children))
  679. (setcar handle (car children)) ;; "multipart/mixed"
  680. (dolist (elem (cdr children))
  681. (mm-uu-dissect-text-parts elem decoded))))))
  682. (t
  683. (dolist (elem handle)
  684. (mm-uu-dissect-text-parts elem decoded))))))
  685. (provide 'mm-uu)
  686. ;;; mm-uu.el ends here