OSX Launchd Startup Manage with Preference Pane
[openafs.git] / src / platform / DARWIN / AFSPreference / AFSCommanderPref.m
1 //
2 //  AFSCommanderPref.m
3 //  AFSCommander
4 //
5 //  Created by Claudio Bisegni on 10/05/07.
6 //  Copyright (c) 2007 INFN - National Institute of Nuclear Physics. All rights reserved.
7 //
8
9 #import "AFSCommanderPref.h"
10 #import "IpConfiguratorCommander.h"
11 #import "TokenCredentialController.h"
12 #import "InfoController.h"
13 #import "TaskUtil.h"
14 #import "PListManager.h"
15 #import "DialogUtility.h"
16 #import "NSString+search.h"
17 #include <sys/param.h>
18 #include <sys/stat.h>
19 #include <sys/wait.h>
20 #include <sys/types.h>
21 #include <sys/fcntl.h>
22 #include <sys/errno.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #import <CoreServices/CoreServices.h>
27
28
29 #define ADD_CELL_CONTROL_TAG 1
30 #define REMOVE_CELL_CONTROL_TAG 2
31
32 #define TABLE_TOKENS_LIST 1
33 #define TABLE_CELL_LIST 2
34
35 #define TAB_TOKENS 1
36 #define TAB_CELL_SERV_DB 2
37 #define TAB_CACHE 3
38 #define TAB_LINK 4
39
40 //CellServDB table id
41 #define CELLSRVDB_TABLE_USR_DFLT_CHECK_COLUMN   0
42 #define CELLSRVDB_TABLE_DFLT_CHECK_COLUMN               1
43 #define CELLSRVDB_TABLE_NAME_COLUMN                             2
44 #define CELLSRVDB_TABLE_DESCRIPTION_COLUMN              3
45
46 @implementation AFSCommanderPref
47
48 // -------------------------------------------------------------------------------
49 //  initWithBundle:
50 // -------------------------------------------------------------------------------
51 - (id)initWithBundle:(NSBundle *)bundle
52 {
53     if ( ( self = [super initWithBundle:bundle] ) != nil ) {
54         //appID = kAfsCommanderID;
55                 prefStartUp = 1;
56     }
57     return self;
58 }
59
60 // -------------------------------------------------------------------------------
61 //  mainView:
62 // -------------------------------------------------------------------------------
63 - (NSView *) mainView {
64         if (prefStartUp == 1){
65                 SInt32 osxMJVers = 0;
66                 SInt32 osxMnVers = 0;
67                 if (Gestalt(gestaltSystemVersionMajor, &osxMJVers) == noErr && Gestalt(gestaltSystemVersionMinor, &osxMnVers) == noErr) {
68                         if (osxMJVers == 10 && osxMnVers>= 5) {
69                                 [afsCommanderView  setFrameSize:NSMakeSize(668, [afsCommanderView frame].size.height)];
70                 prefStartUp = 0;
71                         }
72                 }
73         }
74         
75     return afsCommanderView;
76 }
77
78 // -------------------------------------------------------------------------------
79 //  mainViewDidLoad:
80 // -------------------------------------------------------------------------------
81 - (void) mainViewDidLoad
82 {
83         //CellServDB Table
84         [((NSTableView*)cellList) setDelegate:self];
85         [((NSTableView*)cellList) setTarget:self];
86         [((NSTableView*)cellList) setDoubleAction:@selector(tableDoubleAction:)];
87         
88         
89 }
90
91 // -------------------------------------------------------------------------------
92 //  didSelect:
93 // -------------------------------------------------------------------------------
94 - (void) didSelect
95 {
96         //try to install the launchd file for backgrounder
97         //Remove launchd ctrl file
98         @try {
99                 [PListManager installBackgrounderLaunchdFile:YES 
100                                                                                 resourcePath:[[self bundle] resourcePath]];
101         }
102         @catch (NSException * e) {
103                 NSDictionary *excecptDic = [e userInfo];
104                 NSNumber *keyNum = [excecptDic objectForKey:@"agent_folder_error"];
105                 if(keyNum && [keyNum boolValue]) {
106                         // the dir HOME_LAUNCHD_AGENT_FOLDER (PListManager.h) must be created
107                         NSBeginAlertSheet([[NSString stringWithString:kDoYouWantCreateTheDirectory] stringByAppendingString:HOME_LAUNCHD_AGENT_FOLDER],
108                                                           @"Create", @"Cancel", nil,                                                                            
109                                                           [[self mainView] window],     self, @selector(credentialAtLoginTimeEventCreationLaunchAgentDir:returnCode:contextInfo:), NULL, 
110                                                           nil, @"", nil);
111                 }
112         }
113         @finally {
114                 
115         }
116         
117         
118         // Set Developer info
119         [textFieldDevInfoLabel setStringValue:kDevelopInfo];
120         // creating the lock
121         tokensLock = [[NSLock alloc] init];
122         
123         //Initialization cellservdb and token list
124         filteredCellDB = nil;
125         tokenList = nil;
126         
127         [self readPreferenceFile];
128                         
129         // alloc the afs property mananger
130         afsProperty = [[AFSPropertyManager alloc] init];
131         
132         // register preference pane to detect menuextra killed by user
133         [[NSDistributedNotificationCenter defaultCenter] addObserver:self
134                                                                                                                 selector:@selector(refreshTokensNotify:)
135                                                                                                                         name:kAfsCommanderID
136                                                                                                                   object:kMExtraTokenOperation];
137          
138         [[NSDistributedNotificationCenter defaultCenter] addObserver:self 
139                                                                                                                 selector:@selector(refreshGui:) 
140                                                                                                                         name:kAfsCommanderID 
141                                                                                                                   object:kMenuExtraEventOccured];
142         
143         //Register for mount/unmount afs volume
144         [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self 
145                                                                                                                    selector:@selector(afsVolumeMountChange:) 
146                                                                                                                            name:NSWorkspaceDidMountNotification object:nil];
147         
148         [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self 
149                                                                                                                    selector:@selector(afsVolumeMountChange:) 
150                                                                                                                            name:NSWorkspaceDidUnmountNotification object:nil];
151         
152         // set self as table data source
153         [((NSTableView*)cellList) setDataSource:self];
154         [((NSTableView*)tokensTable) setDataSource:self];
155         
156         //check the afs state
157         [self setAfsStatus];
158         
159         // let show the configuration after prefpane is open
160         [self refreshConfiguration:nil];
161         
162         // refresh the token list
163         //[self refreshTokens:nil];
164         
165         //refresh table to reflect the NSSearchField contained text
166         [self searchCellTextEvent:nil];
167 }
168
169 // -------------------------------------------------------------------------------
170 //  credentialAtLoginTimeEventCreationLaunchAgentDir:
171 // -------------------------------------------------------------------------------
172 - (void) credentialAtLoginTimeEventCreationLaunchAgentDir:(NSWindow*)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo {
173         [alert close];
174         switch (returnCode) {
175                 case  1:
176                         if([[NSFileManager defaultManager] createDirectoryAtPath:[HOME_LAUNCHD_AGENT_FOLDER stringByExpandingTildeInPath] 
177                                                                                  withIntermediateDirectories:NO
178                                                                                                                   attributes:nil
179                                                                                                                            error:nil]) {
180                                 
181                                 //Create the file
182                                 [PListManager installBackgrounderLaunchdFile:YES
183                                                                                                 resourcePath:[[self bundle] resourcePath]];
184                                 [self showMessage:kDirectoryCreated];
185                         } else {
186                                 [self showMessage:kErrorCreatingDirectory];
187                         }
188                         break;
189                 case 0:
190                         break;
191         }
192 }
193
194
195 // -------------------------------------------------------------------------------
196 //  willUnselect:
197 // -------------------------------------------------------------------------------
198 - (void)willUnselect
199 {
200         // remove self as datasource
201         [((NSTableView*)cellList) setDataSource:nil];
202         [((NSTableView*)tokensTable) setDataSource:nil];
203
204         //release the afs property manager
205         if(afsProperty) [afsProperty release];
206         //release tokens list
207         if(tokenList) [tokenList release];      
208         //Remove the cell temp array
209         if(filteredCellDB) [filteredCellDB release];
210         
211         [self writePreferenceFile];
212         
213         // unregister preference pane to detect menuextra killed by user
214         [[NSDistributedNotificationCenter defaultCenter] removeObserver:self
215                                                                                                                            name:kAfsCommanderID
216                                                                                                                          object:kMExtraClosedNotification];
217         [[NSDistributedNotificationCenter defaultCenter] removeObserver:self
218                                                                                                                            name:kAfsCommanderID
219                                                                                                                          object:kMExtraTokenOperation];
220         [[NSDistributedNotificationCenter defaultCenter] removeObserver:self
221                                                                                                                            name:kAfsCommanderID
222                                                                                                                          object:kMenuExtraEventOccured];
223         [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self 
224                                                                                                                                   name:NSWorkspaceDidMountNotification object:nil];
225         [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self 
226                                                                                                                                   name:NSWorkspaceDidUnmountNotification object:nil];
227         
228         [self stopTimer];
229         [tokensLock release];
230 }
231
232
233 // -------------------------------------------------------------------------------
234 //  startTimer:
235 // -------------------------------------------------------------------------------
236 - (void)startTimer{
237         //start the time for check tokens validity
238         if(timerForCheckTokensList) return;
239         timerForCheckTokensList = [NSTimer scheduledTimerWithTimeInterval:TOKENS_REFRESH_TIME_IN_SEC 
240                                                                                                                            target:self 
241                                                                                                                          selector:@selector(refreshTokens:) 
242                                                                                                                          userInfo:nil 
243                                                                                                                           repeats:YES];
244         [timerForCheckTokensList fire]; 
245 }
246
247 // -------------------------------------------------------------------------------
248 //  stopTimer:
249 // -------------------------------------------------------------------------------
250 - (void)stopTimer{
251         if(!timerForCheckTokensList) return;
252         [timerForCheckTokensList invalidate];   
253         timerForCheckTokensList = nil;
254 }
255
256
257 // -------------------------------------------------------------------------------
258 //  readPreferenceFile:
259 // -------------------------------------------------------------------------------
260 - (void) readPreferenceFile
261 {
262         
263         // read the preference for aklog use
264         NSNumber *useAklogPrefValue = (NSNumber*)CFPreferencesCopyValue((CFStringRef)PREFERENCE_USE_AKLOG, (CFStringRef)kAfsCommanderID,  
265                                                                                                                                         kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
266         NSNumber *aklogTokenAtLogin = (NSNumber*)CFPreferencesCopyValue((CFStringRef)PREFERENCE_AKLOG_TOKEN_AT_LOGIN, (CFStringRef)kAfsCommanderID,  
267                                                                                                                                         kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
268         [useAklogCheck setState:[useAklogPrefValue intValue]];
269         [aklogCredentialAtLoginTime setEnabled:useAklogPrefValue && [useAklogPrefValue boolValue]];
270         [aklogCredentialAtLoginTime setState:aklogTokenAtLogin && [aklogTokenAtLogin boolValue]];
271
272         //check krb5 at login time
273         [installKRB5AuthAtLoginButton setState:[PListManager checkKrb5AtLoginTimeLaunchdEnable]];
274
275         //check for AFS enable at startup
276         NSNumber *afsEnableStartupTime = (NSNumber*)CFPreferencesCopyValue((CFStringRef)PREFERENCE_START_AFS_AT_STARTUP, 
277                                                                                                                                            (CFStringRef)kAfsCommanderID,  kCFPreferencesAnyUser, kCFPreferencesAnyHost);
278         if(afsEnableStartupTime) 
279                 startAFSAtLogin = [afsEnableStartupTime boolValue];
280         else 
281                 startAFSAtLogin = false;
282         //set the check button state
283         [checkButtonAfsAtBootTime setState:startAFSAtLogin];
284         
285         NSNumber *showStatusMenu =  (NSNumber*)CFPreferencesCopyValue((CFStringRef)PREFERENCE_SHOW_STATUS_MENU,  (CFStringRef)kAfsCommanderID,  kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
286         [(NSButton*)afsMenucheckBox setState: [showStatusMenu boolValue]];
287         
288         //backgrounder state
289         [backgrounderActivationCheck setState:[PListManager launchdJobState:BACKGROUNDER_P_FILE]];
290 }
291
292 // -------------------------------------------------------------------------------
293 //  willUnselect:
294 // -------------------------------------------------------------------------------
295 - (void) writePreferenceFile
296 {
297         //Set the preference for afs path
298         /*CFPreferencesSetValue((CFStringRef)PREFERENCE_AFS_SYS_PAT, 
299                                                   (CFStringRef)[((NSTextField*) installationPathTextField ) stringValue], 
300                                                   (CFStringRef)kAfsCommanderID, kCFPreferencesAnyUser, kCFPreferencesAnyHost);*/
301         
302         //Set the preference for aklog use
303         CFPreferencesSetValue((CFStringRef)PREFERENCE_USE_AKLOG, 
304                                                   (CFNumberRef)[NSNumber numberWithInt:[useAklogCheck state]], 
305                                                   (CFStringRef)kAfsCommanderID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
306
307         //set AFS enable state at startup
308         CFPreferencesSetValue((CFStringRef)PREFERENCE_START_AFS_AT_STARTUP, 
309                                                   (CFNumberRef)[NSNumber numberWithBool:startAFSAtLogin], 
310                                                   (CFStringRef)kAfsCommanderID, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
311         
312         //set aklog at login
313         CFPreferencesSetValue((CFStringRef)PREFERENCE_AKLOG_TOKEN_AT_LOGIN, 
314                                                   (CFNumberRef)[NSNumber numberWithBool:[aklogCredentialAtLoginTime state]], 
315                                                   (CFStringRef)kAfsCommanderID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
316         
317         //set aklog at login
318         CFPreferencesSetValue((CFStringRef)PREFERENCE_SHOW_STATUS_MENU, 
319                                                   (CFNumberRef)[NSNumber numberWithBool:[afsMenucheckBox state]], 
320                                                   (CFStringRef)kAfsCommanderID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
321         
322         CFPreferencesSynchronize((CFStringRef)kAfsCommanderID,  kCFPreferencesAnyUser, kCFPreferencesAnyHost);
323         CFPreferencesSynchronize((CFStringRef)kAfsCommanderID,  kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
324         
325         [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kAFSMenuExtraID object:kPrefChangeNotification];
326 }
327
328 // -------------------------------------------------------------------------------
329 //  saveConfiguration:
330 // -------------------------------------------------------------------------------
331 - (IBAction) saveConfiguration:(id) sender
332 {
333         @try{
334                 
335                 //[afsProperty setCellName:[cellNameTextEdit stringValue]];
336                 [afsProperty setCellName:[afsProperty getDefaultCellName]];
337                 
338                 //save configurations
339                 [afsProperty saveConfigurationFiles:YES];
340                 
341                 
342                 //Reload all configuration
343                 [self refreshConfiguration:nil];
344                 
345                 //refresh table to reflect the NSSearchField contained text
346                 [self searchCellTextEvent:nil];
347                 
348                 //Show dialog for notifity al saving process ar gone ell
349                 [self showMessage:kConfigurationSaved];
350         }@catch(NSException *e){
351                 [self showMessage:[e reason]];
352         } @finally {
353                 [((NSTableView*)cellList) reloadData];
354         }
355         
356 }
357
358 // -------------------------------------------------------------------------------
359 //  saveCacheManagerParam:
360 // -------------------------------------------------------------------------------
361 - (IBAction) saveCacheManagerParam:(id) sender
362 {
363         @try{
364                 //Update the value form view to afs property manager class
365                 [self updateCacheParamFromView];
366                 [afsProperty saveCacheConfigurationFiles:YES];
367                 [self showMessage:kSavedCacheConfiguration];
368         }@catch(NSException *e){
369                 [self showMessage:[e reason]];
370         } @finally {
371                 [((NSTableView*)cellList) reloadData];
372         }
373 }
374
375 // -------------------------------------------------------------------------------
376 //  refreshConfiguration:
377 // -------------------------------------------------------------------------------
378 - (IBAction) refreshConfiguration:(id) sender
379 {
380         NSString *afsBasePath = PREFERENCE_AFS_SYS_PAT_STATIC;
381         @try{
382                 // set the afs path
383                 [afsProperty setPath:afsBasePath];
384                 
385                 // load configuration
386                 [afsProperty loadConfiguration];
387                 
388                 //set the afs version label
389                 [afsVersionLabel setStringValue:[afsProperty getAfsVersion]];
390                 
391                 //set the current default cell
392                 [afsDefaultCellLabel setStringValue:[afsProperty getDefaultCellName]];
393                 
394                 // Update cache view
395                 [self fillCacheParamView];
396                 
397                 //Filter the cellServDb and allocate filtered array
398                 [self filterCellServDB:nil];
399                 
400         }@catch(NSException *e){
401                 [self showMessage:[e reason]];
402         } @finally {
403                 [((NSTableView*)cellList) reloadData];
404         }
405 }
406
407 // -------------------------------------------------------------------------------
408 //  fillCacheParamView:
409 // -------------------------------------------------------------------------------
410 -(void) fillCacheParamView
411 {
412         [dynRoot setState:[afsProperty dynRoot]?NSOnState:NSOffState];
413         [afsDB setState:[afsProperty afsDB]?NSOnState:NSOffState];
414         [statCacheEntry setIntValue:[afsProperty statCacheEntry]];
415         [dCacheDim setIntValue:[afsProperty dCacheDim]];
416         [cacheDimension setIntValue:[afsProperty cacheDimension]];
417         [daemonNumber setIntValue:[afsProperty daemonNumber]];
418         [afsRootMountPoint setStringValue:[afsProperty afsRootMountPoint]];
419         [nVolEntry setIntValue:[afsProperty nVolEntry]];
420         
421         //new version property
422         //[verbose setEnabled:[afsProperty useAfsdConfConfigFile]];
423         [verbose setState:[afsProperty verbose]?NSOnState:NSOffState];
424         
425 }
426
427 // -------------------------------------------------------------------------------
428 //  updateCacheParamFromView:
429 // -------------------------------------------------------------------------------
430 -(void) updateCacheParamFromView
431 {
432         NSString *tmpAfsPath = [afsRootMountPoint stringValue];
433         if(!tmpAfsPath || ([tmpAfsPath length] == 0) || ([tmpAfsPath characterAtIndex:0] != '/')) 
434                 @throw [NSException exceptionWithName:@"updateCacheParamFromView" 
435                                                                            reason:kBadAfsRootMountPoint
436                                                                          userInfo:nil];
437
438         
439         [afsProperty setDynRoot:[dynRoot state]==NSOnState];
440         [afsProperty setAfsDB:[afsDB state]==NSOnState];
441         [afsProperty setStatCacheEntry:[statCacheEntry intValue]];
442         [afsProperty setDCacheDim:[dCacheDim intValue]]; 
443         [afsProperty setCacheDimension:[cacheDimension intValue]]; 
444         [afsProperty setDaemonNumber:[daemonNumber intValue]];
445         [afsProperty setAfsRootMountPoint:tmpAfsPath];
446         [afsProperty setNVolEntry:[nVolEntry intValue]];
447         [afsProperty setVerbose:[verbose state]==NSOnState];
448 }
449
450
451 // -------------------------------------------------------------------------------
452 //  showCellIP:
453 // -------------------------------------------------------------------------------
454 - (IBAction) showCellIP:(id) sender
455 {
456         int rowSelected = [((NSTableView *) cellList) selectedRow];
457         [self modifyCellByIDX:rowSelected];
458 }
459
460 // -------------------------------------------------------------------------------
461 //  modifyCellByIDX:
462 // -------------------------------------------------------------------------------
463 -(void) modifyCellByIDX:(int) idx
464 {
465         [self modifyCell:[self getCellByIDX:idx]];
466 }
467
468 // -------------------------------------------------------------------------------
469 //  modifyCellByIDX:
470 // -------------------------------------------------------------------------------
471 -(void) modifyCell:(DBCellElement*) cellElement
472 {
473         [NSBundle loadNibNamed:@"IpPanel" owner:self];
474         [((IpConfiguratorCommander*) ipConfControllerCommander) setWorkCell:cellElement];
475         [NSApp beginSheet: ipConfigurationSheet
476            modalForWindow: [[self mainView] window]
477                 modalDelegate: self
478            didEndSelector: @selector(didEndSheet:returnCode:contextInfo:)
479                   contextInfo: nil];
480 }
481
482 // -------------------------------------------------------------------------------
483 //  addMoifyCell:
484 // -------------------------------------------------------------------------------
485 - (IBAction) addRemoveCell:(id) sender
486 {
487         switch([((NSControl*) sender) tag]){
488                 case ADD_CELL_CONTROL_TAG:
489                 {
490                         DBCellElement *newCell = [[DBCellElement alloc] init];
491                         if(!newCell) break;
492                         
493                         [newCell setCellName:kNewCellName];
494                         [newCell setCellComment:kNewCellComment];
495                         //cellArray = ;
496                         [[afsProperty getCellList] addObject:newCell];
497                         [newCell release];
498                         
499                         //Modify new cell
500                         [self modifyCell:newCell];
501                 }
502                 break;
503                         
504                 case REMOVE_CELL_CONTROL_TAG:
505                 {
506                         int index = 0;
507                         NSIndexSet *selectedIndex = [(NSTableView*)cellList selectedRowIndexes];
508                         if( [selectedIndex count] > 0) {
509                                 index = [selectedIndex firstIndex]; 
510                                 do {
511                                         DBCellElement *cellElement =  (DBCellElement*)[filteredCellDB objectAtIndex:index];
512                                         [[afsProperty getCellList] removeObject:cellElement];
513                                 } while ((index = [selectedIndex indexGreaterThanIndex:index]) != NSNotFound);
514                         }
515                 }
516                 break;
517         }
518         //Filter the cellServDb and allocate filtered array
519         [self searchCellTextEvent:nil];
520         [(NSTableView*)cellList deselectAll:nil];
521         [(NSTableView*)cellList reloadData];
522 }
523
524 // -------------------------------------------------------------------------------
525 //  repairHelperTool:
526 // -------------------------------------------------------------------------------
527 - (void) repairHelperTool
528 {
529         struct stat st;
530     int fdTool;
531         int status = 0;
532         NSLog(@"repairHelperTool"); 
533         NSString *afshlpPath = [[self bundle] pathForResource:@"afshlp" ofType:nil];
534         
535         
536     
537     // Open tool exclusively, so nobody can change it while we bless it.
538     fdTool = open([afshlpPath UTF8String], O_NONBLOCK | O_RDONLY | O_EXLOCK, 0);
539     
540     if(fdTool == -1)
541     {
542         NSLog(@"Exclusive open while repairing tool failed: %d.", errno);
543         exit(-1);
544     }
545     
546     if(fstat(fdTool, &st))
547     {
548         NSLog(@"fstat failed.");
549         exit(-1);
550     }
551     
552     if(st.st_uid != 0)
553     {
554                 status = [[AuthUtil shared] autorize];
555                 if(status == noErr){
556                         fchown(fdTool, 0, st.st_gid);
557                         
558                         // Disable group and world writability and make setuid root.
559                         fchmod(fdTool, (st.st_mode & (~(S_IWGRP | S_IWOTH)))/* | S_ISUID*/);
560                         const char *args[] = {"root", [afshlpPath UTF8String],0L};
561                         [[AuthUtil shared] execUnixCommand:"/usr/sbin/chown" 
562                                                                                   args:args
563                                                                                 output:nil];
564                         [[AuthUtil shared] deautorize];
565                 }
566     } else  NSLog(@"st_uid = 0");
567     
568         
569     
570     close(fdTool);
571     
572     NSLog(@"Self-repair done.");
573         
574 }
575
576
577 // -------------------------------------------------------------------------------
578 //  startStopAfs:
579 // -------------------------------------------------------------------------------
580 - (IBAction) startStopAfs:(id) sender
581 {
582         BOOL currentAfsState = NO;
583         @try {
584                 currentAfsState = [afsProperty checkAfsStatus];
585                 // make the parameter to call the root helper app
586                 if(currentAfsState){
587                         //shutdown afs
588                         NSLog(@"Shutting down afs");
589                         [afsProperty shutdown];
590                 } else {
591                         //Start afs
592                         NSLog(@"Starting up afs");
593                         [afsProperty startup];
594                 }
595                 [self refreshGui:nil];
596         }
597         @catch (NSException * e) {
598                 [self showMessage:[e reason]];
599         }
600         @finally {
601                 [[AuthUtil shared] deautorize];
602         }
603 }
604
605 // -------------------------------------------------------------------------------
606 //  info:
607 // -------------------------------------------------------------------------------
608 - (void) refreshGui:(NSNotification *)notification{
609         BOOL afsIsUp = [afsProperty checkAfsStatus];
610         [self setAfsStatus];
611         [tokensButton setEnabled:afsIsUp];
612         [unlogButton setEnabled:afsIsUp];
613
614 }
615
616 // -------------------------------------------------------------------------------
617 //  -(void) refreshTokensNotify:(NSNotification*)notification
618 // -------------------------------------------------------------------------------
619 -(void) refreshTokensNotify:(NSNotification*)notification {
620         [self refreshTokens:nil];
621 }
622
623 // -------------------------------------------------------------------------------
624 //  afsVolumeMountChange: Track the afs volume state change
625 // -------------------------------------------------------------------------------
626 - (void) afsVolumeMountChange:(NSNotification *)notification{
627         // Cehck if is mounted or unmounted afs
628         if([[[notification userInfo] objectForKey:@"NSDevicePath"] isEqualToString:@"/afs"]){
629                 [self setAfsStatus];
630                 [self refreshTokens:nil];
631         }
632 }
633
634 // -------------------------------------------------------------------------------
635 //  info:
636 // -------------------------------------------------------------------------------
637 - (IBAction) info:(id) sender
638 {
639         [((InfoController*) infoController) showHtmlResource:[[self bundle] pathForResource:@"license" ofType:@"rtf"]];
640
641         [NSApp beginSheet: infoSheet
642            modalForWindow: [[self mainView] window]
643                 modalDelegate: self
644            didEndSelector:  @selector(didEndInfoSheet:returnCode:contextInfo:)
645                   contextInfo: nil];
646 }
647
648 // -------------------------------------------------------------------------------
649 //  tableDoubleAction:
650 // -------------------------------------------------------------------------------
651 - (IBAction) tableDoubleAction:(id) sender
652 {
653         [self showCellIP:nil];
654 }
655
656 // -------------------------------------------------------------------------------
657 //  getNewToken:
658 // -------------------------------------------------------------------------------
659 - (IBAction) getNewToken:(id) sender
660 {
661         BOOL useAklog = [useAklogCheck state] == NSOnState;
662         if(useAklog){
663                 //[AFSPropertyManager aklog];
664                 [afsProperty getTokens:false 
665                                                    usr:nil 
666                                                    pwd:nil];
667                 [self refreshTokens:nil];
668                 //Inform afs menuextra to updata afs status
669                 [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kAFSMenuExtraID object:kMExtraAFSStateChange];
670
671         } else {
672                 [NSBundle loadNibNamed:@"CredentialPanel" owner:self];
673                 [NSApp beginSheet: credentialSheet
674                    modalForWindow: [[self mainView] window]
675                         modalDelegate: self
676                    didEndSelector: @selector(didEndCredentialSheet:returnCode:contextInfo:)
677                           contextInfo: nil];
678         }
679 }
680
681
682 // -------------------------------------------------------------------------------
683 //  getCurrentCellInDB:
684 // -------------------------------------------------------------------------------
685 - (IBAction) unlog:(id) sender
686 {
687         int index = -1;
688         NSIndexSet *selectedIndex = [(NSTableView*)tokensTable selectedRowIndexes];
689         if( [selectedIndex count] > 0) {
690                 index = [selectedIndex firstIndex]; 
691                 do {
692                         NSString *tokenDesc = [tokenList objectAtIndex:index];
693                         NSString *cellToUnlog = [tokenDesc estractTokenByDelimiter:@"afs@" 
694                                                                                                                           endToken:@" "];
695                         [afsProperty unlog:cellToUnlog];
696                 } while ((index = [selectedIndex indexGreaterThanIndex: index]) != NSNotFound);
697         } else {
698                 [afsProperty unlog:nil];
699         }
700         [self refreshTokens:nil];
701         //Inform afs menuextra to updata afs status
702         [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kAFSMenuExtraID object:kMExtraAFSStateChange];
703
704 }
705
706
707 // -------------------------------------------------------------------------------
708 //  aklogSwitchEvent:
709 // -------------------------------------------------------------------------------
710 - (IBAction) aklogSwitchEvent:(id) sender
711 {
712         //afs menu extra is loaded inform it to read preference
713         @try {
714                 if(![useAklogCheck state]) {
715                         //deselect the checkbox
716                         [aklogCredentialAtLoginTime setState:NO];
717                 }
718                 
719                 [self writePreferenceFile];
720                 
721                 //Enable disable aklog at login time checkbox according the useAklog checkbox
722                 [aklogCredentialAtLoginTime setEnabled:[useAklogCheck state]];
723                 
724         }
725         @catch (NSException * e) {
726                 [self showMessage:[e reason]];
727         }
728         
729                 
730 }
731
732 // -------------------------------------------------------------------------------
733 //  credentialAtLoginTimeEvent:
734 // -------------------------------------------------------------------------------
735 - (IBAction) credentialAtLoginTimeEvent:(id) sender {
736         [self writePreferenceFile];
737 }
738
739 // -------------------------------------------------------------------------------
740 //  afsStartupSwitchEvent:
741 // -------------------------------------------------------------------------------
742 - (IBAction) afsStartupSwitchEvent:(id) sender {
743         NSString *rootHelperApp = [[self bundle] pathForResource:@"afshlp" ofType:@""];
744         //get the new state
745         startAFSAtLogin = [checkButtonAfsAtBootTime state];
746         const char *startupConfigureOption[] = {"start_afs_at_startup", startAFSAtLogin?"enable":"disable", 0L};
747         if([[AuthUtil shared] autorize] == noErr) {
748                         //now disable the launchd configuration
749                         [[AuthUtil shared] execUnixCommand:[rootHelperApp UTF8String]
750                                                                                   args:startupConfigureOption
751                                                                                 output:nil];
752         }
753 }
754
755
756 // -------------------------------------------------------------------------------
757 //  afsMenuActivationEvent:
758 // -------------------------------------------------------------------------------
759 - (IBAction) krb5KredentialAtLoginTimeEvent:(id) sender {
760         //
761         NSString *rootHelperApp = [[self bundle] pathForResource:@"afshlp" ofType:@""];
762         const char *args[] = {"enable_krb5_startup", [[installKRB5AuthAtLoginButton stringValue] UTF8String], "", 0L};
763         
764         //Check helper app
765         [self repairHelperTool];
766         if([[AuthUtil shared] autorize] == noErr) {
767                 [[AuthUtil shared] execUnixCommand:[rootHelperApp UTF8String] 
768                                                                           args:args
769                                                                         output:nil];
770                 
771                 //check if all is gone well
772                 [installKRB5AuthAtLoginButton setState:[PListManager checkKrb5AtLoginTimeLaunchdEnable]];
773         }
774 }
775
776 // -------------------------------------------------------------------------------
777 //  afsMenuActivationEvent:
778 // -------------------------------------------------------------------------------
779 -(IBAction) afsMenuActivationEvent:(id) sender
780 {
781         CFPreferencesSetValue((CFStringRef)PREFERENCE_SHOW_STATUS_MENU, 
782                                                   (CFNumberRef)[NSNumber numberWithBool:[afsMenucheckBox state]], 
783                                                   (CFStringRef)kAfsCommanderID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
784         
785         CFPreferencesSynchronize((CFStringRef)kAfsCommanderID,  kCFPreferencesAnyUser, kCFPreferencesAnyHost);
786         CFPreferencesSynchronize((CFStringRef)kAfsCommanderID,  kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
787         
788         //notify the backgrounder
789         [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kAFSMenuExtraID object:kMExtraAFSMenuChangeState];
790 }
791
792 // -------------------------------------------------------------------------------
793 //  searchCellTextEvent:
794 //              Fileter the CellServDB list according to NSSearch content
795 // -------------------------------------------------------------------------------
796 - (IBAction) searchCellTextEvent:(id) sender
797 {
798         
799         NSString *searchText = [[textSearchField stringValue] lowercaseString]; //filter string
800         [self filterCellServDB:searchText];
801         [((NSTableView*)cellList) reloadData];
802 }
803
804 // -------------------------------------------------------------------------------
805 //  clearCellServDBFiltering:
806 //              clear the NSSearchField and showw all CellServDB table
807 // -------------------------------------------------------------------------------
808 - (void) clearCellServDBFiltering {
809         //Clear the text search
810         [textSearchField setStringValue:@""];
811         //load the temp array with all cell servdb
812         [self searchCellTextEvent:nil];
813 }
814 // --------------------------------------o-----------------------------------------
815 //  filterCellServDB:
816 //  make the NSMutableArray with all cellservdb or filtered element
817 // -------------------------------------------------------------------------------
818 - (void) filterCellServDB:(NSString*)textToFilter {
819         DBCellElement *cellElement; //Filtered element
820         BOOL doFilter = !(textToFilter == nil || ([textToFilter length] == 0));
821         
822         // We can do filtering and make the temp array
823         if(filteredCellDB){
824                 [filteredCellDB release];
825         }
826         filteredCellDB = [[NSMutableArray alloc] init];
827         NSEnumerator *e = [[afsProperty getCellList] objectEnumerator];
828         while(cellElement = (DBCellElement*)[e nextObject]) {
829                 // check if the element can be get
830                 if(doFilter) {
831                         //Get the CellServDB array enumerator
832                         NSRange rsltRng = [[[cellElement getCellName] lowercaseString] rangeOfString:textToFilter];
833                    if(rsltRng.location != NSNotFound) {
834                         //we can add this cell to filtered
835                         [filteredCellDB addObject:[cellElement retain]];
836                    }
837                 } else {
838                         [filteredCellDB addObject:[cellElement retain]];
839
840                 }
841         }
842 }
843                    
844 // -------------------------------------------------------------------------------
845 //  getCurrentCellInDB:
846 // -------------------------------------------------------------------------------
847 - (DBCellElement*) getCurrentCellInDB
848 {
849         int rowSelected = [((NSTableView *) cellList) selectedRow];
850         return [self getCellByIDX:rowSelected];
851 }
852
853 // -------------------------------------------------------------------------------
854 //  getCurrentCellInDB:
855 // -------------------------------------------------------------------------------
856 - (DBCellElement*) getCellByIDX:(int) idx
857 {
858         //NSMutableArray *cellArray = [afsProperty getCellList];
859         DBCellElement *cellElement =  (DBCellElement*)[filteredCellDB objectAtIndex:idx];
860         return cellElement;
861 }
862
863 // -------------------------------------------------------------------------------
864 //  showMessage:
865 // -------------------------------------------------------------------------------
866 -(void) showMessage:(NSString*) message{
867         NSAlert *alert = [[NSAlert alloc] init];
868         
869         [alert setMessageText:message];
870         [alert beginSheetModalForWindow:[[self mainView] window]
871                                           modalDelegate:nil 
872                                          didEndSelector:nil
873                                                 contextInfo:nil];
874         [alert release];
875 }
876
877 // -------------------------------------------------------------------------------
878 //  manageButtonState:
879 // -------------------------------------------------------------------------------
880 -(void) manageButtonState:(int) rowSelected {
881         [((NSControl*) cellIpButton) setEnabled:rowSelected >= 0];
882         [((NSControl*) removeCellButton) setEnabled:rowSelected >= 0];
883 }
884
885 // -------------------------------------------------------------------------------
886 //  setAfsStatus:
887 // -------------------------------------------------------------------------------
888 -(void) setAfsStatus
889 {
890         BOOL afsIsUp = [afsProperty checkAfsStatus];
891         BOOL afsEnabledAtStartup = [afsProperty checkAfsStatusForStartup];
892
893
894         [((NSButton *)startStopButton) setTitle: (afsIsUp?kAfsButtonShutdown:kAfsButtonStartup)];
895         
896         NSMutableAttributedString *colorTitle =[[NSMutableAttributedString alloc] initWithAttributedString:[((NSButton *)startStopButton) attributedTitle]];
897     NSRange titleRange = NSMakeRange(0, [colorTitle length]);
898         
899     [colorTitle addAttribute:NSForegroundColorAttributeName
900                        value:(afsIsUp?[NSColor redColor]:[NSColor blackColor])
901                        range:titleRange];
902         
903     [((NSButton *)startStopButton) setAttributedTitle:colorTitle];
904         [checkButtonAfsAtBootTime setState:afsEnabledAtStartup];
905         if(afsIsUp) {
906                 [self startTimer];
907         } else {
908                 [self stopTimer];
909         }
910 }
911
912 // -------------------------------------------------------------------------------
913 //  refreshToken:
914 // -------------------------------------------------------------------------------
915 - (void) refreshTokens:(NSTimer*)theTimer;
916 {
917         if(![tokensLock tryLock]) return;
918         if(tokenList){
919                 [tokenList release];
920         }
921         
922         tokenList = [afsProperty getTokenList];
923         [((NSTableView*)tokensTable) reloadData];
924         [tokensLock unlock];
925 }
926
927 // -------------------------------------------------------------------------------
928 //  removeExtra:
929 // -------------------------------------------------------------------------------
930 - (IBAction) addLink:(id) sender {
931         [NSBundle loadNibNamed:@"SymLinkEdit" owner:self];
932         
933         [NSApp beginSheet: lyncCreationSheet
934            modalForWindow: [[self mainView] window]
935                 modalDelegate: self
936            didEndSelector: @selector(didEndSymlinkSheet:returnCode:contextInfo:)
937                   contextInfo: nil];
938         
939 }
940
941 // -------------------------------------------------------------------------------
942 //  removeExtra:
943 // -------------------------------------------------------------------------------
944 - (IBAction) removeLink:(id) sender {
945         
946 }
947
948 // -------------------------------------------------------------------------------
949 //  removeExtra:
950 // -------------------------------------------------------------------------------
951 - (IBAction) enableLink:(id) sender {
952         
953 }
954
955 // -------------------------------------------------------------------------------
956 //  removeExtra:
957 // -------------------------------------------------------------------------------
958 - (IBAction) manageBackgrounderActivation:(id)sender {
959         [PListManager launchctlCommand:[(NSButton*)sender state] 
960                                                 userDomain:YES 
961                                                         option:[NSArray arrayWithObjects:@"-S", @"Aqua", nil] 
962                                                  plistName:[NSString stringWithFormat:@"%@.plist", BACKGROUNDER_P_FILE]];
963         //re ad the status to check taht all is gone well
964         [backgrounderActivationCheck setState:[PListManager launchdJobState:BACKGROUNDER_P_FILE]];
965 }
966
967
968 // -------------------------------------------------------------------------------
969 //  - (void)tabView:(NSTabView *)tabView willSelectTabViewItem: (NSTabViewItem *)tabViewItem
970 // -------------------------------------------------------------------------------
971 - (void)tabView:(NSTabView *)tabView willSelectTabViewItem: (NSTabViewItem *)tabViewItem 
972 {
973         //check to see if the cache param tab is the tab that will be selected
974         if([((NSString*)[tabViewItem identifier]) intValue] == TAB_LINK)
975         {
976                 [ViewUtility enbleDisableControlView:[tabViewItem view]
977                                                                 controlState:NO];
978         }
979 }
980
981 @end
982
983 @implementation AFSCommanderPref (NSTableDataSource)
984
985
986 // -------------------------------------------------------------------------------
987 //  tableView:
988 //              Manage the checkbox of CellServDB Table
989
990 // -------------------------------------------------------------------------------
991 - (void)tableView:(NSTableView *)table 
992    setObjectValue:(id)data 
993    forTableColumn:(NSTableColumn *)col 
994                           row:(int)row
995 {
996         NSString *identifier = (NSString*)[col identifier];
997         switch([table tag]){
998                 case TABLE_TOKENS_LIST:
999                         break;
1000                         
1001                 case TABLE_CELL_LIST:
1002                         // we are editing checkbox for cellservdb table
1003                         if([identifier intValue] == CELLSRVDB_TABLE_USR_DFLT_CHECK_COLUMN) {
1004                                 // set the user default cell
1005                                 DBCellElement *cellElement =  (DBCellElement*)[filteredCellDB objectAtIndex:row];
1006                                 [afsProperty setDefaultCellByName:[cellElement getCellName]];
1007                                 //[afsDefaultCellLabel setStringValue:[afsProperty getDefaultCellName]];
1008                                 [((NSTableView*)cellList) reloadData];
1009                         } else if([identifier intValue] == CELLSRVDB_TABLE_DFLT_CHECK_COLUMN) {
1010                                 // set the cell for wich the user want to get token
1011                                 DBCellElement *cellElement =  (DBCellElement*)[filteredCellDB objectAtIndex:row];
1012                                 [cellElement setUserDefaultForToken:![cellElement userDefaultForToken]];
1013                         }  
1014                         break;
1015         }
1016         
1017 }
1018
1019
1020 // -------------------------------------------------------------------------------
1021 //  tableView:
1022 //              refresh delegate method for two AFSCommander table
1023 // -------------------------------------------------------------------------------
1024 - (id)  tableView:(NSTableView *) aTableView
1025         objectValueForTableColumn:(NSTableColumn *) aTableColumn
1026                                                   row:(int) rowIndex
1027 {  
1028         
1029         id result = nil;
1030         NSString *identifier = (NSString*)[aTableColumn identifier];
1031         switch([aTableView tag]){
1032                 case TABLE_TOKENS_LIST:
1033                         //We are refreshing tokens table
1034                         result = [self getTableTokensListValue:[identifier intValue] row:rowIndex];
1035                         break;
1036                         
1037                 case TABLE_CELL_LIST:
1038                         //We are refreshing cell db table
1039                         result = [self getTableCelListValue:[identifier intValue] row:rowIndex];
1040                         break;
1041                 
1042         }
1043         return result;  
1044 }
1045
1046
1047 // -------------------------------------------------------------------------------
1048 //  getTableCelListValue:
1049 // -------------------------------------------------------------------------------
1050 - (id)getTableTokensListValue:(int) colId row:(int)row
1051 {
1052         id result = nil;
1053         if(!tokenList) return nil;
1054         switch(colId){
1055                 case 0:
1056                         result = (NSString*)[tokenList objectAtIndex:row];
1057                         break;
1058         }
1059         return result;
1060 }
1061
1062
1063 // -------------------------------------------------------------------------------
1064 //  getTableCelListValue:
1065 // -------------------------------------------------------------------------------
1066 - (id)getTableCelListValue:(int) colId row:(int)row
1067 {
1068         id result = nil;
1069         //NSMutableArray *cellArray = [afsProperty getCellList];
1070         DBCellElement *cellElement =  (DBCellElement*)[filteredCellDB objectAtIndex:row];
1071         switch(colId){
1072                 case CELLSRVDB_TABLE_USR_DFLT_CHECK_COLUMN:
1073                         result = [NSNumber numberWithInt:[cellElement userDefaultForCell]];
1074                         break;
1075                         
1076                 case CELLSRVDB_TABLE_DFLT_CHECK_COLUMN:
1077                         result = [NSNumber numberWithInt:[cellElement userDefaultForToken]];
1078                         break;
1079                 case CELLSRVDB_TABLE_NAME_COLUMN:
1080                         result = [cellElement getCellName];
1081                         break;
1082                         
1083                 case CELLSRVDB_TABLE_DESCRIPTION_COLUMN:
1084                         result = [cellElement getCellComment];
1085                         break;
1086         }
1087         return result;
1088 }
1089
1090 // -------------------------------------------------------------------------------
1091 //  numberOfRowsInTableView:
1092 // -------------------------------------------------------------------------------
1093 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
1094 {
1095         int rowCount = 0;
1096         //NSMutableArray *cellArray = nil;
1097         switch([aTableView tag]){
1098                 case TABLE_TOKENS_LIST:
1099                         if(tokenList)  rowCount = [tokenList count];
1100                         break;
1101                         
1102                 case TABLE_CELL_LIST:
1103                         //cellArray = [afsProperty getCellList];
1104                         if(filteredCellDB)  rowCount = [filteredCellDB count];
1105                         break;
1106                         
1107         }       
1108         return rowCount;  
1109 }
1110 @end
1111
1112
1113 @implementation AFSCommanderPref (TableDelegate)
1114 // -------------------------------------------------------------------------------
1115 //  selectionShouldChangeInTableView:
1116 // -------------------------------------------------------------------------------
1117 - (BOOL)selectionShouldChangeInTableView:(NSTableView *)aTable
1118 {
1119         [self manageButtonState:[aTable selectedRow]];
1120         return YES;
1121 }
1122
1123 // -------------------------------------------------------------------------------
1124 //  tableView:
1125 // -------------------------------------------------------------------------------
1126 - (BOOL)tableView:(NSTableView *)aTable shouldSelectRow:(int)aRow
1127 {
1128         [self manageButtonState:aRow];
1129         return YES;
1130 }
1131
1132 @end
1133
1134
1135 @implementation AFSCommanderPref (ModalDelegate)
1136 // -------------------------------------------------------------------------------
1137 //  didEndSheet:
1138 // -------------------------------------------------------------------------------
1139 - (void)didEndSheet:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
1140 {
1141     [sheet orderOut:self];
1142         //Filter the cellServDb and allocate filtered array
1143         [self searchCellTextEvent:nil];
1144         [((NSTableView*)cellList) reloadData];
1145 }
1146
1147 // -------------------------------------------------------------------------------
1148 //  Klog credential request
1149 // -------------------------------------------------------------------------------
1150 - (void)didEndCredentialSheet:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
1151 {
1152         if([((TokenCredentialController*)credentialCommander) takenToken] == YES){
1153                 /*[AFSPropertyManager klog:[((TokenCredentialController*)credentialCommander) uName] 
1154                                                         uPwd:[((TokenCredentialController*)credentialCommander) uPwd] ];*/
1155                 [afsProperty getTokens:true 
1156                                                    usr:[((TokenCredentialController*)credentialCommander) uName] 
1157                                                    pwd:[((TokenCredentialController*)credentialCommander) uPwd]];
1158         }
1159     [sheet orderOut:self];
1160         [self refreshTokens:nil];
1161         //Inform afs menuextra to updata afs status
1162         [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kAFSMenuExtraID object:kMExtraAFSStateChange];
1163
1164 }
1165
1166 // -------------------------------------------------------------------------------
1167 //  Klog credential request
1168 // -------------------------------------------------------------------------------
1169 - (void)didEndInfoSheet:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
1170 {
1171         [sheet orderOut:self];
1172 }
1173
1174 // -------------------------------------------------------------------------------
1175 //  symlink edite
1176 // -------------------------------------------------------------------------------
1177 - (void)didEndSymlinkSheet:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
1178 {
1179         [lyncCreationSheet orderOut:self];
1180 }
1181 @end