AmendHub

Download

nulleric

/

Fix-a-Fork

/

main.c

 

(View History)

eric   Release 1.0.1-a Latest amendment: 36 on 2024-04-05

1 /*
2 Copyright Eric Helgeson 2023-2024.
3 */
4
5 #include "main.h"
6 #include "file_ext.h"
7 #include <Script.h>
8
9 // Globals
10 OSType gType;
11 OSType gCreator;
12 long gHasAppleEvents;
13
14 // Change the modification date on the parent folder so the
15 // Finder notices a change.
16 OSErr TouchFolder(short vRefNum, long parID)
17 {
18 CInfoPBRec rec;
19 Str63 name;
20 short err;
21
22 rec.hFileInfo.ioNamePtr = name;
23 name[0]=0;
24 rec.hFileInfo.ioVRefNum = vRefNum;
25 rec.hFileInfo.ioDirID = parID;
26 rec.hFileInfo.ioFDirIndex = -1;
27 rec.hFileInfo.ioFVersNum = 0;
28 err = PBGetCatInfoSync(&rec);
29 if(err)
30 return err;
31 GetDateTime(&rec.dirInfo.ioDrMdDat);
32
33 rec.hFileInfo.ioVRefNum = vRefNum;
34 rec.hFileInfo.ioDirID = parID;
35 rec.hFileInfo.ioFDirIndex = -1;
36 rec.hFileInfo.ioFVersNum = 0;
37 rec.hFileInfo.ioNamePtr[0] = 0;
38 err = PBSetCatInfoSync(&rec);
39 return err;
40 }
41
42 pascal OSErr DoOpenDoc(AppleEvent *event, AppleEvent *reply, long handlerRefcon)
43 {
44 FSSpec fss;
45 AEDescList docList;
46 OSErr err = noErr;
47 long index, itemsInList;
48 Size actualSize;
49 AEKeyword keywd;
50 DescType returnedType;
51 short fRefNum = 0;
52
53 err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docList);
54 if(err != noErr) return err;
55 err = AECountItems(&docList, &itemsInList);
56 if(err != noErr) return err;
57
58 for(index = 1; index <= itemsInList; index++)
59 {
60 err = AEGetNthPtr(&docList, index, typeFSS, &keywd, &returnedType, (Ptr)&fss, sizeof(fss), &actualSize);
61 if(err) return err;
62
63 err = FSpOpenDF(&fss, fsRdPerm, &fRefNum);
64 if(err) return err;
65
66 err = openFile(fss.name, fRefNum, fss.vRefNum, fss.parID);
67 if(err)
68 return err;
69 else
70 gHandledByDnD = true;
71 }
72 AEDisposeDesc(&docList);
73 return noErr;
74 }
75
76 void InstallEventHandlers()
77 {
78 EventRecord event;
79 OSErr err = 0;
80 short i = 0;
81
82 if(Gestalt(gestaltAppleEventsAttr, &gHasAppleEvents) == noErr)
83 {
84 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, &DoOpenDoc, 0L, false);
85 } else {
86 return;
87 }
88 do {
89 WaitNextEvent(highLevelEventMask, &event, 30, 0);
90 i = i+1;
91 } while(event.what != kHighLevelEvent && i < 5);
92 if(event.what == kHighLevelEvent)
93 AEProcessAppleEvent(&event);
94 }
95
96 OSErr MyGetWDInfo(short wdRefNum, short *vRefNum, long *dirID, long *procID)
97 {
98 OSErr result;
99 WDPBRec wdPB;
100 wdPB.ioVRefNum = wdRefNum;
101 wdPB.ioWDIndex = 0;
102 wdPB.ioNamePtr = nil;
103 result = PBGetWDInfoSync(&wdPB);
104 *vRefNum = wdPB.ioWDVRefNum;
105 *dirID = wdPB.ioWDDirID;
106 *procID = wdPB.ioWDProcID;
107 return result;
108 }
109
110 void OpenFileDialog()
111 {
112 long dirID = 0, procID = 0;
113 short volRefNum = 0;
114 SFReply tr = {0};
115 short fRefNum = 0;
116
117 Point where;
118 where.h = 100;
119 where.v = 50;
120
121 do {
122 SFGetFile(where, nil, nil, -1, nil, nil, &tr);
123 if(tr.good)
124 {
125 MyGetWDInfo(tr.vRefNum, &volRefNum, &dirID, &procID);
126 HOpen(tr.vRefNum, dirID, tr.fName, fsRdPerm, &fRefNum);
127 openFile(tr.fName, fRefNum, volRefNum, dirID);
128 }
129 } while(tr.good);
130 }
131
132 OSErr openFile(unsigned char *fName, short fRefNum, short vRefNum, long dirID)
133 {
134 OSErr err = noErr;
135 Str255 errString = "\p";
136 long count = BUF_SIZE;
137 FInfo fi = {0};
138 Boolean found = false;
139 char ext[5] = {0};
140 short i = 0, j = 0;
141
142 err = FSRead(fRefNum, &count, gBuf);
143 // eofErr == partial read, probably small file, ok to continue.
144 if(err && err != eofErr) return err;
145 // Check for magic in first 1024 bytes
146 if(isBinHex4())
147 found = true;
148 else if(isSit5())
149 found = true;
150 else if(isSit15())
151 found = true;
152 else if(isBinSit())
153 found = true;
154 else if(isDsk4())
155 found = true;
156 else if(isZip())
157 found = true;
158 else if(isMar())
159 found = true;
160 else if(isCpt())
161 found = true;
162
163 // Checks @ 1024
164 if(!found && count >= 2048)
165 {
166 SetFPos(fRefNum, fsFromStart, 1024);
167 FSRead(fRefNum, &count, gBuf);
168
169 if(isDsk_1024())
170 found = true;
171 }
172
173 if(!found)
174 {
175 for(i = fName[0]; i > 0; i--)
176 if(fName[i] == '.')
177 break;
178 if(i != fName[0] && (fName[0] - i) <= 5) // There is an extension
179 {
180 i = i + 1; // increment to avoid '.'
181 // Parse file extension
182 for(; i <= fName[0]; i++)
183 ext[j++] = fName[i];
184 LowerText(ext, StringLen(ext));
185 found = CheckFileExt(ext, &gType, &gCreator);
186 }
187 }
188
189 if(found)
190 {
191 if(gCreator != 0 && gType != 0)
192 {
193 err = HGetFInfo(vRefNum, dirID, fName, &fi);
194 if(err) return err;
195 fi.fdType = gType;
196 fi.fdCreator = gCreator;
197 err = HSetFInfo(vRefNum, dirID, fName, &fi);
198
199 if(err)
200 {
201 NumToString(err, errString);
202 ParamText("\pCould't set type/creator for ", fName, "\p err: ", errString);
203 StopAlert(128, nil);
204 }
205 }
206 // else unkown type/creator
207 } else {
208 ParamText("\pCould't determine type/creator for ", fName, "\p", "\p");
209 StopAlert(128, nil);
210 }
211
212 TouchFolder(vRefNum, dirID);
213 return FSClose(fRefNum);
214 }
215
216 void main()
217 {
218 MaxApplZone();
219 InitGraf(&qd.thePort);
220 InitFonts();
221 InitWindows();
222 InitMenus();
223 TEInit();
224 InitDialogs(nil);
225 InitCursor();
226
227 FlushEvents(everyEvent, 0);
228 InstallEventHandlers();
229 if(!gHandledByDnD)
230 OpenFileDialog();
231 return;
232 }
233 // TODO: Move to own file.
234
235 Boolean isBinHex4()
236 {
237 // FixMe: Magic can be any line in the first 8k of the file.
238 return magicCheck("BinHex 4.0", 10, 34, 'BINA', 'SITx');
239 }
240
241 Boolean isSit15()
242 {
243 short stuffitVersion = 0;
244 if(magicCheck("SIT!", 4, 0, 'SIT!', 'SIT!'))
245 {
246 gType = 0;
247 gCreator = 0;
248 // 0x01 for 1.5.x, 0x02 for 1.6-4.5
249 stuffitVersion = gBuf[14];
250 return (stuffitVersion == 0x01 || stuffitVersion == 0x02) && magicCheck("rLau", 4, 10, 'SIT!', 'SIT!');
251 }
252 return false;
253 }
254
255 Boolean isSit5()
256 {
257 short stuffitVersion = gBuf[82]; // 0x05
258 return (stuffitVersion == 0x05 && magicCheck("StuffIt (c)1997", 15, 0, 'SITD', 'SIT!'));
259 }
260
261 Boolean isBinSit()
262 {
263 short stuffitVersion = 0;
264 if(magicCheck("SIT!", 4, 0 + 128, 'SIT!', 'SIT!'))
265 {
266 gType = 0;
267 gCreator = 0;
268 // 0x01 for 1.5.x, 0x02 for 1.6-4.5
269 stuffitVersion = gBuf[14 + 128];
270 return (stuffitVersion == 0x01 || stuffitVersion == 0x02) && magicCheck("rLau", 4, 10 + 128, 'BINA', 'SITx');
271 }
272 return false;
273 }
274
275 Boolean isDsk4()
276 {
277 char magic[] = "\1\0";
278 return magicCheck(magic, 2, 52, 'dImg', 'dCpy');
279 }
280 // Disk Copy 6
281 Boolean isDsk_1024()
282 {
283 return magicCheck("BD", 2, 0, 'DDim', 'ddsk');
284 }
285
286 // Very loose check, do last.
287 Boolean isCpt()
288 {
289 char magic[] = "\1\1";
290 return magicCheck(magic, 2, 0, 'PACT', 'CPCT');
291 }
292
293 Boolean isMar()
294 {
295 return magicCheck("MAR", 3, 0, 'MARf', 'MARc');
296 }
297
298 Boolean isZip()
299 {
300 return magicCheck("PK", 2, 0, 'ZIP ', 'IZip');
301 }
302
303 short StringLen(const char *str)
304 {
305 const char *s;
306 for (s = str; *s; ++s);
307 return (s-str);
308 }
309
310 Boolean StringCompare(const char *lhs, const char *rhs)
311 {
312 short i = 0;
313 short len = StringLen(lhs);
314 if(len != StringLen(rhs)) return false;
315
316 for(i = 0; i < len; i++)
317 if(lhs[i] != rhs[i])
318 return false;
319 return true;
320 }
321
322 Boolean magicCheck(char *magic, short len, short offset, OSType type, OSType creator)
323 {
324 short i;
325 for(i = 0; i < len; i++)
326 if(gBuf[offset+i] != magic[i])
327 return false;
328 gType = type;
329 gCreator = creator;
330 return true;
331 }