Update of /project/cl-smtp/cvsroot/cl-smtp In directory clnet:/tmp/cvs-serv13213
Modified Files: CHANGELOG README attachments.lisp cl-smtp.asd cl-smtp.lisp Added Files: mime-types.lisp Log Message: Fixed bug with the file attachments to solve corrupted files when processed with chunking turned on. (Brian Sorg) Added automatically including mime types for attachesments of common known extensions. (Brian Sorg) Added Html-messages option to send-mail function. (Brian Sorg)
--- /project/cl-smtp/cvsroot/cl-smtp/CHANGELOG 2007/10/18 19:10:37 1.8 +++ /project/cl-smtp/cvsroot/cl-smtp/CHANGELOG 2007/11/03 23:53:29 1.9 @@ -1,3 +1,13 @@ +Version 20071104.1 +2007.11.04 +Fixed bug with the file attachments to solve corrupted files when +processed with chunking turned on. (Brian Sorg) +Added automatically including mime types for attachesments +of common known extensions. (Brian Sorg) +Added Html-messages option to send-mail function. (Brian Sorg) +Change attachments.lisp, cl-smtp.asd, cl-smtp.lisp, README, CHANGLOG +Add mime-type.lisp + Version 20071018.1 2007.10.18 Reverted the non allegro base64 functionality in attachment.lisp, --- /project/cl-smtp/cvsroot/cl-smtp/README 2007/09/04 18:54:06 1.6 +++ /project/cl-smtp/cvsroot/cl-smtp/README 2007/11/03 23:53:29 1.7 @@ -17,8 +17,8 @@ ------------------------------------------------
(cl-smtp:send-email host from to subject message - &key (port 25) cc bcc reply-to extra-headers authentication - attachments (buffer-size 256)) + &key (port 25) cc bcc reply-to extra-headers html-message + authentication attachments (buffer-size 256))
Arguments: - host (String) : hostname or ip-adress of the smtpserver @@ -32,6 +32,7 @@ - reply-to (String) : email adress - displayname (String) : displayname of the sender - extra-headers (Cons) : extra headers as alist + - html-message (String) : message body formatted with HTML tags - authentication (Cons) : list with 3 elements (:method "username" "password") method is a keyword :plain or :login --- /project/cl-smtp/cvsroot/cl-smtp/attachments.lisp 2007/10/16 17:33:19 1.4 +++ /project/cl-smtp/cvsroot/cl-smtp/attachments.lisp 2007/11/03 23:53:29 1.5 @@ -37,98 +37,131 @@ (dotimes (i (length chars) arr) (setf (aref arr i) (pop chars)))))
-(defun make-random-boundary (&optional (length 50) (boundary-chars *boundary-chars*)) +(defun make-random-boundary (&optional (length 30) + (boundary-chars *boundary-chars*)) (let ((boundary (make-string length)) + (prefix "_---------_") (chars-length (length boundary-chars))) - (dotimes (i length boundary) - (setf (aref boundary i) (svref *boundary-chars* (random chars-length)))))) + (dotimes (i length (concatenate 'string prefix boundary)) + (setf (aref boundary i) + (svref *boundary-chars* (random chars-length))))))
-(defun generate-multipart-header (sock boundary) +(defun generate-multipart-header (sock boundary &key (multipart-type "mixed")) (write-to-smtp sock - (format nil "Content-type: multipart/mixed;~%~tBoundary="~a"" - boundary))) + (format nil "Content-type: multipart/~a;~%~tBoundary="~a"" + multipart-type boundary)))
+(defun generate-message-header (sock + &key boundary ;; uniques string of character -- see make-random-boundary + content-type ;; "text/plain; charset=ISO-8859-1" + content-disposition ;; inline attachment + content-transfer-encoding ;; 7 bit or 8 bit + (include-blank-line? t)) + (when boundary + (write-to-smtp sock (format nil "--~a" boundary))) + (when content-type + (write-to-smtp sock (format nil "Content-type: ~a" content-type))) + (when content-disposition + (write-to-smtp sock (format nil "Content-Disposition: ~A" + content-disposition))) + (when content-transfer-encoding + (write-to-smtp sock (format nil "Content-Transfer-Encoding: ~A" + content-transfer-encoding))) + (when include-blank-line? (write-blank-line sock)))
-(defun wrap-message-with-multipart-dividers (message boundary) +(defun send-attachment-header (sock boundary name)
- (concatenate 'string (format nil "--~a~%" boundary) - (format nil "Content-type: text/plain~%") - (format nil "Content-Disposition: inline~%") - (format nil "~%") - message (format nil "~%"))) + (generate-message-header + sock + :boundary boundary + :content-type (format nil "~a;~%~tname="~a"" (lookup-mime-type name) name) + :content-transfer-encoding "base64" + :content-disposition (format nil "attachment; filename="~a"" name))) + +(defun send-end-marker (sock boundary) + ;; Note the -- at beginning and end of boundary is required + (write-to-smtp sock (format nil "~%--~a--~%" boundary)))
(defun send-attachment (sock attachment boundary buffer-size) - (print-debug (format nil "Sending attachment: ~a" attachment)) (when (probe-file attachment) (let ((name (file-namestring attachment))) (send-attachment-header sock boundary name) - (base64-encode-file attachment sock :buffer-size buffer-size) - ))) - -(defun send-attachment-header (sock boundary name) + (base64-encode-file attachment sock :buffer-size buffer-size))))
- (write-to-smtp sock - (format nil "~%--~a~%Content-type: application/octet-stream;~%~tname="~a"~%Content-Transfer-Encoding: base64~%Content-Disposition: attachment; filename="~a"~%" - boundary - name - name))) - -(defun send-attachments-end-marker (sock boundary) - (write-to-smtp sock - (format nil "~%--~a--~%" boundary))) - (defun base64-encode-file (file-in sock &key (buffer-size 256) ;; in KB - (wrap-at-column 76)) - (declare (ignorable wrap-at-column)) - (let* ((max-buffer-size (* buffer-size 1024)) - (byte-count 0) - (buffer (make-array max-buffer-size - :element-type '(unsigned-byte 8)))) + (wrap-at-column 70)) + "Encodes the file contents given by file-in, which can be of any form appropriate to with-open-file, and write the base-64 encoded version to sock, which is a socket. + +Buffer-size, given in KB, controls how much of the file is processed and written to the socket at one time. A buffer-size of 0, processes the file all at once, regardless of its size. One will have to weigh the speed vs, memory consuption risks when chosing which way is best. + +Wrap-at-column controls where the encode string is divided for line breaks." (when (probe-file file-in) ;;-- open filein --------- (with-open-file (strm-in file-in :element-type '(unsigned-byte 8)) - - (loop - (setq byte-count 0) - ;; read a portion of the file into the buffer - (setq byte-count (dotimes (i max-buffer-size max-buffer-size) - (let ((bchar (read-byte strm-in nil 'EOF))) - (if (eql bchar 'EOF) - (return i) - (setf (aref buffer i) bchar))))) - (print-debug (format nil "~%** Byte Count ~a~%" byte-count)) - ;; encode the buffer and write out to stream - #+allegro - (write-string (excl:usb8-array-to-base64-string - (if (< byte-count max-buffer-size) - (trimmed-buffer byte-count buffer) - buffer) - wrap-at-column) sock) - #-allegro - (cl-base64:usb8-array-to-base64-stream - (if (< byte-count max-buffer-size) - (trimmed-buffer byte-count buffer) - buffer) - sock :columns wrap-at-column) - (force-output sock) - ;;-- when finished reading exit do loop - (when (< byte-count max-buffer-size) - (return))))))) - -(defun trimmed-buffer (byte-count buffer) - "Creates an array the length of byte-count and copies contents of buffer into it. -Needed in Lispworks, Lispworks initialized all elements of the buffer array when it was made, allegro doesn't -seem to have this behavior" - (let ((trimmed-buffer (make-array byte-count :element-type '(unsigned-byte 8)))) - (dotimes (i byte-count trimmed-buffer) - (setf (aref trimmed-buffer i) (aref buffer i))))) - - - - - - - + (let* ((;; convert buffer size given to bytes + ;; or compute bytes based on file + max-buffer-size + (if (zerop buffer-size) + (file-length strm-in) + ;; Ensures 64 bit encoding is properly + ;; divided so that filler + ;; characters are not required between chunks + (* 24 (truncate (/ (* buffer-size 1024) 24))))) + (column-count 0) + (eof? nil) + (buffer (make-array max-buffer-size + :element-type '(unsigned-byte 8)))) + (loop + (print-debug (format nil "~%Process attachment ~a~%" file-in)) + (let* ((;; read a portion of the file into the buffer arrary and + ;; returns the index where it stopped + byte-count (dotimes (i max-buffer-size max-buffer-size) + (let ((bchar (read-byte strm-in nil 'EOF))) + (if (eql bchar 'EOF) + (progn + (setq eof? t) + (return i)) + (setf (aref buffer i) bchar)))))) + (if (zerop buffer-size) + ;; send file all at once to socket. + #+allegro + (write-string (excl:usb8-array-to-base64-string + buffer wrap-at-column) sock) + #-allegro + (cl-base64:usb8-array-to-base64-stream + buffer sock :columns wrap-at-column) + ;; otherwise process file in chunks. + ;; The extra encoded-string, + ;; and its subseq functions are brute force methods + ;; to properly handle the wrap-at-column feature + ;; between buffers. + ;; Not the most efficient way, + ;; but it works and uses existing functions + ;; in the cl-base64 package. + (let* ((;; drops off extra elements that were not filled in in reading, this is important for lisp systems that default a value into + ;; the array when it is created. -- ie Lispworks, SBCL + trimmed-buffer (if eof? + (subseq buffer 0 byte-count) + buffer)) + (encoded-string + #+allegro + (cl-base64:usb8-array-to-base64-string + trimmed-buffer) + #-allegro + (cl-base64:usb8-array-to-base64-string + trimmed-buffer))) + (loop for ch across encoded-string + do (progn + (write-char ch sock) + (incf column-count) + (when (= column-count wrap-at-column) + (setq column-count 0) + (write-char #\Newline sock)))))) + (force-output sock) + (print-debug (format nil "~% Eof is ~a~%" eof?)) + (when (or (zerop buffer-size) + eof?) + (return)))))))) --- /project/cl-smtp/cvsroot/cl-smtp/cl-smtp.asd 2007/10/18 19:10:37 1.9 +++ /project/cl-smtp/cvsroot/cl-smtp/cl-smtp.asd 2007/11/03 23:53:29 1.10 @@ -29,7 +29,10 @@ (print ,str)))
(asdf:defsystem :cl-smtp - :version "20071018.1" + :version "20071104.1" + :perform (load-op :after (op webpage) + (pushnew :cl-smtp cl:*features*)) :depends-on (:usocket #-allegro :cl-base64) :components ((:file "cl-smtp" :depends-on ("attachments")) - (:file "attachments"))) + (:file "attachments") + (:file "mime-types"))) --- /project/cl-smtp/cvsroot/cl-smtp/cl-smtp.lisp 2007/09/04 18:56:58 1.7 +++ /project/cl-smtp/cvsroot/cl-smtp/cl-smtp.lisp 2007/11/03 23:53:29 1.8 @@ -18,6 +18,8 @@
(in-package :cl-smtp)
+(defparameter *content-type* "text/plain; charset=ISO-8859-1") + (defparameter *x-mailer* (format nil "(~A ~A)" (lisp-implementation-type) (lisp-implementation-version))) @@ -61,12 +63,13 @@
(defun send-email (host from to subject message &key (port 25) cc bcc reply-to extra-headers - display-name authentication + html-message display-name authentication attachments (buffer-size 256)) (send-smtp host from (check-arg to "to") subject (mask-dot message) :port port :cc (check-arg cc "cc") :bcc (check-arg bcc "bcc") :reply-to reply-to :extra-headers extra-headers + :html-message html-message :display-name display-name :authentication authentication :attachments (check-arg attachments "attachments") @@ -76,56 +79,64 @@
(defun send-smtp (host from to subject message - &key (port 25) cc bcc reply-to extra-headers + &key (port 25) cc bcc reply-to extra-headers html-message display-name authentication attachments buffer-size) - (let ((sock (usocket:socket-stream (usocket:socket-connect host port))) - (boundary (make-random-boundary))) + (let* ((sock (usocket:socket-stream (usocket:socket-connect host port))) + (boundary (make-random-boundary)) + (html-boundary (if (and attachments html-message) + (make-random-boundary) + boundary))) (unwind-protect (progn (open-smtp-connection sock :authentication authentication) - (write-to-smtp sock - (format nil "MAIL FROM:~@[~A ~]<~A>" display-name from)) - (multiple-value-bind (code msgstr) - (read-from-smtp sock) - (when (/= code 250) - (error "in MAIL FROM command: ~A" msgstr))) - (compute-rcpt-command sock to) - (compute-rcpt-command sock cc) - (compute-rcpt-command sock bcc) - (write-to-smtp sock "DATA") - (multiple-value-bind (code msgstr) - (read-from-smtp sock) - (when (/= code 354) - (error "in DATA command: ~A" msgstr))) - (write-to-smtp sock (format nil "Date: ~A" (get-email-date-string))) - (write-to-smtp sock (format nil "From: ~@[~A <~]~A~@[>~]" - display-name from display-name)) - (write-to-smtp sock (format nil "To: ~{ ~a~^,~}" to)) - (when cc - (write-to-smtp sock (format nil "Cc: ~{ ~a~^,~}" cc))) - (write-to-smtp sock (format nil "Subject: ~A" subject)) - (write-to-smtp sock (format nil "X-Mailer: cl-smtp ~A" - *x-mailer*)) - (when reply-to - (write-to-smtp sock (format nil "Reply-To: ~A" reply-to))) - (when (and extra-headers - (listp extra-headers)) - (dolist (l extra-headers) - (write-to-smtp sock - (format nil "~A: ~{~a~^,~}" (car l) (rest l))))) - (write-to-smtp sock "Mime-Version: 1.0") - (when attachments - (generate-multipart-header sock boundary)) - (write-char #\Return sock) - (write-char #\NewLine sock) - (when attachments - (setq message (wrap-message-with-multipart-dividers - message boundary))) + (send-smtp-headers sock :from from :to to :cc cc :bcc bcc :reply-to reply-to :display-name display-name :extra-headers extra-headers :subject subject) + (send-multipart-headers + sock :attachment-boundary (when attachments boundary) + :html-boundary html-boundary) + ;;----------- Send the body Message --------------------------- + ;;--- Send the proper headers depending on plain-text, + ;;--- multi-part or html email + (cond ((and attachments html-message) + ;; if both present, start attachment section, + ;; then define alternative section, + ;; then write alternative header + (progn + (generate-message-header + sock :boundary boundary :include-blank-line? nil) + (generate-multipart-header sock html-boundary + :multipart-type "alternative") + (write-blank-line sock) + (generate-message-header + sock :boundary html-boundary :content-type *content-type* + :content-disposition "inline" :include-blank-line? nil))) + (attachments + (generate-message-header + sock :boundary boundary + :content-type *content-type* :content-disposition "inline" + :include-blank-line? nil)) + (html-message + (generate-message-header + sock :boundary html-boundary :content-type *content-type* + :content-disposition "inline")) + (t + (generate-message-header sock :content-type *content-type* + :include-blank-line? nil))) + (write-blank-line sock) (write-to-smtp sock message) + (write-blank-line sock) + ;;---------- Send Html text if needed ------------------------- + (when html-message + (generate-message-header + sock :boundary html-boundary + :content-type "text/html; charset=ISO-8859-1" + :content-disposition "inline") + (write-to-smtp sock html-message) + (send-end-marker sock html-boundary)) + ;;---------- Send Attachments ----------------------------------- (when attachments (dolist (attachment attachments) (send-attachment sock attachment boundary buffer-size)) - (send-attachments-end-marker sock boundary)) + (send-end-marker sock boundary)) (write-char #. sock) (write-char #\Return sock) (write-char #\NewLine sock) @@ -190,6 +201,49 @@ (when (/= code 250) (error "wrong response from smtp server: ~A" msgstr))))))
+(defun send-smtp-headers (sock + &key from to cc bcc reply-to + extra-headers display-name subject) + (write-to-smtp sock + (format nil "MAIL FROM:~@[~A ~]<~A>" display-name from)) + (multiple-value-bind (code msgstr) + (read-from-smtp sock) + (when (/= code 250) + (error "in MAIL FROM command: ~A" msgstr))) + (compute-rcpt-command sock to) + (compute-rcpt-command sock cc) + (compute-rcpt-command sock bcc) + (write-to-smtp sock "DATA") + (multiple-value-bind (code msgstr) + (read-from-smtp sock) + (when (/= code 354) + (error "in DATA command: ~A" msgstr))) + (write-to-smtp sock (format nil "Date: ~A" (get-email-date-string))) + (write-to-smtp sock (format nil "From: ~@[~A <~]~A~@[>~]" + display-name from display-name)) + (write-to-smtp sock (format nil "To: ~{ ~a~^,~}" to)) + (when cc + (write-to-smtp sock (format nil "Cc: ~{ ~a~^,~}" cc))) + (write-to-smtp sock (format nil "Subject: ~A" subject)) + (write-to-smtp sock (format nil "X-Mailer: cl-smtp ~A" + *x-mailer*)) + (when reply-to + (write-to-smtp sock (format nil "Reply-To: ~A" reply-to))) + (when (and extra-headers + (listp extra-headers)) + (dolist (l extra-headers) + (write-to-smtp sock + (format nil "~A: ~{~a~^,~}" (car l) (rest l))))) + (write-to-smtp sock "Mime-Version: 1.0")) + +(defun send-multipart-headers (sock &key attachment-boundary html-boundary) + (cond (attachment-boundary + (generate-multipart-header sock attachment-boundary + :multipart-type "mixed")) + (html-boundary (generate-multipart-header + sock html-boundary + :multipart-type "alternative")) + (t nil)))
(defun compute-rcpt-command (sock adresses) (dolist (to adresses) @@ -198,7 +252,6 @@ (read-from-smtp sock) (when (/= code 250) (error "in RCPT TO command: ~A" msgstr))))) -
(defun write-to-smtp (sock command) (print-debug (format nil "to server: ~A" command)) @@ -207,6 +260,11 @@ (write-char #\NewLine sock) (force-output sock))
+(defun write-blank-line (sock) + (write-char #\Return sock) + (write-char #\NewLine sock) + (force-output sock)) + (defun read-from-smtp (sock) (let* ((line (read-line sock)) (response-code (parse-integer line :start 0 :junk-allowed t))) @@ -214,7 +272,7 @@ (if (= (char-code (elt line 3)) (char-code #-)) (read-from-smtp sock) (values response-code line)))) - + (defun get-email-date-string () (multiple-value-bind (sec min h d m y wd) (get-decoded-time) (let* ((month (elt '("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec") (- m 1))) @@ -224,8 +282,7 @@ (get-universal-time))))) (format nil "~A, ~2,'0d ~A ~d ~2,'0d:~2,'0d:~2,'0d ~D" weekday d month y h min sec timezone)))) - - + (defun get-timezone-from-integer (x) (let ((min (/ x 60)) (hour (/ x 3600)))
--- /project/cl-smtp/cvsroot/cl-smtp/mime-types.lisp 2007/11/03 23:53:29 NONE +++ /project/cl-smtp/cvsroot/cl-smtp/mime-types.lisp 2007/11/03 23:53:29 1.1 ;;; -*- mode: Lisp -*- ;;; This file is part of CL-SMTP, the Lisp SMTP Client
;;; Copyright (C) 2004/2005/2006/2007 Jan Idzikowski
;;; This library is free software; you can redistribute it and/or ;;; modify it under the terms of the Lisp Lesser General Public License ;;; (http://opensource.franz.com/preamble.html), known as the LLGPL.
;;; This library is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; Lisp Lesser GNU General Public License for more details.
;;; File: attachments.lisp ;;; Description: encoding and transmitting login to include a mime attachment
;;; ;;; Contributed by Brian Sorg ;;; (in-package :cl-smtp)
(eval-when (:compile-toplevel :load-toplevel) ;;; Some of the most common file extensions with the mime types and descriptions. ;;; Extracted from numberous webpages. (defparameter *mime-type-descriptions* '(("386" "application/octet-stream" "Windows Enhanced Mode Driver or Swap File") ("001" "application/x-001" "FAX Datafile") ("3GPP" "audio/3gpp" "3rd Generation Partnership Project. Multimedia over 3rd generation wireless networks. H.263 video is the mandatory video format in 3GPP and AMR is the main audio/speech format.") ("7CB" "application/vnd.ecdis-update" "Electronic Chart Display and Information System (ECDIS)") ("aa" "audio/audible" "Audible file format (audio books)") ("aab" "application/x-authorware-bin" "Macromedia Authorware Binary") ("aac" "audio/aac" "Advanced Audio Coding File. Part of MPEG-2 and MPEG-4 standard. (Apple iTunes Store)") ("aam" "application/x-authorware-map" "Authorware Map (Shockwave?)") ("aas" "application/x-authorware-seg" "Authorware Shocked Packet (Segment) ") ("aba" "text/x-palm-aba" "AddressBook Archive (Palm)") ("ac3" "audio/ac3" "Adaptive Transform Coder 3 (relates to the bitstream format of Dolby Digital)") ("adr" "application/x-msaddr" "Address Book") ("aexpk" "application/pgp-keys" "Armored extracted public key (PGP)") ("afl" "video/animaflex" "Font file (for Allways) (Lotus 1-2-3)") ("ahtml" "magnus-internal/cgi-advertiser" " ") ("ai" "application/postscript" "Encapsulated PostScript (metafile) (Adobe Illustrator)") ("aif" "audio/x-aiff" "Audio Interchange File Format") ("aifc" "audio/x-aiff" "Audio Interchange File Format") ("aiff" "audio/x-aiff" "Audio Interchange File Format") ("aim" "application/x-aim" "AIM file - AOL Instant Messanger") ("alt" "application/x-up-alert" "Menu file (WordPerfect Library)") ("aos" "application/x-nokia-" "Add-On Software (Nokia 9000)") ("arj" "application/x-arj" "Compressed file archive created by ARJ or winzip") ("art" "image/x-jg" "AOL Johnson-Grace Compressed File and Another Ray Tracer Format") ("asc" "application/pgp-encrypted" "Armored Encrypted file (PGP)") ("asd" "application/astound" "Autosave file (Word for Windows)") ("asf" "application/vnd.ms-asf video/x-ms-asf video/x-ms-wm" "Windows Media file - Advanced Streaming Format (ASF), NetShow") ("asn" "application/astound" " ") ("asp" "text/html" "Active Server Pages - standard HTML documents interlaced with ActiveX script code ") ("asr" "video/x-ms-asf" "Microsoft NetShow") ("asx" "video/x-ms-asf application/x-mplayer2" "VXtreme (Microsoft streaming AV)") ("asz" "application/astound" " ") ("au" "audio/basic" "8-bit u-law [PCM] / 8000 Hz") ("avi" "video/x-msvideo" "Windows Video file") ("axs" "application/olescript" " ") ("bas" "text/plain" "BASIC program") ("bat" "application/octet-stream" "DOS BAT (Batch) file.") ("bcpio" "application/x-bcpio" "Old Binary CPIO") ("bexpk" "application/pgp-keys" "binary extracted public key (PGP)") ("bin" "application/octet-stream" "Uninterpreted Binary Data") ("bk" "application/vnd.framemaker" "FrameMaker book ") ("bleep" "application/bleeper" " ") ("bmp" "image/x-bmp" "Windows Bitmap (PaintBrush)") ("btf" "image/prs.btf" "NationsBank Check Images (also .btif)") ("c" "text/plain" "C program") ("c++" "text/plain" "C program") ("cab" "application/cab" "Cabinet file Microsoft installation archive. opersyss=win32, mac cpu=x86, ppc, mips, alpha") ("cal" "application/x-msschedplus" "MS schedplus or calendar") ("cat" "application/pdf" "PDF Catalog (Used with Acrobat Reader and Search plug-in)") ("cat" "application/vnd.ms-pki.seccat" "Security Catalog") ("ccs" "text/ccs" "Cluster Configuration System used with the Global File System (GFS) in Red Hat Linux") ("cdda" "audio/aiff" "CD Audio Track") ("cda" "audio/x-cda" "CD Audio Track") ("cdf" "text/plain" "Channel Definition Format - MS push std") ("cdr" "application/x-coreldrw" "Corel Draw (metafile)") ("cer" " application/pkix-cert" "Certificatefile") ("cfm" "wwwserver/wsapi" "Cold Fusion Markup") ("cgi" "magnus-internal/cgi" "Common Gateway Interface") ("cgm" "image/cgm" "Computer Graphics Metafile ") ("chat" "application/x-chat" " ") ("che" "application/x-up-cacheop" " ") ("cht" "audio/x-dspeech" "Chart (Harvard Graphics 2.0 - SoftCraft Presenter)") ("cil" "application/vnd.ms-artgalry" "Clip Gallery Download Packages") ("class" "application/java-vm" "Java") ("cli" "application/vnd.ms-artgalry" " ") ("clp" "application/x-msclip" "Windows Clipboard (metafile)") ("cmx" "image/x-cmx" " ") ("cnc" "application/x-cnc" "CNC general program data") ("cod" "image/cis-cod" "Datafile (Forecast Plus - MS Multiplan - StatPac Gold)") ("coda" "application/x-coda" " ") ("com" "application/octet-stream" "DOS COM Executable (similar to exe, but a direct memory image)") ("cpi" "image/cpi" "ColorLab Processed Image ") ("cpio" "application/x-cpio" "IEEE Std1003.2 (`POSIX') CPIO") ("cpt" "application/mac-compactpro" "Compact Pro Archive") ("crd" "application/x-mscardfile" "MS cardfile") ("crt" "application/x-x509-ca-cert" "Certificatefile") ("csh" "application/x-csh" "CSH Script") ("csm" "application/x-cu-seeme" "Precompiled headers (Borland C++ 4.5)") ("css" "text/css" "Cascading Style Sheets") ("csv" "text/csv" "Comma-Separated Values (Excel, Lotus 123, FoxPro, MS Outlook)") ("ct" "image/" "Iris CT Graphic or Scitex CT Handshake Bitmap ") ("cu" "application/x-cu-seeme" " ") ("cut" "image/x-halo-cut" "Bitmap graphics") ("dat" "application/octet-stream" "Data file. Can be anything, text, graphics, binary, ...") ("dba" "text/x-palm-dba" "DateBook Archive (Palm)") ("dbf" "application/octet-stream" "DataBase File (FoxPro, dBase) ") ("dbm" "wwwserver/wsapi" "ColdFusion IIS Plugin") ("dca" "application/dca-rft" "IBM Doc Content Arch") ("dcr" "application/x-director" "Macromedia Director (Shockwave)") ("deb" "application/octet-stream" "Binary for debian UNIX") ("der" "application/x-x509-ca-cert" "Certificatefile") ("dir" "application/x-director" "Macromedia Director (Shockwave)") ("dll" "application/x-msdownload" "Dynamically Linked Library (DOS) pe-portable executable opersys=win32, mac cpu=x86, ppc, mips, alpha") ("dms" "application/octet-stream" "Compressed Amiga file archive created by DISKMASHER") ("doc" "application/msword" "MS Word") ("dot" "application/msword" "MS Word (Template)") ("dsf" "image/x-mgx-dsf" "Micrografx Designer 6 (metafile)") ("dst" "application/tajima" "PC-RDist Distribution file ") ("dtd" "text/xml" "SGML Document (Type) Definition file") ("dus" "audio/x-dspeech" "Readiris font dictionary") ("dvi" "application/x-dvi" "TeX DVI (Device Independent)") ("dwc" "application/dwc" "compressed archive") ("dwf" "drawing/x-dwf" "Autodesk WHIP! Drawing Web file") ("dwg" "application/x-acad" "AutoCAD Drawing") ("dxf" "application/vnd.dxf" "Drawing eXchange Format, Data Exchange File, AutoCAD (vector)") ("dxr" "application/x-director" "Macromedia Director (Shockwave)") ("ebk" "application/x-expandedbook" " ") ("emf" "image/x-emf" "Enhanced metafile created in Microsoft Windows and Visio 2002 applications") ("eml" "message/rfc822" "MS Internet Mail Message (Outlook Express and others)") ("enc" "application/pre-encrypted" "Pre-encrypted Data (also Sniffer trace)") ("eps" "application/postscript" "Encapsulated PostScript (raster)") ("erf" "application/x-hsp-erf" " ") ("es" "audio/echospeech" " ") ("etf" "image/x-etf" "Enriched Text file") ("etx" "text/x-setext" "Structure Enchanced Text") ("evy" "application/x-envoy" "Document (WordPerfect Envoy)") ("exe" "application/x-pe-" "pe-portable executable opersys=win32, mac cpu=x86, ppc, mips, alpha") ("fdf" "application/vnd.fdf" "acrobat reader") ("fh4" "image/x-freehand" "Vector graphics (Aldus FreeHand 4.x)") ("fh5" "image/x-freehand" "Freehand 5")
[378 lines skipped]