git.fiddlerwoaroof.com
Browse code

bug18636 (handle underscore) and rfe9010 (soft newlines)

Kevin Layer authored on 30/09/2009 20:31:11
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
-