Back to home page

MITgcm

 
 

    


File indexing completed on 2018-03-02 18:44:47 UTC

view on githubraw file Latest commit ec6cf3b0 on 2003-08-26 20:45:25 UTC
ec6cf3b09d Ed H*0001 /* macbhex.c -- simple binhex decoding routine */
                0002 /* (C) Copyright 1993,1994 by Carnegie Mellon University
                0003  * All Rights Reserved.
                0004  *
                0005  * Permission to use, copy, modify, distribute, and sell this software
                0006  * and its documentation for any purpose is hereby granted without
                0007  * fee, provided that the above copyright notice appear in all copies
                0008  * and that both that copyright notice and this permission notice
                0009  * appear in supporting documentation, and that the name of Carnegie
                0010  * Mellon University not be used in advertising or publicity
                0011  * pertaining to distribution of the software without specific,
                0012  * written prior permission.  Carnegie Mellon University makes no
                0013  * representations about the suitability of this software for any
                0014  * purpose.  It is provided "as is" without express or implied
                0015  * warranty.
                0016  *
                0017  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
                0018  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                0019  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
                0020  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                0021  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
                0022  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                0023  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                0024  * SOFTWARE.
                0025  */
                0026 
                0027 #include <stdio.h>
                0028 #include <ctype.h>
                0029 #include <memory.h>
                0030 #include "part.h"
                0031 #include "macnapp.h"
                0032 #include "macmpack.h"
                0033 
                0034 /* from macos.c: */
                0035 extern void renameDescFile(char *, short, long);
                0036 
                0037 char binhex_decode[256] = {
                0038     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0039     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0040     -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1,
                0041     13, 14, 15, 16, 17, 18, 19, -1, 20, 21, -1, -1, -1, -1, -1, -1,
                0042     22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1,
                0043     37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, -1, -1, -1, -1,
                0044     48, 49, 50, 51, 52, 53, 54, -1, 55, 56, 57, 58, 59, 60, -1, -1,
                0045     61, 62, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0046     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0047     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0048     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0049     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0050     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0051     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0052     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0053     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                0054 };
                0055 #define BHEXVAL(c) (binhex_decode[(unsigned char) c])
                0056 
                0057 typedef union {
                0058     unsigned char c[4];
                0059     unsigned long val;
                0060 } longbuf;
                0061 
                0062 typedef struct {
                0063     OSType type, creator;
                0064     unsigned short flags;
                0065     long dlen, rlen;
                0066 } binhex_header;
                0067 
                0068 #define STATE_START  0
                0069 #define STATE_FNAME  1
                0070 #define STATE_HEADER 2
                0071 #define STATE_HCRC   3
                0072 #define STATE_DFORK  4
                0073 #define STATE_DCRC   5
                0074 #define STATE_RFORK  6
                0075 #define STATE_RCRC   7
                0076 #define STATE_DONE   8
                0077 #define STATE_ERROR  9
                0078 
                0079 typedef struct binhex_state {
                0080     short state;            /* current state */
                0081     short part;             /* current part number */
                0082     unsigned short CRC;     /* cumulative CRC */
                0083     unsigned short fileCRC; /* CRC value from file */
                0084     longbuf octetbuf;       /* buffer for decoded 6-bit values */
                0085     short octetin;          /* current input position in octetbuf */
                0086     short donepos;          /* ending position in octetbuf */
                0087     short inCRC;            /* flag set when reading a CRC */
                0088     long count;             /* generic counter */
                0089     FILE *outfile;          /* output file */
                0090     short marker;           /* flag indicating maker */
                0091     unsigned char rlebuf;   /* buffer for last run length encoding value */
                0092     PCstr namebuf[65];      /* buffer for binhex filename */
                0093     binhex_header head;     /* buffer for header */
                0094     FSSpec fspec;           /* output file */
                0095 } binhex_state;
                0096 
                0097 /* global state */
                0098 static binhex_state bh;
                0099 
                0100 /* process a binhex character
                0101  */
                0102 static void binhex_process(struct part *inpart)
                0103 {
                0104     unsigned short tmpcrc, cval;
                0105     unsigned char ctmp, c = bh.rlebuf;
                0106     StandardFileReply reply;
                0107     FInfo finfo;
                0108     char buf[256];
                0109     
                0110     /* do CRC */
                0111     ctmp = bh.inCRC ? c : 0;
                0112     cval = bh.CRC & 0xf000;
                0113     tmpcrc = ((unsigned short) (bh.CRC << 4) | (ctmp >> 4))
                0114             ^ (cval | (cval >> 7) | (cval >> 12));
                0115     cval = tmpcrc & 0xf000;
                0116     bh.CRC = ((unsigned short) (tmpcrc << 4) | (ctmp & 0x0f))
                0117             ^ (cval | (cval >> 7) | (cval >> 12));
                0118 
                0119     /* handle state */
                0120     switch (bh.state) {
                0121         case STATE_START:
                0122             bh.state = STATE_FNAME;
                0123             bh.count = 1;
                0124             *bh.namebuf = (c & 63);
                0125             break;
                0126         case STATE_FNAME:
                0127             bh.namebuf[bh.count] = c;
                0128             if (bh.count++ > *bh.namebuf) {
                0129                 bh.state = STATE_HEADER;
                0130                 bh.count = 0;
                0131             }
                0132             break;
                0133         case STATE_HEADER:
                0134             ((char *)&bh.head)[bh.count] = c;
                0135             if (++bh.count == 18) {
                0136                 bh.state = STATE_HCRC;
                0137                 bh.inCRC = 1;
                0138                 bh.count = 0;
                0139             }
                0140             break;
                0141         case STATE_DFORK:
                0142         case STATE_RFORK:
                0143             putc(c, bh.outfile);
                0144             if (--bh.count == 0) {
                0145                 fclose(bh.outfile);
                0146                 bh.outfile = NULL;
                0147                 ++bh.state;
                0148                 bh.inCRC = 1;
                0149             }
                0150             break;
                0151         case STATE_HCRC:
                0152         case STATE_DCRC:
                0153         case STATE_RCRC:
                0154             if (!bh.count++) {
                0155                 bh.fileCRC = (unsigned short) c << 8;
                0156             } else {
                0157                 if ((bh.fileCRC | c) != bh.CRC) {
                0158                     if (bh.state > STATE_HCRC) {
                0159                         HDelete(bh.fspec.vRefNum, bh.fspec.parID, bh.fspec.name);
                0160                         SetCursor(&arrow);
                0161                         yell("BinHex file corrupted in transit");
                0162                         SetCursor(&watch);
                0163                     }
                0164                     bh.state = STATE_ERROR;
                0165                     break;
                0166                 }
                0167                 bh.CRC = 0;
                0168                 if (++bh.state == STATE_DONE) {
                0169                     finfo.fdType = bh.head.type;
                0170                     finfo.fdCreator = bh.head.creator;
                0171                     finfo.fdFlags = bh.head.flags & 0xf800;
                0172                     HSetFInfo(bh.fspec.vRefNum, bh.fspec.parID, bh.fspec.name, &finfo);
                0173                     PtoCstr(bh.fspec.name);
                0174                     renameDescFile((char *)bh.fspec.name, bh.fspec.vRefNum, bh.fspec.parID);
                0175                     break;
                0176                 }
                0177                 bh.count = bh.head.rlen;
                0178                 if (bh.state == STATE_DFORK) {
                0179                     /* prompt user */
                0180                     sprintf(buf, "Saving BinHex file %s", C(bh.namebuf));
                0181                     chat(buf);
                0182                     SetCursor(&arrow);
                0183                     NAputFile("\pSave decoded BinHex file as:", P(bh.namebuf), &reply);
                0184                     SetCursor(&watch);
                0185                     statrefresh();
                0186                     if (!reply.sfGood) {
                0187                         didchat = -1;
                0188                         bh.state = STATE_ERROR;
                0189                     } else {
                0190                         bh.fspec = reply.sfFile;
                0191                         HCreate(bh.fspec.vRefNum, bh.fspec.parID, bh.fspec.name,
                0192                             bh.head.creator, bh.head.type);
                0193                         bh.count = bh.head.dlen;
                0194                     }
                0195                 }
                0196                 if (bh.count) {
                0197                     bh.inCRC = 0;
                0198                     bh.outfile = Macopen(inpart->infile, bh.fspec.name, bh.fspec.vRefNum,
                0199                         bh.fspec.parID, 1, bh.state == STATE_DFORK ? 0 : 1, fsWrPerm);
                0200                     if (!bh.outfile) {
                0201                         bh.state = STATE_ERROR;
                0202                         HDelete(bh.fspec.vRefNum, bh.fspec.parID, bh.fspec.name);
                0203                         SetCursor(&arrow);
                0204                         yell("Failed to open file for writing");
                0205                         SetCursor(&watch);
                0206                     }
                0207                 } else {
                0208                     ++bh.state;
                0209                 }
                0210             }
                0211             break;
                0212     }
                0213 }
                0214 
                0215 /*
                0216  * decode a binhex file
                0217  *  returns -1 on fatal error, 0 for continue, 1 for done
                0218  */
                0219 int os_binhex(struct part *inpart, int part, int nparts)
                0220 {
                0221     long val;
                0222     int c;
                0223     char *bptr;
                0224     short octetpos;
                0225     static char buf[1024];
                0226     
                0227     /* reset state */
                0228     if (part == 1) {
                0229         bh.state = STATE_START;
                0230         bh.part = 0;
                0231         bh.CRC = 0;
                0232         bh.octetbuf.val = 0;
                0233         bh.octetin = 26;
                0234         bh.donepos = 3;
                0235         bh.inCRC = 0;
                0236         bh.outfile = NULL;
                0237         bh.marker = 0;
                0238     }
                0239     if (++bh.part != part) bh.state = STATE_ERROR;
                0240     
                0241     /* do nothing on error/completion */
                0242     if (!inpart) {
                0243         if (bh.state < STATE_DONE) bh.state = STATE_ERROR;
                0244     } else {
                0245         /* skip blank lines */
                0246         do {
                0247             if (part_gets(buf, sizeof (buf), inpart) == NULL) return (0);
                0248         } while (*buf == '\n');
                0249         bptr = buf;
                0250         if (part == 1 && *bptr++ != ':') bh.state = STATE_ERROR;
                0251         
                0252         /* line reading loop */
                0253         do {
                0254             /* check line for separator */
                0255             if (!strncmp(buf, "--- ", 4)) break;
                0256             buf[strlen(buf) - 1] = '\0';
                0257             
                0258             /* loop through line of binhex charaters */
                0259             while (bh.state < STATE_DONE) {
                0260                 /* fill in octetbuf */
                0261                 do {
                0262                     if ((val = BHEXVAL(*bptr++)) == -1) {
                0263                         if (bptr[-1]) {
                0264                             --bh.donepos;
                0265                             if (bh.octetin >= 14) --bh.donepos;
                0266                             if (bh.octetin >= 20) --bh.donepos;
                0267                         }
                0268                         break;
                0269                     }
                0270                     bh.octetbuf.val |= val << bh.octetin;
                0271                 } while ((bh.octetin -= 6) > 2);
                0272                 if (!bptr[-1]) break;
                0273                 
                0274                 /* handle decoded characters -- run length encoding (rle) detection */
                0275                 for (octetpos = 0; octetpos < bh.donepos; ++octetpos) {
                0276                     /* get character & handle rle */
                0277                     c = bh.octetbuf.c[octetpos];
                0278                     if (c == 0x90 && !bh.marker++) continue;
                0279                     if (bh.marker) {
                0280                         if (c == 0) {
                0281                             bh.rlebuf = 0x90;
                0282                             binhex_process(inpart);
                0283                         } else {
                0284                             while (--c > 0) {
                0285                                 binhex_process(inpart);
                0286                             }
                0287                         }
                0288                         bh.marker = 0;
                0289                     } else {
                0290                         bh.rlebuf = (unsigned char) c;
                0291                         binhex_process(inpart);
                0292                     }
                0293                     if (bh.state >= STATE_DONE) break;
                0294                 }
                0295                 if (bh.donepos < 3 && bh.state < STATE_DONE) bh.state = STATE_ERROR;
                0296                 bh.octetin = 26;
                0297                 bh.octetbuf.val = 0;
                0298             }
                0299         } while (bh.state < STATE_DONE && part_gets(bptr = buf, sizeof (buf), inpart) != NULL);
                0300     }
                0301     
                0302     /* error clean up */
                0303     if (bh.state == STATE_ERROR && bh.outfile) {
                0304         fclose(bh.outfile);
                0305         bh.outfile = NULL;
                0306         HDelete(bh.fspec.vRefNum, bh.fspec.parID, bh.fspec.name);
                0307     }
                0308     
                0309     return (bh.state == STATE_ERROR ? 1 : 0);
                0310 }