PrompterController.m [plain text]
/*
* PrompterController.m
*
* $Header$
*
* Copyright 2004 Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*/
#import "KerberosAgentController.h"
#import "PrompterController.h"
#import "AuthenticationController.h"
#import "ChangePasswordController.h"
#import "KerberosErrorAlert.h"
#define ResponseSpacing 16
#define PromptSpacing 12
#pragma mark -
// ---------------------------------------------------------------------------
krb5_error_code GraphicalKerberosPrompter (krb5_context context,
void *data,
const char *name,
const char *banner,
int num_prompts,
krb5_prompt prompts[])
{
krb5_error_code err = 0;
int i;
NSMutableArray *promptsArray = NULL;
PrompterController *controller = NULL;
if (!err) {
promptsArray = [[NSMutableArray alloc] init];
if (promptsArray == NULL) { err = ENOMEM; }
}
if (!err) {
for (i = 0; i < num_prompts; i++) {
Prompt *prompt = [[Prompt alloc] initWithPrompt: &prompts[i]];
if (prompt == NULL) { err = ENOMEM; break; }
[promptsArray addObject: prompt];
[prompt release];
}
}
if (!err) {
NSString *message = (name != NULL) ? [NSString stringWithUTF8String: name] : NULL;
NSString *description = (banner != NULL) ? [NSString stringWithUTF8String: banner] : NULL;;
controller = [[PrompterController alloc] initWithTitle: message
banner: description
prompts: promptsArray];
if (controller == NULL) { err = klFatalDialogErr; }
}
if (!err) {
NSWindow *parentWindow = [[NSApp delegate] activeWindow];
if (parentWindow != NULL) {
err = [controller runSheetModalForWindow: parentWindow];
} else {
err = [controller runWindow];
}
}
if (!err) {
for (i = 0; i < num_prompts; i++) {
Prompt *prompt = [promptsArray objectAtIndex: i];
[prompt saveResponseInPrompt: &prompts[i]];
}
}
[promptsArray release];
[controller release];
return err;
}
#pragma mark -
@implementation Prompt
// ---------------------------------------------------------------------------
- (id) initWithPrompt: (krb5_prompt *) prompt
{
if ((self = [super init])) {
promptString = NULL;
responseString = NULL;
if (prompt == NULL) {
[self release];
return NULL;
}
promptString = [[NSString alloc] initWithCString: prompt->prompt];
if (promptString == NULL) {
[self release];
return NULL;
}
secure = prompt->hidden;
responseString = [[NSMutableString alloc] init];
if (responseString == NULL) {
[self release];
return NULL;
}
}
return self;
}
// ---------------------------------------------------------------------------
- (void) dealloc
{
if (promptString != NULL) { [promptString release]; }
if (responseString != NULL) { [responseString release]; }
[super dealloc];
}
// ---------------------------------------------------------------------------
- (NSString *) prompt
{
return promptString;
}
// ---------------------------------------------------------------------------
- (BOOL) secure
{
return secure;
}
// ---------------------------------------------------------------------------
- (void) setResponse: (NSString *) response
{
[responseString setString: response];
}
// ---------------------------------------------------------------------------
- (void) saveResponseInPrompt: (krb5_prompt *) prompt
{
if (prompt != NULL) {
const char *response = [responseString UTF8String];
unsigned int responseLength = strlen (response) + 1;
unsigned int replyLength = (responseLength >= prompt->reply->length) ? prompt->reply->length : responseLength;
memmove (prompt->reply->data, response, replyLength * sizeof (char));
prompt->reply->data[replyLength - 1] = '\0';
prompt->reply->length = strlen (prompt->reply->data);
}
}
@end
#pragma mark -
@implementation PrompterController
// ---------------------------------------------------------------------------
- (id) initWithTitle: (NSString *) title
banner: (NSString *) banner
prompts: (NSArray *) prompts
{
if ((self = [super initWithWindowNibName: @"PrompterController"])) {
dprintf ("PrompterController initializing");
result = klNoErr;
titleString = NULL;
bannerString = NULL;
promptsArray = NULL;
responseTextFieldArray = NULL;
applicationNameString = NULL;
applicationIconPathString = NULL;
isSheet = NO;
responseTextFieldArray = [[NSMutableArray alloc] init];
if (responseTextFieldArray == NULL) {
[self release];
return NULL;
}
if (title != NULL) { titleString = [title retain]; }
if (banner != NULL) { bannerString = [banner retain]; }
if (prompts == NULL) {
[self release];
return NULL;
}
promptsArray = [prompts retain];
}
return self;
}
// ---------------------------------------------------------------------------
- (void) dealloc
{
dprintf ("PrompterController deallocating");
if (titleString != NULL) { [titleString release]; }
if (bannerString != NULL) { [bannerString release]; }
if (promptsArray != NULL) { [promptsArray release]; }
if (responseTextFieldArray != NULL) { [responseTextFieldArray release]; }
if (applicationNameString != NULL) { [applicationNameString release]; }
if (applicationIconPathString != NULL) { [applicationIconPathString release]; }
[super dealloc];
}
#pragma mark -- Loading --
// ---------------------------------------------------------------------------
- (void) windowDidLoad
{
dprintf ("Entering PrompterController windowDidLoad");
// Set up some values used later to dynamically size the window
NSRect singleResponseFrame = [responsesBox frame];
float singlePromptHeight = [responsesBox frame].size.height;
NSSize baseWindowSize = [[[self window] contentView] frame].size;
baseWindowSize.height -= singlePromptHeight;
int promptCount = [promptsArray count];
int i;
// Set up the dialog icon:
NSImage *applicationIconImage = [NSImage imageNamed: @"NSApplicationIcon"];
[kerberosIconImageView setImage: applicationIconImage];
if (applicationIconPathString != NULL) {
NSImage *badgeImage = [[NSWorkspace sharedWorkspace] iconForFile: applicationIconPathString];
[kerberosIconImageView setBadgeImage: badgeImage];
}
// Title and Banner
[[self window] setTitle: (titleString == NULL) ? @"" : titleString];
[bannerTextField setStringValue: (bannerString == NULL) ? @"" : bannerString];
if (promptCount > 0) {
// Resize the prompts matrix
NSSize spacingSize = { 0, ResponseSpacing };
[promptsMatrix setIntercellSpacing: spacingSize];
[promptsMatrix renewRows: promptCount columns: 1];
[promptsMatrix sizeToCells];
} else {
// if there are no prompts, hide everything related to them
[promptsMatrix setHidden: YES];
[promptsMatrix setEnabled: FALSE];
[responsesBox setHidden: YES];
[cancelButton setHidden: YES];
[cancelButton setEnabled: FALSE];
}
// Resize the window to hold the new cells.
// The matrix cells will automatically be moved down.
NSSize windowSize = baseWindowSize;
if (promptCount > 0) {
windowSize.height += ((singlePromptHeight * [promptsArray count]) +
(PromptSpacing * ([promptsArray count] - 1)));
}
[[self window] setContentSize: windowSize];
// Prompt and Response Text Fields
//
// Note that we can't have an NSMatrix with NSSecureTextFields in it because
// of a bug in NSMatrix (stringValue on the secure text field returns bullets).
for (i = 0; i < promptCount; i++) {
NSTextField *responseTextField = NULL;
Prompt *prompt = [promptsArray objectAtIndex: i];
// Set the prompt
[[promptsMatrix cellAtRow: i column: 0] setObjectValue: [prompt prompt]];
// Create the response text field:
NSRect frameRect = singleResponseFrame;
frameRect.origin.y += ((promptCount - 1) - i) * (PromptSpacing + frameRect.size.height);
if ([prompt secure]) {
NSSecureTextField *responseSecureTextField = [[NSSecureTextField alloc] initWithFrame: frameRect];
[[responseSecureTextField cell] setEchosBullets: YES];
responseTextField = responseSecureTextField;
} else {
responseTextField = [[NSTextField alloc] initWithFrame: frameRect];
}
[responseTextField setEnabled: YES];
[responseTextField setEditable: YES];
[responseTextField setBezeled: YES];
[responseTextField setBezelStyle: NSTextFieldSquareBezel];
[responseTextField setAlignment: NSLeftTextAlignment];
[responseTextField setDrawsBackground: YES];
[responseTextField setBackgroundColor: [NSColor whiteColor]];
[responseTextField setFont: [NSFont systemFontOfSize: 13]];
[responseTextField setStringValue: @""];
[responseTextFieldArray addObject: responseTextField];
[[[self window] contentView] addSubview: responseTextField];
if (i == 0) {
[[self window] setInitialFirstResponder: responseTextField];
} else {
// chain up the text field so we can tab between them
[[responseTextFieldArray objectAtIndex: i - 1] setNextKeyView: responseTextField];
}
[responseTextField release];
}
// connect the last text field to the first one
if (promptCount > 1) {
[[responseTextFieldArray objectAtIndex: promptCount - 1] setNextKeyView:
[responseTextFieldArray objectAtIndex: 0]];
}
}
#pragma mark -- Actions --
// ---------------------------------------------------------------------------
- (IBAction) ok: (id) sender
{
unsigned int i;
for (i = 0; i < [promptsArray count]; i++) {
NSTextField *responseTextField = [responseTextFieldArray objectAtIndex: i];
Prompt *prompt = [promptsArray objectAtIndex: i];
[prompt setResponse: [responseTextField stringValue]];
}
[self stopWithCode: klNoErr];
}
// ---------------------------------------------------------------------------
- (IBAction) cancel: (id) sender
{
[self stopWithCode: klUserCanceledErr];
}
#pragma mark -- Miscellaneous --
// ---------------------------------------------------------------------------
- (int) runWindow
{
isSheet = NO;
[[NSApp delegate] addActiveWindow: [self window]];
[[self window] center];
[self showWindow: self];
[NSApp run];
[self close];
[[NSApp delegate] removeActiveWindow: [self window]];
return result;
}
// ---------------------------------------------------------------------------
- (int) runSheetModalForWindow: (NSWindow *) parentWindow
{
isSheet = YES;
[NSApp beginSheet: [self window]
modalForWindow: parentWindow
modalDelegate: self
didEndSelector: NULL
contextInfo: NULL];
int err = [NSApp runModalForWindow: [self window]];
[self close];
return err;
}
// ---------------------------------------------------------------------------
- (void) stopWithCode: (int) returnCode
{
if (isSheet) {
[NSApp endSheet: [self window] returnCode: returnCode];
[NSApp stopModalWithCode: returnCode];
} else {
result = returnCode;
[NSApp stop: self];
}
}
// ---------------------------------------------------------------------------
- (BOOL) worksWhenModal
{
return YES;
}
@end