[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

UUdecode



    Date: Tue, 29 Oct 1991 04:42 EST
    From: p2@porter.asl.dialnet.symbolics.com (Peter Paine)

    [...]

    Does anyone have a UUdecode facility?

All of our administrative E-Mail is handled by a Novell network running
on PC's.  When a DOS file is attached to a message and passed to
Internet it gets UUEncoded.  This prompted me to look into the
UUEncode/UUDecode problem.  You will notice a ZMail command for viewing
the uuencoded data defined inside comments.  This is because most of our
encoded files are actually text.  It should contain enough information
for you to make your own command to write the decoded data to a file.


-- Craig Lanning <CLanning@trc.scra.org>



Following is the Lisp code to implement UUCoding:
------------------------------ Begin ------------------------------
;;; -*- Mode: LISP; Syntax: Common-Lisp; Package: USER; Base: 10 -*-


;;;
;;; UU Encode/Decode
;;;

;;;
;;; This code should probably be reimplemented as an encoding/decoding
;;; stream which can handle the "begin <mode> <filename>" and "end"
;;; lines.
;;;

;;; Theoretical basis:
;;;
;;; UU Encoding is done by reading up to 45 bytes from the input file and
;;; encoding each set of three 8-bit bytes into a set of four 6-bit bytes.

;;; NOTE: The UUENCODE function does not insert the
;;;       "begin <mode> <filename>" line or the "end" line.

(defun ENCHAR (char)
  (code-char (+ (logand char #b00111111) #x20)))

(defun PUT8 (value pos char)
  (dpb (char-code char) (byte 8 (* pos 8)) value))

(defun GET6 (value pos)
  (enchar (ldb (byte 6 (* pos 6)) value)))

(defun UUENCODE (istream ostream)
  (labels (;(Enchar (ch) (code-char (+ (logand ch #b00111111) #x20)))
	   ;; For some reason, LET-SUBST chokes on PUT8 and GET6 -- CLanning 
	   ;(Put8 (value pos char)
	   ;  (dpb (char-code char) (byte 8 (* pos 8)) value))
	   ;(Get6 (value pos)
	   ;  (enchar (ldb (byte 6 (* pos 6)) value)))
	   (Encode (stream array start)
	     (let ((num 0))
	       (dotimes (i 3)
		 (setf num (put8 num (- 2 i) (aref array (+ start i)))))
	       (dotimes (i 4)
		 (write-char (get6 num (- 3 i)) stream))))
	   (Line-Read (stream array count)
	     (loop for i from 0 below count
		   as ch = (read-char stream nil nil)
		   if ch do (setf (aref array i) ch)
		   else do (return-from line-read i))
	     count))
    (loop with buf = (make-array 80 :element-type 'string-char)
	  for siz = (line-read istream buf 45)
	  do (write-char (enchar siz) ostream)
	     (loop for pos from 0 below siz by 3
		   do (encode ostream buf pos))
	     (write-char #\Return ostream)
	  until (zerop siz))))


;;; Theoretical basis:
;;;
;;; UU Decoding is done by reading one line from the input file and
;;; decoding each set of four 6-bit bytes into a set of three 8-bit bytes.

;;; NOTE: The UUDECODE function expects to be positioned after the
;;;       "begin <mode> <filename>" line.  Also, it will not check for
;;;       the presence of the "end" line.

#|
;;; used for debugging
(defun DECHAR (char)
  (logand (- (char-code ch) #x20) #b00111111))

(defun PUT6 (value pos char)
  (dbp (dechar char) (byte 6 (* pos 6)) value))

(defun GET8 (value pos)
  (chode-char (ldb (byte 8 (* pos 8)) value)))
|#

(defun UUDECODE (istream ostream)
  (labels ((Dechar (ch) (logand (- (char-code ch) #x20) #b00111111))
	   (Put6 (integer pos char) (dpb (dechar char) (byte 6 (* pos 6)) integer))
	   (Get8 (integer pos) (code-char (ldb (byte 8 (* pos 8)) integer)))
	   (Decode (stream array start flag)
	     (let ((integer 0))
	       (when (> flag 0)
		 (setf integer (put6 integer 3 (aref array start)))
		 (setf integer (put6 integer 2 (aref array (+ start 1))))
		 (write-char (get8 integer 2) stream))
	       (when (> flag 1)
		 (setf integer (put6 integer 1 (aref array (+ start 2))))
		 (write-char (get8 integer 1) stream))
	       (when (> flag 2)
		 (setf integer (put6 integer 0 (aref array (+ start 3))))
		 (write-char (get8 integer 0) stream)))))
    (loop for line = (read-line istream)
	  as len = (dechar (aref line 0))
	  until (zerop len)
	  do (loop for i from 1 by 4
		   for siz downfrom len by 3
		   do (decode ostream line i siz)
		   when (<= siz 0)
		     return))))

#|
zwei:
(define-zmail-top-level-command com-ZMAIL-VIEW-UUENCODED-MESSAGE
   "UU Decodes and display the contents of the current message."
   (must-have-msg)
  (let ((start-bp (search (send (msg-interval *msg*) :first-bp) "
begin"))
	end-bp encoded-bp)
    (unless start-bp (error "Unable to find start of UU Encoded block"))
    (setq start-bp (forward-word start-bp -1))
    (setq encoded-bp (forward-line start-bp))
    (setq end-bp (search start-bp "
end"))
    (format t "~2%------------------- ~A -------------------~2%" (bp-line start-bp))
    (with-interval-stream (istream encoded-bp end-bp)
      (cl-user::uudecode istream cl:*standard-output*))
    (format t "~2%------------------- End -------------------~%")
    )
  dis-none)
|#
------------------------------- End -------------------------------