Add patcher/upgrader/installer thingy.
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
BOOL NeedsPrivs( NSString *path );
|
||||||
|
NSString *CopyWithPrivs( NSString *src, NSString *dest );
|
||||||
|
NSString *Copy( NSString *src, NSString *dest );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2006 Steve Checkoway
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
#import "CopyFiles.h"
|
||||||
|
#include <Security/Authorization.h>
|
||||||
|
#include <Security/AuthorizationTags.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static NSString *COPY_FAILED;
|
||||||
|
static NSString *EXECUTE_FAILED;
|
||||||
|
static NSString *AUTH_FAILED;
|
||||||
|
|
||||||
|
static void LoadStrings()
|
||||||
|
{
|
||||||
|
static bool bLoaded = false;
|
||||||
|
if( bLoaded )
|
||||||
|
return;
|
||||||
|
COPY_FAILED = NSLocalizedString( @"Copy failed.", nil );
|
||||||
|
EXECUTE_FAILED = NSLocalizedString( @"Execute failed.", nil );
|
||||||
|
AUTH_FAILED = NSLocalizedString( @"Authentication failed. File not patched.", nil );
|
||||||
|
bLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL CheckDir( const char *path )
|
||||||
|
{
|
||||||
|
DIR *dir = opendir( path );
|
||||||
|
int fd = dirfd( dir );
|
||||||
|
struct dirent entry, *ep;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
fchdir( fd );
|
||||||
|
for( err = readdir_r(dir, &entry, &ep); ep && !err; err = readdir_r(dir, &entry, &ep) )
|
||||||
|
{
|
||||||
|
if( !strcmp(".", entry.d_name) || !strcmp("..", entry.d_name) )
|
||||||
|
continue;
|
||||||
|
if( access(entry.d_name, W_OK|R_OK) )
|
||||||
|
{
|
||||||
|
closedir( dir );
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
if( entry.d_type == DT_DIR )
|
||||||
|
{
|
||||||
|
if( CheckDir(entry.d_name) )
|
||||||
|
{
|
||||||
|
closedir( dir );
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
fchdir( fd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir( dir );
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL NeedsPrivs( NSString *path )
|
||||||
|
{
|
||||||
|
const char *p = [path UTF8String];
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if( stat(p, &sb) )
|
||||||
|
return YES;
|
||||||
|
if( access(p, W_OK|R_OK) ) // I don't care to parse stat output.
|
||||||
|
return YES;
|
||||||
|
if( (sb.st_mode & S_IFDIR) && CheckDir(p) )
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *CopyWithPrivs( NSString *src, NSString *dest )
|
||||||
|
{
|
||||||
|
LoadStrings();
|
||||||
|
OSStatus error;
|
||||||
|
static AuthorizationRef authRef;
|
||||||
|
static BOOL bCreated = false;
|
||||||
|
|
||||||
|
if( !bCreated )
|
||||||
|
{
|
||||||
|
AuthorizationFlags flags = kAuthorizationFlagDefaults;
|
||||||
|
AuthorizationItem item = { kAuthorizationRightExecute, 0, NULL, 0 };
|
||||||
|
AuthorizationRights rights = { 1, &item };
|
||||||
|
|
||||||
|
error = AuthorizationCreate( NULL, kAuthorizationEmptyEnvironment, flags, &authRef );
|
||||||
|
|
||||||
|
if (error != errAuthorizationSuccess)
|
||||||
|
return @"Failed to create authorization.";
|
||||||
|
|
||||||
|
|
||||||
|
flags = kAuthorizationFlagDefaults |
|
||||||
|
kAuthorizationFlagInteractionAllowed |
|
||||||
|
kAuthorizationFlagPreAuthorize |
|
||||||
|
kAuthorizationFlagExtendRights;
|
||||||
|
|
||||||
|
error = AuthorizationCopyRights( authRef, &rights, NULL, flags, NULL );
|
||||||
|
|
||||||
|
if (error != errAuthorizationSuccess)
|
||||||
|
return AUTH_FAILED;
|
||||||
|
bCreated = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Don't pass path as the first argument. AuthorizationExecuteWithPrivileges must do it.
|
||||||
|
char path[] = "/bin/cp";
|
||||||
|
const char *argv[] = { "-Rf", [src UTF8String], [dest UTF8String], NULL };
|
||||||
|
NSString *result = nil;
|
||||||
|
|
||||||
|
error = AuthorizationExecuteWithPrivileges( authRef, path, kAuthorizationFlagDefaults, (char **)argv, NULL );
|
||||||
|
|
||||||
|
if (error == errAuthorizationSuccess)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
pid_t pid = wait( &status );
|
||||||
|
|
||||||
|
if( pid == -1 )
|
||||||
|
result = [NSString stringWithUTF8String:strerror(errno)];
|
||||||
|
else if( !WIFEXITED(status) || WEXITSTATUS(status) )
|
||||||
|
result = COPY_FAILED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = EXECUTE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *Copy( NSString *src, NSString *dest )
|
||||||
|
{
|
||||||
|
LoadStrings();
|
||||||
|
// Again, don't pass the path.
|
||||||
|
NSArray *argv = [NSArray arrayWithObjects:@"-Rf", src, dest, nil];
|
||||||
|
NSTask *task = [NSTask launchedTaskWithLaunchPath:@"/bin/cp" arguments:argv];
|
||||||
|
|
||||||
|
[task waitUntilExit];
|
||||||
|
return [task terminationStatus] ? COPY_FAILED : nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2006 Steve Checkoway
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# The format of this file is:
|
||||||
|
# Application name
|
||||||
|
# Bundle ID
|
||||||
|
# version1
|
||||||
|
# version2
|
||||||
|
# ...
|
||||||
|
# The version key -ALL- or no version keys matches all versions.
|
||||||
|
|
||||||
|
StepMania
|
||||||
|
com.StepMania
|
||||||
|
-ALL-
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>${EXECUTABLE_NAME}</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>smicon</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.StepMania.Patcher</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>${PRODUCT_NAME}</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>ITGp</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>NSMainNibFile</key>
|
||||||
|
<string>MainMenu</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 42;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
|
||||||
|
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
|
||||||
|
AA2BF5C30A4F6E1B00A21643 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = AA2BF5C10A4F6E1B00A21643 /* Localizable.strings */; };
|
||||||
|
AAD7D8740A36C53E0073BAC6 /* Identification.txt in Resources */ = {isa = PBXBuildFile; fileRef = AAD7D8730A36C53E0073BAC6 /* Identification.txt */; };
|
||||||
|
AAD7D8BF0A36CC020073BAC6 /* smicon.icns in Resources */ = {isa = PBXBuildFile; fileRef = AAD7D8BE0A36CC020073BAC6 /* smicon.icns */; };
|
||||||
|
AAF586BC0A27D9300046D33E /* CopyFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF586BB0A27D9300046D33E /* CopyFiles.m */; };
|
||||||
|
AAF586BF0A27D9410046D33E /* Upgrader.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF586BE0A27D9410046D33E /* Upgrader.m */; };
|
||||||
|
AAF586CC0A27DA7F0046D33E /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = AAF586CA0A27DA7F0046D33E /* MainMenu.nib */; };
|
||||||
|
AAF586CF0A27DA900046D33E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AAF586CD0A27DA900046D33E /* InfoPlist.strings */; };
|
||||||
|
AAF587560A2826240046D33E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AAF587550A2826240046D33E /* Security.framework */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||||
|
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
|
||||||
|
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
|
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
|
||||||
|
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
|
||||||
|
32CA4F630368D1EE00C91783 /* Patcher_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Patcher_Prefix.pch; sourceTree = "<group>"; };
|
||||||
|
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
8D1107320486CEB800E47090 /* Patcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Patcher.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
AA2BF5C20A4F6E1B00A21643 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
|
AAD7D8730A36C53E0073BAC6 /* Identification.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Identification.txt; sourceTree = "<group>"; };
|
||||||
|
AAD7D8BE0A36CC020073BAC6 /* smicon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = smicon.icns; path = ../smicon.icns; sourceTree = SOURCE_ROOT; };
|
||||||
|
AAF586BA0A27D9300046D33E /* CopyFiles.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 30; path = CopyFiles.h; sourceTree = "<group>"; };
|
||||||
|
AAF586BB0A27D9300046D33E /* CopyFiles.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = CopyFiles.m; sourceTree = "<group>"; };
|
||||||
|
AAF586BD0A27D9410046D33E /* Upgrader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Upgrader.h; sourceTree = "<group>"; };
|
||||||
|
AAF586BE0A27D9410046D33E /* Upgrader.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Upgrader.m; sourceTree = "<group>"; };
|
||||||
|
AAF586CB0A27DA7F0046D33E /* en */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = en; path = en.lproj/MainMenu.nib; sourceTree = "<group>"; };
|
||||||
|
AAF586CE0A27DA900046D33E /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
|
AAF587550A2826240046D33E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
8D11072E0486CEB800E47090 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
|
||||||
|
AAF587560A2826240046D33E /* Security.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
080E96DDFE201D6D7F000001 /* Classes */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
AAF586BD0A27D9410046D33E /* Upgrader.h */,
|
||||||
|
AAF586BE0A27D9410046D33E /* Upgrader.m */,
|
||||||
|
);
|
||||||
|
name = Classes;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
|
||||||
|
);
|
||||||
|
name = "Linked Frameworks";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
29B97324FDCFA39411CA2CEA /* AppKit.framework */,
|
||||||
|
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */,
|
||||||
|
29B97325FDCFA39411CA2CEA /* Foundation.framework */,
|
||||||
|
);
|
||||||
|
name = "Other Frameworks";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
19C28FACFE9D520D11CA2CBB /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
8D1107320486CEB800E47090 /* Patcher.app */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
29B97314FDCFA39411CA2CEA /* Patcher */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
080E96DDFE201D6D7F000001 /* Classes */,
|
||||||
|
29B97315FDCFA39411CA2CEA /* Other Sources */,
|
||||||
|
29B97317FDCFA39411CA2CEA /* Resources */,
|
||||||
|
29B97323FDCFA39411CA2CEA /* Frameworks */,
|
||||||
|
19C28FACFE9D520D11CA2CBB /* Products */,
|
||||||
|
);
|
||||||
|
name = Patcher;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
AAF586BA0A27D9300046D33E /* CopyFiles.h */,
|
||||||
|
AAF586BB0A27D9300046D33E /* CopyFiles.m */,
|
||||||
|
32CA4F630368D1EE00C91783 /* Patcher_Prefix.pch */,
|
||||||
|
29B97316FDCFA39411CA2CEA /* main.m */,
|
||||||
|
);
|
||||||
|
name = "Other Sources";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
29B97317FDCFA39411CA2CEA /* Resources */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
AA2BF5C10A4F6E1B00A21643 /* Localizable.strings */,
|
||||||
|
AAD7D8BE0A36CC020073BAC6 /* smicon.icns */,
|
||||||
|
AAD7D8730A36C53E0073BAC6 /* Identification.txt */,
|
||||||
|
8D1107310486CEB800E47090 /* Info.plist */,
|
||||||
|
AAF586CD0A27DA900046D33E /* InfoPlist.strings */,
|
||||||
|
AAF586CA0A27DA7F0046D33E /* MainMenu.nib */,
|
||||||
|
);
|
||||||
|
name = Resources;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
AAF587550A2826240046D33E /* Security.framework */,
|
||||||
|
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
|
||||||
|
1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
8D1107260486CEB800E47090 /* Patcher */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Patcher" */;
|
||||||
|
buildPhases = (
|
||||||
|
8D1107290486CEB800E47090 /* Resources */,
|
||||||
|
8D11072C0486CEB800E47090 /* Sources */,
|
||||||
|
8D11072E0486CEB800E47090 /* Frameworks */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = Patcher;
|
||||||
|
productInstallPath = "$(HOME)/Applications";
|
||||||
|
productName = Patcher;
|
||||||
|
productReference = 8D1107320486CEB800E47090 /* Patcher.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Patcher" */;
|
||||||
|
hasScannedForEncodings = 1;
|
||||||
|
knownRegions = (
|
||||||
|
English,
|
||||||
|
Japanese,
|
||||||
|
French,
|
||||||
|
German,
|
||||||
|
en,
|
||||||
|
);
|
||||||
|
mainGroup = 29B97314FDCFA39411CA2CEA /* Patcher */;
|
||||||
|
projectDirPath = "";
|
||||||
|
targets = (
|
||||||
|
8D1107260486CEB800E47090 /* Patcher */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
8D1107290486CEB800E47090 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
AAF586CC0A27DA7F0046D33E /* MainMenu.nib in Resources */,
|
||||||
|
AAF586CF0A27DA900046D33E /* InfoPlist.strings in Resources */,
|
||||||
|
AAD7D8740A36C53E0073BAC6 /* Identification.txt in Resources */,
|
||||||
|
AAD7D8BF0A36CC020073BAC6 /* smicon.icns in Resources */,
|
||||||
|
AA2BF5C30A4F6E1B00A21643 /* Localizable.strings in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
8D11072C0486CEB800E47090 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
8D11072D0486CEB800E47090 /* main.m in Sources */,
|
||||||
|
AAF586BC0A27D9300046D33E /* CopyFiles.m in Sources */,
|
||||||
|
AAF586BF0A27D9410046D33E /* Upgrader.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
AA2BF5C10A4F6E1B00A21643 /* Localizable.strings */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
AA2BF5C20A4F6E1B00A21643 /* en */,
|
||||||
|
);
|
||||||
|
name = Localizable.strings;
|
||||||
|
sourceTree = SOURCE_ROOT;
|
||||||
|
};
|
||||||
|
AAF586CA0A27DA7F0046D33E /* MainMenu.nib */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
AAF586CB0A27DA7F0046D33E /* en */,
|
||||||
|
);
|
||||||
|
name = MainMenu.nib;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
AAF586CD0A27DA900046D33E /* InfoPlist.strings */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
AAF586CE0A27DA900046D33E /* en */,
|
||||||
|
);
|
||||||
|
name = InfoPlist.strings;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
C01FCF4B08A954540054247B /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||||
|
GCC_ENABLE_CPP_RTTI = NO;
|
||||||
|
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||||
|
GCC_MODEL_TUNING = G4;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||||
|
INFOPLIST_FILE = Info.plist;
|
||||||
|
INSTALL_PATH = "$(HOME)/Applications";
|
||||||
|
PRODUCT_NAME = Patcher;
|
||||||
|
WRAPPER_EXTENSION = app;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
C01FCF4C08A954540054247B /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ARCHS = (
|
||||||
|
ppc,
|
||||||
|
i386,
|
||||||
|
);
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||||
|
GCC_ENABLE_CPP_RTTI = NO;
|
||||||
|
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||||
|
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||||
|
GCC_MODEL_TUNING = G4;
|
||||||
|
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||||
|
INFOPLIST_FILE = Info.plist;
|
||||||
|
INSTALL_PATH = "$(HOME)/Applications";
|
||||||
|
PRODUCT_NAME = Patcher;
|
||||||
|
WRAPPER_EXTENSION = app;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
C01FCF4F08A954540054247B /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/..";
|
||||||
|
GCC_VERSION = 3.3;
|
||||||
|
GCC_VERSION_i386 = 4.0;
|
||||||
|
GCC_VERSION_ppc = 3.3;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET_i386 = 10.4;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET_ppc = 10.2;
|
||||||
|
PREBINDING = NO;
|
||||||
|
SDKROOT = /Developer/SDKs/MacOSX10.2.8.sdk;
|
||||||
|
SDKROOT_i386 = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||||
|
SDKROOT_ppc = /Developer/SDKs/MacOSX10.2.8.sdk;
|
||||||
|
ZERO_LINK = NO;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
C01FCF5008A954540054247B /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/..";
|
||||||
|
GCC_VERSION = 3.3;
|
||||||
|
GCC_VERSION_i386 = 4.0;
|
||||||
|
GCC_VERSION_ppc = 3.3;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET_i386 = 10.4;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET_ppc = 10.2;
|
||||||
|
PREBINDING = NO;
|
||||||
|
SDKROOT = /Developer/SDKs/MacOSX10.2.8.sdk;
|
||||||
|
SDKROOT_i386 = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||||
|
SDKROOT_ppc = /Developer/SDKs/MacOSX10.2.8.sdk;
|
||||||
|
ZERO_LINK = NO;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Patcher" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
C01FCF4B08A954540054247B /* Debug */,
|
||||||
|
C01FCF4C08A954540054247B /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Patcher" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
C01FCF4F08A954540054247B /* Debug */,
|
||||||
|
C01FCF5008A954540054247B /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#ifdef __OBJC__
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2006 Steve Checkoway
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/* Upgrader */
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface Upgrader : NSObject
|
||||||
|
{
|
||||||
|
IBOutlet NSButton *m_Choose;
|
||||||
|
IBOutlet NSButton *m_Okay;
|
||||||
|
IBOutlet NSPanel *m_Panel;
|
||||||
|
IBOutlet NSProgressIndicator *m_ProgressBar;
|
||||||
|
IBOutlet NSProgressIndicator *m_Searching;
|
||||||
|
IBOutlet NSTextField *m_StatusText;
|
||||||
|
IBOutlet NSTextField *m_SelectionText;
|
||||||
|
IBOutlet NSTextField *m_PatchingText;
|
||||||
|
IBOutlet NSWindow *m_Window;
|
||||||
|
NSString *m_sAppID;
|
||||||
|
NSArray *m_vVersions;
|
||||||
|
NSString *m_sName;
|
||||||
|
NSString *m_sError;
|
||||||
|
NSString *m_sPath;
|
||||||
|
}
|
||||||
|
- (IBAction) chooseFile:(id)sender;
|
||||||
|
- (IBAction) upgrade:(id)sender;
|
||||||
|
- (void) findApp:(id)obj;
|
||||||
|
- (void) foundApp:(id)obj;
|
||||||
|
- (void) upgradeFile:(id)path;
|
||||||
|
- (void) sheetEnded:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
|
||||||
|
- (BOOL) panel:(id)sender isValidFilename:(NSString *)filename;
|
||||||
|
- (BOOL) panel:(id)sender shouldShowFilename:(NSString *)filename;
|
||||||
|
- (BOOL) checkPath:(NSString *)path;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2006 Steve Checkoway
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
@@ -0,0 +1,364 @@
|
|||||||
|
#import "Upgrader.h"
|
||||||
|
#import "CopyFiles.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@implementation Upgrader
|
||||||
|
|
||||||
|
// Generate English strings using: genstring -o en.lproj Upgrader.m
|
||||||
|
|
||||||
|
static NSString *CHOOSE_FILE;
|
||||||
|
static NSString *PATCH_FILE;
|
||||||
|
static NSString *PATCH_COMPLETE;
|
||||||
|
static NSString *QUIT;
|
||||||
|
static NSString *ERROR;
|
||||||
|
static NSString *ERROR_MESSAGE;
|
||||||
|
static NSString *PATCH_FILES_MISSING;
|
||||||
|
static NSString *PATCHER_CORRUPTED;
|
||||||
|
static NSString *CORRUPT_TITLE;
|
||||||
|
static NSString *PATCHING;
|
||||||
|
static NSString *SEARCHING;
|
||||||
|
static NSString *SELECTION;
|
||||||
|
static NSString *WINDOW_TITLE;
|
||||||
|
|
||||||
|
static NSOpenPanel *panel = nil;
|
||||||
|
|
||||||
|
- (void)awakeFromNib
|
||||||
|
{
|
||||||
|
NSString *path = [[NSBundle mainBundle] pathForResource:@"Identification" ofType:@"txt"];
|
||||||
|
NSData *data = [NSData dataWithContentsOfFile:path];
|
||||||
|
NSString *stringData = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
|
||||||
|
|
||||||
|
CHOOSE_FILE = NSLocalizedString( @"Choose file to patch.", nil );
|
||||||
|
PATCH_FILE = NSLocalizedString( @"Patch file.", nil );
|
||||||
|
PATCH_COMPLETE = NSLocalizedString( @"Patch complete.", nil );
|
||||||
|
QUIT = NSLocalizedString( @"Quit", nil );
|
||||||
|
ERROR = NSLocalizedString( @"Error", nil );
|
||||||
|
ERROR_MESSAGE = NSLocalizedString( @"Patching failed:\n%@", nil );
|
||||||
|
PATCH_FILES_MISSING = NSLocalizedString( @"Patch files missing.", nil );
|
||||||
|
PATCHER_CORRUPTED = NSLocalizedString( @"This patcher has become corrupted.", nil );
|
||||||
|
CORRUPT_TITLE = NSLocalizedString( @"Corrupt Patcher", nil );
|
||||||
|
PATCHING = NSLocalizedString( @"Patching", nil );
|
||||||
|
SEARCHING = NSLocalizedString( @"Searching for %@...", nil );
|
||||||
|
SELECTION = NSLocalizedString( @"You have chosen to patch \"%@\" in the folder:\n%@", nil );
|
||||||
|
WINDOW_TITLE = NSLocalizedString( @"StepMania Patcher", nil );
|
||||||
|
|
||||||
|
if( !data )
|
||||||
|
{
|
||||||
|
NSRunCriticalAlertPanel( CORRUPT_TITLE, PATCHER_CORRUPTED, @"OK", nil, nil );
|
||||||
|
[NSApp terminate:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sName = nil;
|
||||||
|
m_sAppID = nil;
|
||||||
|
m_vVersions = nil;
|
||||||
|
|
||||||
|
NSArray *lines = [stringData componentsSeparatedByString:@"\n"];
|
||||||
|
NSEnumerator *iter = [lines objectEnumerator];
|
||||||
|
NSString *line;
|
||||||
|
NSMutableArray *versions = [NSMutableArray array];
|
||||||
|
|
||||||
|
while( (line = [iter nextObject]) )
|
||||||
|
{
|
||||||
|
line = [line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||||
|
if( [line length] == 0 || [line characterAtIndex:0] == '#' )
|
||||||
|
continue;
|
||||||
|
if( m_sName == nil )
|
||||||
|
{
|
||||||
|
m_sName = [line retain];
|
||||||
|
}
|
||||||
|
else if( m_sAppID == nil )
|
||||||
|
{
|
||||||
|
m_sAppID = [line retain];
|
||||||
|
}
|
||||||
|
else if( [line isEqualToString:@"-ALL-"] )
|
||||||
|
{
|
||||||
|
versions = nil;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[versions addObject:line];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !m_sName || !m_sAppID )
|
||||||
|
{
|
||||||
|
NSRunCriticalAlertPanel( CORRUPT_TITLE, PATCHER_CORRUPTED, @"OK", nil, nil );
|
||||||
|
[NSApp terminate:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
if( versions && [versions count] )
|
||||||
|
m_vVersions = [versions retain];
|
||||||
|
|
||||||
|
// Set strings.
|
||||||
|
[m_StatusText setStringValue:[NSString stringWithFormat:SEARCHING, m_sName]];
|
||||||
|
[m_SelectionText setStringValue:@""];
|
||||||
|
[m_PatchingText setStringValue:PATCHING];
|
||||||
|
|
||||||
|
[m_Searching setUsesThreadedAnimation:YES];
|
||||||
|
[m_ProgressBar setUsesThreadedAnimation:YES];
|
||||||
|
[m_Window setTitle:WINDOW_TITLE];
|
||||||
|
|
||||||
|
[NSThread detachNewThreadSelector:@selector(findApp:) toTarget:self withObject:nil];
|
||||||
|
[m_Choose setEnabled:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[m_sName release];
|
||||||
|
[m_sAppID release];
|
||||||
|
[m_vVersions release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction) chooseFile:(id)sender
|
||||||
|
{
|
||||||
|
if( !panel )
|
||||||
|
{
|
||||||
|
panel = [[NSOpenPanel openPanel] retain];
|
||||||
|
[panel setCanChooseDirectories:YES];
|
||||||
|
[panel setAllowsMultipleSelection:NO];
|
||||||
|
[panel setDelegate:self];
|
||||||
|
[panel setDirectory:@"/Applications"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if( [panel runModal] == NSFileHandlingPanelOKButton )
|
||||||
|
{
|
||||||
|
NSString *dir, *app;
|
||||||
|
|
||||||
|
[m_StatusText setStringValue:PATCH_FILE];
|
||||||
|
[m_Okay setEnabled:YES];
|
||||||
|
[m_sPath release];
|
||||||
|
m_sPath = [[panel filename] retain];
|
||||||
|
dir = [m_sPath stringByDeletingLastPathComponent];
|
||||||
|
app = [[m_sPath lastPathComponent] stringByDeletingPathExtension];
|
||||||
|
[m_SelectionText setStringValue:[NSString stringWithFormat:SELECTION, app, dir]];
|
||||||
|
[m_Okay setTitle:@"OK"];
|
||||||
|
[m_Okay setAction:@selector(upgrade:)];
|
||||||
|
[m_Okay setTarget:self];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction) upgrade:(id)sender
|
||||||
|
{
|
||||||
|
[NSApp beginSheet:m_Panel
|
||||||
|
modalForWindow:[sender window]
|
||||||
|
modalDelegate:self
|
||||||
|
didEndSelector:@selector(sheetEnded:returnCode:contextInfo:)
|
||||||
|
contextInfo:NULL];
|
||||||
|
[NSThread detachNewThreadSelector:@selector(upgradeFile:) toTarget:self withObject:m_sPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) findApp:(id)obj
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
[m_Searching startAnimation:self];
|
||||||
|
|
||||||
|
// Find ITG
|
||||||
|
CFStringRef key = CFSTR( "ApplicationBundlePath" );
|
||||||
|
CFPropertyListRef list = CFPreferencesCopyAppValue( key, (CFStringRef)m_sAppID );
|
||||||
|
|
||||||
|
NSString *sPath = nil;
|
||||||
|
|
||||||
|
if( list && CFGetTypeID(list) != CFDictionaryGetTypeID() )
|
||||||
|
{
|
||||||
|
CFRelease( list );
|
||||||
|
list = NULL;
|
||||||
|
}
|
||||||
|
if( list )
|
||||||
|
{
|
||||||
|
CFTypeRef value;
|
||||||
|
CFDictionaryRef dict = (CFDictionaryRef)list;
|
||||||
|
|
||||||
|
if( m_vVersions )
|
||||||
|
{
|
||||||
|
NSEnumerator *iter = [m_vVersions objectEnumerator];
|
||||||
|
id version;
|
||||||
|
|
||||||
|
while( (version = [iter nextObject]) )
|
||||||
|
{
|
||||||
|
if( CFDictionaryGetValueIfPresent(dict, (CFStringRef)version, &value) &&
|
||||||
|
CFGetTypeID(value) == CFStringGetTypeID() &&
|
||||||
|
[self checkPath:(NSString *)value] )
|
||||||
|
{
|
||||||
|
sPath = (NSString *)CFRetain( value );
|
||||||
|
[sPath autorelease];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSDictionary *dict = (NSDictionary *)list;
|
||||||
|
NSEnumerator *iter = [dict objectEnumerator];
|
||||||
|
id path;
|
||||||
|
|
||||||
|
while( (path = [iter nextObject]) )
|
||||||
|
{
|
||||||
|
if( ![path isKindOfClass:[NSString class]] || ![self checkPath:path] )
|
||||||
|
continue;
|
||||||
|
sPath = [[path retain] autorelease];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CFRelease( list );
|
||||||
|
}
|
||||||
|
if( !sPath )
|
||||||
|
{
|
||||||
|
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
||||||
|
|
||||||
|
[ws findApplications];
|
||||||
|
sPath = [ws fullPathForApplication:m_sName];
|
||||||
|
|
||||||
|
if( ![self checkPath:sPath] )
|
||||||
|
sPath = nil;
|
||||||
|
}
|
||||||
|
[self performSelectorOnMainThread:@selector(foundApp:) withObject:sPath waitUntilDone:YES];
|
||||||
|
[m_Searching stopAnimation:self];
|
||||||
|
[pool release];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) foundApp:(id)obj
|
||||||
|
{
|
||||||
|
NSString *path = (NSString *)obj;
|
||||||
|
|
||||||
|
if( path ) // found
|
||||||
|
{
|
||||||
|
NSString *dir = [path stringByDeletingLastPathComponent];
|
||||||
|
NSString *app = [[path lastPathComponent] stringByDeletingPathExtension];
|
||||||
|
|
||||||
|
[m_sPath release];
|
||||||
|
m_sPath = [path retain];
|
||||||
|
[m_Okay setEnabled:YES];
|
||||||
|
[m_StatusText setStringValue:PATCH_FILE];
|
||||||
|
[m_SelectionText setStringValue:[NSString stringWithFormat:SELECTION, app, dir]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sPath = @"";
|
||||||
|
[m_StatusText setStringValue:CHOOSE_FILE];
|
||||||
|
}
|
||||||
|
[m_Choose setEnabled:YES];
|
||||||
|
[m_Choose setNeedsDisplay:YES];
|
||||||
|
[m_Okay setNeedsDisplay:YES];
|
||||||
|
[m_StatusText setNeedsDisplay:YES];
|
||||||
|
[m_SelectionText setNeedsDisplay:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) upgradeFile:(id)path
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
NSBundle *bundle = [NSBundle mainBundle];
|
||||||
|
NSString *patch = [bundle pathForResource:@"Contents" ofType:@"" inDirectory:@"Patch"];
|
||||||
|
NSArray *parentFiles = [bundle pathsForResourcesOfType:@"" inDirectory:@"Patch/ParentContents"];
|
||||||
|
|
||||||
|
if( patch && parentFiles)
|
||||||
|
{
|
||||||
|
[m_ProgressBar startAnimation:self];
|
||||||
|
|
||||||
|
if( NeedsPrivs(path) )
|
||||||
|
m_sError = CopyWithPrivs( patch, path );
|
||||||
|
else
|
||||||
|
m_sError = Copy( patch, path );
|
||||||
|
|
||||||
|
path = [path stringByDeletingLastPathComponent];
|
||||||
|
NSEnumerator *enumerator = [parentFiles objectEnumerator];
|
||||||
|
while( !m_sError && (patch = [enumerator nextObject]) )
|
||||||
|
{
|
||||||
|
if( NeedsPrivs(path) )
|
||||||
|
m_sError = CopyWithPrivs( patch, path );
|
||||||
|
else
|
||||||
|
m_sError = Copy( patch, path );
|
||||||
|
}
|
||||||
|
|
||||||
|
[m_ProgressBar stopAnimation:self];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sError = PATCH_FILES_MISSING;
|
||||||
|
}
|
||||||
|
[NSApp performSelectorOnMainThread:@selector(endSheet:) withObject:m_Panel waitUntilDone:YES];
|
||||||
|
[pool release];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) sheetEnded:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
|
||||||
|
{
|
||||||
|
[m_Panel orderOut:self];
|
||||||
|
if( m_sError )
|
||||||
|
{
|
||||||
|
NSRunCriticalAlertPanel( ERROR, ERROR_MESSAGE, @"OK", nil, nil, m_sError );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[m_StatusText setStringValue:PATCH_COMPLETE];
|
||||||
|
[m_Okay setTitle:QUIT];
|
||||||
|
[m_Okay setAction:@selector(terminate:)];
|
||||||
|
[m_Okay setTarget:NSApp];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) panel:(id)sender isValidFilename:(NSString *)filename
|
||||||
|
{
|
||||||
|
return [filename hasSuffix:@".app"] && [self checkPath:filename];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) panel:(id)sender shouldShowFilename:(NSString *)filename
|
||||||
|
{
|
||||||
|
if( [filename hasSuffix:@".app"] )
|
||||||
|
return [self checkPath:filename];
|
||||||
|
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if( stat([filename UTF8String], &sb) )
|
||||||
|
return NO;
|
||||||
|
return (sb.st_mode & S_IFDIR) == S_IFDIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) checkPath:(NSString *)path
|
||||||
|
{
|
||||||
|
NSBundle *b = [NSBundle bundleWithPath:path];
|
||||||
|
|
||||||
|
if( !b )
|
||||||
|
return NO;
|
||||||
|
if( ![[b objectForInfoDictionaryKey:@"CFBundleIdentifier"] isEqualToString:m_sAppID] )
|
||||||
|
return NO;
|
||||||
|
if( m_vVersions == nil )
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
NSString *bundleVersion = [b objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||||
|
NSEnumerator *iter = [m_vVersions objectEnumerator];
|
||||||
|
NSString *version;
|
||||||
|
|
||||||
|
while( (version = [iter nextObject]) )
|
||||||
|
if( [bundleVersion isEqualToString:version] )
|
||||||
|
return YES;
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2006 Steve Checkoway
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
IBClasses = (
|
||||||
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||||
|
{
|
||||||
|
ACTIONS = {chooseFile = id; upgrade = id; };
|
||||||
|
CLASS = Upgrader;
|
||||||
|
LANGUAGE = ObjC;
|
||||||
|
OUTLETS = {
|
||||||
|
"m_Choose" = NSButton;
|
||||||
|
"m_Okay" = NSButton;
|
||||||
|
"m_Panel" = NSPanel;
|
||||||
|
"m_PatchingText" = NSTextField;
|
||||||
|
"m_ProgressBar" = NSProgressIndicator;
|
||||||
|
"m_Searching" = NSProgressIndicator;
|
||||||
|
"m_SelectionText" = NSTextField;
|
||||||
|
"m_StatusText" = NSTextField;
|
||||||
|
"m_Window" = NSWindow;
|
||||||
|
};
|
||||||
|
SUPERCLASS = NSObject;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
IBVersion = 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IBDocumentLocation</key>
|
||||||
|
<string>39 98 356 240 0 0 1920 1178 </string>
|
||||||
|
<key>IBEditorPositions</key>
|
||||||
|
<dict>
|
||||||
|
<key>29</key>
|
||||||
|
<string>207 529 151 44 0 0 1920 1178 </string>
|
||||||
|
</dict>
|
||||||
|
<key>IBFramework Version</key>
|
||||||
|
<string>446.1</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>29</integer>
|
||||||
|
<integer>217</integer>
|
||||||
|
</array>
|
||||||
|
<key>IBSystem Version</key>
|
||||||
|
<string>8J135</string>
|
||||||
|
<key>IBUserGuides</key>
|
||||||
|
<dict>
|
||||||
|
<key>21</key>
|
||||||
|
<dict>
|
||||||
|
<key>guideLocations</key>
|
||||||
|
<array>
|
||||||
|
<string>Horizontal:180.000000</string>
|
||||||
|
</array>
|
||||||
|
<key>guidesLocked</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
Binary file not shown.
@@ -0,0 +1,29 @@
|
|||||||
|
int main( int argc, const char *argv[] )
|
||||||
|
{
|
||||||
|
return NSApplicationMain( argc, argv );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2006 Steve Checkoway
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
Reference in New Issue
Block a user