/* * NDResourceFork.m * * Created by nathan on Wed Dec 05 2001. * Copyright (c) 2001 Nathan Day. All rights reserved. * * Currently ResourceFork will not add resource forks to files * or create new files with resource forks * */ #import "TKResourceFile.h" #import OSErr createResourceFork( NSURL * aURL ); @implementation TKResourceFile /* * resourceForkForReadingAtURL: */ + (id)resourceForkForReadingAtURL:(NSURL *)aURL { return [[[self alloc] initForReadingAtURL:aURL] autorelease]; } /* * resourceForkForWritingAtURL: */ + (id)resourceForkForWritingAtURL:(NSURL *)aURL { return [[[self alloc] initForWritingAtURL:aURL] autorelease]; } /* * resourceForkForReadingAtPath: */ + (id)resourceForkForReadingAtPath:(NSString *)aPath { return [[[self alloc] initForReadingAtPath:aPath] autorelease]; } /* * resourceForkForWritingAtPath: */ + (id)resourceForkForWritingAtPath:(NSString *)aPath { return [[[self alloc] initForWritingAtPath:aPath] autorelease]; } /* * initForReadingAtURL: */ - (id)initForReadingAtURL:(NSURL *)aURL { return [self initForPermission:fsRdPerm AtURL:aURL]; } /* * initForWritingAtURL: */ - (id)initForWritingAtURL:(NSURL *)aURL { return [self initForPermission:fsWrPerm AtURL:aURL]; } /* * initForPermission:AtURL: */ - (id)initForPermission:(char)aPermission AtURL:(NSURL *)aURL { return [self initForPermission:aPermission AtPath:[aURL path]]; } - (id)initForPermission:(char)aPermission AtPath:(NSString *)aPath { NSParameterAssert( aPath != nil ); NSParameterAssert( [aPath length] > 0 ); if (self = [super init]) { CFURLRef urlRef; bool fileExists, createdFSRef; FSRef fsRef; OSErr theErr; HFSUniStr255 dForkName; // Create a CFURL with the specified POSIX path. urlRef = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, (CFStringRef) aPath, kCFURLPOSIXPathStyle, FALSE ); NSParameterAssert( urlRef != NULL ); // Check whether the file exists already. fileExists = [[NSFileManager defaultManager] fileExistsAtPath: aPath]; if (!fileExists) { CFRelease( urlRef ); NSParameterAssert( fileExists ); } // Try to create an FSRef from the URL. (If the specified file doesn't exist, this // function will return false, but if we've reached this code we've already insured // that the file exists.) createdFSRef = CFURLGetFSRef( urlRef, &fsRef ); CFRelease( urlRef ); NSParameterAssert( createdFSRef == YES ); // get the name of the OS's data fork theErr = FSGetDataForkName ( &dForkName ); NSParameterAssert( theErr == noErr ); // finally, open our resource fork theErr = FSOpenResourceFile ( &fsRef, dForkName.length, dForkName.unicode, aPermission, &fileReference); //NSParameterAssert( theErr == noErr ); } return self; } /* * initForReadingAtPath: */ - (id)initForReadingAtPath:(NSString *)aPath { if( [[NSFileManager defaultManager] fileExistsAtPath:aPath] ){ return [self initForPermission:fsRdPerm AtPath:aPath]; }else{ NSLog(@"Error Opening file, does not exist"); return nil; } } /* * initForWritingAtPath: */ - (id)initForWritingAtPath:(NSString *)aPath { return [self initForPermission:fsWrPerm AtPath:aPath]; } /* * dealloc */ - (void)dealloc { //CloseResFile( fileReference ); [super dealloc]; } - (OSErr)changeResource:(short)anID forData:(NSData *)aData forType:(ResType)aType { Handle theResHandle; Handle resToCopyToHandle; OSErr theErr; short thePreviousRefNum; thePreviousRefNum = CurResFile(); UseResFile( fileReference ); if (!aData || !anID) return paramErr; if (noErr != (theErr = ResError()) ) return theErr; resToCopyToHandle = Get1Resource( aType, anID ); if( noErr == (theErr = ResError()) ) { // copy NSData's bytes to a handle if ( noErr == (theErr = PtrToHand ( [aData bytes], &theResHandle, [aData length] )) ) { int x = GetHandleSize(theResHandle); //NSLog(@"%d", x); //NSLog(@"%d", ); if(GetHandleSize(resToCopyToHandle)!=0){ SetHandleSize(resToCopyToHandle, x); HLock(resToCopyToHandle); HLock( theResHandle ); memmove(*theResHandle, *resToCopyToHandle, x); //AddResource( theResHandle, aType, anID, thePName ); HUnlock( theResHandle ); HUnlock(resToCopyToHandle); ChangedResource(resToCopyToHandle); } } ReleaseResource(theResHandle); } ReleaseResource(resToCopyToHandle); UseResFile( thePreviousRefNum ); return theErr; } //- (OSErr)setResourceFileEndiannessMarker: - (OSErr)addData:(NSData *)aData type:(ResType)aType Id:(short)anID name:(NSString *)aName attributes: (ResAttributes)attributes { Handle theResHandle; OSErr theErr; if (!aData || !aName) return paramErr; if( noErr == (theErr = [self removeType:aType Id:anID]) ) { short thePreviousRefNum; thePreviousRefNum = CurResFile(); if (noErr != (theErr = ResError()) ) return theErr; UseResFile( fileReference ); if (noErr != (theErr = ResError()) ) return theErr; // copy NSData's bytes to a handle if ( noErr == (theErr = PtrToHand ( [aData bytes], &theResHandle, [aData length] )) ) { //NSLog(@"running function"); Str255 thePName; //CopyCStringToPascal ( [aName lossyCString], thePName ); ConstStringPtr thePNamePtr = (ConstStringPtr) &thePName; thePNamePtr = CFStringGetPascalStringPtr((CFStringRef) aName, kCFStringEncodingASCII ); HLock( theResHandle ); AddResource( theResHandle, aType, anID, thePName ); HUnlock( theResHandle ); if (noErr == (theErr = ResError()) ) { SetResAttrs(theResHandle, attributes); if (noErr == (theErr = ResError()) ) { ChangedResource(theResHandle); if (noErr == (theErr = ResError()) ) { ReleaseResource( theResHandle ); } } } } UseResFile( thePreviousRefNum ); } return theErr; } /* * dataForType:Id: */ - (NSData *)dataForType:(ResType)aType Index:(short)anIndex { NSData *theData; Handle theResHandle; short thePreviousRefNum; thePreviousRefNum = CurResFile(); if (noErr != ResError() ) return nil; UseResFile( fileReference ); if (noErr != ResError() ) return nil; theResHandle = Get1IndResource( aType, anIndex ); if( NULL == theResHandle || noErr != ResError() ) { UseResFile( thePreviousRefNum ); return nil; } HLock(theResHandle); theData = [NSData dataWithBytes:*theResHandle length:GetHandleSize( theResHandle )]; HUnlock(theResHandle); ReleaseResource( theResHandle ); UseResFile( thePreviousRefNum ); return theData; } - (NSData *)dataForType:(ResType)aType ID:(short)anID { NSData *theData; Handle theResHandle; short thePreviousRefNum; thePreviousRefNum = CurResFile(); if (noErr != ResError() ) return nil; UseResFile( fileReference ); if (noErr != ResError() ) return nil; theResHandle = Get1Resource( aType, anID ); if( NULL == theResHandle || noErr != ResError() ) { UseResFile( thePreviousRefNum ); return nil; } HLock(theResHandle); theData = [NSData dataWithBytes:*theResHandle length:GetHandleSize( theResHandle )]; HUnlock(theResHandle); ReleaseResource( theResHandle ); UseResFile( thePreviousRefNum ); return theData; } /* * -addString:type:Id:name: * adds a string to the resource fork as a pascal string */ - (OSErr)updateRes{ UpdateResFile( fileReference ); return ResError(); } /* * removeType: Id: */ - (OSErr)removeType:(ResType)aType Id:(short)anID { short thePreviousRefNum; Handle theResHandle; OSErr theErr; thePreviousRefNum = CurResFile(); if (noErr != (theErr = ResError()) ) return theErr; UseResFile( fileReference ); if (noErr != (theErr = ResError()) ) return theErr; theResHandle = Get1Resource( aType, anID ); theErr = ResError( ); if( theResHandle && theErr == noErr ) { RemoveResource( theResHandle ); // Disposed of in current resource file if (noErr == (theErr = ResError()) ) DisposeHandle(theResHandle); } else theErr = noErr; // this fails silently if the resource isn't present UseResFile( thePreviousRefNum ); return theErr; } - (short)count:(ResType)aType { short resCount; short thePreviousRefNum; thePreviousRefNum = CurResFile(); if (noErr != ResError() ) return 0; UseResFile( fileReference ); if (noErr != ResError() ) return 0; resCount = Count1Resources(aType); UseResFile( thePreviousRefNum ); return resCount; } -(OSErr)closeFile{ CloseResFile( fileReference ); return ResError(); } - (short)resId:(ResType)aType Index:(short)anIndex { short thePreviousRefNum; short truID; ResType theType; Str255 pName; Handle resHandle; thePreviousRefNum = CurResFile(); NSParameterAssert( ResError() == noErr ); UseResFile( fileReference ); NSParameterAssert( ResError() == noErr ); SetResLoad(FALSE); NSParameterAssert( ResError() == noErr ); resHandle = Get1IndResource( aType, anIndex ); NSParameterAssert( resHandle != NULL ); NSParameterAssert( ResError() == noErr ); GetResInfo(resHandle, &truID, &theType, pName); NSParameterAssert( ResError() == noErr ); ReleaseResource( resHandle ); NSParameterAssert( ResError() == noErr ); SetResLoad(TRUE); NSParameterAssert( ResError() == noErr ); UseResFile( thePreviousRefNum ); // reset back to resource previously set NSParameterAssert( ResError() == noErr ); return truID; } - (id)resName:(ResType)aType Index:(short)anIndex { short thePreviousRefNum; short truID; ResType theType; Str255 pName; //char cName[255]; Handle resHandle; thePreviousRefNum = CurResFile(); NSParameterAssert( ResError() == noErr ); UseResFile( fileReference ); NSParameterAssert( ResError() == noErr ); SetResLoad(FALSE); NSParameterAssert( ResError() == noErr ); resHandle = Get1IndResource( aType, anIndex ); NSParameterAssert( resHandle != NULL ); GetResInfo(resHandle, &truID, &theType, pName); NSParameterAssert( ResError() == noErr ); ReleaseResource( resHandle ); NSParameterAssert( ResError() == noErr ); SetResLoad(TRUE); NSParameterAssert( ResError() == noErr ); UseResFile( thePreviousRefNum ); NSParameterAssert( ResError() == noErr ); //CopyPascalStringToC(pName, cName); //return [NSString stringWithCString:cName]; return (NSString *)CFStringCreateWithPascalString (NULL, pName, kCFStringEncodingASCII); } -(TKEndianness)endiannessOfResourceFile { TKEndianness resourceFileFormat; ThemeDataFormatForResourceFile(fileReference,&resourceFileFormat); return resourceFileFormat; } -(void)setEndiannessOfResourceFile:(TKEndianness)endianness { SetThemeDataFormatForResourceFile(fileReference,endianness); } @end