Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / 5a / 85fc7ccbbc83dfed3f44029d7bbebc79167c2d
1 Return-Path: <amdragon@mit.edu>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 1F1EE431FBC\r
6         for <notmuch@notmuchmail.org>; Mon, 21 Apr 2014 11:38:18 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id 26ae3WpmMoN7 for <notmuch@notmuchmail.org>;\r
16         Mon, 21 Apr 2014 11:38:14 -0700 (PDT)\r
17 Received: from dmz-mailsec-scanner-3.mit.edu (dmz-mailsec-scanner-3.mit.edu\r
18         [18.9.25.14])\r
19         (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\r
20         (No client certificate requested)\r
21         by olra.theworths.org (Postfix) with ESMTPS id 33118431FC7\r
22         for <notmuch@notmuchmail.org>; Mon, 21 Apr 2014 11:38:02 -0700 (PDT)\r
23 X-AuditID: 1209190e-f79ee6d000000c40-9d-53556589d3f0\r
24 Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
25         (using TLS with cipher AES256-SHA (256/256 bits))\r
26         (Client did not present a certificate)\r
27         by dmz-mailsec-scanner-3.mit.edu (Symantec Messaging Gateway) with SMTP\r
28         id 22.75.03136.98565535; Mon, 21 Apr 2014 14:38:01 -0400 (EDT)\r
29 Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11])\r
30         by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id s3LIc1vd018354; \r
31         Mon, 21 Apr 2014 14:38:01 -0400\r
32 Received: from drake.dyndns.org\r
33         (216-15-114-40.c3-0.arl-ubr1.sbo-arl.ma.cable.rcn.com\r
34         [216.15.114.40]) (authenticated bits=0)\r
35         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
36         by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id s3LIbs8B029726\r
37         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
38         Mon, 21 Apr 2014 14:38:00 -0400\r
39 Received: from amthrax by drake.dyndns.org with local (Exim 4.77)\r
40         (envelope-from <amdragon@mit.edu>)\r
41         id 1WcJ6I-0003lI-HQ; Mon, 21 Apr 2014 14:37:54 -0400\r
42 From: Austin Clements <amdragon@MIT.EDU>\r
43 To: notmuch@notmuchmail.org\r
44 Subject: [PATCH 10/11] emacs: Rewrite content ID handling\r
45 Date: Mon, 21 Apr 2014 14:37:47 -0400\r
46 Message-Id: <1398105468-14317-11-git-send-email-amdragon@mit.edu>\r
47 X-Mailer: git-send-email 1.9.1\r
48 In-Reply-To: <1398105468-14317-1-git-send-email-amdragon@mit.edu>\r
49 References: <1398105468-14317-1-git-send-email-amdragon@mit.edu>\r
50 X-Brightmail-Tracker:\r
51  H4sIAAAAAAAAA+NgFtrAIsWRmVeSWpSXmKPExsUixCmqrduZGhpssPmKucX1mzOZHRg9nq26\r
52         xRzAGMVlk5Kak1mWWqRvl8CVsXH6UfaCJ5YV09exNDA+0uti5OSQEDCRmLm8mQXCFpO4cG89\r
53         WxcjF4eQwGwmiYaj05ggnI2MEkcWzmGGcO4wSVy59ROsRUhgLqPEn4nOIDabgIbEtv3LGUFs\r
54         EQFpiZ13Z7N2MXJwMAuoSfzpUgEJCwtYSmxsmcUMEmYRUJVo7NAFCfMKOEos757GDnGEnMTJ\r
55         Y5NZQWxOoHjb6pfsEJscJDbsXcM0gZF/ASPDKkbZlNwq3dzEzJzi1GTd4uTEvLzUIl1jvdzM\r
56         Er3UlNJNjOCAkeTbwfj1oNIhRgEORiUe3gKj0GAh1sSy4srcQ4ySHExKoryvooBCfEn5KZUZ\r
57         icUZ8UWlOanFhxglOJiVRHjXawLleFMSK6tSi/JhUtIcLErivG+trYKFBNITS1KzU1MLUotg\r
58         sjIcHEoSvDdTgBoFi1LTUyvSMnNKENJMHJwgw3mAhl8EqeEtLkjMLc5Mh8ifYlSUEudtA0kI\r
59         gCQySvPgemER/YpRHOgVYd4WkCoeYDKA634FNJgJaPCTLSEgg0sSEVJSDYzuZqW/PxdWPLzy\r
60         arJeqsxH6WW1Szr/rufY6HvztHShkC939ym2LyIB54U0vRIqNu2KS3ZYqdCsJOkefvusYzNL\r
61         YrrjKrUDszzyancweXGu/Zuut3mT3dHPX1YZT6tUWaVhqr/jf6DpyRzOAmPbBx93ndVImXlY\r
62         dsL5cJtLrgKbJDVcxKJby5RYijMSDbWYi4oTASkhZonDAgAA\r
63 X-BeenThere: notmuch@notmuchmail.org\r
64 X-Mailman-Version: 2.1.13\r
65 Precedence: list\r
66 List-Id: "Use and development of the notmuch mail system."\r
67         <notmuch.notmuchmail.org>\r
68 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
69         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
70 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
71 List-Post: <mailto:notmuch@notmuchmail.org>\r
72 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
73 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
74         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
75 X-List-Received-Date: Mon, 21 Apr 2014 18:38:18 -0000\r
76 \r
77 Besides generally cleaning up the code and separating the general\r
78 content ID handling from the w3m-specific code, this fixes several\r
79 problems.\r
80 \r
81 Foremost is that, previously, the code roughly assumed that referenced\r
82 parts would be in the same multipart/related as the reference.\r
83 According to RFC 2392, nothing could be further from the truth:\r
84 content IDs are supposed to be globally unique and globally\r
85 addressable.  This is nonsense, but this patch at least fixes things\r
86 so content IDs can be anywhere in the same message.\r
87 \r
88 As a side-effect of the above, this handles multipart/alternate\r
89 content-IDs more in line with RFC 2046 section 5.1.2 (not that I've\r
90 ever seen this in the wild).  This also properly URL-decodes cid:\r
91 URLs, as per RFC 2392 (the previous code did not), and applies crypto\r
92 settings from the show buffer (the previous code used the global\r
93 crypto settings).\r
94 ---\r
95  emacs/notmuch-show.el | 120 +++++++++++++++++++++++++++++++-------------------\r
96  1 file changed, 74 insertions(+), 46 deletions(-)\r
97 \r
98 diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el\r
99 index 9411c9a..f758091 100644\r
100 --- a/emacs/notmuch-show.el\r
101 +++ b/emacs/notmuch-show.el\r
102 @@ -503,6 +503,73 @@ (defun notmuch-show-toggle-part-invisibility (&optional button)\r
103           (overlay-put overlay 'invisible (not show))\r
104           t)))))\r
105  \r
106 +;; Part content ID handling\r
107 +\r
108 +(defvar notmuch-show--cids nil\r
109 +  "Alist from raw content ID to (MSG PART).")\r
110 +(make-variable-buffer-local 'notmuch-show--cids)\r
111 +\r
112 +(defun notmuch-show--register-cids (msg part)\r
113 +  "Register content-IDs in PART and all of PART's sub-parts."\r
114 +  (let ((content-id (plist-get part :content-id)))\r
115 +    (when content-id\r
116 +      ;; Note that content-IDs are globally unique, except when they\r
117 +      ;; aren't: RFC 2046 section 5.1.4 permits children of a\r
118 +      ;; multipart/alternative to have the same content-ID, in which\r
119 +      ;; case the MUA is supposed to pick the best one it can render.\r
120 +      ;; We simply add the content-ID to the beginning of our alist;\r
121 +      ;; so if this happens, we'll take the last (and "best")\r
122 +      ;; alternative (even if we can't render it).\r
123 +      (push (list content-id msg part) notmuch-show--cids)))\r
124 +  ;; Recurse on sub-parts\r
125 +  (let ((ctype (notmuch-split-content-type\r
126 +               (downcase (plist-get part :content-type)))))\r
127 +    (cond ((equal (first ctype) "multipart")\r
128 +          (mapc (apply-partially #'notmuch-show--register-cids msg)\r
129 +                (plist-get part :content)))\r
130 +         ((equal ctype '("message" "rfc822"))\r
131 +          (notmuch-show--register-cids\r
132 +           msg\r
133 +           (first (plist-get (first (plist-get part :content)) :body)))))))\r
134 +\r
135 +(defun notmuch-show--get-cid-content (cid)\r
136 +  "Return a list (CID-content content-type) or nil.\r
137 +\r
138 +This will only find parts from messages that have been inserted\r
139 +into the current buffer.  CID must be a raw content ID, without\r
140 +enclosing angle brackets, a cid: prefix, or URL encoding.  This\r
141 +will return nil if the CID is unknown or cannot be retrieved."\r
142 +  (let ((descriptor (cdr (assoc cid notmuch-show--cids))))\r
143 +    (when descriptor\r
144 +      (let* ((msg (first descriptor))\r
145 +            (part (second descriptor))\r
146 +            ;; Request caching for this content, as some messages\r
147 +            ;; reference the same cid: part many times (hundreds!).\r
148 +            (content (notmuch-get-bodypart-binary\r
149 +                      msg part notmuch-show-process-crypto 'cache))\r
150 +            (content-type (plist-get part :content-type)))\r
151 +       (list content content-type)))))\r
152 +\r
153 +(defun notmuch-show-setup-w3m ()\r
154 +  "Instruct w3m how to retrieve content from a \"related\" part of a message."\r
155 +  (interactive)\r
156 +  (if (boundp 'w3m-cid-retrieve-function-alist)\r
157 +    (unless (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist)\r
158 +      (push (cons 'notmuch-show-mode #'notmuch-show--cid-w3m-retrieve)\r
159 +           w3m-cid-retrieve-function-alist)))\r
160 +  (setq mm-inline-text-html-with-images t))\r
161 +\r
162 +(defvar w3m-current-buffer) ;; From `w3m.el'.\r
163 +(defun notmuch-show--cid-w3m-retrieve (url &rest args)\r
164 +  ;; url includes the cid: prefix and is URL encoded (see RFC 2392).\r
165 +  (let* ((cid (url-unhex-string (substring url 4)))\r
166 +        (content-and-type\r
167 +         (with-current-buffer w3m-current-buffer\r
168 +           (notmuch-show--get-cid-content cid))))\r
169 +    (when content-and-type\r
170 +      (insert (first content-and-type))\r
171 +      (second content-and-type))))\r
172 +\r
173  ;; MIME part renderers\r
174  \r
175  (defun notmuch-show-multipart/*-to-list (part)\r
176 @@ -527,56 +594,11 @@ (defun notmuch-show-insert-part-multipart/alternative (msg part content-type nth\r
177        (indent-rigidly start (point) 1)))\r
178    t)\r
179  \r
180 -(defun notmuch-show-setup-w3m ()\r
181 -  "Instruct w3m how to retrieve content from a \"related\" part of a message."\r
182 -  (interactive)\r
183 -  (if (boundp 'w3m-cid-retrieve-function-alist)\r
184 -    (unless (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist)\r
185 -      (push (cons 'notmuch-show-mode 'notmuch-show-w3m-cid-retrieve)\r
186 -           w3m-cid-retrieve-function-alist)))\r
187 -  (setq mm-inline-text-html-with-images t))\r
188 -\r
189 -(defvar w3m-current-buffer) ;; From `w3m.el'.\r
190 -(defvar notmuch-show-w3m-cid-store nil)\r
191 -(make-variable-buffer-local 'notmuch-show-w3m-cid-store)\r
192 -\r
193 -(defun notmuch-show-w3m-cid-store-internal (content-id msg part)\r
194 -  (push (list content-id msg part) notmuch-show-w3m-cid-store))\r
195 -\r
196 -(defun notmuch-show-w3m-cid-store (msg part)\r
197 -  (let ((content-id (plist-get part :content-id)))\r
198 -    (when content-id\r
199 -      (notmuch-show-w3m-cid-store-internal (concat "cid:" content-id)\r
200 -                                          msg part))))\r
201 -\r
202 -(defun notmuch-show-w3m-cid-retrieve (url &rest args)\r
203 -  (let ((matching-part (with-current-buffer w3m-current-buffer\r
204 -                        (assoc url notmuch-show-w3m-cid-store))))\r
205 -    (if matching-part\r
206 -       (let* ((msg (nth 1 matching-part))\r
207 -              (part (nth 2 matching-part))\r
208 -              (content-type (plist-get part :content-type)))\r
209 -         ;; Request content caching, as some messages reference the\r
210 -         ;; same cid: part many times (hundreds!), which results in\r
211 -         ;; many calls to `notmuch show'.\r
212 -         (insert (notmuch-get-bodypart-binary\r
213 -                  msg part notmuch-show-process-crypto 'cache))\r
214 -         content-type)\r
215 -      nil)))\r
216 -\r
217  (defun notmuch-show-insert-part-multipart/related (msg part content-type nth depth button)\r
218    (let ((inner-parts (plist-get part :content))\r
219         (start (point)))\r
220  \r
221 -    ;; We assume that the first part is text/html and the remainder\r
222 -    ;; things that it references.\r
223 -\r
224 -    ;; Stash the non-primary parts.\r
225 -    (mapc (lambda (part)\r
226 -           (notmuch-show-w3m-cid-store msg part))\r
227 -         (cdr inner-parts))\r
228 -\r
229 -    ;; Render the primary part.\r
230 +    ;; Render the primary part.  FIXME: Support RFC 2387 Start header.\r
231      (notmuch-show-insert-bodypart msg (car inner-parts) depth)\r
232      ;; Add hidden buttons for the rest\r
233      (mapc (lambda (inner-part)\r
234 @@ -888,6 +910,12 @@ (defun notmuch-show-insert-bodypart (msg part depth &optional hide)\r
235  \r
236  (defun notmuch-show-insert-body (msg body depth)\r
237    "Insert the body BODY at depth DEPTH in the current thread."\r
238 +\r
239 +  ;; Register all content IDs for this message.  According to RFC\r
240 +  ;; 2392, content IDs are *global*, but it's okay if an MUA treats\r
241 +  ;; them as only global within a message.\r
242 +  (notmuch-show--register-cids msg (first body))\r
243 +\r
244    (mapc (lambda (part) (notmuch-show-insert-bodypart msg part depth)) body))\r
245  \r
246  (defun notmuch-show-make-symbol (type)\r
247 -- \r
248 1.9.1\r
249 \r