Changeset 29

Show
Ignore:
Timestamp:
12/08/04 21:00:51 (4 years ago)
Author:
kevin
Message:

Tunnels now identify themselves with UUIDs rather than names
When iterating over lists of tunnels and such, use NSEnumerator rather than a for loop (unless we want to modify the array during the loop)
Fix a few code style things I ran across
Fix a preferences size issue I ran into where the first pref view (i.e. General) was being resized incorrectly (because blankView was being created *after* switching to General initially)
Remove an unnecessary -arrayWithArray: call; just retain the original object instead
Fix a dealloc issue - in dealloc, call -release for ivars, not -dealloc

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/PreferenceController.m

    r28 r29  
    77- (id)init 
    88{ 
    9         if(!(self = [super init])) 
    10         { 
    11                 return nil; 
    12         } 
    13          
    14         sharedPreferenceController = self; 
    15          
    16         [NSBundle loadNibNamed:@"Preferences" owner:sharedPreferenceController]; 
    17  
    18         blankView = [[NSView alloc] init]; 
     9        if(self = [super init]) 
     10        { 
     11                sharedPreferenceController = self; 
     12 
     13                blankView = [[NSView alloc] init]; 
     14                 
     15                [NSBundle loadNibNamed:@"Preferences" owner:sharedPreferenceController]; 
     16        } 
    1917         
    2018        return self; 
     
    2321- (void)dealloc 
    2422{ 
    25         [blankView dealloc]; 
     23        [blankView release]; 
    2624        [super dealloc]; 
    2725} 
     
    145143        { 
    146144                if(([array objectAtIndex:1]) && (currentController != [array objectAtIndex:1])) 
    147                       { 
     145              { 
    148146                        [currentController closePreferences]; 
    149147 
  • trunk/PreferenceViews/TunnelsView.m

    r28 r29  
    33#import "PreferenceController.h" 
    44#import "TunnelController.h" 
     5#import "Utilities.h" 
    56 
    67@implementation TunnelsView 
    78 
    8 - (void) awakeFromNib { 
    9         if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_2) { 
     9- (void) awakeFromNib 
     10
     11        if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_2)  
     12        { 
    1013                // Ack, we gotta disable the dynamic ports tab 
    1114                int dynamicTabIndex = [tunnelDetailsTabView indexOfTabViewItemWithIdentifier:@"dynamicPorts"]; 
     
    2023{ 
    2124        /* Get all tunnels. */ 
    22         tunnels = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] arrayForKey:tunnelsString]] retain]; 
     25        [[NSUserDefaults standardUserDefaults] synchronize]; 
     26        tunnels = [[NSMutableArray alloc] initWithArray: 
     27                                        [[NSUserDefaults standardUserDefaults] arrayForKey:tunnelsString]]; 
    2328         
    2429        if(!tunnels) { 
     
    5358- (IBAction)addTunnel:(id)sender 
    5459{ 
    55         int i; 
    5660        BOOL match = NO; 
    5761         
    58         for(i=0; i < [tunnels count]; i++) { 
    59                 if([[[tunnels objectAtIndex:i] objectForKey:@"TunnelName"] isEqualToString:@"New Tunnel"]) { 
     62        NSEnumerator *e = [tunnels objectEnumerator]; 
     63        NSDictionary *aTunnel; 
     64        while (aTunnel = [e nextObject]) 
     65        { 
     66                if ([[aTunnel objectForKey:@"TunnelName"] isEqualToString:@"New Tunnel"]) 
     67                { 
    6068                        match = YES; 
    6169                } 
    6270        } 
    6371         
    64         if(!match) 
     72        if (!match) 
    6573        { 
    6674                NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 
    6775                [dict setObject:@"New Tunnel" forKey:@"TunnelName"]; 
     76                [dict setObject:CreateUUID() forKey:@"TunnelUUID"]; 
    6877                 
    6978                [tunnels addObject:dict]; 
     
    8998        [self hideTunnelDetails]; 
    9099 
    91         [[TunnelController sharedController] removeTunnelWithName:[[tunnels objectAtIndex:index] objectForKey:@"TunnelName"]]; 
     100        [[TunnelController sharedController] removeTunnelWithUUID:[[tunnels objectAtIndex:index] objectForKey:@"TunnelUUID"]]; 
    92101        [tunnels removeObjectAtIndex:index]; 
    93102 
     
    362371- (void)saveTunnelDetails 
    363372{ 
    364         NSMutableDictionary *dict = [[[NSMutableDictionary alloc] init] autorelease]; 
    365  
    366373        if(tunnelIndex < 0) 
    367374        { 
     
    369376        } 
    370377         
     378        NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[tunnels objectAtIndex:tunnelIndex]]; 
    371379         
    372380        if([[tunnelName stringValue] isEqualToString:@""]) { [tunnelName setStringValue:@"Some Tunnel"]; } 
     
    377385        if(![[[tunnels objectAtIndex:tunnelIndex] objectForKey:@"TunnelName"] isEqualToString:[tunnelName stringValue]]) 
    378386        { 
    379                 [[TunnelController sharedController] changeTunnelName:[[tunnels objectAtIndex:tunnelIndex] objectForKey:@"TunnelName"] 
    380                                                                                                            toName:[tunnelName stringValue]]; 
     387                [[TunnelController sharedController] changeTunnel:[[tunnels objectAtIndex:tunnelIndex] objectForKey:@"TunnelUUID"] 
     388                                                                                                           setName:[tunnelName stringValue]]; 
    381389        } 
    382390         
  • trunk/SSHKeychain.xcode/project.pbxproj

    r25 r29  
    5757                        shellScript = "echo \"Cleaning up unneeded files...\"\nfind $BUILD_ROOT/$WRAPPER_NAME '(' -name '.svn' -or -name '.DS_Store' ')' -prune -exec rm -rf '{}' ';'"; 
    5858                }; 
     59                0A7F548E07676EB500E1C1E4 = { 
     60                        fileEncoding = 4; 
     61                        isa = PBXFileReference; 
     62                        lastKnownFileType = sourcecode.c.h; 
     63                        path = Utilities.h; 
     64                        refType = 4; 
     65                        sourceTree = "<group>"; 
     66                }; 
     67                0A7F548F07676EB500E1C1E4 = { 
     68                        fileEncoding = 4; 
     69                        isa = PBXFileReference; 
     70                        lastKnownFileType = sourcecode.c.objc; 
     71                        path = Utilities.m; 
     72                        refType = 4; 
     73                        sourceTree = "<group>"; 
     74                }; 
     75                0A7F549007676EB500E1C1E4 = { 
     76                        fileRef = 0A7F548E07676EB500E1C1E4; 
     77                        isa = PBXBuildFile; 
     78                        settings = { 
     79                        }; 
     80                }; 
     81                0A7F549107676EB500E1C1E4 = { 
     82                        fileRef = 0A7F548F07676EB500E1C1E4; 
     83                        isa = PBXBuildFile; 
     84                        settings = { 
     85                        }; 
     86                }; 
     87                0A7F549A07676F2400E1C1E4 = { 
     88                        isa = PBXFileReference; 
     89                        lastKnownFileType = wrapper.framework; 
     90                        name = Carbon.framework; 
     91                        path = /System/Library/Frameworks/Carbon.framework; 
     92                        refType = 0; 
     93                        sourceTree = "<absolute>"; 
     94                }; 
     95                0A7F549B07676F2400E1C1E4 = { 
     96                        fileRef = 0A7F549A07676F2400E1C1E4; 
     97                        isa = PBXBuildFile; 
     98                        settings = { 
     99                        }; 
     100                }; 
     101                0A7F554E07677DCC00E1C1E4 = { 
     102                        fileEncoding = 4; 
     103                        isa = PBXFileReference; 
     104                        lastKnownFileType = sourcecode.c.h; 
     105                        path = NSMenu_Additions.h; 
     106                        refType = 4; 
     107                        sourceTree = "<group>"; 
     108                }; 
     109                0A7F554F07677DCC00E1C1E4 = { 
     110                        fileEncoding = 4; 
     111                        isa = PBXFileReference; 
     112                        lastKnownFileType = sourcecode.c.objc; 
     113                        path = NSMenu_Additions.m; 
     114                        refType = 4; 
     115                        sourceTree = "<group>"; 
     116                }; 
     117                0A7F555007677DCC00E1C1E4 = { 
     118                        fileRef = 0A7F554E07677DCC00E1C1E4; 
     119                        isa = PBXBuildFile; 
     120                        settings = { 
     121                        }; 
     122                }; 
     123                0A7F555107677DCC00E1C1E4 = { 
     124                        fileRef = 0A7F554F07677DCC00E1C1E4; 
     125                        isa = PBXBuildFile; 
     126                        settings = { 
     127                        }; 
     128                }; 
    59129                0A925562075F22B800B98A2B = { 
    60130                        isa = PBXFileReference; 
     
    86156                                CCC9E42906A6763E00422E9E, 
    87157                                1058C7A1FEA54F0111CA2CBB, 
     158                                0A7F549A07676F2400E1C1E4, 
    88159                        ); 
    89160                        isa = PBXGroup; 
     
    182253                29B97315FDCFA39411CA2CEA = { 
    183254                        children = ( 
     255                                0A7F554E07677DCC00E1C1E4, 
     256                                0A7F554F07677DCC00E1C1E4, 
     257                                0A7F548E07676EB500E1C1E4, 
     258                                0A7F548F07676EB500E1C1E4, 
    184259                                32CA4F630368D1EE00C91783, 
    185260                                CCCDD4A706A576CF00B68ED1, 
     
    377452                                CC586C5106C3D56A00D73261, 
    378453                                CC6C191507421C8700CB0A18, 
     454                                0A7F549007676EB500E1C1E4, 
     455                                0A7F555007677DCC00E1C1E4, 
    379456                        ); 
    380457                        isa = PBXHeadersBuildPhase; 
     
    433510                                CC586C5206C3D56A00D73261, 
    434511                                CC6C191607421C8700CB0A18, 
     512                                0A7F549107676EB500E1C1E4, 
     513                                0A7F555107677DCC00E1C1E4, 
    435514                        ); 
    436515                        isa = PBXSourcesBuildPhase; 
     
    451530                                CCC9E42A06A6763E00422E9E, 
    452531                                CCC9E42B06A6763F00422E9E, 
     532                                0A7F549B07676F2400E1C1E4, 
    453533                        ); 
    454534                        isa = PBXFrameworksBuildPhase; 
  • trunk/TODO

    r28 r29  
    88- The option to not display messages regarding tunnels (Nov 05 - Marc Liyanage  - Feature suggestion for SSHKeychain) 
    99- Listen to local forwarded ports and start up the tunnel on demand (that's going to require some hacking with random ports to have ssh listening on) 
    10 - Give tunnels UUIDs for identification instead of using their names (<http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFPlugIns/Tasks/GeneratingUUID.html>) 
    1110 
    12111.0 TODO: 
  • trunk/TunnelController.h

    r17 r29  
    2121 
    2222- (void)sync; 
    23 - (void)changeTunnelName:(NSString *)oldName toName:(NSString *)newName; 
    24 - (void)removeTunnelWithName:(NSString *)name
     23- (void)changeTunnel:(NSString *)uuid setName:(NSString *)newName; 
     24- (void)removeTunnelWithUUID:(NSString *)uuid
    2525 
    2626- (void)setToolTipForActiveTunnels; 
  • trunk/TunnelController.m

    r28 r29  
    44#import "PreferenceController.h" 
    55#import "Libs/SSHTunnel.h" 
     6#import "Utilities.h" 
     7#import "NSMenu_Additions.h" 
    68 
    79#include "SSHKeychain_Prefix.pch" 
     
    1618- (id)init 
    1719{                
    18         if(!(self = [super init])) 
    19         { 
    20                 return nil; 
    21         } 
    22          
    23         [[NSNotificationCenter defaultCenter] addObserver:self 
    24                                         selector:@selector(applicationDidFinishLaunching:) 
    25                                         name:@"NSApplicationDidFinishLaunchingNotification" object:NSApp]; 
    26          
    27         [[NSNotificationCenter defaultCenter] addObserver:self 
    28                                                  selector:@selector(applicationWillTerminate:) 
    29                                                      name:@"NSApplicationWillTerminateNotification" object:NSApp]; 
    30          
    31         [[NSNotificationCenter defaultCenter] addObserver:self 
    32                                                  selector:@selector(agentFilledNotification:) name:@"AgentFilled" object:nil]; 
    33          
    34         [[NSNotificationCenter defaultCenter] addObserver:self 
    35                                                  selector:@selector(agentEmptiedNotification:) name:@"AgentEmptied" object:nil]; 
    36  
    37         sharedTunnelController = self; 
    38  
    39         notificationQueue  = [[NSMutableArray alloc] init]; 
    40         notificationLock   = [[NSLock alloc] init]; 
    41         notificationThread = [[NSThread currentThread] retain]; 
    42         notificationPort   = [[NSMachPort alloc] init]; 
    43  
    44         [notificationPort setDelegate:self]; 
    45  
    46         [[NSRunLoop currentRunLoop] addPort:notificationPort forMode:(NSString *)kCFRunLoopCommonModes]; 
     20        if(self = [super init]) 
     21        { 
     22                [[NSNotificationCenter defaultCenter] addObserver:self 
     23                                                selector:@selector(applicationDidFinishLaunching:) 
     24                                                name:@"NSApplicationDidFinishLaunchingNotification" object:NSApp]; 
     25                 
     26                [[NSNotificationCenter defaultCenter] addObserver:self 
     27                                                         selector:@selector(applicationWillTerminate:) 
     28                                                                 name:@"NSApplicationWillTerminateNotification" object:NSApp]; 
     29                 
     30                [[NSNotificationCenter defaultCenter] addObserver:self 
     31                                                         selector:@selector(agentFilledNotification:) name:@"AgentFilled" object:nil]; 
     32                 
     33                [[NSNotificationCenter defaultCenter] addObserver:self 
     34                                                         selector:@selector(agentEmptiedNotification:) name:@"AgentEmptied" object:nil]; 
     35 
     36                sharedTunnelController = self; 
     37 
     38                notificationQueue  = [[NSMutableArray alloc] init]; 
     39                notificationLock   = [[NSLock alloc] init]; 
     40                notificationThread = [[NSThread currentThread] retain]; 
     41                notificationPort   = [[NSMachPort alloc] init]; 
     42 
     43                [notificationPort setDelegate:self]; 
     44 
     45                [[NSRunLoop currentRunLoop] addPort:notificationPort forMode:(NSString *)kCFRunLoopCommonModes]; 
     46        } 
    4747         
    4848        return self; 
     
    7676        NSArray *newTunnels; 
    7777        NSMutableDictionary *dict; 
    78         int i, j
     78        int i
    7979        BOOL match; 
    8080         
    8181        if(!tunnels) { return; } 
    8282         
    83         newTunnels = [NSArray arrayWithArray:[[NSUserDefaults standardUserDefaults] arrayForKey:tunnelsString]]; 
    84  
    85         for(i=0; i < [newTunnels count]; i++)  
    86         { 
     83        [[NSUserDefaults standardUserDefaults] synchronize]; 
     84        newTunnels = [[NSUserDefaults standardUserDefaults] arrayForKey:tunnelsString]; 
     85         
     86        // Because we're adding UUIDs, we should give them to all tunnels that don't yet have them 
     87        BOOL setUUID = NO; 
     88        NSEnumerator *e =  [newTunnels objectEnumerator]; 
     89        NSDictionary *aTunnel; 
     90        NSMutableArray *modifiedTunnels = [NSMutableArray array]; 
     91        while (aTunnel = [e nextObject]) { 
     92                if ([aTunnel objectForKey:@"TunnelUUID"] == nil) 
     93                { 
     94                        NSMutableDictionary *modifiedTunnel = [NSMutableDictionary dictionaryWithDictionary:aTunnel]; 
     95                        [modifiedTunnel setObject:CreateUUID() forKey:@"TunnelUUID"]; 
     96                        [modifiedTunnels addObject:modifiedTunnel]; 
     97                        setUUID = YES; 
     98                } else { 
     99                        [modifiedTunnels addObject:aTunnel]; 
     100                } 
     101        } 
     102        if (setUUID) { 
     103                newTunnels = [NSArray arrayWithArray:modifiedTunnels]; 
     104                [[NSUserDefaults standardUserDefaults] setObject:newTunnels forKey:tunnelsString]; 
     105        } 
     106         
     107        e = [newTunnels objectEnumerator]; 
     108        while (aTunnel = [e nextObject]) { 
    87109                match = NO; 
    88110                 
    89                 for(j=0; j < [tunnels count]; j++) 
    90                 { 
    91                         if([[[newTunnels objectAtIndex:i] objectForKey:@"TunnelName"] isEqualToString: 
    92                                 [[tunnels objectAtIndex:j] objectForKey:@"TunnelName"]]) 
     111                for(i=0; i < [tunnels count]; i++) 
     112                { 
     113                        NSDictionary *oldTunnel = [tunnels objectAtIndex:i]; 
     114                        if([[aTunnel objectForKey:@"TunnelUUID"] isEqualToString: 
     115                                [oldTunnel objectForKey:@"TunnelUUID"]]) 
    93116                        { 
    94                                 dict = [NSMutableDictionary dictionaryWithDictionary:[newTunnels objectAtIndex:i]]; 
    95  
    96                                 if([[tunnels objectAtIndex:j] objectForKey:@"TunnelObject"])  
    97                                 { 
    98                                         [dict setObject:[[tunnels objectAtIndex:j] objectForKey:@"TunnelObject"] forKey:@"TunnelObject"]; 
    99                                 } 
    100  
    101                                 [tunnels replaceObjectAtIndex:j withObject:dict]; 
     117                                dict = [NSMutableDictionary dictionaryWithDictionary:aTunnel]; 
     118 
     119                                if([oldTunnel objectForKey:@"TunnelObject"])  
     120                                { 
     121                                        [dict setObject:[oldTunnel objectForKey:@"TunnelObject"] forKey:@"TunnelObject"]; 
     122                                } 
     123 
     124                                [tunnels replaceObjectAtIndex:i withObject:dict]; 
    102125 
    103126                                match = YES; 
     
    107130                if(!match) 
    108131                { 
    109                         dict = [NSMutableDictionary dictionaryWithDictionary:[newTunnels objectAtIndex:i]]; 
    110                          
    111                         [[mainMenuTunnelsItem addItemWithTitle:[dict objectForKey:@"TunnelName"] 
    112                                                         action:@selector(toggleTunnel:) keyEquivalent:@""] setTarget:self]; 
    113                          
    114                         [[dockMenuTunnelsItem addItemWithTitle:[dict objectForKey:@"TunnelName"] 
    115                                                         action:@selector(toggleTunnel:) keyEquivalent:@""] setTarget:self]; 
    116                          
    117                         [[statusbarMenuTunnelsItem addItemWithTitle:[dict objectForKey:@"TunnelName"] 
    118                                                         action:@selector(toggleTunnel:) keyEquivalent:@""] setTarget:self]; 
     132                        dict = [NSMutableDictionary dictionaryWithDictionary:aTunnel]; 
     133                         
     134                        id <NSMenuItem> mItem; 
     135                        mItem = [mainMenuTunnelsItem addItemWithTitle:[dict objectForKey:@"TunnelName"] 
     136                                                                                                   action:@selector(toggleTunnel:) 
     137                                                                                        keyEquivalent:@""]; 
     138                        [mItem setTarget:self]; 
     139                        [mItem setRepresentedObject:[dict objectForKey:@"TunnelUUID"]]; 
     140                         
     141                        mItem = [dockMenuTunnelsItem addItemWithTitle:[dict objectForKey:@"TunnelName"] 
     142                                                                                                   action:@selector(toggleTunnel:) 
     143                                                                                        keyEquivalent:@""]; 
     144                        [mItem setTarget:self]; 
     145                        [mItem setRepresentedObject:[dict objectForKey:@"TunnelUUID"]]; 
     146                         
     147                        mItem = [statusbarMenuTunnelsItem addItemWithTitle:[dict objectForKey:@"TunnelName"] 
     148                                                                                                                action:@selector(toggleTunnel:) keyEquivalent:@""]; 
     149                        [mItem setTarget:self]; 
     150                        [mItem setRepresentedObject:[dict objectForKey:@"TunnelUUID"]]; 
    119151                         
    120152                        [tunnels addObject:[NSMutableDictionary dictionaryWithDictionary:dict]]; 
     
    123155} 
    124156 
    125 - (void)changeTunnelName:(NSString *)oldName toName:(NSString *)newName 
    126 { 
    127         int i; 
    128          
    129         if(!tunnels) { return; } 
    130                         
    131         for(i=0; i < [tunnels count]; i++)  
    132         { 
    133                 if([[[tunnels objectAtIndex:i] objectForKey:@"TunnelName"] isEqualToString:oldName]) 
    134                 { 
    135                         [[tunnels objectAtIndex:i] setObject:newName forKey:@"TunnelName"]; 
    136                          
    137                         [[mainMenuTunnelsItem itemWithTitle:oldName] setTitle:newName]; 
    138                         [[statusbarMenuTunnelsItem itemWithTitle:oldName] setTitle:newName]; 
    139                         [[dockMenuTunnelsItem itemWithTitle:oldName] setTitle:newName]; 
     157- (void)changeTunnel:(NSString *)uuid setName:(NSString *)newName 
     158{ 
     159        if(!tunnels) { return; } 
     160         
     161        NSEnumerator *e = [tunnels objectEnumerator]; 
     162        NSMutableDictionary *aTunnel; 
     163        while (aTunnel = [e nextObject]) 
     164        { 
     165                if([[aTunnel objectForKey:@"TunnelUUID"] isEqualToString:uuid]) 
     166                { 
     167                        [aTunnel setObject:newName forKey:@"TunnelName"]; 
     168                         
     169                        [[mainMenuTunnelsItem itemWithRepresentation:uuid] setTitle:newName]; 
     170                        [[statusbarMenuTunnelsItem itemWithRepresentation:uuid] setTitle:newName]; 
     171                        [[dockMenuTunnelsItem itemWithRepresentation:uuid] setTitle:newName]; 
    140172                         
    141173                        return; 
     
    147179{ 
    148180        Controller *controller = [Controller sharedController]; 
    149         int i; 
    150181        int active = 0; 
    151182         
     
    155186        } 
    156187         
    157         for(i=0; i < [tunnels count]; i++)  
    158         { 
    159                 if([[tunnels objectAtIndex:i] objectForKey:@"TunnelObject"]) 
     188        NSEnumerator *e = [tunnels objectEnumerator]; 
     189        NSDictionary *aTunnel; 
     190        while (aTunnel = [e nextObject]) 
     191        { 
     192                if([aTunnel objectForKey:@"TunnelObject"]) 
    160193                { 
    161194                        active++; 
     
    172205} 
    173206 
    174 - (void)removeTunnelWithName:(NSString *)name 
     207- (void)removeTunnelWithUUID:(NSString *)uuid 
    175208{ 
    176209        SSHTunnel *tunnel; 
    177         int i; 
    178          
    179         if(!tunnels) { return; } 
    180                  
    181         for(i=0; i < [tunnels count]; i++)  
    182         { 
    183                 if([[[tunnels objectAtIndex:i] objectForKey:@"TunnelName"] isEqualToString:name]) 
    184                 { 
    185                         tunnel = [[tunnels objectAtIndex:i] objectForKey:@"TunnelObject"]; 
    186                          
    187                         if(tunnel) 
     210         
     211        if(!tunnels) { return; } 
     212         
     213        NSEnumerator *e = [tunnels objectEnumerator]; 
     214        NSDictionary *aTunnel; 
     215        while (aTunnel = [e nextObject]) 
     216        { 
     217                if([[aTunnel objectForKey:@"TunnelUUID"] isEqualToString:uuid]) 
     218                { 
     219                        tunnel = [aTunnel objectForKey:@"TunnelObject"]; 
     220                         
     221                        if (tunnel) 
    188222                        { 
    189223                                [tunnel closeTunnel]; 
    190224                        } 
    191225                         
    192                         [tunnels removeObjectAtIndex:i]; 
    193  
    194                         [mainMenuTunnelsItem removeItem:[mainMenuTunnelsItem itemWithTitle:name]]; 
    195                         [dockMenuTunnelsItem removeItem:[dockMenuTunnelsItem itemWithTitle:name]]; 
    196                         [statusbarMenuTunnelsItem removeItem:[statusbarMenuTunnelsItem itemWithTitle:name]]; 
     226                        [tunnels removeObjectIdenticalTo:aTunnel]; 
     227 
     228                        [mainMenuTunnelsItem removeItem:[mainMenuTunnelsItem itemWithRepresentation:uuid]]; 
     229                        [dockMenuTunnelsItem removeItem:[dockMenuTunnelsItem itemWithRepresentation:uuid]]; 
     230                        [statusbarMenuTunnelsItem removeItem:[statusbarMenuTunnelsItem itemWithRepresentation:uuid]]; 
    197231                } 
    198232        } 
     
    200234 
    201235- (void)closeAllTunnels 
    202 { 
    203         int i; 
    204          
    205         if(!tunnels) { return; } 
    206          
    207         for(i=0; i < [tunnels count]; i++)  
    208         { 
    209                 if([[tunnels objectAtIndex:i] objectForKey:@"TunnelObject"])  
    210                 { 
    211                         SSHTunnel *tunnel = [[tunnels objectAtIndex:i] objectForKey:@"TunnelObject"]; 
    212                         NSString *name = [[tunnels objectAtIndex:i] objectForKey:@"TunnelName"]; 
     236{       
     237        if(!tunnels) { return; } 
     238         
     239        NSEnumerator *e = [tunnels objectEnumerator]; 
     240        NSMutableDictionary *aTunnel; 
     241        while (aTunnel = [e nextObject])  
     242        { 
     243                if([aTunnel objectForKey:@"TunnelObject"])  
     244                { 
     245                        SSHTunnel *tunnel = [aTunnel objectForKey:@"TunnelObject"]; 
     246                        NSString *uuid = [aTunnel objectForKey:@"TunnelUUID"]; 
    213247                         
    214248                        [tunnel closeTunnel]; 
    215                         [[tunnels objectAtIndex:i] removeObjectForKey:@"TunnelObject"]; 
    216                          
    217                         [[mainMenuTunnelsItem itemWithTitle:name] setState:NO]; 
    218                         [[statusbarMenuTunnelsItem itemWithTitle:name] setState:NO]; 
    219                         [[dockMenuTunnelsItem itemWithTitle:name] setState:NO]; 
     249                        [aTunnel removeObjectForKey:@"TunnelObject"]; 
     250                         
     251                        [[mainMenuTunnelsItem itemWithRepresentation:uuid] setState:NO]; 
     252                        [[statusbarMenuTunnelsItem itemWithRepresentation:uuid] setState:NO]; 
     253                        [[dockMenuTunnelsItem itemWithRepresentation:uuid] setState:NO]; 
    220254                } 
    221255        } 
     
    227261{ 
    228262        SSHTunnel *tunnel; 
    229         NSString *name
    230  
    231         int i; 
    232          
    233         if(!tunnels) { return; } 
    234          
    235         for(i=0; i < [tunnels count]; i++)  
    236         { 
    237                 if([[tunnels objectAtIndex:i] objectForKey:@"LaunchAfterSleep"])  
     263        NSString *uuid
     264         
     265        if(!tunnels) { return; } 
     266         
     267        NSEnumerator *e = [tunnels objectEnumerator]; 
     268        NSMutableDictionary *aTunnel; 
     269        while (aTunnel = [e nextObject]) 
     270        { 
     271                if([aTunnel objectForKey:@"LaunchAfterSleep"])  
    238272                { 
    239273                        /* First kill the tunnel, if it's still open. */ 
    240                         if([[tunnels objectAtIndex:i] objectForKey:@"TunnelObject"])  
     274                        if([aTunnel objectForKey:@"TunnelObject"])  
    241275                        { 
    242                                 tunnel = [[tunnels objectAtIndex:i] objectForKey:@"TunnelObject"]; 
    243                                 name = [[tunnels objectAtIndex:i] objectForKey:@"TunnelName"]; 
     276                                tunnel = [aTunnel objectForKey:@"TunnelObject"]; 
     277                                uuid = [aTunnel objectForKey:@"TunnelUUID"]; 
    244278                         
    245279                                [tunnel closeTunnel]; 
    246                                 [[tunnels objectAtIndex:i] removeObjectForKey:@"TunnelObject"]; 
    247                          
    248                                 [[mainMenuTunnelsItem itemWithTitle:name] setState:NO]; 
    249                                 [[statusbarMenuTunnelsItem itemWithTitle:name] setState:NO]; 
    250                                 [[dockMenuTunnelsItem itemWithTitle:name] setState:NO]; 
     280                                [aTunnel removeObjectForKey:@"TunnelObject"]; 
     281                         
     282                                [[mainMenuTunnelsItem itemWithRepresentation:uuid] setState:NO]; 
     283                                [[statusbarMenuTunnelsItem itemWithRepresentation:uuid] setState:NO]; 
     284                                [[dockMenuTunnelsItem itemWithRepresentation:uuid] setState:NO]; 
    251285                        } 
    252286 
    253                         [self openTunnelWithDict:[tunnels objectAtIndex:i]]; 
     287                        [self openTunnelWithDict:aTunnel]; 
    254288                } 
    255289        } 
     
    261295{ 
    262296        NSMutableDictionary *dict; 
    263         int i; 
    264297        SSHTunnel *tunnel; 
    265298         
     
    268301        if(!tunnels) { return; } 
    269302         
    270         for(i=0; i < [tunnels count]; i++)  
    271         { 
    272                 if([[[tunnels objectAtIndex:i] objectForKey:@"TunnelName"] isEqualToString:[sender title]])  
    273                 { 
    274                         dict = [tunnels objectAtIndex:i]; 
     303        NSEnumerator *e = [tunnels objectEnumerator]; 
     304        NSMutableDictionary *aTunnel; 
     305        while (aTunnel = [e nextObject]) 
     306        { 
     307                if([[aTunnel objectForKey:@"TunnelUUID"] isEqualToString:[sender representedObject]])  
     308                { 
     309                        dict = aTunnel; 
     310                        break; 
    275311                } 
    276312        } 
     
    301337- (void)handleClosedTunnels:(NSString *)contextInfo 
    302338{ 
    303         int i, last_terminated; 
     339        int last_terminated; 
    304340        NSString *output; 
    305341        BOOL fails_exceeded = NO; 
     
    309345        } 
    310346 
    311         [[mainMenuTunnelsItem itemWithTitle:contextInfo] setState:NO]; 
    312         [[statusbarMenuTunnelsItem itemWithTitle:contextInfo] setState:NO]; 
    313         [[dockMenuTunnelsItem itemWithTitle:contextInfo] setState:NO]; 
    314          
    315         if(!tunnels) { return; } 
    316  
    317         for(i=0; i < [tunnels count]; i++)  
    318         { 
    319                 if([[[tunnels objectAtIndex:i] objectForKey:@"TunnelName"] isEqualToString:contextInfo])  
    320                 { 
    321                         SSHTunnel *tunnel = [[tunnels objectAtIndex:i] objectForKey:@"TunnelObject"]; 
    322  
     347        [[mainMenuTunnelsItem itemWithRepresentation:contextInfo] setState:NO]; 
     348        [[statusbarMenuTunnelsItem itemWithRepresentation:contextInfo] setState:NO]; 
     349        [[dockMenuTunnelsItem itemWithRepresentation:contextInfo] setState:NO]; 
     350         
     351        if(!tunnels) { return; } 
     352         
     353        NSEnumerator *e = [tunnels objectEnumerator]; 
     354        NSMutableDictionary *aTunnel; 
     355        while (aTunnel = [e nextObject]) 
     356        { 
     357                if([[aTunnel objectForKey:@"TunnelUUID"] isEqualToString:contextInfo])  
     358                { 
     359                        SSHTunnel *tunnel = [aTunnel objectForKey:@"TunnelObject"]; 
     360                         
    323361                        if(tunnel)  
    324362                        { 
     
    328366                                output = [tunnel getOutput]; 
    329367                                 
    330                                 [[tunnels objectAtIndex:i] removeObjectForKey:@"TunnelObject"]; 
    331  
    332                                 if([[tunnels objectAtIndex:i] objectForKey:@"LastTerminated"])  
    333                                 { 
    334                                         last_terminated = [[[tunnels objectAtIndex:i] objectForKey:@"LastTerminated"] intValue]; 
     368                                [aTunnel removeObjectForKey:@"TunnelObject"]; 
     369 
     370                                if([aTunnel objectForKey:@"LastTerminated"])  
     371                                { 
     372                                        last_terminated = [[aTunnel objectForKey:@"LastTerminated"] intValue]; 
    335373                                } 
    336374 
     
    338376                                { 
    339377                                        fails_exceeded = YES; 
    340                                         [[tunnels objectAtIndex:i] removeObjectForKey:@"LastTerminated"]; 
     378                                        [aTunnel removeObjectForKey:@"LastTerminated"]; 
    341379                                }  
    342380                                 
    343381                                else if((allKeysOnAgent) && ([output length] < 1)) 
    344382                                { 
    345                                         [[tunnels objectAtIndex:i] setObject:[NSNumber numberWithInt:time(nil)] forKey:@"LastTerminated"]; 
    346                                         [self openTunnelWithDict:[tunnels objectAtIndex:i]]; 
     383                                        [aTunnel setObject:[NSNumber numberWithInt:time(nil)] forKey:@"LastTerminated"]; 
     384                                        [self openTunnelWithDict:aTunnel]; 
    347385                                } 
    348386 
     
    351389                                        [self warningPanelWithTitle:local(@"TunnelTerminated")  
    352390                                                         andMessage:[NSString stringWithFormat:@"(%@) %@", 
    353                                                                  [[tunnels objectAtIndex:i] objectForKey:@"TunnelName"], 
     391                                                                 [aTunnel objectForKey:@"TunnelName"], 
    354392                                                                 local(@"TunnelTerminatedAndCouldNotBeRestarted")]]; 
    355393                                } 
     
    358396                                        [self warningPanelWithTitle:local(@"TunnelTerminated")  
    359397                                                         andMessage:[NSString stringWithFormat:@"(%@) %@", 
    360                                                                  [[tunnels objectAtIndex:i] objectForKey:@"TunnelName"], 
     398                                                                 [aTunnel objectForKey:@"TunnelName"], 
    361399                                                                 local(@"TunnelTerminatedAndCouldNotBeRestarted")]]; 
    362400                                } 
     
    366404                                        [self warningPanelWithTitle:local(@"TunnelForwardingFailed")  
    367405                                                         andMessage:[NSString stringWithFormat:@"(%@) %@", 
    368                                                                  [[tunnels objectAtIndex:i] objectForKey:@"TunnelName"], 
     406                                                                 [aTunnel objectForKey:@"TunnelName"], 
    369407                                                                 local(@"ForwardingFailedDuringInitialization")]]; 
    370408                                }  
     
    374412                                        [self warningPanelWithTitle:local(@"TunnelSetupFailed") 
    375413                                                         andMessage:[NSString stringWithFormat:@"(%@) Error:\n%@",  
    376                                                                  [[tunnels objectAtIndex:i] objectForKey:@"TunnelName"], 
     414                                                                 [aTunnel objectForKey:@"TunnelName"], 
    377415                                                                 output]]; 
    378416                                } 
     
    382420                                        [self warningPanelWithTitle:local(@"TunnelTerminated") 
    383421                                                         andMessage:[NSString stringWithFormat:@"(%@) %@", 
    384                         &nb