Permalink
Browse files

Merge branch 'master' into CodeSigning

  • Loading branch information...
2 parents 3d8be2d + 7a283bf commit 3c37f775fb994762c61ba2da05e9ee0d4a3d6329 @andymatuschak andymatuschak committed Aug 16, 2012
View
@@ -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
View
@@ -128,6 +128,7 @@ - (id)init;
[[self task] setStandardInput:[self inputPipe]];
[[self task] setStandardOutput:[self outputPipe]];
+ [[self task] setStandardError:[self outputPipe]];
}
return self;
View
@@ -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);
@@ -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];
@@ -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;
}
}
@@ -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
View
@@ -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
View
@@ -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];
@@ -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];
}
View
@@ -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
@@ -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;
@@ -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
View
@@ -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
View
@@ -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
View
@@ -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
Oops, something went wrong.

0 comments on commit 3c37f77

Please sign in to comment.