Browse code
bug18636 (handle underscore) and rfe9010 (soft newlines)
Kevin Layer authored on 30/09/2009 20:31:11
Showing 4 changed files
Showing 4 changed files
... | ... |
@@ -1,3 +1,13 @@ |
1 |
+2009-09-30 Kevin Layer <layer@gemini.franz.com> |
|
2 |
+ |
|
3 |
+ * mime-api.cl: rfe9010: decode-header-text: remove "soft" |
|
4 |
+ newlines in the decoded text |
|
5 |
+ * mime-transfer-encoding.cl: bug18636: underscore handling: |
|
6 |
+ refine previous fix to be more surgical and conditional on a |
|
7 |
+ keyword argument, because other routines use these functions |
|
8 |
+ * t-imap.cl: the start of a test suite for the mime side of |
|
9 |
+ things |
|
10 |
+ |
|
1 | 11 |
2009-09-30 Kevin Layer <layer@gemini.franz.com> |
2 | 12 |
|
3 | 13 |
* mime-transfer-encoding.cl: bug18636: handle underscore |
... | ... |
@@ -426,18 +426,22 @@ This is a multi-part message in MIME format.~%")) |
426 | 426 |
(declare (optimize (speed 3)) |
427 | 427 |
(string text)) |
428 | 428 |
(let ((pos 0) |
429 |
- (len (length text))) |
|
429 |
+ (len (length text)) |
|
430 |
+ last-tail) |
|
430 | 431 |
(declare (fixnum pos len)) |
431 | 432 |
(with-output-to-string (res) |
432 | 433 |
(while (< pos len) |
433 |
- (multiple-value-bind (matched whole charset encoding encoded) |
|
434 |
- (match-re "=\\?([^?]+)\\?(q|b)\\?(.*?)\\?=" text |
|
434 |
+ (multiple-value-bind (matched whole charset encoding encoded tail) |
|
435 |
+ (match-re "=\\?([^?]+)\\?(q|b)\\?(.*?)\\?=(\\s+)?" text |
|
435 | 436 |
:start pos |
436 | 437 |
:case-fold t |
437 | 438 |
:return :index) |
438 | 439 |
|
439 |
- (if (null matched) |
|
440 |
- (return)) |
|
440 |
+ (when (null matched) |
|
441 |
+ (when last-tail |
|
442 |
+ (write-string text res |
|
443 |
+ :start (car last-tail) :end (cdr last-tail))) |
|
444 |
+ (return)) |
|
441 | 445 |
|
442 | 446 |
;; Write out the "before" stuff. |
443 | 447 |
(write-string text res :start pos :end (car whole)) |
... | ... |
@@ -451,7 +455,8 @@ This is a multi-part message in MIME format.~%")) |
451 | 455 |
then (qp-decode-string text |
452 | 456 |
:start (car encoded) |
453 | 457 |
:end (cdr encoded) |
454 |
- :external-format ef) |
|
458 |
+ :external-format ef |
|
459 |
+ :underscores-are-spaces t) |
|
455 | 460 |
else ;; FIXME: Clean this up with/if rfe6174 is completed. |
456 | 461 |
(octets-to-string |
457 | 462 |
(base64-string-to-usb8-array |
... | ... |
@@ -459,7 +464,8 @@ This is a multi-part message in MIME format.~%")) |
459 | 464 |
:external-format ef)) |
460 | 465 |
res)) |
461 | 466 |
|
462 |
- (setf pos (cdr whole)))) |
|
467 |
+ (setf pos (cdr whole)) |
|
468 |
+ (setf last-tail tail))) |
|
463 | 469 |
|
464 | 470 |
;; Write out the remaining portion. |
465 | 471 |
(write-string text res :start pos)))) |
... | ... |
@@ -184,8 +184,6 @@ |
184 | 184 |
then (return) |
185 | 185 |
else (out byte3)) |
186 | 186 |
else (out value))))) |
187 |
- elseif (eq byte #.(char-code #\_)) |
|
188 |
- then (out #.(char-code #\space)) |
|
189 | 187 |
else (out byte))) |
190 | 188 |
|
191 | 189 |
t)))) |
... | ... |
@@ -197,7 +195,8 @@ |
197 | 195 |
;; 1) the supplied or allocated array |
198 | 196 |
;; 2) the just past the last byte populated in the array. |
199 | 197 |
(defun qp-decode-usb8 (in out &key (start1 0) (end1 (length in)) |
200 |
- (start2 0) end2) |
|
198 |
+ (start2 0) end2 |
|
199 |
+ underscores-are-spaces) |
|
201 | 200 |
(declare (optimize (speed 3)) |
202 | 201 |
((simple-array (unsigned-byte 8) (*)) in out) |
203 | 202 |
(fixnum start1 end1 start2 end2)) |
... | ... |
@@ -262,20 +261,24 @@ |
262 | 261 |
then (return) |
263 | 262 |
else (out byte3)) |
264 | 263 |
else (out value))))) |
265 |
- elseif (eq byte #.(char-code #\_)) |
|
266 |
- then (out #.(char-code #\space)) |
|
264 |
+ elseif (and underscores-are-spaces (eq byte #.(char-code #\_))) |
|
265 |
+ then ;; See the discussion in bug18636 about why this is |
|
266 |
+ ;; done. |
|
267 |
+ (out #.(char-code #\space)) |
|
267 | 268 |
else (out byte))) |
268 | 269 |
|
269 | 270 |
(values out start2))))) |
270 | 271 |
|
271 | 272 |
(defun qp-decode-string (string &key (start 0) (end (length string)) |
272 | 273 |
(return :string) |
273 |
- (external-format :default)) |
|
274 |
+ (external-format :default) |
|
275 |
+ underscores-are-spaces) |
|
274 | 276 |
(multiple-value-bind (vec len) |
275 | 277 |
(string-to-octets string :start start :end end :null-terminate nil |
276 | 278 |
:external-format :latin1) |
277 | 279 |
(multiple-value-setq (vec len) |
278 |
- (qp-decode-usb8 vec vec :end1 len)) |
|
280 |
+ (qp-decode-usb8 vec vec :end1 len |
|
281 |
+ :underscores-are-spaces underscores-are-spaces)) |
|
279 | 282 |
(ecase return |
280 | 283 |
(:string |
281 | 284 |
(octets-to-string vec :end len :external-format external-format)) |
... | ... |
@@ -316,5 +319,3 @@ |
316 | 319 |
(t |
317 | 320 |
;; defined in mime-parse.cl |
318 | 321 |
(stream-to-stream-copy outstream instream count)))) |
319 |
- |
|
320 |
- |
... | ... |
@@ -20,6 +20,8 @@ |
20 | 20 |
;; requires smtp module too |
21 | 21 |
|
22 | 22 |
(eval-when (compile load eval) |
23 |
+ (require :smtp) |
|
24 |
+ (require :imap) |
|
23 | 25 |
(require :test)) |
24 | 26 |
|
25 | 27 |
|
... | ... |
@@ -227,30 +229,34 @@ |
227 | 229 |
|
228 | 230 |
(net.post-office:close-connection pb))) |
229 | 231 |
|
232 |
+ |
|
233 |
+(defun test-mime () |
|
234 |
+ (test-equal |
|
235 |
+ "foobar baz" |
|
236 |
+ (net.post-office:decode-header-text "=?utf-8?q?foo?= |
|
237 |
+ =?utf-8?q?bar?= baz")) |
|
238 |
+ (test-equal |
|
239 |
+ "before brucejones hello" |
|
240 |
+ (net.post-office:decode-header-text "before =?utf-8?q?bruce?= =?utf-8?q?jones?= hello")) |
|
241 |
+ (test-equal |
|
242 |
+ "[Franz Wiki] Update of \"Office/EmployeeDirectory\" by SteveHaflich" |
|
243 |
+ (net.post-office:decode-header-text "=?utf-8?q?=5BFranz_Wiki=5D_Update_of_=22Office/EmployeeDirectory=22_by_St?= |
|
244 |
+ =?utf-8?q?eveHaflich?=")) |
|
245 |
+ ) |
|
230 | 246 |
|
231 | 247 |
|
232 | 248 |
(defun test-imap () |
233 | 249 |
(handler-bind ((net.post-office:po-condition |
234 | 250 |
#'(lambda (con) |
235 | 251 |
(format t "Got imap condition: ~a~%" con)))) |
236 |
- |
|
237 |
- (test-connect) |
|
238 |
- |
|
239 |
- (test-sends) |
|
240 |
- |
|
241 |
- (test-flags) |
|
242 |
- |
|
243 |
- (test-mailboxes) |
|
244 |
- |
|
245 |
- (test-pop) |
|
246 |
- |
|
247 |
- |
|
248 |
- )) |
|
252 |
+ (test-mime) |
|
253 |
+;;;; Only jkf is setup to run the tests. |
|
254 |
+ (when (string= "jkf" (sys:getenv "USER")) |
|
255 |
+ (test-connect) |
|
256 |
+ (test-sends) |
|
257 |
+ (test-flags) |
|
258 |
+ (test-mailboxes) |
|
259 |
+ (test-pop)))) |
|
249 | 260 |
|
250 | 261 |
|
251 | 262 |
(if* *do-test* then (do-test :imap #'test-imap)) |
252 |
- |
|
253 |
- |
|
254 |
- |
|
255 |
- |
|
256 |
- |