source: trunk/PrefsPane/src/NetworkSettingsUpdater.m @ 1046

Revision 1044, 7.7 KB checked in by speck, 4 months ago (diff)

2 minor clang fixes.

Line 
1/* Copyright (C) 2008-2009 Peter Speck
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#import "NetworkSettingsUpdater.h"
18#import "GBDebug.h"
19
20/*
21 Getting settings:
22 http://developer.apple.com/documentation/Networking/Reference/SysConfig/SCNetworkConfiguration/index.html
23
24 Committing changes:
25 http://developer.apple.com/documentation/Networking/Reference/SysConfig/SCPreferences/CompositePage.html
26*/
27
28@interface NetworkSettingsUpdater()
29
30- (BOOL)updateNetworkService:(SCNetworkServiceRef)serviceR; // returns YES if needs update.
31
32@end
33
34@implementation NetworkSettingsUpdater
35
36BOOL cfstreql(CFStringRef a, CFStringRef b);
37BOOL cfstreql(CFStringRef a, CFStringRef b)
38{
39    if ((a != NULL) != (b != NULL))
40        return NO;
41    return !a || !CFStringCompare(a, b, 0);
42}
43
44- (id)initWithProxyPort:(int)proxyPort
45         withWantEnable:(BOOL)wantEnable
46{
47    if ((self = [super init])) {
48        _proxyPort = proxyPort;
49        _wantEnable = wantEnable;
50        _actionDescription = [[NSMutableArray arrayWithCapacity:20] retain];
51    }
52    return self;
53}
54
55- (void)dealloc
56{
57    [_actionDescription release];
58    [super dealloc];
59}
60
61- (BOOL)updateNetworkService:(SCNetworkServiceRef)serviceR
62{
63    int wantedPort = _wantEnable ? _proxyPort : 0;
64    const CFStringRef wantedHost = _wantEnable ? CFSTR("127.0.0.1") : NULL;
65    //
66    SCNetworkProtocolRef protoR = SCNetworkServiceCopyProtocol(serviceR, kSCNetworkProtocolTypeProxies);
67    if (!protoR)
68        return NO; // this protocol has not been enabled.
69    if (!SCNetworkProtocolGetEnabled(protoR))
70        return NO;
71    CFDictionaryRef proxyDictR = SCNetworkProtocolGetConfiguration(protoR); // returns NULL if no configuration.
72    //NSLog(@"   proxyDict: %@", proxyDictR);
73    const void *httpEnableP = proxyDictR ? CFDictionaryGetValue(proxyDictR, kSCPropNetProxiesHTTPEnable) : NULL;
74    const void *httpHostP = proxyDictR ? CFDictionaryGetValue(proxyDictR, kSCPropNetProxiesHTTPProxy) : NULL;
75    const void *httpPortP = proxyDictR ? CFDictionaryGetValue(proxyDictR, kSCPropNetProxiesHTTPPort) : NULL;
76#define GetCasted(value, type) ((value) && (CFGetTypeID(value) == type##GetTypeID()) \
77? ((type##Ref)value) : NULL)
78    CFStringRef host = GetCasted(httpHostP, CFString);
79    NSNumber* port = (NSNumber*)GetCasted(httpPortP, CFNumber);
80    NSNumber* enabled = (NSNumber*)GetCasted(httpEnableP, CFNumber);
81    DebugNSLog(@"  Settings{%@} enable = %@, host = %@, port = %@", (proxyDictR ? @"has" : @"missing"), enabled, host, port);
82    BOOL needsUpdateEnabled = NO;
83    BOOL needsUpdateHost = NO;
84    BOOL needsUpdatePort = NO;
85    CFMutableDictionaryRef newProxyDictR;
86    if (proxyDictR)
87        newProxyDictR = CFDictionaryCreateMutableCopy(NULL, 0, proxyDictR);
88    else
89        newProxyDictR = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
90    // just keep old host/port when we disable proxy.
91    if (wantedHost && !cfstreql(wantedHost, host)) {
92        DebugNSLog(@"  host needs update: %@ -> %@", host, wantedHost);
93        needsUpdateHost = YES;
94        CFDictionarySetValue(newProxyDictR, kSCPropNetProxiesHTTPProxy, wantedHost);
95    }
96    if (wantedPort && (port ? [port intValue] : 0) != wantedPort) {
97        DebugNSLog(@"  port needs update: %@ -> %d", port, wantedPort);
98        needsUpdatePort = YES;
99        NSNumber* value = [NSNumber numberWithInt:wantedPort];
100        CFDictionarySetValue(newProxyDictR, kSCPropNetProxiesHTTPPort, value);
101    }
102    if ((enabled && [enabled intValue]) != _wantEnable) {
103        DebugNSLog(@"  enabled needs update: %@ -> %d", enabled, (int)_wantEnable);
104        needsUpdateEnabled = YES;
105        NSNumber* value = [NSNumber numberWithInt:(_wantEnable ? 1 : 0)];
106        CFDictionarySetValue(newProxyDictR, kSCPropNetProxiesHTTPEnable, value);
107        /*
108        if (_wantEnable) {
109            NSNumber* value = [NSNumber numberWithInt:1];
110            CFDictionarySetValue(newProxyDictR, kSCPropNetProxiesHTTPEnable, value);
111        } else {
112            CFDictionaryRemoveValue(newProxyDictR, kSCPropNetProxiesHTTPEnable);
113        }
114         */
115    }
116    DebugNSLog(@"  needsUpdate = %d+%d+%d\n", needsUpdateEnabled, needsUpdateHost, needsUpdatePort);
117    [_actionDescription addObject:(NSString*)SCNetworkServiceGetName(serviceR)];
118    if (!needsUpdateEnabled && !needsUpdateHost && !needsUpdatePort) {
119        [_actionDescription addObject:@"      No change."];
120        CFRelease(newProxyDictR);
121        return NO;
122    }
123    if (_wantEnable) {
124        if (needsUpdateEnabled && needsUpdateHost && needsUpdatePort) {
125            [_actionDescription addObject:@"      Enable proxy and set host/port."];
126        } else if (!needsUpdateHost && !needsUpdatePort) {
127            [_actionDescription addObject:@"      Enable proxy."];
128        } else {
129            NSMutableArray* a = [NSMutableArray arrayWithCapacity:3];
130            if (needsUpdateEnabled)
131                [a addObject:@"Enable proxy"];
132            if (needsUpdateHost) {
133                NSString* s = [NSString stringWithFormat:@"update host ('%@' -> '%@)",
134                               (host ? (NSString*)host : @""), wantedHost];
135                [a addObject:s];
136            }
137            if (needsUpdatePort) {
138                NSString* s = [NSString stringWithFormat:@"update port: %@ -> %d",
139                    (port ? [NSString stringWithFormat:@"%d", [port intValue]] : @"none"),
140                    wantedPort];
141                [a addObject:s];
142            }
143            if (![a count])
144                [a addObject:@"???? no modifications?"];
145            NSString* msg = [NSString stringWithFormat:@"    %@", [a componentsJoinedByString:@", "]];
146            [_actionDescription addObject:msg];
147        }
148    } else {
149        [_actionDescription addObject:@"      Disable proxy."];
150    }
151    // DebugNSLogNSLog(@" new dict: %@", newProxyDictR);
152    BOOL ok = SCNetworkProtocolSetConfiguration(protoR, newProxyDictR);
153    CFRelease(newProxyDictR);
154    if (!ok)
155        DebugNSLog(@"SCNetworkProtocolSetConfiguration failed!");
156    return YES;
157}
158
159- (SCPreferencesRef)createSCPreferencesRef:(BOOL)commit
160{
161    CFStringRef appName = CFSTR("GlimmerBlocker");
162    return SCPreferencesCreate(NULL, appName, NULL);
163}
164
165- (BOOL)updateSettingsWithCommit:(BOOL)commit
166{
167    [_actionDescription removeAllObjects];
168    SCPreferencesRef prefsR = [self createSCPreferencesRef:commit];
169    NSAssert(prefsR, @"prefsR");
170    // can only get lock using auth.
171    BOOL gotLock = commit ? SCPreferencesLock(prefsR, NO) : NO;
172    if (commit && !gotLock)
173        NSLog(@"Can't get preferences lock");
174    SCNetworkSetRef networkSetR = SCNetworkSetCopyCurrent(prefsR);
175    NSAssert(networkSetR, @"networkSetR");
176    //
177    BOOL needsUpdate = NO;
178    CFArrayRef networkServicesArrayR = SCNetworkSetCopyServices(networkSetR);
179    NSAssert(networkServicesArrayR, @"networkServicesArrayR");
180    for (CFIndex i = 0; i < CFArrayGetCount(networkServicesArrayR); i++) {
181        SCNetworkServiceRef serviceR = CFArrayGetValueAtIndex(networkServicesArrayR, i);
182        BOOL enabled = SCNetworkServiceGetEnabled(serviceR);
183        DebugNSLog(@"Service [%ld], name = %@%@", (long)i, SCNetworkServiceGetName(serviceR),
184              enabled ? @"" : @"  (disabled)");
185        if (!enabled)
186            continue;
187        if ([self updateNetworkService:serviceR])
188            needsUpdate = YES;
189    }
190    //
191    CFRelease(networkServicesArrayR);
192    CFRelease(networkSetR);
193    BOOL ok = !needsUpdate;
194    if (needsUpdate && commit) {
195        ok = SCPreferencesCommitChanges(prefsR);
196        if (!ok) {
197            NSLog(@" SCPreferencesCommitChanges failed");
198        } else {
199            ok = SCPreferencesApplyChanges(prefsR);
200            if (!ok)
201                NSLog(@" SCPreferencesApplyChanges failed");
202        }
203        //
204        if (gotLock) {
205            BOOL unlocked = SCPreferencesUnlock(prefsR);
206            if (!unlocked)
207                NSLog(@"### Got problem releasing prefs lock");
208        }
209    }
210    CFRelease(prefsR);
211    return ok;
212}
213
214@end
Note: See TracBrowser for help on using the repository browser.