Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 1 | /**************************************************************** |
2 | MacBinaryIII.c |
||
3 | |||
4 | Copyright 1997 Christopher Evans (cevans@poppybank.com) |
||
5 | |||
6 | Basic encoding and decoding of Macintosh files to the |
||
7 | MacBinary III spec. |
||
8 | |||
9 | This file is part of the MacBinaryIII_src_C.sit package |
||
10 | see macbin3.h for more information |
||
11 | |||
12 | ****************************************************************/ |
||
13 | |||
14 | /*****************************************************************************/ |
||
15 | /* Includes */ |
||
16 | /*****************************************************************************/ |
||
17 | |||
18 | #include |
||
19 | #include |
||
20 | #include "macbin3.h" |
||
21 | |||
22 | /*****************************************************************************/ |
||
23 | /* Macros, typedefs */ |
||
24 | /*****************************************************************************/ |
||
25 | |||
26 | /* source (the macbinary file) will be deleted */ |
||
27 | #define DELETE_MACBINARY_SOURCE |
||
28 | |||
29 | /* enable encoding |
||
30 | #define INCLUDE_ENCODE_MACBINARY */ |
||
31 | |||
32 | /* enable decoding */ |
||
33 | #define INCLUDE_DECODE_MACBINARY |
||
34 | |||
35 | /* include own CRC 32 Bit Calculation |
||
36 | #define INCLUDE_CRC32CALC */ |
||
37 | |||
38 | /* produce some helpful printouts for tracing |
||
39 | #define TRACE_MACBINARY */ |
||
40 | |||
41 | |||
42 | |||
43 | #define LONG_AT_OFFSET(data, offset) *((long *)((unsigned char *)&data[offset])) |
||
44 | #define WORD_AT_OFFSET(data, offset) *((Word *)((unsigned char *)&data[offset])) |
||
45 | #define BYTE_AT_OFFSET(data, offset) *((Byte *)((unsigned char *)&data[offset])) |
||
46 | #define PTR_AT_OFFSET(data, offset) ((Ptr)((unsigned char *)&data[offset])) |
||
47 | |||
48 | typedef unsigned short Word; |
||
49 | |||
50 | #define kOldVersionOffset 0 |
||
51 | #define kFileNameLengthOffset 1 |
||
52 | #define kFileNameOffset 2 |
||
53 | #define kFileTypeOffset 65 |
||
54 | #define kFileCreatorOffset 69 |
||
55 | #define kFinderFlagsHiOffset 73 |
||
56 | #define kVersionCheckZero 74 |
||
57 | #define kFileVPositionOffset 75 |
||
58 | #define kFileHPositionOffset 77 |
||
59 | #define kFileFolderIDOffset 79 |
||
60 | #define kProtectedFlagOffset 81 |
||
61 | #define kVersionOneCheckZero 82 |
||
62 | #define kDataForkLengthOffset 83 |
||
63 | #define kResourceForkLengthOffset 87 |
||
64 | #define kFileCreationDateOffset 91 |
||
65 | #define kFileModificationDateOffset 95 |
||
66 | #define kGetInfoCommentLengthOffset 99 |
||
67 | #define kFinderFlagsLowOffset 101 |
||
68 | #define kMacbinarySigOffset 102 |
||
69 | #define kFilenameScriptOffset 106 |
||
70 | #define kExtendedFinderFlagsOffset 107 |
||
71 | #define kTotalFileLengthOffset 116 |
||
72 | #define kSecondaryHeaderLengthOffset 120 |
||
73 | #define kCurrentVersionOffset 122 |
||
74 | #define kMinimumVersionOffset 123 |
||
75 | #define kCRCOffset 124 |
||
76 | |||
77 | #define kResourceForkMaxLen (1024 * 1024 * 16) |
||
78 | |||
79 | |||
80 | /*****************************************************************************/ |
||
81 | /* Module level Vars */ |
||
82 | /*****************************************************************************/ |
||
83 | |||
84 | #ifdef INCLUDE_CRC32CALC |
||
85 | static unsigned long crc_table[256] = { |
||
86 | 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, |
||
87 | 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, |
||
88 | 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, |
||
89 | 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, |
||
90 | 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, |
||
91 | 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, |
||
92 | 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, |
||
93 | 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, |
||
94 | 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, |
||
95 | 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, |
||
96 | 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, |
||
97 | 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, |
||
98 | 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, |
||
99 | 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, |
||
100 | 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, |
||
101 | 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, |
||
102 | 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, |
||
103 | 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, |
||
104 | 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, |
||
105 | 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, |
||
106 | 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, |
||
107 | 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, |
||
108 | 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, |
||
109 | 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, |
||
110 | 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, |
||
111 | 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, |
||
112 | 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, |
||
113 | 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, |
||
114 | 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, |
||
115 | 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, |
||
116 | 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, |
||
117 | 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, |
||
118 | 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, |
||
119 | 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, |
||
120 | 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, |
||
121 | 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, |
||
122 | 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, |
||
123 | 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, |
||
124 | 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, |
||
125 | 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, |
||
126 | 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, |
||
127 | 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, |
||
128 | 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, |
||
129 | 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, |
||
130 | 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, |
||
131 | 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, |
||
132 | 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, |
||
133 | 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, |
||
134 | 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, |
||
135 | 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, |
||
136 | 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, |
||
137 | 0x2d02ef8dL |
||
138 | }; |
||
139 | #endif |
||
140 | |||
141 | |||
142 | /*****************************************************************************/ |
||
143 | /* Prototypes */ |
||
144 | /*****************************************************************************/ |
||
145 | |||
146 | static Boolean HeaderIsMacBinary(char *header, |
||
147 | Word *version, |
||
148 | long maxDataLen); |
||
149 | static Boolean FSpExists(FSSpec *file); |
||
150 | #ifdef INCLUDE_CRC32CALC |
||
151 | static unsigned long crc32(unsigned long seed, unsigned char *p, size_t len); |
||
152 | #else |
||
153 | extern unsigned long crc32(unsigned long seed, unsigned char *p, size_t len); |
||
154 | #endif |
||
155 | static OSErr GetDesktopComment(FSSpec *file, char*comment, long *length); |
||
156 | static OSErr SetDesktopComment(FSSpec *file, char*comment, long length); |
||
157 | static Handle EncodeMacbinary(FSSpec *file); |
||
158 | static OSErr DecodeMacBinary(Handle data, FSSpec *destination); |
||
159 | |||
160 | /*****************************************************************************/ |
||
161 | /* Functions */ |
||
162 | /*****************************************************************************/ |
||
163 | |||
164 | |||
165 | #ifdef INCLUDE_CRC32CALC |
||
166 | /* taken from the mcvert source code */ |
||
167 | static unsigned long crc32(unsigned long seed, unsigned char *p, size_t len) |
||
168 | { |
||
169 | unsigned long hold; /* crc computed so far */ |
||
170 | size_t i; /* index into data */ |
||
171 | |||
172 | hold = seed; /* start with seed */ |
||
173 | for (i = 0; i < len; i++, p++) |
||
174 | { |
||
175 | hold ^= (*p << 8); |
||
176 | hold = (hold << 8) ^ crc_table[(unsigned char) (hold >> 8)]; |
||
177 | } |
||
178 | |||
179 | return (hold); |
||
180 | } /* crc32() */ |
||
181 | #endif |
||
182 | |||
183 | |||
184 | |||
185 | static Boolean FSpExists(FSSpec *file) |
||
186 | { |
||
187 | FInfo fndrInfo; |
||
188 | |||
189 | return FSpGetFInfo(file, &fndrInfo) == noErr; |
||
190 | } |
||
191 | |||
192 | |||
193 | static Boolean HeaderIsMacBinary(char *header, |
||
194 | Word *version, |
||
195 | long maxDataLen) |
||
196 | { |
||
197 | Boolean isIt = false; |
||
198 | unsigned long resourceForkLength, dataForkLength, df_rf_length; |
||
199 | short commentLength; |
||
200 | Byte mbVersion; |
||
201 | |||
202 | #ifdef TRACE_MACBINARY |
||
203 | printf("\n\n Function HeaderIsMacBinary(): "); |
||
204 | #endif |
||
205 | |||
206 | if(LONG_AT_OFFSET(header, kMacbinarySigOffset) == 'mBIN') |
||
207 | { |
||
208 | isIt = true; |
||
209 | mbVersion = 130; |
||
210 | } |
||
211 | else |
||
212 | if(BYTE_AT_OFFSET(header, kVersionCheckZero) == 0 && |
||
213 | BYTE_AT_OFFSET(header, kOldVersionOffset) == 0) |
||
214 | { |
||
215 | if(WORD_AT_OFFSET(header, kCRCOffset) == |
||
216 | crc32(0, (unsigned char*) &header, 124)) |
||
217 | { |
||
218 | isIt = true; |
||
219 | mbVersion = 129; |
||
220 | } |
||
221 | else |
||
222 | { |
||
223 | if(BYTE_AT_OFFSET(header, kVersionOneCheckZero) == 0) |
||
224 | { |
||
225 | isIt = true; |
||
226 | mbVersion = 128; |
||
227 | } |
||
228 | } |
||
229 | } |
||
230 | |||
231 | #ifdef TRACE_MACBINARY |
||
232 | printf("\n mbVersion: %d",mbVersion); |
||
233 | #endif |
||
234 | |||
235 | resourceForkLength = LONG_AT_OFFSET(header, kResourceForkLengthOffset); |
||
236 | dataForkLength = LONG_AT_OFFSET(header, kDataForkLengthOffset); |
||
237 | commentLength = WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset); |
||
238 | df_rf_length = dataForkLength + resourceForkLength; |
||
239 | |||
240 | #ifdef TRACE_MACBINARY |
||
241 | printf("\n resourceForkLength: %d",resourceForkLength); |
||
242 | printf("\n dataForkLength: %d",dataForkLength); |
||
243 | printf("\n commentLength: %d",commentLength); |
||
244 | printf("\n df_rf_length: %d",df_rf_length); |
||
245 | printf("\n 1. isIt: bool: %d", |
||
246 | isIt); |
||
247 | printf("\n BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1 bool: %d", |
||
248 | BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1); |
||
249 | printf("\n BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31 bool: %d", |
||
250 | BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31); |
||
251 | printf("\n dataForkLength >= 0 bool: %d", |
||
252 | dataForkLength >= 0); |
||
253 | printf("\n resourceForkLength >= 0 bool: %d", |
||
254 | resourceForkLength >= 0); |
||
255 | printf("\n resourceForkLength <= 0x%8x bool: %d", |
||
256 | kResourceForkMaxLen, resourceForkLength <= kResourceForkMaxLen); |
||
257 | printf("\n dataForkLength <= %8u bool: %d", |
||
258 | maxDataLen, dataForkLength <= maxDataLen); |
||
259 | printf("\n df_rf_length > 0 bool: %d", |
||
260 | df_rf_length > 0); |
||
261 | printf("\n df_rf_length <= %8u bool: %d", |
||
262 | maxDataLen, df_rf_length <= maxDataLen); |
||
263 | #endif |
||
264 | |||
265 | if(isIt && |
||
266 | BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1 && |
||
267 | BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31 && |
||
268 | dataForkLength >= 0 && |
||
269 | resourceForkLength >= 0 && |
||
270 | resourceForkLength <= kResourceForkMaxLen && |
||
271 | df_rf_length > 0 && |
||
272 | df_rf_length <= maxDataLen) |
||
273 | { |
||
274 | isIt = true; |
||
275 | } |
||
276 | else |
||
277 | isIt = false; /* something is wrong with the header */ |
||
278 | |||
279 | #ifdef TRACE_MACBINARY |
||
280 | printf("\n 2. isIt: bool: %d", |
||
281 | isIt); |
||
282 | #endif |
||
283 | |||
284 | if(version) |
||
285 | *version = mbVersion; |
||
286 | return isIt; |
||
287 | } |
||
288 | |||
289 | |||
290 | |||
291 | Boolean FSpIsMacBinary(FSSpec *file) |
||
292 | { |
||
293 | char header[128]; |
||
294 | short dfRefNum = 0; |
||
295 | OSErr err; |
||
296 | long size; |
||
297 | Boolean isIt = false; |
||
298 | CInfoPBRec pb; |
||
299 | long maxDataLen; |
||
300 | |||
301 | memset(&pb, 0, sizeof(CInfoPBRec)); |
||
302 | pb.hFileInfo.ioNamePtr = file->name; |
||
303 | pb.hFileInfo.ioVRefNum = file->vRefNum; |
||
304 | pb.hFileInfo.ioFDirIndex = 0; /* query a file */ |
||
305 | pb.hFileInfo.ioDirID = file->parID; |
||
306 | err = PBGetCatInfo(&pb,false); |
||
307 | maxDataLen = pb.hFileInfo.ioFlLgLen; |
||
308 | |||
309 | memset(header, 0, 128); |
||
310 | |||
311 | err = FSpOpenDF(file, fsRdPerm, &dfRefNum); |
||
312 | if(!err) |
||
313 | { |
||
314 | err = GetEOF(dfRefNum, &size); |
||
315 | if(size > 128) |
||
316 | { |
||
317 | size = 128; |
||
318 | err = FSRead(dfRefNum, &size, &header); |
||
319 | |||
320 | if(err == noErr) |
||
321 | { |
||
322 | isIt = HeaderIsMacBinary(header, nil, maxDataLen); |
||
323 | } |
||
324 | } |
||
325 | FSClose(dfRefNum); |
||
326 | } |
||
327 | return isIt; |
||
328 | } |
||
329 | |||
330 | |||
331 | |||
332 | #ifdef INCLUDE_ENCODE_MACBINARY |
||
333 | |||
334 | static OSErr GetDesktopComment(FSSpec *file, char*comment, long *length) |
||
335 | { |
||
336 | DTPBRec pb; |
||
337 | OSErr err; |
||
338 | |||
339 | pb.ioCompletion = nil; |
||
340 | pb.ioNamePtr = NULL; |
||
341 | pb.ioVRefNum = file->vRefNum; |
||
342 | |||
343 | err = PBDTGetPath(&pb); |
||
344 | |||
345 | if(err == noErr) |
||
346 | { |
||
347 | pb.ioNamePtr = file->name; |
||
348 | pb.ioDTBuffer = comment; |
||
349 | pb.ioDirID = file->parID; |
||
350 | err = PBDTGetComment(&pb, false); |
||
351 | *length = pb.ioDTActCount; |
||
352 | } |
||
353 | return err; |
||
354 | } |
||
355 | |||
356 | |||
357 | |||
358 | |||
359 | OSErr EncodeMacbinaryFile(FSSpec *file) |
||
360 | { |
||
361 | Handle data; |
||
362 | OSErr err = paramErr; |
||
363 | short dfRefNum; |
||
364 | |||
365 | data = EncodeMacbinary(file); |
||
366 | |||
367 | if(data) |
||
368 | { |
||
369 | if(file->name[0] > 27) |
||
370 | file->name[0] = 27; |
||
371 | |||
372 | PtoCstr(file->name); |
||
373 | strcat((char*)file->name, ".bin"); |
||
374 | CtoPstr((char *)file->name); |
||
375 | |||
376 | FSpDelete(file); |
||
377 | if(FSpCreate(file, 'dMB3', 'mBIN', smSystemScript) == noErr) |
||
378 | { |
||
379 | err = FSpOpenDF(file, fsWrPerm, &dfRefNum); |
||
380 | if(err == noErr) |
||
381 | { |
||
382 | long inOutCount = GetHandleSize(data); |
||
383 | |||
384 | HLock(data); |
||
385 | err = FSWrite(dfRefNum,&inOutCount,*data); |
||
386 | HUnlock(data); |
||
387 | FSClose(dfRefNum); |
||
388 | } |
||
389 | } |
||
390 | DisposeHandle(data); |
||
391 | } |
||
392 | return err; |
||
393 | } |
||
394 | |||
395 | |||
396 | |||
397 | |||
398 | |||
399 | static Handle EncodeMacbinary(FSSpec *file) |
||
400 | { |
||
401 | Handle result = nil; |
||
402 | FInfo fndrInfo; |
||
403 | FXInfo fndrXInfo; |
||
404 | OSErr err; |
||
405 | CInfoPBRec pb; |
||
406 | short dfRefNum, rfRefNum; |
||
407 | long ioCount; |
||
408 | char buffer[128]; |
||
409 | char header[128]; |
||
410 | char comment[256]; |
||
411 | long resourceForkLength, dataForkLength, commentLength; |
||
412 | |||
413 | memset(&header, 0, sizeof(header)); |
||
414 | err = FSpGetFInfo(file, &fndrInfo); |
||
415 | |||
416 | memset(&pb, 0, sizeof(CInfoPBRec)); |
||
417 | pb.hFileInfo.ioNamePtr = file->name; |
||
418 | pb.hFileInfo.ioVRefNum = file->vRefNum; |
||
419 | pb.hFileInfo.ioFDirIndex = 0; //query a file |
||
420 | pb.hFileInfo.ioDirID = file->parID; |
||
421 | err = PBGetCatInfo(&pb,false); |
||
422 | |||
423 | fndrXInfo = pb.hFileInfo.ioFlXFndrInfo; |
||
424 | |||
425 | BYTE_AT_OFFSET(header, kFileNameLengthOffset) = file->name[0]; |
||
426 | BlockMoveData( &(file->name[1]), |
||
427 | PTR_AT_OFFSET(header, |
||
428 | kFileNameOffset), |
||
429 | file->name[0]); |
||
430 | LONG_AT_OFFSET(header, kFileTypeOffset) = fndrInfo.fdType; |
||
431 | LONG_AT_OFFSET(header, kFileCreatorOffset) = fndrInfo.fdCreator; |
||
432 | |||
433 | BYTE_AT_OFFSET(header, kFinderFlagsHiOffset) = |
||
434 | (fndrInfo.fdFlags & 0xFF00) >> 8; |
||
435 | BYTE_AT_OFFSET(header, kFinderFlagsLowOffset) = |
||
436 | (fndrInfo.fdFlags & 0x00FF); |
||
437 | |||
438 | WORD_AT_OFFSET(header, kFileVPositionOffset) = fndrInfo.fdLocation.v; |
||
439 | WORD_AT_OFFSET(header, kFileHPositionOffset) = fndrInfo.fdLocation.h; |
||
440 | WORD_AT_OFFSET(header, kFileFolderIDOffset) = fndrInfo.fdFldr; |
||
441 | |||
442 | LONG_AT_OFFSET(header, kFileCreationDateOffset) = pb.hFileInfo.ioFlCrDat; |
||
443 | LONG_AT_OFFSET(header, kFileModificationDateOffset) = |
||
444 | pb.hFileInfo.ioFlMdDat; |
||
445 | |||
446 | LONG_AT_OFFSET(header, kMacbinarySigOffset) = 'mBIN'; |
||
447 | BYTE_AT_OFFSET(header, kFilenameScriptOffset) = fndrXInfo.fdScript; |
||
448 | BYTE_AT_OFFSET(header, kExtendedFinderFlagsOffset) = fndrXInfo.fdXFlags; |
||
449 | |||
450 | LONG_AT_OFFSET(header, kTotalFileLengthOffset) = 0; |
||
451 | WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset) = 0; |
||
452 | |||
453 | WORD_AT_OFFSET(header, kCurrentVersionOffset) = 130; |
||
454 | WORD_AT_OFFSET(header, kMinimumVersionOffset) = 129; |
||
455 | |||
456 | err = FSpOpenDF(file,fsRdPerm,&dfRefNum); |
||
457 | if(err == noErr) |
||
458 | { |
||
459 | err = GetEOF(dfRefNum,&dataForkLength); |
||
460 | LONG_AT_OFFSET(header, kDataForkLengthOffset) = dataForkLength; |
||
461 | } |
||
462 | else |
||
463 | { |
||
464 | dfRefNum = 0; |
||
465 | } |
||
466 | |||
467 | err = FSpOpenRF(file,fsRdPerm,&rfRefNum); |
||
468 | if(err == noErr) |
||
469 | { |
||
470 | err = GetEOF(rfRefNum,&resourceForkLength); |
||
471 | LONG_AT_OFFSET(header, kResourceForkLengthOffset) = resourceForkLength; |
||
472 | } |
||
473 | else |
||
474 | { |
||
475 | rfRefNum = 0; |
||
476 | } |
||
477 | |||
478 | memset(comment, 0, 256); |
||
479 | if(GetDesktopComment(file, comment, &commentLength) != noErr) |
||
480 | commentLength = 0; |
||
481 | |||
482 | WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset) = commentLength; |
||
483 | WORD_AT_OFFSET(header, kCRCOffset) = |
||
484 | crc32( 0, (unsigned char*) &header, 124); |
||
485 | |||
486 | result = TempNewHandle(0, &err); |
||
487 | if(result) |
||
488 | { |
||
489 | err = PtrAndHand(&header,result,128); |
||
490 | |||
491 | if(dfRefNum && dataForkLength) |
||
492 | { |
||
493 | err = noErr; |
||
494 | while(dataForkLength > 0 && err == noErr) |
||
495 | { |
||
496 | ioCount = 128; |
||
497 | err = FSRead(dfRefNum,&ioCount,&buffer); |
||
498 | |||
499 | if(err == noErr || err == eofErr) |
||
500 | err = PtrAndHand(&buffer,result,128); |
||
501 | |||
502 | dataForkLength -= ioCount; |
||
503 | } |
||
504 | } |
||
505 | |||
506 | if(rfRefNum && resourceForkLength) |
||
507 | { |
||
508 | err = noErr; |
||
509 | while(resourceForkLength > 0 && err == noErr) |
||
510 | { |
||
511 | ioCount = 128; |
||
512 | err = FSRead(rfRefNum,&ioCount,&buffer); |
||
513 | |||
514 | if(err == noErr || err == eofErr) |
||
515 | err = PtrAndHand(&buffer,result,128); |
||
516 | |||
517 | resourceForkLength -= ioCount; |
||
518 | } |
||
519 | } |
||
520 | |||
521 | if(commentLength) |
||
522 | { |
||
523 | PtrAndHand(&comment,result,commentLength); |
||
524 | } |
||
525 | } |
||
526 | |||
527 | if(rfRefNum) |
||
528 | FSClose(rfRefNum); |
||
529 | |||
530 | if(dfRefNum) |
||
531 | FSClose(dfRefNum); |
||
532 | |||
533 | return result; |
||
534 | } |
||
535 | |||
536 | #endif /* INCLUDE_ENCODE_MACBINARY */ |
||
537 | |||
538 | |||
539 | |||
540 | #ifdef INCLUDE_DECODE_MACBINARY |
||
541 | |||
542 | static OSErr SetDesktopComment(FSSpec *file, char*comment, long length) |
||
543 | { |
||
544 | DTPBRec pb; |
||
545 | OSErr err; |
||
546 | |||
547 | pb.ioCompletion = nil; |
||
548 | pb.ioNamePtr = NULL; |
||
549 | pb.ioVRefNum = file->vRefNum; |
||
550 | |||
551 | err = PBDTGetPath(&pb); |
||
552 | |||
553 | if(err == noErr) |
||
554 | { |
||
555 | pb.ioNamePtr = file->name; |
||
556 | pb.ioDTBuffer = comment; |
||
557 | pb.ioDirID = file->parID; |
||
558 | pb.ioDTReqCount = length; |
||
559 | err = PBDTSetComment(&pb, false); |
||
560 | } |
||
561 | return err; |
||
562 | } |
||
563 | |||
564 | |||
565 | |||
566 | |||
567 | OSErr DecodeMacBinaryFile(FSSpec *source) |
||
568 | { |
||
569 | Handle data = nil; |
||
570 | OSErr err; |
||
571 | short dfRefNum = 0; |
||
572 | long size; |
||
573 | FSSpec McBin_source; |
||
574 | |||
575 | memcpy(McBin_source.name,source->name,source->name[0]+1); |
||
576 | McBin_source.vRefNum = source->vRefNum; |
||
577 | McBin_source.parID = source->parID; |
||
578 | |||
579 | err = FSpOpenDF(source, fsRdPerm, &dfRefNum); |
||
580 | if(!err) |
||
581 | { |
||
582 | err = GetEOF(dfRefNum, &size); |
||
583 | |||
584 | data = TempNewHandle(size, &err); |
||
585 | |||
586 | if(data) |
||
587 | { |
||
588 | HLock(data); |
||
589 | err = FSRead(dfRefNum,&size,*data); |
||
590 | HUnlock(data); |
||
591 | } |
||
592 | FSClose(dfRefNum); |
||
593 | } |
||
594 | |||
595 | if(data && err == noErr) |
||
596 | { |
||
597 | err = DecodeMacBinary(data, source); |
||
598 | DisposeHandle(data); |
||
599 | } |
||
600 | |||
601 | #ifdef DELETE_MACBINARY_SOURCE |
||
602 | if (err == noErr) |
||
603 | err = FSpDelete(&McBin_source); |
||
604 | #endif |
||
605 | |||
606 | return err; |
||
607 | } |
||
608 | |||
609 | |||
610 | |||
611 | |||
612 | |||
613 | static OSErr DecodeMacBinary(Handle data, FSSpec *destination) |
||
614 | { |
||
615 | Handle result = nil; |
||
616 | FInfo fndrInfo; |
||
617 | OSErr err; |
||
618 | CInfoPBRec pb; |
||
619 | short dfRefNum, rfRefNum; |
||
620 | long ioCount; |
||
621 | char header[128]; |
||
622 | char comment[256]; |
||
623 | long resourceForkLength, dataForkLength, commentLength; |
||
624 | Boolean isMacBinaryFile = false; |
||
625 | short headerEnd = 128; |
||
626 | long rfOffset; |
||
627 | long maxDataLen; |
||
628 | |||
629 | memset(&pb, 0, sizeof(CInfoPBRec)); |
||
630 | pb.hFileInfo.ioNamePtr = destination->name; |
||
631 | pb.hFileInfo.ioVRefNum = destination->vRefNum; |
||
632 | pb.hFileInfo.ioFDirIndex = 0; /* query a file */ |
||
633 | pb.hFileInfo.ioDirID = destination->parID; |
||
634 | err = PBGetCatInfo(&pb,false); |
||
635 | maxDataLen = pb.hFileInfo.ioFlLgLen; |
||
636 | |||
637 | HLock(data); |
||
638 | memcpy(header, *data, 128); |
||
639 | |||
640 | /* already checked with FSpIsMacBinary() */ |
||
641 | isMacBinaryFile = HeaderIsMacBinary(header, nil, maxDataLen);; |
||
642 | |||
643 | if(!isMacBinaryFile) |
||
644 | return paramErr; |
||
645 | |||
646 | if(WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset)) |
||
647 | { |
||
648 | headerEnd = WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset); |
||
649 | headerEnd = (headerEnd + 127) & ~127L; |
||
650 | } |
||
651 | |||
652 | resourceForkLength = LONG_AT_OFFSET(header, kResourceForkLengthOffset); |
||
653 | dataForkLength = LONG_AT_OFFSET(header, kDataForkLengthOffset); |
||
654 | commentLength = WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset); |
||
655 | |||
656 | memcpy( destination->name, |
||
657 | PTR_AT_OFFSET(header, |
||
658 | kFileNameLengthOffset), |
||
659 | BYTE_AT_OFFSET(header, |
||
660 | kFileNameLengthOffset)); |
||
661 | |||
662 | fndrInfo.fdType = LONG_AT_OFFSET(header, kFileTypeOffset); |
||
663 | fndrInfo.fdCreator = LONG_AT_OFFSET(header, kFileCreatorOffset); |
||
664 | |||
665 | fndrInfo.fdFlags = BYTE_AT_OFFSET(header, kFinderFlagsHiOffset); |
||
666 | fndrInfo.fdFlags << 8; |
||
667 | fndrInfo.fdFlags |= BYTE_AT_OFFSET(header, kFinderFlagsLowOffset); |
||
668 | |||
669 | fndrInfo.fdLocation.v = WORD_AT_OFFSET(header, kFileVPositionOffset); |
||
670 | fndrInfo.fdLocation.h = WORD_AT_OFFSET(header, kFileHPositionOffset); |
||
671 | fndrInfo.fdFldr = WORD_AT_OFFSET(header, kFileFolderIDOffset); |
||
672 | /* |
||
673 | index = 1; |
||
674 | checkFile = *destination; |
||
675 | while(FSpExists(&checkFile)) |
||
676 | { |
||
677 | checkFile = *destination; |
||
678 | |||
679 | if(index < 10) |
||
680 | checkFile.name[++checkFile.name[0]] = '0' + index; |
||
681 | else |
||
682 | checkFile.name[++checkFile.name[0]] = ('a' - 10) + index; |
||
683 | index++; |
||
684 | } |
||
685 | *destination = checkFile; |
||
686 | */ |
||
687 | err = FSpCreate(destination, |
||
688 | fndrInfo.fdCreator, |
||
689 | fndrInfo.fdType, |
||
690 | smSystemScript); |
||
691 | |||
692 | dfRefNum = 0; |
||
693 | if(err == noErr) |
||
694 | { |
||
695 | err = FSpOpenDF(destination, fsRdWrPerm, &dfRefNum); |
||
696 | } |
||
697 | |||
698 | if(err == noErr && dfRefNum) |
||
699 | { |
||
700 | ioCount = dataForkLength; |
||
701 | err = FSWrite(dfRefNum,&ioCount,*data + headerEnd); |
||
702 | FSClose(dfRefNum); |
||
703 | } |
||
704 | |||
705 | rfRefNum = 0; |
||
706 | if(err == noErr) |
||
707 | { |
||
708 | err = FSpOpenRF(destination, fsRdWrPerm, &rfRefNum); |
||
709 | } |
||
710 | |||
711 | rfOffset = headerEnd + dataForkLength; |
||
712 | rfOffset = (rfOffset + 127) & ~127L; |
||
713 | |||
714 | if(err == noErr && rfRefNum) |
||
715 | { |
||
716 | ioCount = resourceForkLength; |
||
717 | err = FSWrite(rfRefNum,&ioCount,*data + rfOffset); |
||
718 | FSClose(rfRefNum); |
||
719 | } |
||
720 | |||
721 | rfOffset += resourceForkLength; |
||
722 | rfOffset = (rfOffset + 127) & ~127L; |
||
723 | |||
724 | if(err == noErr) |
||
725 | { |
||
726 | FSpSetFInfo(destination,&fndrInfo); |
||
727 | |||
728 | memset(&pb, 0, sizeof(CInfoPBRec)); |
||
729 | pb.hFileInfo.ioNamePtr = destination->name; |
||
730 | pb.hFileInfo.ioVRefNum = destination->vRefNum; |
||
731 | pb.hFileInfo.ioFDirIndex = 0; /* query a file */ |
||
732 | pb.hFileInfo.ioDirID = destination->parID; |
||
733 | err = PBGetCatInfo(&pb,false); |
||
734 | |||
735 | if(err == noErr) |
||
736 | { |
||
737 | pb.hFileInfo.ioDirID = destination->parID; |
||
738 | pb.hFileInfo.ioFlCrDat = |
||
739 | LONG_AT_OFFSET(header, kFileCreationDateOffset); |
||
740 | pb.hFileInfo.ioFlMdDat = |
||
741 | LONG_AT_OFFSET(header, kFileModificationDateOffset); |
||
742 | pb.hFileInfo.ioFlXFndrInfo.fdXFlags = |
||
743 | BYTE_AT_OFFSET(header, kExtendedFinderFlagsOffset); |
||
744 | pb.hFileInfo.ioFlXFndrInfo.fdScript = |
||
745 | BYTE_AT_OFFSET(header, kFilenameScriptOffset); |
||
746 | err = PBSetCatInfo(&pb, false); |
||
747 | } |
||
748 | |||
749 | if(commentLength) |
||
750 | { |
||
751 | memcpy(comment,*data + rfOffset, commentLength); |
||
752 | SetDesktopComment(destination, comment, commentLength); |
||
753 | } |
||
754 | |||
755 | } |
||
756 | HUnlock(data); |
||
757 | return err; |
||
758 | } |
||
759 | |||
760 | #endif /* INCLUDE_DECODE_MACBINARY */>><>=>=>=>=>=>=>=>=>=>=>=>><>><>> |
||
761 |