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!" ==/