KIM Identity selection dialog work. Updated to match changes to KIM API
authorJustin Anderson <jander@mit.edu>
Tue, 23 Sep 2008 22:20:04 +0000 (22:20 +0000)
committerJustin Anderson <jander@mit.edu>
Tue, 23 Sep 2008 22:20:04 +0000 (22:20 +0000)
ticket: 6055

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20748 dc483132-0cff-0310-8789-dd5450dbe970

src/kim/agent/mac/Identities.h
src/kim/agent/mac/Identities.m
src/kim/agent/mac/KerberosAgentController.m
src/kim/agent/mac/KerberosFormatters.h [new file with mode: 0644]
src/kim/agent/mac/KerberosFormatters.m [new file with mode: 0644]
src/kim/agent/mac/SelectIdentityController.h
src/kim/agent/mac/SelectIdentityController.m
src/kim/agent/mac/resources/English.lproj/SelectIdentity.xib

index 556d0b07500b64411c2c35967046962b355a97a3..82819f8ee2c622671f5e3be574a0be18033bccf3 100644 (file)
@@ -22,6 +22,8 @@
  * or implied warranty.
  */
 
+#import <Cocoa/Cocoa.h>
+
 @interface Identity : NSObject {
     kim_identity kimIdentity;
     int state;
@@ -29,6 +31,8 @@
     int favorite;
     
 }
+@property(readonly) NSString *principal;
+@property(readonly) NSString *timeRemaining;
 @property           int       state;
 @property           cc_time_t expirationTime;
 @property(readonly) int       favorite;
@@ -47,7 +51,7 @@
     NSConnection *threadConnection;
 
 }
-@property(readonly) NSArray *identities;
+@property(readonly, copy) NSArray *identities;
 
 - (int) update;
 
index f950bc13e37661910f63dab30b0fd8d377eb6a96..211d980ee92074a6c1edb319d29e52a8724e0478 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #import "Identities.h"
+#import <Kerberos/kim.h>
 
 @implementation Identity
 
     return (!err && kim_comparison_is_equal_to (comparison));
 }
 
+// ---------------------------------------------------------------------------
+
+- (NSString *)principal
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_string display_string = NULL;
+    NSString *result = nil;
+    
+    err = kim_identity_get_display_string(kimIdentity, &display_string);
+    
+    if (!err) {
+        result = [NSString stringWithCString:display_string encoding:NSUTF8StringEncoding];
+    }
+    else {
+        result = @"-";
+    }
+    return result;
+}
+
+// ---------------------------------------------------------------------------
+
+- (NSDate *)expirationDate
+{
+    return [NSDate dateWithTimeIntervalSince1970:expirationTime];
+}
+
+// ---------------------------------------------------------------------------
+
+- (NSString *)timeRemaining
+{
+    NSString *result = nil;
+    
+    if (expirationTime > 0) {
+       time_t now = time(NULL);
+       time_t lifetime = expirationTime - now;
+       time_t seconds  = (lifetime % 60);
+       time_t minutes  = (lifetime / 60 % 60);
+       time_t hours    = (lifetime / 3600 % 24);
+       time_t days     = (lifetime / 86400);
+       
+       if (seconds >  0) { seconds = 0; minutes++; }
+       if (minutes > 59) { minutes = 0; hours++; }
+       if (hours   > 23) { hours   = 0; days++; }
+       
+       result = [NSString stringWithFormat:@"%02ld:%02ld", hours, minutes];
+    } else {
+       result = @"Expired";
+    }
+    
+    
+    NSLog(@"timeRemaining = %@ (expirationTime == %ld)", result, expirationTime);
+    return result;
+}
+
+- (NSString *)description
+{
+    NSString *result = nil;
+    kim_error err = KIM_NO_ERROR;
+    kim_string display_name = NULL;
+
+    err = kim_identity_get_display_string(kimIdentity, &display_name);
+    
+    if (!err) {
+        result = [NSString stringWithCString:display_name encoding:NSUTF8StringEncoding];
+    }
+    return result;
+}
+
+@end
+
+@interface Identities ()
+
+@property(readwrite, copy) NSArray *identities;
+
 @end
 
 @implementation Identities
         }
         
         if (!err) {
-            kim_favorite_identities kimFavoriteIdentities = NULL;
+            kim_preferences kimPreferences = NULL;
+            kim_options kimOptions = NULL;
             kim_count i;
             kim_count count = 0;
             
-            err = kim_favorite_identities_create (&kimFavoriteIdentities);
+            err = kim_preferences_create(&kimPreferences);
             
             if (!err) {
-                err = kim_favorite_identities_get_number_of_identities (kimFavoriteIdentities,
+                err = kim_preferences_get_number_of_favorite_identities(kimPreferences,
                                                                         &count);
             }
             
                 kim_identity kimIdentity = NULL;
                 Identity *identity = NULL;
                 
-                err = kim_favorite_identities_get_identity_at_index (kimFavoriteIdentities, 
-                                                                     i, &kimIdentity);
+                err = kim_preferences_get_favorite_identity_at_index(kimPreferences,
+                                                                     i,
+                                                                     &kimIdentity,
+                                                                     &kimOptions);
                 
                 if (!err) {
                     identity = [[[Identity alloc] initWithFavoriteIdentity: kimIdentity] autorelease];
                 kim_identity_free (&kimIdentity);
             }
         
-            kim_favorite_identities_free (&kimFavoriteIdentities);
+            kim_preferences_free(&kimPreferences);
         }
         
         if (!err) {
             }
             
             if (!err) {
-                [identity setState: state];
-                [identity setExpirationTime: expirationTime];
+                identity.state = state;
+                identity.expirationTime = expirationTime;
             }
         }
         
     }
 
     if (!err) {
-        if (identities) { [identities release]; }
-        
-        identities = [[NSArray alloc] initWithArray: newIdentities];
+        /* Use @property setter to trigger KVO notifications */
+        self.identities = newIdentities;
         if (!identities) { err = ENOMEM; }            
     }
     
index 9313a8c14d8546a111f552d8b263d0f0d6267322..20b74015a3963ff8efea3bbed154343e855f6a18 100644 (file)
@@ -34,7 +34,9 @@
 {
     SelectIdentityController *controller = [[SelectIdentityController alloc] init];
     int result = [controller runWindow];
-
+    if (result != 0) {
+       NSLog(@"SelectIdentityController -runWindow result was %d", result);
+    }
 
 }
 
diff --git a/src/kim/agent/mac/KerberosFormatters.h b/src/kim/agent/mac/KerberosFormatters.h
new file mode 100644 (file)
index 0000000..2d5336f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 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 <Cocoa/Cocoa.h>
+
+
+@interface KerberosTimeFormatter : NSFormatter {
+
+}
+
+- (NSString *)stringForObjectValue:(id)anObject;
+
+- (BOOL)getObjectValue:(id *)anObject 
+            forString:(NSString *)string 
+      errorDescription:(NSString **)error;
+
+- (NSAttributedString *)attributedStringForObjectValue:(id)anObject 
+                                withDefaultAttributes:(NSDictionary *)attributes;
+@end
diff --git a/src/kim/agent/mac/KerberosFormatters.m b/src/kim/agent/mac/KerberosFormatters.m
new file mode 100644 (file)
index 0000000..e1675bb
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2008 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 "KerberosFormatters.h"
+
+#define EXPIRED_STRING @"Expired"
+
+@implementation KerberosTimeFormatter
+
+/*
+ * For display of Kerberos expiration times.
+ * Converts an NSDate into an NSString like "09:53" for 9 hours and 53 minutes
+ * in the future. Returns @"Expired" if expiration date is before now.
+ */
+- (NSString *)stringForObjectValue:(id)anObject
+{
+    NSString *result = nil;
+    if (anObject == nil || ![anObject respondsToSelector:@selector(timeIntervalSince1970)]) {
+       result = [NSString stringWithFormat:@"%s given invalid object %@", 
+                  _cmd, NSStringFromClass([anObject class])];
+    }
+    else {
+       time_t lifetime = [(NSDate *)anObject timeIntervalSince1970] - time(NULL);
+       
+       if (lifetime > 0) {
+           time_t seconds  = (lifetime % 60);
+           time_t minutes  = (lifetime / 60 % 60);
+           time_t hours    = (lifetime / 3600 % 24);
+           time_t days     = (lifetime / 86400);
+           
+           if (seconds >  0) { seconds = 0; minutes++; }
+           if (minutes > 59) { minutes = 0; hours++; }
+           if (hours   > 23) { hours   = 0; days++; }
+           
+           result = [NSString stringWithFormat:@"%02ld:%02ld", hours, minutes];
+       } else {
+           result = EXPIRED_STRING;
+       }
+    }
+    
+    return result;
+}
+
+/*
+ * Converts NSStrings like @"09:53" into NSDate representation of that point 
+ * in the future. If string is @"Expired", NSDate is set to 1970.
+ */
+
+- (BOOL)getObjectValue:(id *)anObject 
+            forString:(NSString *)string 
+      errorDescription:(NSString **)error
+{
+    NSArray *tokens = [string componentsSeparatedByString:@":"];
+    *anObject = nil;
+    
+    if ([tokens count] == 2) {
+       NSInteger hours = [[tokens objectAtIndex:0] longValue];
+       NSInteger minutes = [[tokens objectAtIndex:1] longValue];
+       *anObject = [NSDate dateWithTimeIntervalSince1970:(hours * 60 * 60) + (minutes * 60)];
+    } else if ([string isEqualToString:EXPIRED_STRING]) {
+       *anObject = [NSDate dateWithTimeIntervalSince1970:0];
+    }
+    
+    if (*anObject == nil) {
+       return false;
+    }
+    return true;
+}
+
+- (NSAttributedString *)attributedStringForObjectValue:(id)anObject 
+                                withDefaultAttributes:(NSDictionary *)attributes
+{
+    NSAttributedString *resultString = nil;
+    NSString *plainString = [self stringForObjectValue:anObject];
+    NSMutableDictionary *newAttributes = [attributes mutableCopy];
+    
+    if ([plainString isEqualToString:EXPIRED_STRING]) {
+       [newAttributes setObject:[NSColor redColor] 
+                         forKey:NSForegroundColorAttributeName];
+       [newAttributes setObject: [NSNumber numberWithFloat: 0.3]
+                         forKey: NSObliquenessAttributeName];
+    }
+    
+    resultString = [[NSAttributedString alloc] initWithString:plainString attributes:newAttributes];
+    [newAttributes release];
+    
+    return [resultString autorelease];
+}
+@end
index 7fd4025e8dffea0e5c281be33691e2eec19a8518..741f897f6b5c3ea5dd78a12c459717351c5a6264 100644 (file)
 
 #import <Cocoa/Cocoa.h>
 #import "BadgedImageView.h"
-
+#import "Identities.h"
 
 @interface SelectIdentityController : NSWindowController {
 
+    IBOutlet NSArrayController *identityArrayController;
+    
     IBOutlet BadgedImageView *kerberosIconImageView;
     IBOutlet NSTextField *headerTextField;
     IBOutlet NSTextField *explanationTextField;
@@ -39,6 +41,9 @@
     IBOutlet NSButton *removeIdentityButton;
     IBOutlet NSButton *selectIdentityButton;
     IBOutlet NSButton *cancelButton;
+    
+    Identities *identities;
+    NSTimer *refreshTimer;
 }
 
 - (IBAction) add: (id) sender;
@@ -49,4 +54,6 @@
 
 - (int) runWindow;
 
+- (void) timedRefresh:(NSTimer *)timer;
+
 @end
index ac3dc07265aa876c98e7f56941680a5d58d8f4f9..e7453a90621710f1086ad2a0cb19506091257fc9 100644 (file)
 {
     if ((self = [super initWithWindowNibName: windowNibName])) {
         NSLog (@"SelectIdentityController initializing");
-        
+        identities = [[Identities alloc] init];
+        [identities addObserver:self 
+                     forKeyPath:@"identities" 
+                        options:NSKeyValueObservingOptionNew 
+                        context:@"SelectIdentityController"];
+        refreshTimer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(timedRefresh:) userInfo:nil repeats:true];
     }
     
     return self;
@@ -50,6 +55,9 @@
 
 - (void) dealloc
 {
+    [refreshTimer release];
+    [identities removeObserver:self forKeyPath:@"identities"];
+    [identities release];
     [super dealloc];
 }
 
 
 - (void) windowDidLoad
 {
-    [explanationTextField setStringValue: @"Some explanation text"];    
+    
+    [explanationTextField setStringValue: @"Some explanation text"];
+    
 }    
 
 // ---------------------------------------------------------------------------
 
 - (IBAction) add: (id) sender
 {
+    NSLog(@"Add identity");
 }
 
 // ---------------------------------------------------------------------------
 
 - (IBAction) remove: (id) sender
 {
+    NSLog(@"Remove identity");
 }
 
 // ---------------------------------------------------------------------------
 
 - (IBAction) select: (id) sender
 {
+    NSLog(@"Select identity: %@", identityArrayController.selectedObjects.description);
 }
 
 // ---------------------------------------------------------------------------
 
 - (IBAction) cancel: (id) sender
 {
+    NSLog(@"Cancel identity selection");
 }
 
 // ---------------------------------------------------------------------------
     return 0;
 }
 
+// ---------------------------------------------------------------------------
+
+- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    if ([(NSString *)context isEqualToString:@"SelectIdentityController"]) {
+        NSLog(@"========== identities array changed ==========");
+        identityArrayController.content = [[identities.identities mutableCopy] autorelease];
+    }
+    else {
+        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+    }
+}
+
+- (void) timedRefresh:(NSTimer *)timer
+{
+    [identityArrayController rearrangeObjects];
+}
+
 
 @end
index 938c633622850c684976dbccb4ebf3e5abab73c0..8e912b20398c0277e5c3a4d91ffa87597af4115b 100644 (file)
@@ -2,9 +2,9 @@
 <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02">
        <data>
                <int key="IBDocument.SystemTarget">1050</int>
-               <string key="IBDocument.SystemVersion">9E17</string>
-               <string key="IBDocument.InterfaceBuilderVersion">670</string>
-               <string key="IBDocument.AppKitVersion">949.33</string>
+               <string key="IBDocument.SystemVersion">9F33</string>
+               <string key="IBDocument.InterfaceBuilderVersion">672</string>
+               <string key="IBDocument.AppKitVersion">949.34</string>
                <string key="IBDocument.HIToolboxVersion">352.00</string>
                <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
                        <bool key="EncodedWithXMLCoder">YES</bool>
                                                                                        <object class="NSMutableArray" key="NSTableColumns">
                                                                                                <bool key="EncodedWithXMLCoder">YES</bool>
                                                                                                <object class="NSTableColumn" id="697375404">
+                                                                                                       <string key="NSIdentifier">principal</string>
                                                                                                        <double key="NSWidth">3.429741e+02</double>
                                                                                                        <double key="NSMinWidth">1.499741e+02</double>
                                                                                                        <double key="NSMaxWidth">1.000000e+03</double>
                                                                                                        <reference key="NSTableView" ref="988096643"/>
                                                                                                </object>
                                                                                                <object class="NSTableColumn" id="1004662124">
+                                                                                                       <string key="NSIdentifier">timeRemaining</string>
                                                                                                        <double key="NSWidth">1.003135e+02</double>
                                                                                                        <double key="NSMinWidth">1.000000e+02</double>
                                                                                                        <double key="NSMaxWidth">1.500000e+02</double>
                                                                                                        </object>
                                                                                                        <object class="NSTextFieldCell" key="NSDataCell" id="618557697">
                                                                                                                <int key="NSCellFlags">1140981312</int>
-                                                                                                               <int key="NSCellFlags2">71435264</int>
+                                                                                                               <int key="NSCellFlags2">-2076048384</int>
                                                                                                                <string key="NSContents">Text Cell</string>
                                                                                                                <reference key="NSSupport" ref="26"/>
                                                                                                                <reference key="NSControlView" ref="988096643"/>
                                                <object class="NSButton" id="818868322">
                                                        <reference key="NSNextResponder" ref="928852707"/>
                                                        <int key="NSvFlags">292</int>
-                                                       <string key="NSFrame">{{42, 30}, {22, 22}}</string>
+                                                       <string key="NSFrame">{{43, 30}, {22, 22}}</string>
                                                        <reference key="NSSuperview" ref="928852707"/>
                                                        <bool key="NSEnabled">YES</bool>
                                                        <object class="NSButtonCell" key="NSCell" id="872529405">
                                <string key="NSMinSize">{419, 320}</string>
                                <string key="NSMaxSize">{600, 622}</string>
                        </object>
+                       <object class="NSArrayController" id="333357907">
+                               <object class="NSMutableArray" key="NSDeclaredKeys">
+                                       <bool key="EncodedWithXMLCoder">YES</bool>
+                                       <string>timeRemaining</string>
+                                       <string>principal</string>
+                                       <string>isFavorite</string>
+                                       <string>description</string>
+                                       <string>expirationDate</string>
+                               </object>
+                               <bool key="NSEditable">YES</bool>
+                               <object class="_NSManagedProxy" key="_NSManagedProxy"/>
+                               <bool key="NSAvoidsEmptySelection">YES</bool>
+                               <bool key="NSPreservesSelection">YES</bool>
+                               <bool key="NSSelectsInsertedObjects">YES</bool>
+                               <bool key="NSFilterRestrictsInsertion">YES</bool>
+                               <bool key="NSClearsFilterPredicateOnInsertion">YES</bool>
+                       </object>
+                       <object class="NSCustomObject" id="307777557">
+                               <string key="NSClassName">KerberosTimeFormatter</string>
+                       </object>
                </object>
                <object class="IBObjectContainer" key="IBDocument.Objects">
                        <object class="NSMutableArray" key="connectionRecords">
                                        </object>
                                        <int key="connectionID">300169</int>
                                </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">remove:</string>
-                                               <reference key="source" ref="262677138"/>
-                                               <reference key="destination" ref="818868322"/>
-                                       </object>
-                                       <int key="connectionID">300170</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">add:</string>
-                                               <reference key="source" ref="262677138"/>
-                                               <reference key="destination" ref="774532696"/>
-                                       </object>
-                                       <int key="connectionID">300171</int>
-                               </object>
                                <object class="IBConnectionRecord">
                                        <object class="IBOutletConnection" key="connection">
                                                <string key="label">identityTableView</string>
                                        </object>
                                        <int key="connectionID">300181</int>
                                </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBOutletConnection" key="connection">
+                                               <string key="label">identityArrayController</string>
+                                               <reference key="source" ref="262677138"/>
+                                               <reference key="destination" ref="333357907"/>
+                                       </object>
+                                       <int key="connectionID">300184</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBBindingConnection" key="connection">
+                                               <string key="label">content: arrangedObjects</string>
+                                               <reference key="source" ref="988096643"/>
+                                               <reference key="destination" ref="333357907"/>
+                                               <object class="NSNibBindingConnector" key="connector" id="355877009">
+                                                       <reference key="NSSource" ref="988096643"/>
+                                                       <reference key="NSDestination" ref="333357907"/>
+                                                       <string key="NSLabel">content: arrangedObjects</string>
+                                                       <string key="NSBinding">content</string>
+                                                       <string key="NSKeyPath">arrangedObjects</string>
+                                                       <int key="NSNibBindingConnectorVersion">2</int>
+                                               </object>
+                                       </object>
+                                       <int key="connectionID">300185</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBBindingConnection" key="connection">
+                                               <string key="label">value: arrangedObjects.principal</string>
+                                               <reference key="source" ref="697375404"/>
+                                               <reference key="destination" ref="333357907"/>
+                                               <object class="NSNibBindingConnector" key="connector">
+                                                       <reference key="NSSource" ref="697375404"/>
+                                                       <reference key="NSDestination" ref="333357907"/>
+                                                       <string key="NSLabel">value: arrangedObjects.principal</string>
+                                                       <string key="NSBinding">value</string>
+                                                       <string key="NSKeyPath">arrangedObjects.principal</string>
+                                                       <int key="NSNibBindingConnectorVersion">2</int>
+                                               </object>
+                                       </object>
+                                       <int key="connectionID">300187</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBActionConnection" key="connection">
+                                               <string key="label">remove:</string>
+                                               <reference key="source" ref="333357907"/>
+                                               <reference key="destination" ref="818868322"/>
+                                       </object>
+                                       <int key="connectionID">300189</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBActionConnection" key="connection">
+                                               <string key="label">insert:</string>
+                                               <reference key="source" ref="333357907"/>
+                                               <reference key="destination" ref="774532696"/>
+                                       </object>
+                                       <int key="connectionID">300191</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBOutletConnection" key="connection">
+                                               <string key="label">formatter</string>
+                                               <reference key="source" ref="618557697"/>
+                                               <reference key="destination" ref="307777557"/>
+                                       </object>
+                                       <int key="connectionID">300197</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBBindingConnection" key="connection">
+                                               <string key="label">value: arrangedObjects.expirationDate</string>
+                                               <reference key="source" ref="1004662124"/>
+                                               <reference key="destination" ref="333357907"/>
+                                               <object class="NSNibBindingConnector" key="connector">
+                                                       <reference key="NSSource" ref="1004662124"/>
+                                                       <reference key="NSDestination" ref="333357907"/>
+                                                       <string key="NSLabel">value: arrangedObjects.expirationDate</string>
+                                                       <string key="NSBinding">value</string>
+                                                       <string key="NSKeyPath">arrangedObjects.expirationDate</string>
+                                                       <object class="NSDictionary" key="NSOptions">
+                                                               <string key="NS.key.0">NSConditionallySetsEditable</string>
+                                                               <integer value="0" key="NS.object.0"/>
+                                                       </object>
+                                                       <int key="NSNibBindingConnectorVersion">2</int>
+                                               </object>
+                                       </object>
+                                       <int key="connectionID">300198</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBBindingConnection" key="connection">
+                                               <string key="label">selectionIndexes: selectionIndexes</string>
+                                               <reference key="source" ref="988096643"/>
+                                               <reference key="destination" ref="333357907"/>
+                                               <object class="NSNibBindingConnector" key="connector">
+                                                       <reference key="NSSource" ref="988096643"/>
+                                                       <reference key="NSDestination" ref="333357907"/>
+                                                       <string key="NSLabel">selectionIndexes: selectionIndexes</string>
+                                                       <string key="NSBinding">selectionIndexes</string>
+                                                       <string key="NSKeyPath">selectionIndexes</string>
+                                                       <reference key="NSPreviousConnector" ref="355877009"/>
+                                                       <int key="NSNibBindingConnectorVersion">2</int>
+                                               </object>
+                                       </object>
+                                       <int key="connectionID">300199</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBBindingConnection" key="connection">
+                                               <string key="label">enabled: canRemove</string>
+                                               <reference key="source" ref="818868322"/>
+                                               <reference key="destination" ref="333357907"/>
+                                               <object class="NSNibBindingConnector" key="connector">
+                                                       <reference key="NSSource" ref="818868322"/>
+                                                       <reference key="NSDestination" ref="333357907"/>
+                                                       <string key="NSLabel">enabled: canRemove</string>
+                                                       <string key="NSBinding">enabled</string>
+                                                       <string key="NSKeyPath">canRemove</string>
+                                                       <int key="NSNibBindingConnectorVersion">2</int>
+                                               </object>
+                                       </object>
+                                       <int key="connectionID">300200</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBBindingConnection" key="connection">
+                                               <string key="label">enabled: canInsert</string>
+                                               <reference key="source" ref="774532696"/>
+                                               <reference key="destination" ref="333357907"/>
+                                               <object class="NSNibBindingConnector" key="connector">
+                                                       <reference key="NSSource" ref="774532696"/>
+                                                       <reference key="NSDestination" ref="333357907"/>
+                                                       <string key="NSLabel">enabled: canInsert</string>
+                                                       <string key="NSBinding">enabled</string>
+                                                       <string key="NSKeyPath">canInsert</string>
+                                                       <int key="NSNibBindingConnectorVersion">2</int>
+                                               </object>
+                                       </object>
+                                       <int key="connectionID">300201</int>
+                               </object>
                        </object>
                        <object class="IBMutableOrderedSet" key="objectRecords">
                                <object class="NSArray" key="orderedObjects">
                                                <reference key="object" ref="700535463"/>
                                                <reference key="parent" ref="928852707"/>
                                        </object>
+                                       <object class="IBObjectRecord">
+                                               <int key="objectID">300183</int>
+                                               <reference key="object" ref="333357907"/>
+                                               <reference key="parent" ref="0"/>
+                                               <string key="objectName">Identity Array Controller</string>
+                                       </object>
+                                       <object class="IBObjectRecord">
+                                               <int key="objectID">300196</int>
+                                               <reference key="object" ref="307777557"/>
+                                               <reference key="parent" ref="0"/>
+                                       </object>
                                </object>
                        </object>
                        <object class="NSMutableDictionary" key="flattenedProperties">
                                        <string>300154.IBPluginDependency</string>
                                        <string>300155.IBPluginDependency</string>
                                        <string>300156.IBPluginDependency</string>
+                                       <string>300183.IBPluginDependency</string>
+                                       <string>300196.IBPluginDependency</string>
                                        <string>5.IBEditorWindowLastContentRect</string>
                                        <string>5.IBPluginDependency</string>
                                        <string>5.IBWindowTemplateEditedContentRect</string>
                                        <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
                                        <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
                                        <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-                                       <string>{{606, 810}, {491, 315}}</string>
                                        <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-                                       <string>{{606, 810}, {491, 315}}</string>
+                                       <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+                                       <string>{{606, 541}, {491, 315}}</string>
+                                       <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+                                       <string>{{606, 541}, {491, 315}}</string>
                                        <reference ref="5"/>
                                        <reference ref="5"/>
                                        <string>{{503, 256}, {419, 465}}</string>
                                </object>
                        </object>
                        <nil key="sourceID"/>
-                       <int key="maxID">300182</int>
+                       <int key="maxID">300201</int>
                </object>
                <object class="IBClassDescriber" key="IBDocument.Classes">
                        <object class="NSMutableArray" key="referencedPartialClassDescriptions">
                                                <string key="minorKey"/>
                                        </object>
                                </object>
+                               <object class="IBPartialClassDescription">
+                                       <string key="className">KerberosTimeFormatter</string>
+                                       <string key="superclassName">NSFormatter</string>
+                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
+                                               <string key="majorKey">IBProjectSource</string>
+                                               <string key="minorKey">../Sources/kim/agent/mac/KerberosFormatters.h</string>
+                                       </object>
+                               </object>
                                <object class="IBPartialClassDescription">
                                        <string key="className">SelectIdentityController</string>
                                        <string key="superclassName">NSWindowController</string>
                                                        <string>cancelButton</string>
                                                        <string>explanationTextField</string>
                                                        <string>headerTextField</string>
+                                                       <string>identityArrayController</string>
                                                        <string>identityTableColumn</string>
                                                        <string>identityTableView</string>
                                                        <string>kerberosIconImageView</string>
                                                        <string>NSButton</string>
                                                        <string>NSTextField</string>
                                                        <string>NSTextField</string>
+                                                       <string>NSArrayController</string>
                                                        <string>NSTableColumn</string>
                                                        <string>NSTableView</string>
                                                        <string>BadgedImageView</string>
                                                <string key="minorKey">../Sources/kim/agent/mac/SelectIdentityController.h</string>
                                        </object>
                                </object>
+                               <object class="IBPartialClassDescription">
+                                       <string key="className">SelectIdentityController</string>
+                                       <string key="superclassName">NSWindowController</string>
+                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
+                                               <string key="majorKey">IBUserSource</string>
+                                               <string key="minorKey"/>
+                                       </object>
+                               </object>
                        </object>
                </object>
                <int key="IBDocument.localizationMode">0</int>