From fb6abc7de72d3913fd3dab3eec2ea41fc52c7349 Mon Sep 17 00:00:00 2001 From: German Laullon Date: Sun, 8 May 2011 19:51:40 -0700 Subject: [PATCH] get back the old gitx_asskpasswd --- ApplicationController.m | 4 +- gitx_askpasswd_main.m | 371 ++++++++++++++++------------------------ 2 files changed, 149 insertions(+), 226 deletions(-) diff --git a/ApplicationController.m b/ApplicationController.m index ad7149c..703da02 100644 --- a/ApplicationController.m +++ b/ApplicationController.m @@ -68,8 +68,8 @@ if ([PBGitDefaults useAskPasswd]) { // Make sure Git's SSH password requests get forwarded to our little UI tool: - setenv( "SSH_ASKPASS", [[[NSBundle mainBundle] pathForResource: @"gitx_askpasswd" ofType: @""] UTF8String], 1 ); - setenv( "DISPLAY", "localhost:0", 1 ); + setenv( "SSH_ASKPASS", [[[NSBundle mainBundle] pathForResource: @"gitx_askpasswd" ofType: @""] UTF8String], 1 ); + setenv( "DISPLAY", "localhost:0", 1 ); } [self registerServices]; diff --git a/gitx_askpasswd_main.m b/gitx_askpasswd_main.m index 75a0a34..07a7dbb 100644 --- a/gitx_askpasswd_main.m +++ b/gitx_askpasswd_main.m @@ -9,243 +9,166 @@ #include #import -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define OKBUTTONWIDTH 100.0 -#define OKBUTTONHEIGHT 24.0 -#define CANCELBUTTONWIDTH 100.0 -#define CANCELBUTTONHEIGHT 24.0 -#define PASSHEIGHT 22.0 -#define PASSLABELHEIGHT 16.0 -#define WINDOWAUTOSAVENAME @"GitXAskPasswordWindowFrame" +#define OKBUTTONWIDTH 100.0 +#define OKBUTTONHEIGHT 24.0 +#define CANCELBUTTONWIDTH 100.0 +#define CANCELBUTTONHEIGHT 24.0 +#define PASSHEIGHT 22.0 +#define PASSLABELHEIGHT 16.0 +#define WINDOWAUTOSAVENAME @"GitXAskPasswordWindowFrame" -@interface GAPAppDelegate : NSObject /**/ +@interface GAPAppDelegate : NSObject { + NSPanel* mPasswordPanel; + NSSecureTextField* mPasswordField; +} + +-(NSPanel*) passwordPanel; + +-(IBAction) doOKButton: (id)sender; +-(IBAction) doCancelButton: (id)sender; + +@end + + +@implementation GAPAppDelegate + +-(NSPanel*) passwordPanel +{ + if( !mPasswordPanel ) + { + NSRect box = NSMakeRect( 100, 100, 400, 134 ); + mPasswordPanel = [[NSPanel alloc] initWithContentRect: box + styleMask: NSTitledWindowMask + backing: NSBackingStoreBuffered defer: NO]; + [mPasswordPanel setHidesOnDeactivate: NO]; + [mPasswordPanel setLevel: NSFloatingWindowLevel]; + [mPasswordPanel setTitle: @"GitX SSH Remote Login"]; + if (![mPasswordPanel setFrameUsingName: WINDOWAUTOSAVENAME]) { + [mPasswordPanel center]; + [mPasswordPanel setFrameAutosaveName: WINDOWAUTOSAVENAME]; + } + + box.origin = NSZeroPoint; // Only need local coords from now on. + + // OK: + NSRect okBox = box; + okBox.origin.x = NSMaxX( box ) -OKBUTTONWIDTH -20; + okBox.size.width = OKBUTTONWIDTH; + okBox.origin.y += 20; + okBox.size.height = OKBUTTONHEIGHT; + NSButton *okButton = [[NSButton alloc] initWithFrame: okBox]; + [okButton setTarget: self]; + [okButton setAction: @selector(doOKButton:)]; + [okButton setTitle: @"OK"]; // +++ Localize. + [okButton setKeyEquivalent: @"\r"]; + [okButton setBordered: YES]; + [okButton setBezelStyle: NSRoundedBezelStyle]; + [[mPasswordPanel contentView] addSubview: okButton]; + + // Cancel: + NSRect cancelBox = box; + cancelBox.origin.x = NSMinX( okBox ) -CANCELBUTTONWIDTH -6; + cancelBox.size.width = CANCELBUTTONWIDTH; + cancelBox.origin.y += 20; + cancelBox.size.height = CANCELBUTTONHEIGHT; + NSButton *cancleButton = [[NSButton alloc] initWithFrame: cancelBox]; + [cancleButton setTarget: self]; + [cancleButton setAction: @selector(doCancelButton:)]; + [cancleButton setTitle: @"Cancel"]; // +++ Localize. + [cancleButton setBordered: YES]; + [cancleButton setBezelStyle: NSRoundedBezelStyle]; + [[mPasswordPanel contentView] addSubview: cancleButton]; + + // Password field: + NSRect passBox = box; + passBox.origin.y = NSMaxY(okBox) + 24; + passBox.size.height = PASSHEIGHT; + passBox.origin.x += 104; + passBox.size.width -= 104 + 20; + mPasswordField = [[NSSecureTextField alloc] initWithFrame: passBox]; + [mPasswordField setSelectable: YES]; + [mPasswordField setEditable: YES]; + [mPasswordField setBordered: YES]; + [mPasswordField setBezeled: YES]; + [mPasswordField setBezelStyle: NSTextFieldSquareBezel]; + [mPasswordField selectText: self]; + [[mPasswordPanel contentView] addSubview: mPasswordField]; + + // Password label: + NSRect passLabelBox = box; + passLabelBox.origin.y = NSMaxY(passBox) + 8; + passLabelBox.size.height = PASSLABELHEIGHT; + passLabelBox.origin.x += 100; + passLabelBox.size.width -= 100 + 20; + NSTextField *passwordLabel = [[NSTextField alloc] initWithFrame: passLabelBox]; + [passwordLabel setSelectable: YES]; + [passwordLabel setEditable: NO]; + [passwordLabel setBordered: NO]; + [passwordLabel setBezeled: NO]; + [passwordLabel setDrawsBackground: NO]; + [passwordLabel setStringValue: @"Please enter your password:"]; // +++ Localize. + [[mPasswordPanel contentView] addSubview: passwordLabel]; + + // GitX icon: + NSRect gitxIconBox = box; + gitxIconBox.origin.y = NSMaxY(box) - 78; + gitxIconBox.size.height = 64; + gitxIconBox.origin.x += 20; + gitxIconBox.size.width = 64; + NSImageView *gitxIconView = [[NSImageView alloc] initWithFrame: gitxIconBox]; + [gitxIconView setEditable: NO]; + NSString *gitxIconPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: @"gitx.icns"]; + NSImage *gitxIcon = [[NSImage alloc] initWithContentsOfFile: gitxIconPath]; + [gitxIconView setImage: gitxIcon]; + [[mPasswordPanel contentView] addSubview: gitxIconView]; + } + + return mPasswordPanel; +} + + +-(IBAction) doOKButton: (id)sender +{ + printf( "%s\n", [[mPasswordField stringValue] UTF8String] ); + [[NSApplication sharedApplication] stopModalWithCode: 0]; +} + + +// TODO: Need to find out how to get SSH to cancel. +// When the user cancels the window it is opened again for however +// many times the remote server allows failed attempts. +-(IBAction) doCancelButton: (id)sender +{ + [[NSApplication sharedApplication] stopModalWithCode: 1]; } @end -NSString* url; -OSStatus StorePasswordKeychain (const char *url, UInt32 urlLength, void* password,UInt32 passwordLength); -@implementation GAPAppDelegate - --(void)yesNo:(NSString *)prompt url:(NSString *)url{ - NSAlert *alert = [[NSAlert alloc] init]; - [alert addButtonWithTitle:@"YES"]; - [alert addButtonWithTitle:@"NO"]; - [alert setMessageText:[NSString stringWithFormat:@"%@?",url]]; - [alert setInformativeText:prompt]; - [alert setAlertStyle:NSWarningAlertStyle]; - NSInteger result = [alert runModal]; - - Boolean yes=NO; - if ( result == NSAlertFirstButtonReturn ) { - yes=YES; - } - [alert release]; - printf("%s",yes?"yes":"no"); -} - - -- (void)pasword:(NSString *)prompt url:(NSString *)url{ - - NSRect box = NSMakeRect(0, 0, 200, 24); - - NSSecureTextField * passView = [[NSSecureTextField alloc] initWithFrame: box]; - [passView setSelectable: YES]; - [passView setEditable: YES]; - [passView setBordered: YES]; - [passView setBezeled: YES]; - [passView setBezelStyle: NSTextFieldSquareBezel]; - [passView selectText: self]; - - - NSAlert *alert = [[NSAlert alloc] init]; - [alert addButtonWithTitle:@"Ok"]; - [alert addButtonWithTitle:@"cancel"]; - [alert setMessageText:[NSString stringWithFormat:@"%@?",url]]; - [alert setInformativeText:prompt]; - [alert setAlertStyle:NSWarningAlertStyle]; - [alert setAccessoryView:passView]; - [alert setShowsSuppressionButton:YES]; - [[alert suppressionButton] setTitle:@"Save on keychain"]; - NSInteger result = [alert runModal]; - if ( result == NSAlertFirstButtonReturn ) { - NSString *pas=[passView stringValue]; - printf( "%s", [pas UTF8String] ); - if ([[alert suppressionButton] state] == NSOnState) { - StorePasswordKeychain ([url cStringUsingEncoding:NSASCIIStringEncoding], - [url lengthOfBytesUsingEncoding:NSASCIIStringEncoding], - (void *)[pas cStringUsingEncoding:NSASCIIStringEncoding], - [pas lengthOfBytesUsingEncoding:NSASCIIStringEncoding]); - } - } - - [alert release]; -} - -@end - -void getproclline(pid_t pid, char *command_name); - -void getproclline(pid_t pid, char *command_name) +int main( int argc, const char** argv ) { - int mib[3], argmax, nargs, c = 0; - size_t size; - char *procargs, *sp, *np, *cp; - - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - - size = sizeof(argmax); - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) { - return; - } - - /* Allocate space for the arguments. */ - procargs = (char *)malloc(argmax); - if (procargs == NULL) { - return; - } - - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = pid; - - size = (size_t)argmax; - if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) { - return; - } - - memcpy(&nargs, procargs, sizeof(nargs)); - cp = procargs + sizeof(nargs); - - /* Skip the saved exec_path. */ - for (; cp < &procargs[size]; cp++) { - if (*cp == '\0') { - /* End of exec_path reached. */ - break; - } - } - if (cp == &procargs[size]) { - return; - } - - /* Skip trailing '\0' characters. */ - for (; cp < &procargs[size]; cp++) { - if (*cp != '\0') { - /* Beginning of first argument reached. */ - break; - } - } - if (cp == &procargs[size]) { - return; - } - /* Save where the argv[0] string starts. */ - sp = cp; - - for (np = NULL; c < nargs && cp < &procargs[size]; cp++) { - if (*cp == '\0') { - c++; - if (np != NULL) { - *np = ' '; - } - np = cp; - } - } - sprintf(command_name, "%s",sp); -} - -OSStatus StorePasswordKeychain (const char *url, UInt32 urlLength, void* password,UInt32 passwordLength) -{ - OSStatus status; - status = SecKeychainAddGenericPassword ( - NULL, // default keychain - 4, // length of service name - "GitX", // service name - urlLength, // length of account name - url, // account name - passwordLength, // length of password - password, // pointer to password data - NULL // the item reference - ); - return (status); -} - -OSStatus GetPasswordKeychain (const char *url, UInt32 urlLength ,void *passwordData,UInt32 *passwordLength, - SecKeychainItemRef *itemRef) -{ - OSStatus status ; - status = SecKeychainFindGenericPassword ( - NULL, // default keychain - 4, // length of service name - "GitX", // service name - urlLength, // length of account name - url, // account name - passwordLength, // length of password - passwordData, // pointer to password data - itemRef // the item reference - ); - return (status); -} - - -int main( int argc, const char* argv[] ) -{ - // close stderr to stop cocoa log messages from being picked up by GitX - close(STDERR_FILENO); + // close stderr to stop cocoa log messages from being picked up by GitX + close(STDERR_FILENO); - ProcessSerialNumber myPSN = { 0, kCurrentProcess }; - TransformProcessType( &myPSN, kProcessTransformToForegroundApplication ); - - NSApplication *app = [NSApplication sharedApplication]; - GAPAppDelegate *appDel = [[GAPAppDelegate alloc] init]; - [app setDelegate: appDel]; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - char args[4024]; - getproclline(getppid(),args); - NSString *cmd=[NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:args]]; + ProcessSerialNumber myPSN = { 0, kCurrentProcess }; + TransformProcessType( &myPSN, kProcessTransformToForegroundApplication ); - NSLog(@"cmd: '%@'",cmd); + NSApplication *app = [NSApplication sharedApplication]; + GAPAppDelegate *appDel = [[GAPAppDelegate alloc] init]; + [app setDelegate: appDel]; + NSWindow *passPanel = [appDel passwordPanel]; - if([cmd hasPrefix:@"git-remote"]){ - NSArray *args=[cmd componentsSeparatedByString:@" "]; - NSString *url=[args objectAtIndex:[args count]-1]; - - void *passwordData = nil; - SecKeychainItemRef itemRef = nil; - UInt32 passwordLength = 0; - - OSStatus status = GetPasswordKeychain ([url cStringUsingEncoding:NSASCIIStringEncoding],[url lengthOfBytesUsingEncoding:NSASCIIStringEncoding],&passwordData,&passwordLength,&itemRef); - if (status == noErr) { - SecKeychainItemFreeContent (NULL,passwordData); - NSString *pas=[[NSString stringWithCString:passwordData encoding:NSASCIIStringEncoding] substringToIndex:passwordLength]; - printf( "%s", [pas UTF8String] ); - return 0; - } - - NSString *prompt=[NSString stringWithFormat:@"%@",[NSString stringWithCString:argv[1] encoding:NSASCIIStringEncoding]]; - [appDel pasword:prompt url:url]; - }else{ // yes/no? - NSString *prompt=[NSString stringWithFormat:@"%@",[NSString stringWithCString:argv[1] encoding:NSASCIIStringEncoding]]; - NSArray *args=[cmd componentsSeparatedByString:@" "]; - NSString *url=[args objectAtIndex:1]; - [appDel yesNo:prompt url:url]; - } + [app activateIgnoringOtherApps: YES]; + [passPanel makeKeyAndOrderFront: nil]; + NSInteger code = [app runModalForWindow: passPanel]; - return 0; -} + [defaults synchronize]; + + return code; +} \ No newline at end of file