Skip to content

Commit

Permalink
Merge branch 'master' into CodeSigning
Browse files Browse the repository at this point in the history
  • Loading branch information
andymatuschak committed Aug 16, 2012
2 parents 3d8be2d + 7a283bf commit 3c37f77
Show file tree
Hide file tree
Showing 32 changed files with 5,825 additions and 1,109 deletions.
6 changes: 6 additions & 0 deletions NTSynchronousTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
// returns the result
+(int) task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input output: (NSData**)outData;

+(NSData*)task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;

- (void)run:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;
- (int)result;
- (NSData *)output;

@end

#endif
1 change: 1 addition & 0 deletions NTSynchronousTask.m
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ - (id)init;

[[self task] setStandardInput:[self inputPipe]];
[[self task] setStandardOutput:[self outputPipe]];
[[self task] setStandardError:[self outputPipe]];
}

return self;
Expand Down
101 changes: 86 additions & 15 deletions SUDiskImageUnarchiver.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,35 @@
#import "SULog.h"
#import <CoreServices/CoreServices.h>


@implementation SUDiskImageUnarchiver

+ (BOOL)canUnarchivePath:(NSString *)path
{
return [[path pathExtension] isEqualToString:@"dmg"];
}

// Called on a non-main thread.
- (void)extractDMG
{
// GETS CALLED ON NON-MAIN THREAD!!!
{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSData *result = [NTSynchronousTask task:@"/usr/bin/hdiutil" directory:@"/" withArgs:[NSArray arrayWithObjects: @"isencrypted", archivePath, nil] input:NULL];
if([self isEncrypted:result] && [delegate respondsToSelector:@selector(unarchiver:requiresPasswordReturnedViaInvocation:)]) {
[self performSelectorOnMainThread:@selector(requestPasswordFromDelegate) withObject:nil waitUntilDone:NO];
} else {
[self extractDMGWithPassword:nil];
}

[pool release];
}

// Called on a non-main thread.
- (void)extractDMGWithPassword:(NSString *)password
{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

BOOL mountedSuccessfully = NO;

SULog(@"Extracting %@ as a DMG", archivePath);
Expand All @@ -48,25 +64,52 @@ - (void)extractDMG
}
}
while (noErr == FSPathMakeRefWithOptions((UInt8 *)[mountPoint fileSystemRepresentation], kFSPathMakeRefDoNotFollowLeafSymlink, &tmpRef, NULL));

NSData *promptData = nil;
if (password) {
NSString *data = [NSString stringWithFormat:@"%@\nyes\n", password];
const char *bytes = [data cStringUsingEncoding:NSUTF8StringEncoding];
NSUInteger length = [data lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
promptData = [NSData dataWithBytes:bytes length:length];
}
else
promptData = [NSData dataWithBytes:"yes\n" length:4];

NSArray* arguments = [NSArray arrayWithObjects:@"attach", archivePath, @"-mountpoint", mountPoint, /*@"-noverify",*/ @"-nobrowse", @"-noautoopen", nil];
// set up a pipe and push "yes" (y works too), this will accept any license agreement crap
// not every .dmg needs this, but this will make sure it works with everyone
NSData* yesData = [[[NSData alloc] initWithBytes:"yes\n" length:4] autorelease];
NSArray* arguments = [NSArray arrayWithObjects:@"attach", archivePath, @"-mountpoint", mountPoint, /*@"-noverify",*/ @"-nobrowse", @"-noautoopen", nil];

NSData *output = nil;
NSInteger taskResult = -1;
@try
{
NTSynchronousTask* task = [[NTSynchronousTask alloc] init];

[task run:@"/usr/bin/hdiutil" directory:@"/" withArgs:arguments input:promptData];

taskResult = [task result];
output = [[[task output] copy] autorelease];
[task release];
}
@catch (NSException *localException)
{
goto reportError;
}

NSData *output = nil;
int returnCode = [NTSynchronousTask task:@"/usr/bin/hdiutil" directory:@"/" withArgs:arguments input:yesData output: &output];
if ( returnCode != 0 )
if (taskResult != 0)
{
NSString* resultStr = output ? [[[NSString alloc] initWithData: output encoding: NSUTF8StringEncoding] autorelease] : nil;
SULog( @"hdiutil failed with code: %d data: <<%@>>", returnCode, resultStr );
goto reportError;
if (password != nil && [resultStr rangeOfString:@"Authentication error"].location != NSNotFound && [delegate respondsToSelector:@selector(unarchiver:requiresPasswordReturnedViaInvocation:)]) {
[self performSelectorOnMainThread:@selector(requestPasswordFromDelegate) withObject:nil waitUntilDone:NO];
goto finally;
} else {
SULog( @"hdiutil failed with code: %d data: <<%@>>", taskResult, resultStr );
goto reportError;
}
}
mountedSuccessfully = YES;

// Now that we've mounted it, we need to copy out its contents.
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) {
// On 10.6 and later we don't want to use the File Manager API and instead want to use NSFileManager (fixes #827357).
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) {
// On 10.7 and later we don't want to use the File Manager API and instead want to use NSFileManager (fixes #827357).
NSFileManager *manager = [[[NSFileManager alloc] init] autorelease];
NSError *error = nil;
NSArray *contents = [manager contentsOfDirectoryAtPath:mountPoint error:&error];
Expand All @@ -91,7 +134,7 @@ - (void)extractDMG

if (![manager copyItemAtPath:fromPath toPath:toPath error:&error])
{
SULog(@"Couldn't copy item: %@", error);
SULog(@"Couldn't copy item: %@ : %@", error, error.userInfo ? error.userInfo : @"");
goto reportError;
}
}
Expand Down Expand Up @@ -132,4 +175,32 @@ + (void)load
[self registerImplementation:self];
}

- (BOOL)isEncrypted:(NSData*)resultData
{
BOOL result = NO;
if(resultData)
{
NSString *data = [NSString stringWithCString:(char*)[resultData bytes] encoding:NSUTF8StringEncoding];
if (!NSEqualRanges([data rangeOfString:@"passphrase-count"], NSMakeRange(NSNotFound, 0)))
{
result = YES;
}
}
return result;
}

- (void)requestPasswordFromDelegate
{
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(continueWithPassword:)]];
[invocation setSelector:@selector(continueWithPassword:)];
[invocation setTarget:self];
[invocation retainArguments];
[delegate unarchiver:self requiresPasswordReturnedViaInvocation:invocation];
}

- (void)continueWithPassword:(NSString *)password
{
[NSThread detachNewThreadSelector:@selector(extractDMGWithPassword:) toTarget:self withObject:password];
}

@end
6 changes: 3 additions & 3 deletions SUInstaller.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

@class SUHost;
@interface SUInstaller : NSObject { }
+ (NSString *)appPathInUpdateFolder:(NSString *)updateFolder forHost:(SUHost *)host;
+ (void) installFromUpdateFolder:(NSString *)updateFolder overHost:(SUHost *)host delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator;
+ (void) finishInstallationWithResult:(BOOL)result host:(SUHost *)host error:(NSError *)error delegate:delegate;
+ (NSString *) appPathInUpdateFolder:(NSString *)updateFolder forHost:(SUHost *)host;
+ (void) installFromUpdateFolder:(NSString *)updateFolder overHost:(SUHost *)host installationPath:(NSString *)installationPath delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator;
+ (void) finishInstallationToPath:(NSString *)installationPath withResult:(BOOL)result host:(SUHost *)host error:(NSError *)error delegate:delegate;
+ (NSString*) updateFolder;
+ (void) notifyDelegateOfFailure: (NSDictionary*)dict;
@end
Expand Down
14 changes: 7 additions & 7 deletions SUInstaller.m
Original file line number Diff line number Diff line change
Expand Up @@ -117,30 +117,30 @@ + (NSString *)appPathInUpdateFolder:(NSString *)updateFolder forHost:(SUHost *)h
return isPackage ? nil : path;
}

+ (void)installFromUpdateFolder:(NSString *)inUpdateFolder overHost:(SUHost *)host delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator
+ (void)installFromUpdateFolder:(NSString *)inUpdateFolder overHost:(SUHost *)host installationPath:(NSString *)installationPath delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator
{
BOOL isPackage = NO;
NSString *newAppDownloadPath = [self installSourcePathInUpdateFolder:inUpdateFolder forHost:host isPackage:&isPackage];

if (newAppDownloadPath == nil)
{
[self finishInstallationWithResult:NO host:host error:[NSError errorWithDomain:SUSparkleErrorDomain code:SUMissingUpdateError userInfo:[NSDictionary dictionaryWithObject:@"Couldn't find an appropriate update in the downloaded package." forKey:NSLocalizedDescriptionKey]] delegate:delegate];
[self finishInstallationToPath:installationPath withResult:NO host:host error:[NSError errorWithDomain:SUSparkleErrorDomain code:SUMissingUpdateError userInfo:[NSDictionary dictionaryWithObject:@"Couldn't find an appropriate update in the downloaded package." forKey:NSLocalizedDescriptionKey]] delegate:delegate];
}
else
{
[(isPackage ? [SUPackageInstaller class] : [SUPlainInstaller class]) performInstallationWithPath:newAppDownloadPath host:host delegate:delegate synchronously:synchronously versionComparator:comparator];
[(isPackage ? [SUPackageInstaller class] : [SUPlainInstaller class]) performInstallationToPath:installationPath fromPath:newAppDownloadPath host:host delegate:delegate synchronously:synchronously versionComparator:comparator];
}
}

+ (void)mdimportHost:(SUHost *)host
+ (void)mdimportInstallationPath:(NSString *)installationPath
{
// *** GETS CALLED ON NON-MAIN THREAD!

SULog( @"mdimporting" );

NSTask *mdimport = [[[NSTask alloc] init] autorelease];
[mdimport setLaunchPath:@"/usr/bin/mdimport"];
[mdimport setArguments:[NSArray arrayWithObject:[host installationPath]]];
[mdimport setArguments:[NSArray arrayWithObject:installationPath]];
@try
{
[mdimport launch];
Expand All @@ -158,11 +158,11 @@ + (void)mdimportHost:(SUHost *)host
#define SUNotifyDictErrorKey @"SUNotifyDictError"
#define SUNotifyDictDelegateKey @"SUNotifyDictDelegate"

+ (void)finishInstallationWithResult:(BOOL)result host:(SUHost *)host error:(NSError *)error delegate:delegate
+ (void)finishInstallationToPath:(NSString *)installationPath withResult:(BOOL)result host:(SUHost *)host error:(NSError *)error delegate:delegate
{
if (result)
{
[self mdimportHost:host];
[self mdimportInstallationPath:installationPath];
if ([delegate respondsToSelector:@selector(installerFinishedForHost:)])
[delegate performSelectorOnMainThread: @selector(installerFinishedForHost:) withObject: host waitUntilDone: NO];
}
Expand Down
9 changes: 5 additions & 4 deletions SUPackageInstaller.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
NSString *SUPackageInstallerArgumentsKey = @"SUPackageInstallerArguments";
NSString *SUPackageInstallerHostKey = @"SUPackageInstallerHost";
NSString *SUPackageInstallerDelegateKey = @"SUPackageInstallerDelegate";
NSString *SUPackageInstallerInstallationPathKey = @"SUPackageInstallerInstallationPathKey";

@implementation SUPackageInstaller

+ (void)finishInstallationWithInfo:(NSDictionary *)info
{
[self finishInstallationWithResult:YES host:[info objectForKey:SUPackageInstallerHostKey] error:nil delegate:[info objectForKey:SUPackageInstallerDelegateKey]];
[self finishInstallationToPath:[info objectForKey:SUPackageInstallerInstallationPathKey] withResult:YES host:[info objectForKey:SUPackageInstallerHostKey] error:nil delegate:[info objectForKey:SUPackageInstallerDelegateKey]];
}

+ (void)performInstallationWithInfo:(NSDictionary *)info
Expand All @@ -35,7 +36,7 @@ + (void)performInstallationWithInfo:(NSDictionary *)info
[pool drain];
}

+ (void)performInstallationWithPath:(NSString *)path host:(SUHost *)host delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator
+ (void)performInstallationToPath:(NSString *)installationPath fromPath:(NSString *)path host:(SUHost *)host delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator
{
NSString *command;
NSArray *args;
Expand All @@ -56,11 +57,11 @@ + (void)performInstallationWithPath:(NSString *)path host:(SUHost *)host delegat
if (![[NSFileManager defaultManager] fileExistsAtPath:command])
{
NSError *error = [NSError errorWithDomain:SUSparkleErrorDomain code:SUMissingInstallerToolError userInfo:[NSDictionary dictionaryWithObject:@"Couldn't find Apple's installer tool!" forKey:NSLocalizedDescriptionKey]];
[self finishInstallationWithResult:NO host:host error:error delegate:delegate];
[self finishInstallationToPath:installationPath withResult:NO host:host error:error delegate:delegate];
}
else
{
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:command, SUPackageInstallerCommandKey, args, SUPackageInstallerArgumentsKey, host, SUPackageInstallerHostKey, delegate, SUPackageInstallerDelegateKey, nil];
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:command, SUPackageInstallerCommandKey, args, SUPackageInstallerArgumentsKey, host, SUPackageInstallerHostKey, delegate, SUPackageInstallerDelegateKey, installationPath, SUPackageInstallerInstallationPathKey, nil];
if (synchronously)
[self performInstallationWithInfo:info];
else
Expand Down
26 changes: 26 additions & 0 deletions SUPasswordPrompt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// SUPasswordPrompt.h
// Sparkle
//
// Created by rudy on 8/18/09.
// Copyright 2009 Ambrosia Software, Inc.. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import "Sparkle/SUWindowController.h"

@interface SUPasswordPrompt : SUWindowController
{
IBOutlet NSImageView *mIconView;
IBOutlet NSTextField *mTextDescription;
IBOutlet NSSecureTextField *mPasswordField;
NSString *mPassword;
NSString *mName;
NSImage *mIcon;
}

- (id)initWithHost:(SUHost *)aHost;
- (NSInteger)run;
- (NSString *)password;

@end
86 changes: 86 additions & 0 deletions SUPasswordPrompt.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// SUPasswordPrompt.m
// Sparkle
//
// Created by rudy on 8/18/09.
// Copyright 2009 Ambrosia Software, Inc.. All rights reserved.
//

#import "SUPasswordPrompt.h"


@implementation SUPasswordPrompt

- (id)initWithHost:(SUHost *)aHost
{
self = [super initWithHost:aHost windowNibName:@"SUPasswordPrompt"];
if (self)
{
[self setName:[aHost name]];
[self setIcon:[aHost icon]];
mPassword = nil;
[self setShouldCascadeWindows:NO];
}
return self;
}

- (void)awakeFromNib
{
[mIconView setImage:[self icon]];
}

- (void)setName:(NSString*)name
{
[mName release];
mName = [name retain];
}

- (NSString*)name
{
return mName;
}

- (void)setIcon:(NSImage*)icon
{
[mIcon release];
mIcon = [icon retain];
}

- (NSImage*)icon
{
return mIcon;
}

- (NSString *)password
{
return mPassword;
}

- (void)setPassword:(NSString*)password
{
[mPassword release];
mPassword = [password retain];
}

- (NSInteger)run
{
//modally run a password prompt
NSInteger result = [NSApp runModalForWindow:[self window]];
if(result)
[self setPassword:[mPasswordField stringValue]];
return result;
}

- (IBAction)accept:(id)sender
{
[[self window] orderOut:self];
[NSApp stopModalWithCode:1];
}

- (IBAction)cancel:(id)sender
{
[[self window] orderOut:self];
[NSApp stopModalWithCode:0];
}

@end
2 changes: 1 addition & 1 deletion SUPlainInstaller.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
@class SUHost;

@interface SUPlainInstaller : SUInstaller { }
+ (void)performInstallationWithPath:(NSString *)path host:(SUHost *)host delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator;
+ (void)performInstallationToPath:(NSString *)installationPath fromPath:(NSString *)path host:(SUHost *)host delegate:delegate synchronously:(BOOL)synchronously versionComparator:(id <SUVersionComparison>)comparator;
@end

#endif
Loading

0 comments on commit 3c37f77

Please sign in to comment.