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
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
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
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;
0081 short part;
0082 unsigned short CRC;
0083 unsigned short fileCRC;
0084 longbuf octetbuf;
0085 short octetin;
0086 short donepos;
0087 short inCRC;
0088 long count;
0089 FILE *outfile;
0090 short marker;
0091 unsigned char rlebuf;
0092 PCstr namebuf[65];
0093 binhex_header head;
0094 FSSpec fspec;
0095 } binhex_state;
0096
0097
0098 static binhex_state bh;
0099
0100
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
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
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
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
0217
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
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
0242 if (!inpart) {
0243 if (bh.state < STATE_DONE) bh.state = STATE_ERROR;
0244 } else {
0245
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
0253 do {
0254
0255 if (!strncmp(buf, "--- ", 4)) break;
0256 buf[strlen(buf) - 1] = '\0';
0257
0258
0259 while (bh.state < STATE_DONE) {
0260
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
0275 for (octetpos = 0; octetpos < bh.donepos; ++octetpos) {
0276
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
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 }