git.fiddlerwoaroof.com
Browse code

see ChangeLog

dancy authored on 05/01/2007 21:31:25
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+2007-01-05  Ahmon Dancy  <dancy@dancy>
2
+
3
+	* mime-transfer-encoding.cl: Added qp-decode-stream.
4
+
1 5
 2006-12-21  Kevin Layer  <layer@gemini.franz.com>
2 6
 
3 7
 	* mime-transfer-encoding.cl: fix for building on 8.1.pre-beta.3
... ...
@@ -1,4 +1,4 @@
1
-;; $Id: mime-transfer-encoding.cl,v 1.5 2006/12/21 18:22:15 layer Exp $
1
+;; $Id: mime-transfer-encoding.cl,v 1.6 2007/01/05 21:31:25 dancy Exp $
2 2
 
3 3
 (defpackage :net.post-office
4 4
   (:use #:lisp #:excl)
... ...
@@ -95,93 +95,101 @@
95 95
 
96 96
 ;; Decoding stuff
97 97
 
98
+
99
+;; Used by qp-decode-stream
100
+(defconstant *qp-digit-values*
101
+    #.(let ((arr (make-array 257 :element-type 'fixnum)))
102
+	(dotimes (n 256)
103
+	  (setf (aref arr n)
104
+	    (if* (<= (char-code #\0) n (char-code #\9))
105
+	       then (- n (char-code #\0))
106
+	     elseif (<= (char-code #\A) n (char-code #\F))
107
+	       then (- n (- (char-code #\A) 10))
108
+	       else -1)))
109
+	(setf (aref arr 256) -2)
110
+	arr))
111
+
112
+
113
+(defun qp-decode-stream (instream outstream &key count)
114
+  (declare (optimize (speed 3)))
115
+  
116
+  (let (unread-buf)
117
+  
118
+    (macrolet ((unread (byte)
119
+		 `(progn
120
+		    (setf unread-buf ,byte)
121
+		    (if count
122
+			(incf count))))
123
+	       (get-byte (&key eof-value)
124
+		 `(block get-byte
125
+		    (if* count
126
+		       then (if (zerop count)
127
+				(return-from get-byte ,eof-value))
128
+			    (decf count))
129
+		    (if* unread-buf
130
+		       then (prog1 unread-buf
131
+			      (setf unread-buf nil))
132
+		       else (read-byte instream nil ,eof-value))))
133
+	       (out (byte)
134
+		 `(write-byte ,byte outstream))
135
+	       (eol-p (byte)
136
+		 `(or (eq ,byte 10) (eq ,byte 13))))
137
+	       
138
+      (let (byte)
139
+	(while (setf byte (get-byte))
140
+	  (if* (eq byte #.(char-code #\=))
141
+	     then (let ((nextbyte (get-byte)))
142
+		    (if* (null nextbyte)
143
+		       then ;; stray equal sign.  just dump and terminate.
144
+			    (out byte)
145
+			    (return))
146
+		    (if* (eol-p nextbyte)
147
+		       then ;; soft line break.  
148
+			    (if (eq nextbyte 13) ;; CR
149
+				(setf nextbyte (get-byte)))
150
+			    (if (not (eq nextbyte 10)) ;; LF
151
+				(unread nextbyte))
152
+		       else ;; =XY encoding
153
+			    (let* ((byte3 (get-byte :eof-value 256))
154
+				   (high (aref *qp-digit-values* nextbyte))
155
+				   (low (aref *qp-digit-values* byte3))
156
+				   (value (logior (the fixnum (ash high 4)) low)))
157
+			      (declare (fixnum byte3 high low value))
158
+			      (if* (< value 0)
159
+				 then ;; Invalid or truncated encoding. just dump it.
160
+				      (out byte)
161
+				      (out nextbyte)
162
+				      (if* (eq low -2) ;; EOF
163
+					 then (return)
164
+					 else (out byte3))
165
+				 else (out value)))))
166
+	     else (out byte)))
167
+	
168
+	t))))
169
+
98 170
 ;; 'instream' must be positioned at the beginning of the part body 
99 171
 ;; by the caller beforehand.
100 172
 (defmacro with-decoded-part-body-stream ((sym part instream) &body body)
101
-  (let ((bodystream (gensym))
102
-	(p (gensym))
103
-	(encoding (gensym)))
173
+  (let ((p (gensym))
174
+	(encoding (gensym))
175
+	(count (gensym)))
104 176
     `(let* ((,p ,part)
105
-	    (,encoding (mime-part-encoding ,p)))
106
-       (with-part-stream (,bodystream ,p ,instream :header nil)
107
-	 (excl:with-function-input-stream (,sym #'mime-decode-transfer-encoding
108
-						,bodystream
109
-						,encoding)
110
-	   ,@body)))))
177
+	    (,encoding (mime-part-encoding ,p))
178
+	    (,count (mime-part-body-size ,p)))
179
+       (excl:with-function-input-stream (,sym #'mime-decode-transfer-encoding
180
+					      ,instream
181
+					      ,encoding
182
+					      ,count)
183
+	 ,@body))))
111 184
 					  
112
-(defun mime-decode-transfer-encoding (outstream instream encoding)
113
-  (funcall 
114
-   (cond
115
-    ((equalp encoding "quoted-printable")
116
-     #'qp-decode-stream)
117
-    ((equalp encoding "base64")
118
-     #'excl::base64-decode-stream)
119
-    (t
120
-     #'sys:copy-file))
121
-   instream outstream))
122
-
123
-(defun qp-decode-stream (instream outstream)
124
-  (declare (optimize (speed 3)))
125
-  (let ((linebuf (make-array 4096 :element-type 'character))
126
-	pos char char2 softlinebreak)
127
-    (declare (dynamic-extent linebuf)
128
-	     (fixnum pos))
185
+(defun mime-decode-transfer-encoding (outstream instream encoding count)
186
+  (cond
187
+   ((equalp encoding "quoted-printable")
188
+    (qp-decode-stream instream outstream :count count))
189
+   ((equalp encoding "base64")
190
+    (excl:base64-decode-stream instream outstream :count count :error-p nil))
191
+   (t
192
+    ;; defined in mime-parse.cl
193
+    (stream-to-stream-copy outstream instream count))))
129 194
     
130
-    (loop
131
-      (multiple-value-bind (line dummy max)
132
-	  (simple-stream-read-line instream nil nil linebuf)
133
-	(declare (ignore dummy)
134
-		 (fixnum max)
135
-		 (simple-string line))
136
-	(if (null line)
137
-	    (return))
138
-	
139
-	(if (null max)
140
-	    (setf max (length line)))
141
-	
142
-	(setf pos 0)
143
-	
144
-	(macrolet ((getchar () 
145
-		     `(if (< pos max)
146
-			  (prog1 (schar line pos) (incf pos))))
147
-		   (decode-dig (char)
148
-		     `(the (integer 0 256) (decode-qp-hex-digit ,char))))
149
-		   
150
-	  (while (< pos max)
151
-	    (setf char (getchar))
152
-	    
153
-	    (if* (eq char #\=)
154
-	       then ;; Check for soft line break.
155
-		    (if* (= pos max)
156
-		       then (setf softlinebreak t)
157
-		       else (setf char (getchar))
158
-			    (setf char2 (getchar))
159
-			    
160
-			    (let ((value (logior 
161
-					  (ash (decode-dig char) 4)
162
-					  (decode-dig char2))))
163
-			      (if* (< value 256)
164
-				 then (write-byte value outstream)
165
-				 else ;; We got some bogus input.  
166
-				      ;; Leave it untouched
167
-				      (write-char #\= outstream)
168
-				      (if char
169
-					  (write-char char outstream))
170
-				      (if char2
171
-					  (write-char char2 outstream)))))
172
-	       else (write-char char outstream)))
173
-	  ;; outside 'while' loop.
174
-	
175
-	  (if* softlinebreak
176
-	     then (setf softlinebreak nil)
177
-	     else (write-char #\newline outstream)))))))
178
-
179
-
180
-(defun decode-qp-hex-digit (char)
181
-  (declare (optimize (speed 3) (safety 0) (debug 0)))
182
-  (if* (char<= #\0 char #\9)
183
-     then (- (the (integer 0 255) (char-code char)) #.(char-code #\0))
184
-   elseif (char<= #\A char #\F)
185
-     then (- (the (integer 0 255) (char-code char)) #.(- (char-code #\A) 10))
186
-     else 256))
187 195