merlyn@iwarp.intel.com (Randal Schwartz) (07/20/89)
I have been rather sternly warned against distributing the decrypted
version of the chess font from a week ago. However, the same words
did not seem to apply to my GNU Emacs eexec encode/decode routines. I
received about 100 requests for it, so here it is. (Hint: stop
sending requests!)
This is an update of the code I posted a few months ago to comp.emacs
and comp.lang.postscript. The code works on GNU Emacs version 18.54,
and should probably work all the way back to 18.forty-something, but I
can't be sure. It's sloooooowwww... but it was a quick hack anyway.
This is more properly done in C or (gack!) Postscript.
To repeat what I said before, and make it perfectly clear: I DID NOT
CRACK THE ALGORITHM. I used an article posted in comp.lang.postscript
about six months ago from someone in Europe. I was curious to see if
the numbers were accurate, and implemented them as a quick hack using
the closest roll-your-own tool I had around: GNU Emacs Elisp. My only
claim to fame is *this* *particular* *implementation*. I do not know
anything (nor do I have the time or motivation to find out) about any
other "secrets" regarding Postscript, so don't ask.
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: eexec.el
# Wrapped by merlyn@iwarpl3 on Thu Jul 20 09:12:48 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'eexec.el' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'eexec.el'\"
else
echo shar: Extracting \"'eexec.el'\" \(3707 characters\)
sed "s/^X//" >'eexec.el' <<'END_OF_FILE'
X;;; Postscript eexec support routines
X;;; LastEditDate "Fri May 19 08:57:31 1989"
X;;; Copyright (c) 1989 by Randal L. Schwartz. All Rights Reserved.
X;;; This code may be freely distributed according to the GNU Public License
X
X(defconst hex-string-to-int-table
X (let ((ht (make-vector 256 nil))) ; nil gives error at + if out-of-range
X (mapcar (function (lambda (pair) (aset ht (nth 0 pair) (nth 1 pair))))
X '((?0 0) (?1 1) (?2 2) (?3 3) (?4 4)
X (?5 5) (?6 6) (?7 7) (?8 8) (?9 9)
X (?a 10) (?b 11) (?c 12) (?d 13) (?e 14) (?f 15)
X (?A 10) (?B 11) (?C 12) (?D 13) (?E 14) (?F 15)))
X ht)
X "Table used by hex-string-to-int.")
X
X(defun hex-string-to-int (str)
X "Convert STRING to an integer by parsing it as a hexadecimal number."
X (let ((result 0))
X (mapcar
X (function (lambda (ch)
X (setq result (+ (lsh result 4)
X (aref hex-string-to-int-table ch)))))
X str)
X result))
X
X(defun byte-to-hex-string (byte)
X "Convert BYTE to a two-chararacter string by printing it in hexadecimal."
X (format "%02x" byte))
X
X(defconst eexec-const-init (hex-string-to-int "d971")
X "Used by eexec-endecode. Initial value for state machine.")
X
X(defconst eexec-const-mult (hex-string-to-int "ce6d")
X "Used by eexec-endecode. Multiplier value for state machine.")
X
X(defconst eexec-const-add (hex-string-to-int "58bf")
X "Used by eexec-endecode. Adder value for state machine.")
X
X(defconst eexec-const-seed (concat (mapcar 'hex-string-to-int
X '("17" "ec" "9c" "f3")))
X "Used by eexec-encode. A known good seed from uartpatch.ps.")
X
X(defun eexec-decode ()
X "Decode the first eexec string in the current (possibly narrowed) buffer.
XResult is displayed in a temp buffer."
X (interactive)
X (with-output-to-temp-buffer "*eexec-decode-output*"
X (goto-char (point-min))
X (search-forward "eexec")
X (let (str)
X (while (re-search-forward "[ \t\n]*\\([0-9a-fA-F][0-9a-fA-F]\\)" nil t)
X (setq str (cons (buffer-substring (match-beginning 1)
X (match-end 1))
X str)))
X (setq str (nreverse str))
X (setq str (eexec-endecode (concat (mapcar 'hex-string-to-int str))))
X (princ "Seed: ")
X (princ (apply 'concat (mapcar 'byte-to-hex-string (substring str 0 4))))
X (princ "\nText:\n")
X (princ (substring str 4)))))
X
X(defun eexec-encode (start end &optional seed)
X "Encode text from START to END (region if interactive).
XResult is displayed in a temp buffer. If optional SEED is passed as a
Xfour-character string, use it for initial state, else use the known
Xgood seed (the current value of eexec-const-seed)."
X (interactive "r")
X (with-output-to-temp-buffer "*eexec-encode-output*"
X (let ((i 0))
X (princ "currentfile eexec\n")
X (mapcar (function
X (lambda (ch)
X (princ (byte-to-hex-string ch))
X (if (< (setq i (1+ i)) 32) nil
X (princ "\n")
X (setq i 0))))
X (eexec-endecode
X (concat (or (and (stringp seed)
X (= (length seed) 4)
X seed)
X eexec-const-seed)
X (buffer-substring start end))
X t))
X (if (> i 0) (princ "\n")))))
X
X(defun eexec-endecode (str &optional encode)
X "Decode STR (or encode if optional ENCODE is non-nil), returning result.
XIf decoding, you will probably want to toss the first four bytes,
Xbut they are returned anyway so that you may reencode a decoded string
Xfor verification."
X (let ((state eexec-const-init) outbyte)
X (concat
X (mapcar
X (function
X (lambda (inbyte)
X (setq outbyte (logxor inbyte (logand (lsh state -8)))
X state (logand 65535 (+ state (if encode outbyte inbyte)))
X state (logand 65535 (* state eexec-const-mult))
X state (logand 65535 (+ state eexec-const-add)))
X outbyte))
X str))))
END_OF_FILE
if test 3707 -ne `wc -c <'eexec.el'`; then
echo shar: \"'eexec.el'\" unpacked with wrong size!
fi
# end of 'eexec.el'
fi
echo shar: End of shell archive.
exit 0
--
/== Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ====\
| on contract to Intel, Hillsboro, Oregon, USA |
| merlyn@iwarp.intel.com ...!uunet!iwarp.intel.com!merlyn |
\== Cute Quote: "Welcome to Oregon... Home of the California Raisins!" ==/