]>
Commit | Line | Data |
---|---|---|
7cb34e5c A |
1 | /* |
2 | File: DNSServiceDiscoveryPref.m | |
3 | ||
4 | Abstract: System Preference Pane for Dynamic DNS and Wide-Area DNS Service Discovery | |
5 | ||
9f221bca | 6 | Copyright: (c) Copyright 2005-2011 Apple Inc. All rights reserved. |
7cb34e5c | 7 | |
9f221bca | 8 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. |
7cb34e5c A |
9 | ("Apple") in consideration of your agreement to the following terms, and your |
10 | use, installation, modification or redistribution of this Apple software | |
11 | constitutes acceptance of these terms. If you do not agree with these terms, | |
12 | please do not use, install, modify or redistribute this Apple software. | |
13 | ||
14 | In consideration of your agreement to abide by the following terms, and subject | |
15 | to these terms, Apple grants you a personal, non-exclusive license, under Apple's | |
16 | copyrights in this original Apple software (the "Apple Software"), to use, | |
17 | reproduce, modify and redistribute the Apple Software, with or without | |
18 | modifications, in source and/or binary forms; provided that if you redistribute | |
19 | the Apple Software in its entirety and without modifications, you must retain | |
20 | this notice and the following text and disclaimers in all such redistributions of | |
21 | the Apple Software. Neither the name, trademarks, service marks or logos of | |
9f221bca | 22 | Apple Inc. may be used to endorse or promote products derived from the |
7cb34e5c A |
23 | Apple Software without specific prior written permission from Apple. Except as |
24 | expressly stated in this notice, no other rights or licenses, express or implied, | |
25 | are granted by Apple herein, including but not limited to any patent rights that | |
26 | may be infringed by your derivative works or by other works in which the Apple | |
27 | Software may be incorporated. | |
28 | ||
29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO | |
30 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED | |
31 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
32 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | |
33 | COMBINATION WITH YOUR PRODUCTS. | |
34 | ||
35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR | |
36 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
37 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
38 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION | |
39 | OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT | |
40 | (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN | |
41 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
263eeeab | 42 | */ |
7cb34e5c A |
43 | |
44 | #import "DNSServiceDiscoveryPref.h" | |
12c5fa7a A |
45 | #import "CNDomainBrowserView.h" |
46 | #import "BonjourSCStore.h" | |
47 | #import "BonjourPrefTool.h" | |
48 | #import <Foundation/NSXPCConnection_Private.h> | |
7cb34e5c | 49 | |
32bb7e43 A |
50 | #include "../../Clients/ClientCommon.h" |
51 | ||
12c5fa7a A |
52 | #pragma mark - BonjourPrefTool |
53 | ||
54 | static OSStatus | |
55 | DNSPrefTool_SetKeychainEntry(NSDictionary * secretDictionary) | |
56 | { | |
57 | __block OSStatus result; | |
58 | BonjourPrefTool * prefTool; | |
59 | ||
60 | NSXPCConnection * _connectionToTool = [[NSXPCConnection alloc] initWithServiceName:@"com.apple.preference.bonjour.tool"]; | |
61 | _connectionToTool.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(BonjourPrefToolProtocol)]; | |
62 | [_connectionToTool resume]; | |
63 | ||
64 | #if 0 | |
65 | prefTool = [_connectionToTool remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { | |
66 | NSLog( @"Cannot connect to BonjourPrefTool: %@.", error); | |
67 | result = error.code; | |
68 | }]; | |
69 | #else | |
70 | prefTool = [_connectionToTool synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { | |
71 | NSLog( @"Cannot connect to BonjourPrefTool: %@.", error); | |
72 | result = error.code; | |
73 | }]; | |
32bb7e43 | 74 | #endif |
12c5fa7a A |
75 | [prefTool setKeychainEntry: secretDictionary withStatus: ^(OSStatus status){ |
76 | result = status; | |
77 | }]; | |
78 | ||
79 | [_connectionToTool invalidate]; | |
80 | ||
81 | return (result); | |
82 | } | |
83 | ||
84 | #pragma mark - | |
32bb7e43 | 85 | |
7cb34e5c A |
86 | @implementation DNSServiceDiscoveryPref |
87 | ||
83fb1e36 | 88 | static NSInteger |
7cb34e5c A |
89 | MyArrayCompareFunction(id val1, id val2, void *context) |
90 | { | |
67c8f8a1 | 91 | (void)context; // Unused |
7cb34e5c A |
92 | return CFStringCompare((CFStringRef)val1, (CFStringRef)val2, kCFCompareCaseInsensitive); |
93 | } | |
94 | ||
83fb1e36 | 95 | static NSInteger |
7cb34e5c A |
96 | MyDomainArrayCompareFunction(id val1, id val2, void *context) |
97 | { | |
67c8f8a1 | 98 | (void)context; // Unused |
7cb34e5c A |
99 | NSString *domain1 = [val1 objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; |
100 | NSString *domain2 = [val2 objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; | |
101 | return CFStringCompare((CFStringRef)domain1, (CFStringRef)domain2, kCFCompareCaseInsensitive); | |
102 | } | |
103 | ||
104 | ||
7cb34e5c A |
105 | static void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) |
106 | { | |
67c8f8a1 A |
107 | (void)store; // Unused |
108 | (void)changedKeys; // Unused | |
12c5fa7a | 109 | DNSServiceDiscoveryPref * me = (__bridge DNSServiceDiscoveryPref *)context; |
7cb34e5c A |
110 | assert(me != NULL); |
111 | ||
112 | [me setupInitialValues]; | |
113 | } | |
114 | ||
115 | ||
7cb34e5c A |
116 | -(void)updateStatusImageView |
117 | { | |
118 | int value = [self statusForHostName:currentHostName]; | |
119 | if (value == 0) [statusImageView setImage:successImage]; | |
120 | else if (value > 0) [statusImageView setImage:inprogressImage]; | |
121 | else [statusImageView setImage:failureImage]; | |
122 | } | |
123 | ||
124 | ||
125 | - (void)watchForPreferenceChanges | |
126 | { | |
12c5fa7a | 127 | SCDynamicStoreContext context = { 0, (__bridge void * _Nullable)(self), NULL, NULL, NULL }; |
7cb34e5c A |
128 | SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("watchForPreferenceChanges"), NetworkChanged, &context); |
129 | CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |
130 | CFRunLoopSourceRef rls; | |
131 | ||
132 | assert(store != NULL); | |
133 | assert(keys != NULL); | |
134 | ||
135 | CFArrayAppendValue(keys, SC_DYNDNS_STATE_KEY); | |
136 | CFArrayAppendValue(keys, SC_DYNDNS_SETUP_KEY); | |
137 | ||
138 | (void)SCDynamicStoreSetNotificationKeys(store, keys, NULL); | |
139 | ||
140 | rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); | |
141 | assert(rls != NULL); | |
142 | ||
143 | CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopCommonModes); | |
9f221bca | 144 | CFRelease(rls); |
7cb34e5c A |
145 | |
146 | CFRelease(keys); | |
147 | CFRelease(store); | |
148 | } | |
149 | ||
150 | ||
151 | -(int)statusForHostName:(NSString * )domain | |
152 | { | |
153 | SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("statusForHostName"), NULL, NULL); | |
154 | NSString *lowercaseDomain = [domain lowercaseString]; | |
155 | int status = 1; | |
156 | ||
157 | assert(store != NULL); | |
158 | ||
12c5fa7a | 159 | NSDictionary *dynamicDNS = (NSDictionary *)CFBridgingRelease(SCDynamicStoreCopyValue(store, SC_DYNDNS_STATE_KEY)); |
7cb34e5c A |
160 | if (dynamicDNS) { |
161 | NSDictionary *hostNames = [dynamicDNS objectForKey:(NSString *)SC_DYNDNS_HOSTNAMES_KEY]; | |
162 | NSDictionary *infoDict = [hostNames objectForKey:lowercaseDomain]; | |
163 | if (infoDict) status = [[infoDict objectForKey:(NSString*)SC_DYNDNS_STATUS_KEY] intValue]; | |
7cb34e5c A |
164 | } |
165 | CFRelease(store); | |
166 | ||
167 | return status; | |
168 | } | |
169 | ||
170 | ||
7cb34e5c A |
171 | -(void)readPreferences |
172 | { | |
173 | NSDictionary *origDict; | |
174 | NSArray *regDomainArray; | |
175 | NSArray *hostArray; | |
176 | ||
12c5fa7a A |
177 | if (currentRegDomain) currentRegDomain = nil; |
178 | if (currentBrowseDomainsArray) currentBrowseDomainsArray = nil; | |
179 | if (currentHostName) currentHostName = nil; | |
7cb34e5c A |
180 | |
181 | SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("com.apple.preference.bonjour"), NULL, NULL); | |
12c5fa7a | 182 | origDict = (NSDictionary *)CFBridgingRelease(SCDynamicStoreCopyValue(store, SC_DYNDNS_SETUP_KEY)); |
7cb34e5c A |
183 | |
184 | regDomainArray = [origDict objectForKey:(NSString *)SC_DYNDNS_REGDOMAINS_KEY]; | |
185 | if (regDomainArray && [regDomainArray count] > 0) { | |
186 | currentRegDomain = [[[regDomainArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY] copy]; | |
187 | currentWideAreaState = [[[regDomainArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY] intValue]; | |
188 | } else { | |
12c5fa7a | 189 | currentRegDomain = @""; |
7cb34e5c A |
190 | currentWideAreaState = NO; |
191 | } | |
192 | ||
12c5fa7a | 193 | currentBrowseDomainsArray = [origDict objectForKey:(NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY]; |
7cb34e5c A |
194 | |
195 | hostArray = [origDict objectForKey:(NSString *)SC_DYNDNS_HOSTNAMES_KEY]; | |
196 | if (hostArray && [hostArray count] > 0) { | |
197 | currentHostName = [[[hostArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY] copy]; | |
198 | } else { | |
12c5fa7a | 199 | currentHostName = @""; |
7cb34e5c A |
200 | } |
201 | ||
9f221bca | 202 | if (store) CFRelease(store); |
7cb34e5c A |
203 | } |
204 | ||
205 | ||
4a95efb2 | 206 | - (void)tableViewSelectionDidChange:(NSNotification *)notification |
7cb34e5c A |
207 | { |
208 | [removeBrowseDomainButton setEnabled:[[notification object] numberOfSelectedRows]]; | |
209 | } | |
210 | ||
211 | ||
4a95efb2 | 212 | - (IBAction)addBrowseDomainClicked:(id)sender |
7cb34e5c | 213 | { |
12c5fa7a A |
214 | NSWindow * window = (([NSEvent modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask) ? addBrowseDomainManualWindow : addBrowseDomainWindow; |
215 | [browseDomainTextField setStringValue: [NSString string]]; | |
7cb34e5c | 216 | |
12c5fa7a A |
217 | [self disableControls]; |
218 | [NSApp beginSheet:window modalForWindow:mainWindow modalDelegate:self | |
219 | didEndSelector:@selector(addBrowseDomainSheetDidEnd:returnCode:contextInfo:) contextInfo:(__bridge void * _Null_unspecified)(sender)]; | |
7cb34e5c A |
220 | |
221 | [browseDomainList deselectAll:sender]; | |
222 | [self updateApplyButtonState]; | |
223 | } | |
224 | ||
225 | ||
4a95efb2 | 226 | - (IBAction)removeBrowseDomainClicked:(id)sender |
7cb34e5c | 227 | { |
67c8f8a1 | 228 | (void)sender; // Unused |
7cb34e5c A |
229 | int selectedBrowseDomain = [browseDomainList selectedRow]; |
230 | [browseDomainsArray removeObjectAtIndex:selectedBrowseDomain]; | |
231 | [browseDomainList reloadData]; | |
232 | [self updateApplyButtonState]; | |
233 | } | |
234 | ||
235 | ||
4a95efb2 | 236 | - (IBAction)enableBrowseDomainClicked:(id)sender |
7cb34e5c A |
237 | { |
238 | NSTableView *tableView = sender; | |
239 | NSMutableDictionary *browseDomainDict; | |
12c5fa7a | 240 | NSInteger value; |
7cb34e5c A |
241 | |
242 | browseDomainDict = [[browseDomainsArray objectAtIndex:[tableView clickedRow]] mutableCopy]; | |
243 | value = [[browseDomainDict objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY] intValue]; | |
12c5fa7a | 244 | [browseDomainDict setObject:[NSNumber numberWithInt:(!value)] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY]; |
7cb34e5c A |
245 | [browseDomainsArray replaceObjectAtIndex:[tableView clickedRow] withObject:browseDomainDict]; |
246 | [tableView reloadData]; | |
247 | [self updateApplyButtonState]; | |
248 | } | |
249 | ||
250 | ||
251 | ||
4a95efb2 | 252 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView |
7cb34e5c | 253 | { |
67c8f8a1 | 254 | (void)tableView; // Unused |
7cb34e5c A |
255 | int numberOfRows = 0; |
256 | ||
257 | if (browseDomainsArray) { | |
258 | numberOfRows = [browseDomainsArray count]; | |
259 | } | |
260 | return numberOfRows; | |
261 | } | |
262 | ||
263 | ||
4a95efb2 | 264 | - (void)tabView:(NSTabView *)xtabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem |
7cb34e5c | 265 | { |
67c8f8a1 A |
266 | (void)xtabView; // Unused |
267 | (void)tabViewItem; // Unused | |
7cb34e5c A |
268 | [browseDomainList deselectAll:self]; |
269 | [mainWindow makeFirstResponder:nil]; | |
270 | } | |
271 | ||
272 | ||
4a95efb2 | 273 | - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row |
7cb34e5c | 274 | { |
67c8f8a1 | 275 | (void)tableView; // Unused |
7cb34e5c A |
276 | NSDictionary *browseDomainDict; |
277 | id value = nil; | |
278 | ||
279 | if (browseDomainsArray) { | |
280 | browseDomainDict = [browseDomainsArray objectAtIndex:row]; | |
281 | if (browseDomainDict) { | |
282 | if ([[tableColumn identifier] isEqualTo:(NSString *)SC_DYNDNS_ENABLED_KEY]) { | |
283 | value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY]; | |
284 | } else if ([[tableColumn identifier] isEqualTo:(NSString *)SC_DYNDNS_DOMAIN_KEY]) { | |
12c5fa7a | 285 | value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; |
7cb34e5c A |
286 | } |
287 | } | |
288 | } | |
289 | return value; | |
290 | } | |
291 | ||
292 | ||
293 | - (void)setupInitialValues | |
294 | { | |
295 | [self readPreferences]; | |
296 | ||
297 | if (currentHostName) { | |
298 | [hostName setStringValue:currentHostName]; | |
299 | [self updateStatusImageView]; | |
300 | } | |
301 | ||
302 | if (browseDomainsArray) { | |
7cb34e5c A |
303 | browseDomainsArray = nil; |
304 | } | |
305 | ||
306 | if (currentBrowseDomainsArray) { | |
307 | browseDomainsArray = [currentBrowseDomainsArray mutableCopy]; | |
308 | if (browseDomainsArray) { | |
309 | [browseDomainsArray sortUsingFunction:MyDomainArrayCompareFunction context:nil]; | |
310 | if ([browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO) { | |
12c5fa7a | 311 | [BonjourSCStore setObject: browseDomainsArray forKey: (NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY]; |
7cb34e5c A |
312 | currentBrowseDomainsArray = [browseDomainsArray copy]; |
313 | } | |
314 | } | |
315 | } else { | |
316 | browseDomainsArray = nil; | |
317 | } | |
318 | [browseDomainList reloadData]; | |
319 | ||
320 | if (currentRegDomain && ([currentRegDomain length] > 0)) { | |
12c5fa7a | 321 | regDomainView.domain = currentRegDomain; |
7cb34e5c A |
322 | } |
323 | ||
324 | if (currentWideAreaState) { | |
325 | [self toggleWideAreaBonjour:YES]; | |
326 | } else { | |
327 | [self toggleWideAreaBonjour:NO]; | |
328 | } | |
329 | ||
330 | if (hostNameSharedSecretValue) { | |
7cb34e5c A |
331 | hostNameSharedSecretValue = nil; |
332 | } | |
333 | ||
334 | if (regSharedSecretValue) { | |
7cb34e5c A |
335 | regSharedSecretValue = nil; |
336 | } | |
337 | ||
338 | [self updateApplyButtonState]; | |
339 | [mainWindow makeFirstResponder:nil]; | |
340 | [browseDomainList deselectAll:self]; | |
341 | [removeBrowseDomainButton setEnabled:NO]; | |
342 | } | |
343 | ||
344 | ||
345 | ||
346 | - (void)awakeFromNib | |
12c5fa7a | 347 | { |
7cb34e5c | 348 | prefsNeedUpdating = NO; |
7cb34e5c A |
349 | browseDomainListEnabled = NO; |
350 | defaultRegDomain = nil; | |
351 | currentRegDomain = nil; | |
352 | currentBrowseDomainsArray = nil; | |
353 | currentHostName = nil; | |
354 | hostNameSharedSecretValue = nil; | |
355 | regSharedSecretValue = nil; | |
356 | browseDomainsArray = nil; | |
7cb34e5c A |
357 | currentWideAreaState = NO; |
358 | NSString *successPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"success" ofType:@"tiff"]; | |
359 | NSString *inprogressPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"inprogress" ofType:@"tiff"]; | |
360 | NSString *failurePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"failure" ofType:@"tiff"]; | |
361 | ||
362 | registrationDataSource = [[NSMutableArray alloc] init]; | |
7cb34e5c A |
363 | successImage = [[NSImage alloc] initWithContentsOfFile:successPath]; |
364 | inprogressImage = [[NSImage alloc] initWithContentsOfFile:inprogressPath]; | |
365 | failureImage = [[NSImage alloc] initWithContentsOfFile:failurePath]; | |
366 | ||
367 | [tabView selectFirstTabViewItem:self]; | |
368 | [self setupInitialValues]; | |
7cb34e5c | 369 | [self watchForPreferenceChanges]; |
7cb34e5c A |
370 | |
371 | } | |
372 | ||
12c5fa7a A |
373 | - (void)willSelect |
374 | { | |
375 | [super willSelect]; | |
376 | [bonjourBrowserView startBrowse]; | |
377 | [registrationBrowserView startBrowse]; | |
378 | ||
379 | } | |
380 | ||
381 | - (void)willUnselect | |
382 | { | |
383 | [super willUnselect]; | |
384 | [bonjourBrowserView stopBrowse]; | |
385 | [registrationBrowserView stopBrowse]; | |
386 | } | |
7cb34e5c A |
387 | |
388 | - (IBAction)closeMyCustomSheet:(id)sender | |
389 | { | |
12c5fa7a | 390 | BOOL result = [sender tag]; |
7cb34e5c A |
391 | |
392 | if (result) [NSApp endSheet:[sender window] returnCode:NSOKButton]; | |
393 | else [NSApp endSheet:[sender window] returnCode:NSCancelButton]; | |
394 | } | |
395 | ||
396 | ||
397 | - (void)sharedSecretSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo | |
398 | { | |
12c5fa7a | 399 | NSButton * button = (__bridge NSButton *)contextInfo; |
7cb34e5c A |
400 | [sheet orderOut:self]; |
401 | [self enableControls]; | |
402 | ||
403 | if (returnCode == NSOKButton) { | |
404 | if ([button isEqualTo:hostNameSharedSecretButton]) { | |
405 | hostNameSharedSecretName = [[NSString alloc] initWithString:[sharedSecretName stringValue]]; | |
406 | hostNameSharedSecretValue = [[NSString alloc] initWithString:[sharedSecretValue stringValue]]; | |
407 | } else { | |
408 | regSharedSecretName = [[NSString alloc] initWithString:[sharedSecretName stringValue]]; | |
409 | regSharedSecretValue = [[NSString alloc] initWithString:[sharedSecretValue stringValue]]; | |
410 | } | |
411 | [self updateApplyButtonState]; | |
412 | } | |
413 | [sharedSecretValue setStringValue:@""]; | |
414 | } | |
415 | ||
416 | ||
417 | - (BOOL)domainAlreadyInList:(NSString *)domainString | |
418 | { | |
419 | if (browseDomainsArray) { | |
420 | NSDictionary *domainDict; | |
421 | NSString *domainName; | |
422 | NSEnumerator *arrayEnumerator = [browseDomainsArray objectEnumerator]; | |
67c8f8a1 | 423 | while ((domainDict = [arrayEnumerator nextObject]) != NULL) { |
7cb34e5c A |
424 | domainName = [domainDict objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; |
425 | if ([domainString caseInsensitiveCompare:domainName] == NSOrderedSame) return YES; | |
426 | } | |
427 | } | |
428 | return NO; | |
429 | } | |
430 | ||
431 | ||
432 | - (NSString *)trimCharactersFromDomain:(NSString *)domain | |
433 | { | |
12c5fa7a | 434 | NSMutableCharacterSet * trimSet = [NSMutableCharacterSet whitespaceCharacterSet]; |
7cb34e5c A |
435 | [trimSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; |
436 | return [domain stringByTrimmingCharactersInSet:trimSet]; | |
437 | } | |
438 | ||
439 | ||
440 | - (void)addBrowseDomainSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo | |
441 | { | |
67c8f8a1 | 442 | (void)contextInfo; // Unused |
7cb34e5c A |
443 | [sheet orderOut:self]; |
444 | [self enableControls]; | |
445 | ||
446 | if (returnCode == NSOKButton) { | |
12c5fa7a A |
447 | NSString * newBrowseDomainString; |
448 | if(sheet == addBrowseDomainManualWindow) newBrowseDomainString = [self trimCharactersFromDomain:[browseDomainTextField stringValue]]; | |
449 | else newBrowseDomainString = [self trimCharactersFromDomain:bonjourBrowserView.selectedDNSDomain]; | |
7cb34e5c | 450 | NSMutableDictionary *newBrowseDomainDict; |
7cb34e5c A |
451 | if (browseDomainsArray == nil) browseDomainsArray = [[NSMutableArray alloc] initWithCapacity:0]; |
452 | if ([self domainAlreadyInList:newBrowseDomainString] == NO) { | |
12c5fa7a | 453 | newBrowseDomainDict = [[NSMutableDictionary alloc] initWithCapacity:2]; |
7cb34e5c A |
454 | |
455 | [newBrowseDomainDict setObject:newBrowseDomainString forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; | |
12c5fa7a | 456 | [newBrowseDomainDict setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY]; |
7cb34e5c A |
457 | |
458 | [browseDomainsArray addObject:newBrowseDomainDict]; | |
459 | [browseDomainsArray sortUsingFunction:MyDomainArrayCompareFunction context:nil]; | |
460 | [browseDomainList reloadData]; | |
461 | [self updateApplyButtonState]; | |
462 | } | |
463 | } | |
464 | } | |
465 | ||
7cb34e5c A |
466 | -(void)validateTextFields |
467 | { | |
468 | [hostName validateEditing]; | |
12c5fa7a | 469 | [browseDomainTextField validateEditing]; |
7cb34e5c A |
470 | } |
471 | ||
472 | ||
473 | - (IBAction)changeButtonPressed:(id)sender | |
474 | { | |
475 | NSString * keyName; | |
476 | ||
477 | [self disableControls]; | |
478 | [self validateTextFields]; | |
479 | [mainWindow makeFirstResponder:nil]; | |
480 | [browseDomainList deselectAll:sender]; | |
481 | ||
482 | if ([sender isEqualTo:hostNameSharedSecretButton]) { | |
483 | if (hostNameSharedSecretValue) { | |
484 | [sharedSecretValue setStringValue:hostNameSharedSecretValue]; | |
67c8f8a1 | 485 | } else if ((keyName = [self sharedSecretKeyName:[hostName stringValue]]) != NULL) { |
7cb34e5c A |
486 | [sharedSecretName setStringValue:keyName]; |
487 | [sharedSecretValue setStringValue:@"****************"]; | |
488 | } else { | |
489 | [sharedSecretName setStringValue:[hostName stringValue]]; | |
490 | [sharedSecretValue setStringValue:@""]; | |
491 | } | |
492 | ||
493 | } else { | |
494 | if (regSharedSecretValue) { | |
495 | [sharedSecretValue setStringValue:regSharedSecretValue]; | |
12c5fa7a | 496 | } else if ((keyName = [self sharedSecretKeyName:regDomainView.domain]) != NULL) { |
7cb34e5c A |
497 | [sharedSecretName setStringValue:keyName]; |
498 | [sharedSecretValue setStringValue:@"****************"]; | |
499 | } else { | |
12c5fa7a | 500 | [sharedSecretName setStringValue:regDomainView.domain]; |
7cb34e5c A |
501 | [sharedSecretValue setStringValue:@""]; |
502 | } | |
503 | } | |
504 | ||
505 | [sharedSecretWindow resignFirstResponder]; | |
506 | ||
507 | if ([[sharedSecretName stringValue] length] > 0) [sharedSecretWindow makeFirstResponder:sharedSecretValue]; | |
508 | else [sharedSecretWindow makeFirstResponder:sharedSecretName]; | |
509 | ||
510 | [NSApp beginSheet:sharedSecretWindow modalForWindow:mainWindow modalDelegate:self | |
12c5fa7a A |
511 | didEndSelector:@selector(sharedSecretSheetDidEnd:returnCode:contextInfo:) contextInfo:(__bridge void * _Null_unspecified)(sender)]; |
512 | } | |
513 | ||
514 | ||
515 | - (IBAction)selectWideAreaDomainButtonPressed:(id)sender | |
516 | { | |
517 | NSWindow * window = (([NSEvent modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask) ? selectRegistrationDomainManualWindow : selectRegistrationDomainWindow; | |
518 | regDomainTextField.stringValue = regDomainView.domain; | |
519 | ||
520 | [self disableControls]; | |
521 | [NSApp beginSheet:window modalForWindow:mainWindow modalDelegate:self | |
522 | didEndSelector:@selector(selectWideAreaDomainSheetDidEnd:returnCode:contextInfo:) contextInfo:(__bridge void * _Null_unspecified)(sender)]; | |
523 | ||
524 | [self updateApplyButtonState]; | |
7cb34e5c A |
525 | } |
526 | ||
12c5fa7a A |
527 | - (void)selectWideAreaDomainSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo |
528 | { | |
529 | (void)contextInfo; // Unused | |
530 | [sheet orderOut:self]; | |
531 | [self enableControls]; | |
532 | ||
533 | if (returnCode == NSOKButton) { | |
534 | NSString * newRegDomainString; | |
535 | if(sheet == selectRegistrationDomainManualWindow) newRegDomainString = [self trimCharactersFromDomain:[regDomainTextField stringValue]]; | |
536 | else newRegDomainString = [self trimCharactersFromDomain:registrationBrowserView.selectedDNSDomain]; | |
537 | regDomainView.domain = newRegDomainString; | |
538 | [self updateApplyButtonState]; | |
539 | } | |
540 | } | |
7cb34e5c A |
541 | |
542 | - (IBAction)wideAreaCheckBoxChanged:(id)sender | |
543 | { | |
544 | [self toggleWideAreaBonjour:[sender state]]; | |
545 | [self updateApplyButtonState]; | |
546 | [mainWindow makeFirstResponder:nil]; | |
547 | } | |
548 | ||
549 | ||
12c5fa7a | 550 | |
7cb34e5c A |
551 | - (void)updateApplyButtonState |
552 | { | |
553 | NSString *hostNameString = [hostName stringValue]; | |
12c5fa7a | 554 | NSString *regDomainString = regDomainView.domain; |
9f221bca A |
555 | if ((currentHostName && ([hostNameString compare:currentHostName] != NSOrderedSame)) || |
556 | (currentRegDomain && ([regDomainString compare:currentRegDomain] != NSOrderedSame) && ([wideAreaCheckBox state])) || | |
7cb34e5c A |
557 | (currentHostName == nil && ([hostNameString length]) > 0) || |
558 | (currentRegDomain == nil && ([regDomainString length]) > 0) || | |
559 | (currentWideAreaState != [wideAreaCheckBox state]) || | |
560 | (hostNameSharedSecretValue != nil) || | |
561 | (regSharedSecretValue != nil) || | |
562 | (browseDomainsArray && [browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO)) | |
563 | { | |
564 | [self enableApplyButton]; | |
565 | } else { | |
566 | [self disableApplyButton]; | |
567 | } | |
568 | } | |
569 | ||
570 | ||
4a95efb2 | 571 | - (void)controlTextDidChange:(NSNotification *)notification |
7cb34e5c | 572 | { |
67c8f8a1 | 573 | (void)notification; // Unused |
7cb34e5c A |
574 | [self updateApplyButtonState]; |
575 | } | |
576 | ||
577 | ||
7cb34e5c A |
578 | - (NSMutableArray *)registrationDataSource |
579 | { | |
580 | return registrationDataSource; | |
581 | } | |
582 | ||
583 | ||
7cb34e5c A |
584 | - (NSString *)currentRegDomain |
585 | { | |
586 | return currentRegDomain; | |
587 | } | |
588 | ||
589 | ||
7cb34e5c A |
590 | - (NSArray *)currentBrowseDomainsArray |
591 | { | |
592 | return currentBrowseDomainsArray; | |
593 | } | |
594 | ||
595 | ||
596 | - (NSString *)currentHostName | |
597 | { | |
598 | return currentHostName; | |
599 | } | |
600 | ||
601 | ||
602 | - (NSString *)defaultRegDomain | |
603 | { | |
604 | return defaultRegDomain; | |
605 | } | |
606 | ||
607 | ||
608 | - (void)setDefaultRegDomain:(NSString *)domain | |
609 | { | |
7cb34e5c | 610 | defaultRegDomain = domain; |
7cb34e5c A |
611 | } |
612 | ||
613 | ||
614 | - (void)didSelect | |
615 | { | |
616 | [super didSelect]; | |
617 | mainWindow = [[self mainView] window]; | |
618 | } | |
619 | ||
7cb34e5c | 620 | - (void)mainViewDidLoad |
12c5fa7a | 621 | { |
7cb34e5c A |
622 | [comboAuthButton setString:"system.preferences"]; |
623 | [comboAuthButton setDelegate:self]; | |
7cb34e5c | 624 | [comboAuthButton setAutoupdate:YES]; |
12c5fa7a | 625 | [super mainViewDidLoad]; |
7cb34e5c A |
626 | } |
627 | ||
628 | ||
629 | ||
630 | - (IBAction)applyClicked:(id)sender | |
631 | { | |
67c8f8a1 | 632 | (void)sender; // Unused |
7cb34e5c A |
633 | [self applyCurrentState]; |
634 | } | |
635 | ||
636 | ||
637 | - (void)applyCurrentState | |
638 | { | |
639 | [self validateTextFields]; | |
12c5fa7a A |
640 | [self savePreferences]; |
641 | [self disableApplyButton]; | |
642 | [mainWindow makeFirstResponder:nil]; | |
7cb34e5c A |
643 | } |
644 | ||
645 | ||
646 | - (void)enableApplyButton | |
647 | { | |
648 | [applyButton setEnabled:YES]; | |
649 | [revertButton setEnabled:YES]; | |
650 | prefsNeedUpdating = YES; | |
651 | } | |
652 | ||
653 | ||
654 | - (void)disableApplyButton | |
655 | { | |
656 | [applyButton setEnabled:NO]; | |
657 | [revertButton setEnabled:NO]; | |
658 | prefsNeedUpdating = NO; | |
659 | } | |
660 | ||
661 | ||
662 | - (void)toggleWideAreaBonjour:(BOOL)state | |
663 | { | |
664 | [wideAreaCheckBox setState:state]; | |
12c5fa7a | 665 | [registrationSelectButton setEnabled:state]; |
7cb34e5c A |
666 | [registrationSharedSecretButton setEnabled:state]; |
667 | } | |
668 | ||
669 | ||
4a95efb2 | 670 | - (IBAction)revertClicked:(id)sender |
7cb34e5c A |
671 | { |
672 | [self restorePreferences]; | |
673 | [browseDomainList deselectAll:sender]; | |
674 | [mainWindow makeFirstResponder:nil]; | |
675 | } | |
676 | ||
677 | ||
678 | - (void)restorePreferences | |
679 | { | |
680 | [self setupInitialValues]; | |
681 | } | |
682 | ||
683 | ||
684 | - (void)savePanelWillClose:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo | |
685 | { | |
67c8f8a1 | 686 | (void)sheet; // Unused |
12c5fa7a | 687 | DNSServiceDiscoveryPref * me = (__bridge DNSServiceDiscoveryPref *)contextInfo; |
7cb34e5c A |
688 | |
689 | if (returnCode == NSAlertDefaultReturn) { | |
690 | [me applyCurrentState]; | |
691 | } else if (returnCode == NSAlertAlternateReturn ) { | |
692 | [me restorePreferences]; | |
693 | } | |
694 | ||
695 | [me enableControls]; | |
696 | [me replyToShouldUnselect:(returnCode != NSAlertOtherReturn)]; | |
697 | } | |
698 | ||
699 | ||
700 | -(SecKeychainItemRef)copyKeychainItemforDomain:(NSString *)domain | |
701 | { | |
702 | const char * serviceName = [domain UTF8String]; | |
703 | UInt32 type = 'ddns'; | |
704 | UInt32 typeLength = sizeof(type); | |
705 | ||
706 | SecKeychainAttribute attrs[] = { { kSecServiceItemAttr, strlen(serviceName), (char *)serviceName }, | |
707 | { kSecTypeItemAttr, typeLength, (UInt32 *)&type } }; | |
708 | ||
709 | SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; | |
710 | SecKeychainSearchRef searchRef; | |
711 | SecKeychainItemRef itemRef = NULL; | |
712 | OSStatus err; | |
713 | ||
714 | err = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributes, &searchRef); | |
715 | if (err == noErr) { | |
716 | err = SecKeychainSearchCopyNext(searchRef, &itemRef); | |
717 | if (err != noErr) itemRef = NULL; | |
718 | } | |
719 | return itemRef; | |
720 | } | |
721 | ||
722 | ||
723 | -(NSString *)sharedSecretKeyName:(NSString * )domain | |
724 | { | |
725 | SecKeychainItemRef itemRef = NULL; | |
726 | NSString *keyName = nil; | |
727 | OSStatus err; | |
728 | ||
729 | err = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); | |
730 | assert(err == noErr); | |
731 | ||
732 | itemRef = [self copyKeychainItemforDomain:[domain lowercaseString]]; | |
733 | if (itemRef) { | |
734 | UInt32 tags[1]; | |
735 | SecKeychainAttributeInfo attrInfo; | |
736 | SecKeychainAttributeList *attrList = NULL; | |
737 | SecKeychainAttribute attribute; | |
67c8f8a1 | 738 | unsigned int i; |
7cb34e5c A |
739 | |
740 | tags[0] = kSecAccountItemAttr; | |
741 | attrInfo.count = 1; | |
742 | attrInfo.tag = tags; | |
743 | attrInfo.format = NULL; | |
744 | ||
745 | err = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, &attrList, NULL, NULL); | |
746 | if (err == noErr) { | |
747 | for (i = 0; i < attrList->count; i++) { | |
748 | attribute = attrList->attr[i]; | |
749 | if (attribute.tag == kSecAccountItemAttr) { | |
750 | keyName = [[NSString alloc] initWithBytes:attribute.data length:attribute.length encoding:NSUTF8StringEncoding]; | |
751 | break; | |
752 | } | |
753 | } | |
754 | if (attrList) (void)SecKeychainItemFreeAttributesAndData(attrList, NULL); | |
755 | } | |
756 | CFRelease(itemRef); | |
757 | } | |
12c5fa7a | 758 | return keyName; |
7cb34e5c A |
759 | } |
760 | ||
761 | ||
762 | -(NSString *)domainForHostName:(NSString *)hostNameString | |
763 | { | |
764 | NSString * domainName = nil; | |
765 | char text[64]; | |
766 | char * ptr = NULL; | |
767 | ||
768 | ptr = (char *)[hostNameString UTF8String]; | |
769 | if (ptr) { | |
770 | ptr = (char *)GetNextLabel(ptr, text); | |
771 | domainName = [[NSString alloc] initWithUTF8String:(const char *)ptr]; | |
772 | } | |
12c5fa7a | 773 | return (domainName); |
7cb34e5c A |
774 | } |
775 | ||
776 | ||
777 | - (NSData *)dataForDomain:(NSString *)domainName isEnabled:(BOOL)enabled | |
778 | { | |
779 | NSMutableArray *domainsArray; | |
780 | NSMutableDictionary *domainDict = nil; | |
781 | ||
782 | if (domainName && [domainName length] > 0) { | |
12c5fa7a | 783 | domainDict= [NSMutableDictionary dictionaryWithCapacity:2]; |
7cb34e5c | 784 | [domainDict setObject:domainName forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; |
12c5fa7a | 785 | [domainDict setObject:[NSNumber numberWithBool:enabled] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY]; |
7cb34e5c | 786 | } |
12c5fa7a | 787 | domainsArray = [NSMutableArray arrayWithCapacity:1]; |
7cb34e5c A |
788 | if (domainDict) [domainsArray addObject:domainDict]; |
789 | return [NSArchiver archivedDataWithRootObject:domainsArray]; | |
790 | } | |
791 | ||
792 | ||
793 | - (NSData *)dataForDomainArray:(NSArray *)domainArray | |
794 | { | |
795 | return [NSArchiver archivedDataWithRootObject:domainArray]; | |
796 | } | |
797 | ||
798 | ||
12c5fa7a | 799 | - (NSDictionary *)dictionaryForSharedSecret:(NSString *)secret domain:(NSString *)domainName key:(NSString *)keyName |
7cb34e5c | 800 | { |
12c5fa7a | 801 | NSMutableDictionary *sharedSecretDict = [NSMutableDictionary dictionaryWithCapacity:3]; |
7cb34e5c A |
802 | [sharedSecretDict setObject:secret forKey:(NSString *)SC_DYNDNS_SECRET_KEY]; |
803 | [sharedSecretDict setObject:[domainName lowercaseString] forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; | |
804 | [sharedSecretDict setObject:keyName forKey:(NSString *)SC_DYNDNS_KEYNAME_KEY]; | |
12c5fa7a | 805 | return sharedSecretDict; |
7cb34e5c A |
806 | } |
807 | ||
808 | ||
809 | -(void)savePreferences | |
810 | { | |
811 | NSString *hostNameString = [hostName stringValue]; | |
12c5fa7a | 812 | NSString *regDomainString = regDomainView.domain; |
7cb34e5c A |
813 | NSString *tempHostNameSharedSecretName = hostNameSharedSecretName; |
814 | NSString *tempRegSharedSecretName = regSharedSecretName; | |
7cb34e5c A |
815 | BOOL regSecretWasSet = NO; |
816 | BOOL hostSecretWasSet = NO; | |
12c5fa7a | 817 | BOOL updateHostname = NO; |
7cb34e5c A |
818 | |
819 | hostNameString = [self trimCharactersFromDomain:hostNameString]; | |
7cb34e5c A |
820 | regDomainString = [self trimCharactersFromDomain:regDomainString]; |
821 | tempHostNameSharedSecretName = [self trimCharactersFromDomain:tempHostNameSharedSecretName]; | |
822 | tempRegSharedSecretName = [self trimCharactersFromDomain:tempRegSharedSecretName]; | |
823 | ||
824 | [hostName setStringValue:hostNameString]; | |
12c5fa7a | 825 | regDomainView.domain = regDomainString; |
7cb34e5c A |
826 | |
827 | // Convert Shared Secret account names to lowercase. | |
828 | tempHostNameSharedSecretName = [tempHostNameSharedSecretName lowercaseString]; | |
829 | tempRegSharedSecretName = [tempRegSharedSecretName lowercaseString]; | |
830 | ||
831 | // Save hostname shared secret. | |
832 | if ([hostNameSharedSecretName length] > 0 && ([hostNameSharedSecretValue length] > 0)) { | |
12c5fa7a | 833 | DNSPrefTool_SetKeychainEntry([self dictionaryForSharedSecret:hostNameSharedSecretValue domain:hostNameString key:tempHostNameSharedSecretName]); |
7cb34e5c A |
834 | hostNameSharedSecretValue = nil; |
835 | hostSecretWasSet = YES; | |
836 | } | |
837 | ||
838 | // Save registration domain shared secret. | |
839 | if (([regSharedSecretName length] > 0) && ([regSharedSecretValue length] > 0)) { | |
12c5fa7a | 840 | DNSPrefTool_SetKeychainEntry([self dictionaryForSharedSecret:regSharedSecretValue domain:regDomainString key:tempRegSharedSecretName]); |
7cb34e5c A |
841 | regSharedSecretValue = nil; |
842 | regSecretWasSet = YES; | |
843 | } | |
844 | ||
845 | // Save hostname. | |
846 | if ((currentHostName == NULL) || [currentHostName compare:hostNameString] != NSOrderedSame) { | |
7cb34e5c | 847 | currentHostName = [hostNameString copy]; |
12c5fa7a | 848 | updateHostname = YES; |
7cb34e5c | 849 | } else if (hostSecretWasSet) { |
12c5fa7a A |
850 | currentHostName = @""; |
851 | updateHostname = YES; | |
852 | } | |
853 | ||
854 | if (updateHostname) { | |
855 | [BonjourSCStore setObject: currentHostName.length ? @[@{ | |
856 | (NSString *)SC_DYNDNS_DOMAIN_KEY : currentHostName, | |
857 | (NSString *)SC_DYNDNS_ENABLED_KEY : @YES | |
858 | }] : nil | |
859 | forKey: (NSString *)SC_DYNDNS_HOSTNAMES_KEY]; | |
7cb34e5c A |
860 | } |
861 | ||
862 | // Save browse domain. | |
863 | if (browseDomainsArray && [browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO) { | |
12c5fa7a | 864 | [BonjourSCStore setObject: browseDomainsArray forKey: (NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY]; |
7cb34e5c A |
865 | currentBrowseDomainsArray = [browseDomainsArray copy]; |
866 | } | |
867 | ||
868 | // Save registration domain. | |
869 | if ((currentRegDomain == NULL) || ([currentRegDomain compare:regDomainString] != NSOrderedSame) || (currentWideAreaState != [wideAreaCheckBox state])) { | |
12c5fa7a A |
870 | [BonjourSCStore setObject: @[@{ |
871 | (NSString *)SC_DYNDNS_DOMAIN_KEY : regDomainString, | |
872 | (NSString *)SC_DYNDNS_ENABLED_KEY : [wideAreaCheckBox state] ? @YES : @NO | |
873 | }] | |
874 | forKey: (NSString *)SC_DYNDNS_REGDOMAINS_KEY]; | |
7cb34e5c A |
875 | currentRegDomain = [regDomainString copy]; |
876 | ||
877 | if ([currentRegDomain length] > 0) { | |
878 | currentWideAreaState = [wideAreaCheckBox state]; | |
879 | [registrationDataSource removeObject:regDomainString]; | |
880 | [registrationDataSource addObject:currentRegDomain]; | |
881 | [registrationDataSource sortUsingFunction:MyArrayCompareFunction context:nil]; | |
12c5fa7a | 882 | // [regDomainsComboBox reloadData]; |
7cb34e5c A |
883 | } else { |
884 | currentWideAreaState = NO; | |
885 | [self toggleWideAreaBonjour:NO]; | |
12c5fa7a | 886 | if (defaultRegDomain != nil) regDomainView.domain = defaultRegDomain; |
7cb34e5c A |
887 | } |
888 | } else if (regSecretWasSet) { | |
12c5fa7a A |
889 | [BonjourSCStore setObject: @[@{ |
890 | (NSString *)SC_DYNDNS_DOMAIN_KEY : @"", | |
891 | (NSString *)SC_DYNDNS_ENABLED_KEY : @NO | |
892 | }] | |
893 | forKey: (NSString *)SC_DYNDNS_REGDOMAINS_KEY]; | |
894 | if ([currentRegDomain length] > 0) { | |
895 | [BonjourSCStore setObject: @[@{ | |
896 | (NSString *)SC_DYNDNS_DOMAIN_KEY : currentRegDomain, | |
897 | (NSString *)SC_DYNDNS_ENABLED_KEY : currentWideAreaState ? @YES : @NO | |
898 | }] | |
899 | forKey: (NSString *)SC_DYNDNS_REGDOMAINS_KEY]; | |
900 | } | |
7cb34e5c A |
901 | } |
902 | } | |
903 | ||
904 | ||
905 | - (NSPreferencePaneUnselectReply)shouldUnselect | |
906 | { | |
907 | #if 1 | |
908 | if (prefsNeedUpdating == YES) { | |
909 | ||
910 | [self disableControls]; | |
911 | ||
912 | NSBeginAlertSheet( | |
913 | @"Apply Configuration Changes?", | |
914 | @"Apply", | |
915 | @"Don't Apply", | |
916 | @"Cancel", | |
917 | mainWindow, | |
918 | self, | |
919 | @selector( savePanelWillClose:returnCode:contextInfo: ), | |
920 | NULL, | |
12c5fa7a | 921 | (__bridge void *) self, // sender, |
7cb34e5c A |
922 | @"" ); |
923 | return NSUnselectLater; | |
924 | } | |
925 | #endif | |
926 | ||
927 | return NSUnselectNow; | |
928 | } | |
929 | ||
930 | ||
931 | -(void)disableControls | |
932 | { | |
933 | [hostName setEnabled:NO]; | |
934 | [hostNameSharedSecretButton setEnabled:NO]; | |
7cb34e5c A |
935 | [applyButton setEnabled:NO]; |
936 | [revertButton setEnabled:NO]; | |
937 | [wideAreaCheckBox setEnabled:NO]; | |
12c5fa7a | 938 | [registrationSelectButton setEnabled: NO]; |
7cb34e5c A |
939 | [registrationSharedSecretButton setEnabled:NO]; |
940 | [statusImageView setEnabled:NO]; | |
941 | ||
942 | browseDomainListEnabled = NO; | |
943 | [browseDomainList deselectAll:self]; | |
944 | [browseDomainList setEnabled:NO]; | |
945 | ||
946 | [addBrowseDomainButton setEnabled:NO]; | |
947 | [removeBrowseDomainButton setEnabled:NO]; | |
948 | } | |
949 | ||
950 | ||
4a95efb2 | 951 | - (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row |
7cb34e5c | 952 | { |
67c8f8a1 A |
953 | (void)row; // Unused |
954 | (void)tableView; // Unused | |
7cb34e5c A |
955 | return browseDomainListEnabled; |
956 | } | |
957 | ||
958 | ||
959 | -(void)enableControls | |
960 | { | |
961 | [hostName setEnabled:YES]; | |
962 | [hostNameSharedSecretButton setEnabled:YES]; | |
7cb34e5c | 963 | [wideAreaCheckBox setEnabled:YES]; |
12c5fa7a | 964 | [registrationSelectButton setEnabled: YES]; |
7cb34e5c A |
965 | [registrationSharedSecretButton setEnabled:YES]; |
966 | [self toggleWideAreaBonjour:[wideAreaCheckBox state]]; | |
967 | [statusImageView setEnabled:YES]; | |
968 | [addBrowseDomainButton setEnabled:YES]; | |
969 | ||
970 | [browseDomainList setEnabled:YES]; | |
971 | [browseDomainList deselectAll:self]; | |
972 | browseDomainListEnabled = YES; | |
973 | ||
974 | [removeBrowseDomainButton setEnabled:[browseDomainList numberOfSelectedRows]]; | |
975 | [applyButton setEnabled:prefsNeedUpdating]; | |
976 | [revertButton setEnabled:prefsNeedUpdating]; | |
977 | } | |
978 | ||
979 | ||
980 | - (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view | |
981 | { | |
12c5fa7a | 982 | (void)view; // unused |
7cb34e5c A |
983 | [self enableControls]; |
984 | } | |
985 | ||
986 | ||
987 | - (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view | |
988 | { | |
12c5fa7a | 989 | (void)view; // unused |
7cb34e5c A |
990 | [self disableControls]; |
991 | } | |
992 | ||
67c8f8a1 A |
993 | @end |
994 | ||
995 | ||
996 | // Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion | |
997 | // e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4" | |
998 | // To expand "version" to its value before making the string, use STRINGIFY(version) instead | |
999 | #define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) #s | |
1000 | #define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) | |
1001 | ||
1002 | // NOT static -- otherwise the compiler may optimize it out | |
1003 | // The "@(#) " pattern is a special prefix the "what" command looks for | |
1004 | const char VersionString_SCCS[] = "@(#) Bonjour Preference Pane " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")"; | |
c9d2d929 | 1005 | |
32bb7e43 | 1006 | #if _BUILDING_XCODE_PROJECT_ |
67c8f8a1 A |
1007 | // If the process crashes, then this string will be magically included in the automatically-generated crash log |
1008 | const char *__crashreporter_info__ = VersionString_SCCS + 5; | |
1009 | asm(".desc ___crashreporter_info__, 0x10"); | |
32bb7e43 | 1010 | #endif |