git.fiddlerwoaroof.com
Browse code

2006-11-16 Ahmon Dancy <dancy@dancy>

layer authored on 17/11/2006 00:32:07
Showing 3 changed files
... ...
@@ -1,3 +1,17 @@
1
+2006-11-16  Ahmon Dancy  <dancy@dancy>
2
+
3
+	bug16495: 
4
+	  
5
+	* smtp.cl: send-smtp-1: New external-format keyword arg.
6
+                                Now processes input in terms of bytes
7
+	                        instead of characters.  
8
+
9
+	* mime-api.cl: make-mime-part: Default external-format is :utf8
10
+	now.  Default encoding changed once again.  Now always base64,
11
+	except for when :text is supplied and is stringp, in which case
12
+	the encoded version of the string is examined to see if 7bit can
13
+	be used).
14
+
1 15
 2006-10-18  Ahmon Dancy  <dancy@dancy>
2 16
 
3 17
 	* mime-api.cl: bug16479: Improve default content-transfer-encoding
... ...
@@ -1,18 +1,20 @@
1 1
 #+(version= 8 0)
2
-(sys:defpatch "mime" 1
2
+(sys:defpatch "mime" 2
3 3
   "v0: New module.  See documentation.;
4
-v1: Improve default transfer encoding determination."
4
+v1: Improve default transfer encoding determination;
5
+v2: make-mime-part: Default external-format is :utf8."
5 6
   :type :system
6 7
   :post-loadable t)
7 8
 
8 9
 #+(version= 7 0)
9
-(sys:defpatch "mime" 1
10
+(sys:defpatch "mime" 2
10 11
   "v0: New module.  See documentation.;
11
-v1: Improve default transfer encoding determination."
12
+v1: Improve default transfer encoding determination;
13
+v2: make-mime-part: Default external-format is :utf8."
12 14
   :type :system
13 15
   :post-loadable t)
14 16
 
15
-;; $Id: mime-api.cl,v 1.3 2006/10/18 18:41:57 layer Exp $
17
+;; $Id: mime-api.cl,v 1.4 2006/11/17 00:32:07 layer Exp $
16 18
 
17 19
 (defpackage :net.post-office
18 20
   (:use #:lisp #:excl)
... ...
@@ -100,10 +102,10 @@ v1: Improve default transfer encoding determination."
100 102
 (defun make-mime-part (&key content-type encoding headers 
101 103
 			    (attachmentp nil attachmentp-supplied)
102 104
 			    name text (start 0) end file
103
-			    subparts (external-format :default)
105
+			    subparts (external-format :utf8)
104 106
 			    parameters charset id description)
105 107
   (let ((part (make-instance 'mime-part-constructed))
106
-	type subtype multipart textp filepath)
108
+	type subtype multipart textp filepath orig-text)
107 109
     
108 110
     (if* (and text file)
109 111
        then (error "Only one of :text or :file may be specified"))
... ...
@@ -115,7 +117,8 @@ v1: Improve default transfer encoding determination."
115 117
       (if* (streamp file)
116 118
 	 then (setf filepath (ignore-errors (namestring file)))
117 119
 	 else (setf filepath file)))
118
-    
120
+
121
+    ;; Select default content-type
119 122
     (when (null content-type)
120 123
       (if* filepath
121 124
 	 then (setf content-type (lookup-mime-type filepath)))
... ...
@@ -145,21 +148,34 @@ v1: Improve default transfer encoding determination."
145 148
     
146 149
     (if* (and (not multipart) (null text) (null file))
147 150
        then (error "One of :text or :file must be specified"))
151
+
148 152
     
153
+    ;; Select default charset
149 154
     (if* (and (null charset) textp)
150 155
        then (setf charset 
151 156
 	      (or 
152 157
 	       (guess-charset-from-ef (find-external-format external-format))
153 158
 	       "us-ascii")))
159
+
160
+    ;; For :text, break down to the final usb8.
161
+    (when text
162
+      (setf orig-text text)
163
+      (setf text (if* (stringp text)
164
+		    then (string-to-octets text :null-terminate nil
165
+					   :external-format external-format
166
+					   :start start
167
+					   :end end)
168
+		    else (subseq text start end))))
154 169
     
170
+    ;; Select default encoding, which is always base64 except for
171
+    ;; when :text was supplied as a string, in which case we scan to
172
+    ;; choose between 7bit and base64.
155 173
     (when (and (not multipart) (null encoding))
156
-      (if* textp
157
-	 then (if* (member charset '("us-ascii" "iso-2022-jp")
158
-			   :test #'equalp)
159
-		 then (setf encoding "7bit")
160
-		 else (setf encoding "8bit"))
161
-	 else (setf encoding "base64")))
162
-
174
+      (setf encoding
175
+	(if* (and (stringp orig-text) (not (8-bit-array-p text)))
176
+	   then "7bit"
177
+	   else "base64")))
178
+  
163 179
     (setf (mime-part-type part) type)
164 180
     (setf (mime-part-subtype part) subtype)
165 181
     (setf (mime-part-parameters part) parameters)
... ...
@@ -179,11 +195,7 @@ v1: Improve default transfer encoding determination."
179 195
 	    (if* (not attachmentp-supplied)
180 196
 	       then (setf attachmentp t))
181 197
        else (setf (source-type part) :usb8)
182
-	    (setf (source part) 
183
-	      (if* (stringp text)
184
-		 then (string-to-octets text :null-terminate nil
185
-					:external-format external-format)
186
-		 else (subseq text start end))))
198
+	    (setf (source part) text))
187 199
 
188 200
     (if* (and (not textp) (not attachmentp) (not multipart))
189 201
        then (setf (disposition part) "inline"))
... ...
@@ -206,6 +218,14 @@ v1: Improve default transfer encoding determination."
206 218
     
207 219
     part))
208 220
 
221
+(defun 8-bit-array-p (usb8)
222
+  (declare (optimize (speed 3) (safety 0))
223
+	   ((simple-array (unsigned-byte 8) (*)) usb8))
224
+  (dotimes (n (length usb8))
225
+    (declare (fixnum n))
226
+    (if (> (aref usb8 n) 127)
227
+	(return t))))
228
+
209 229
 (defparameter *ef-nick-to-mime-charset*
210 230
     '((:ascii . "us-ascii")
211 231
       (:iso-2022-jp . "iso-2022-jp")
... ...
@@ -223,7 +243,7 @@ v1: Improve default transfer encoding determination."
223 243
   (let ((ef-name (string-downcase (symbol-name (ef-name (crlf-base-ef ef))))))
224 244
     ;; Try iso-8559-x names.
225 245
     (multiple-value-bind (found ignore suffix)
226
-	(match-re (load-time-value "^iso8859-(\\d+)-base") ef-name)
246
+	(match-re "^iso8859-(\\d+)-base" ef-name)
227 247
       (declare (ignore ignore))
228 248
       (if found
229 249
 	  (return-from guess-charset-from-ef 
... ...
@@ -231,7 +251,7 @@ v1: Improve default transfer encoding determination."
231 251
     
232 252
     ;; Try windows- names.
233 253
     (multiple-value-bind (found whole value)
234
-	(match-re (load-time-value "^(\\d+)-base$") ef-name)
254
+	(match-re "^(\\d+)-base$" ef-name)
235 255
       (declare (ignore whole))
236 256
       (if found
237 257
 	  (return-from guess-charset-from-ef
... ...
@@ -1,17 +1,19 @@
1 1
 #+(version= 8 0)
2
-(sys:defpatch "smtp" 4
2
+(sys:defpatch "smtp" 5
3 3
   "v1: send-letter w/attachments; send-smtp* can take streams;
4 4
 v2: add :port argument to send-letter, send-smtp, send-smtp-auth;
5 5
 v3: fix incompatibility introduced in v2;
6
-v4: remove stray force-output of t."
6
+v4: remove stray force-output of t;
7
+v5: send-smtp-1: New external-format keyword arg."
7 8
   :type :system
8 9
   :post-loadable t)
9 10
 
10 11
 #+(version= 7 0)
11
-(sys:defpatch "smtp" 4
12
+(sys:defpatch "smtp" 5
12 13
   "v2: send-letter w/attachments; send-smtp* can take streams;
13 14
 v3: add :port argument to send-letter, send-smtp, send-smtp-auth;
14
-v4: fix incompatibility introduced in v3."
15
+v4: fix incompatibility introduced in v3;
16
+v5: rm stray force-output of t; send-smtp-1: New external-format keyword arg."
15 17
   :type :system
16 18
   :post-loadable t)
17 19
 
... ...
@@ -41,7 +43,7 @@ v4: fix incompatibility introduced in v3."
41 43
 ;; Suite 330, Boston, MA  02111-1307  USA
42 44
 ;;
43 45
 ;;
44
-;; $Id: smtp.cl,v 1.20 2006/10/16 17:35:38 layer Exp $
46
+;; $Id: smtp.cl,v 1.21 2006/11/17 00:32:07 layer Exp $
45 47
 
46 48
 ;; Description:
47 49
 ;;   send mail to an smtp server.  See rfc821 for the spec.
... ...
@@ -247,7 +249,8 @@ Attachments must be filenames, streams, or mime-part-constructed, not ~s"
247 249
 (defun send-smtp-auth (server from to login password &rest messages)
248 250
   (send-smtp-1 server from to login password messages))
249 251
 
250
-(defun send-smtp-1 (server from to login password messages)
252
+(defun send-smtp-1 (server from to login password messages
253
+		    &key (external-format :default))
251 254
   ;; send the effective concatenation of the messages via
252 255
   ;; smtp to the mail server
253 256
   ;; Each message should be a string or a stream.
... ...
@@ -297,24 +300,24 @@ Attachments must be filenames, streams, or mime-part-constructed, not ~s"
297 300
 	      (when message
298 301
 		(setf stream (if* (streamp message)
299 302
 				then message 
300
-				else (make-string-input-stream message)))
301
-		(unwind-protect 
302
-		    (progn
303
-		      (while (setf ch (read-char stream nil nil))
304
-			(if* (and at-bol (eq ch #\.))
305
-			   then ;; to prevent . from being interpreted as eol
306
-				(write-char #\. sock))
307
-			(if* (eq ch #\newline)
308
-			   then (setq at-bol t)
309
-				(if* (not (eq prev-ch #\return))
310
-				   then (write-char #\return sock))
311
-			   else (setq at-bol nil))
312
-			(write-char ch sock)
313
-			(setq prev-ch ch)))
314
-		  ;; unwind-protect
315
-		  (if* (not (streamp message))
316
-		     then (close stream))))))
317
-		
303
+				else (make-buffer-input-stream
304
+				      (string-to-octets 
305
+				       message 
306
+				       :null-terminate nil
307
+				       :external-format external-format))))
308
+
309
+		(while (setf ch (read-byte stream nil))
310
+		  (if* (and at-bol (eq ch #.(char-code #\.)))
311
+		     then ;; to prevent . from being interpreted as eol
312
+			  (write-char #\. sock))
313
+		  (if* (eq ch #.(char-code #\newline))
314
+		     then (setq at-bol t)
315
+			  (if* (not (eq prev-ch #.(char-code #\return)))
316
+			     then (write-char #\return sock))
317
+		     else (setq at-bol nil))
318
+		  (write-byte ch sock)
319
+		  (setq prev-ch ch)))))
320
+
318 321
 	  (write-char #\return sock) (write-char #\linefeed sock)
319 322
 	  (write-char #\. sock)
320 323
 	  (write-char #\return sock) (write-char #\linefeed sock)