2 * Copyright (c) 2000-2008, 2011, 2013-2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * January 8, 2001 Allan Nathanson <ajn@apple.com>
35 #include <CoreFoundation/CoreFoundation.h>
36 #include <CoreFoundation/CFStringDefaultEncoding.h> // for __CFStringGetUserDefaultEncoding
37 #include "SCPreferencesInternal.h"
38 #include "dy_framework.h"
41 #pragma mark ComputerName
44 static CFStringEncoding
45 getNameEncoding(CFDictionaryRef dict
)
47 CFStringEncoding encoding
;
50 if (!CFDictionaryGetValueIfPresent(dict
,
51 kSCPropSystemComputerNameEncoding
,
52 (const void **)&num
) ||
54 !CFNumberGetValue(num
, kCFNumberSInt32Type
, &encoding
)) {
55 encoding
= CFStringGetSystemEncoding();
63 _SCPreferencesCopyComputerName(SCPreferencesRef prefs
,
64 CFStringEncoding
*nameEncoding
)
67 CFStringRef name
= NULL
;
69 Boolean tempPrefs
= FALSE
;
72 prefs
= SCPreferencesCreate(NULL
, CFSTR("_SCPreferencesCopyComputerName"), NULL
);
79 path
= CFStringCreateWithFormat(NULL
,
84 dict
= SCPreferencesPathGetValue(prefs
, path
);
88 if (isA_CFDictionary(dict
)) {
89 name
= CFDictionaryGetValue(dict
, kSCPropSystemComputerName
);
90 name
= isA_CFString(name
);
96 if (nameEncoding
!= NULL
) {
97 *nameEncoding
= getNameEncoding(dict
);
101 if (tempPrefs
) CFRelease(prefs
);
102 _SCErrorSet(name
!= NULL
? kSCStatusOK
: kSCStatusNoKey
);
108 SCDynamicStoreKeyCreateComputerName(CFAllocatorRef allocator
)
110 return SCDynamicStoreKeyCreate(allocator
,
112 kSCDynamicStoreDomainSetup
,
118 SCDynamicStoreCopyComputerName(SCDynamicStoreRef store
,
119 CFStringEncoding
*nameEncoding
)
121 CFDictionaryRef dict
= NULL
;
123 CFStringRef name
= NULL
;
125 key
= SCDynamicStoreKeyCreateComputerName(NULL
);
126 dict
= SCDynamicStoreCopyValue(store
, key
);
130 * Let's try looking in the preferences.plist file until
131 * (a) we add an API to retrieve the name regardless of
132 * where it is stored and
133 * (b) this API is deprecated
135 name
= _SCPreferencesCopyComputerName(NULL
, nameEncoding
);
138 if (!isA_CFDictionary(dict
)) {
139 _SCErrorSet(kSCStatusNoKey
);
143 name
= isA_CFString(CFDictionaryGetValue(dict
, kSCPropSystemComputerName
));
145 _SCErrorSet(kSCStatusNoKey
);
150 if (nameEncoding
!= NULL
) {
151 *nameEncoding
= getNameEncoding(dict
);
154 _SCErrorSet(kSCStatusOK
);
159 if (dict
!= NULL
) CFRelease(dict
);
165 SCPreferencesSetComputerName(SCPreferencesRef prefs
,
167 CFStringEncoding encoding
)
169 CFDictionaryRef dict
;
170 CFMutableDictionaryRef newDict
;
178 if (!isA_CFString(name
)) {
179 _SCErrorSet(kSCStatusInvalidArgument
);
183 len
= CFStringGetLength(name
);
189 path
= CFStringCreateWithFormat(NULL
,
195 dict
= SCPreferencesPathGetValue(prefs
, path
);
197 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
199 newDict
= CFDictionaryCreateMutable(NULL
,
201 &kCFTypeDictionaryKeyCallBacks
,
202 &kCFTypeDictionaryValueCallBacks
);
205 if ((name
!= NULL
) && (CFStringGetLength(name
) > 0)) {
206 CFDictionarySetValue(newDict
, kSCPropSystemComputerName
, name
);
208 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &encoding
);
209 CFDictionarySetValue(newDict
, kSCPropSystemComputerNameEncoding
, num
);
212 CFDictionaryRemoveValue(newDict
, kSCPropSystemComputerNameRegion
);
213 if (encoding
== kCFStringEncodingMacRoman
) {
214 UInt32 userEncoding
= 0;
215 UInt32 userRegion
= 0;
217 __CFStringGetUserDefaultEncoding(&userEncoding
, &userRegion
);
218 if ((userEncoding
== kCFStringEncodingMacRoman
) && (userRegion
!= 0)) {
219 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &userRegion
);
220 CFDictionarySetValue(newDict
, kSCPropSystemComputerNameRegion
, num
);
225 CFDictionaryRemoveValue(newDict
, kSCPropSystemComputerName
);
226 CFDictionaryRemoveValue(newDict
, kSCPropSystemComputerNameEncoding
);
227 CFDictionaryRemoveValue(newDict
, kSCPropSystemComputerNameRegion
);
230 if (CFDictionaryGetCount(newDict
) > 0) {
231 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
233 ok
= SCPreferencesPathRemoveValue(prefs
, path
);
238 SC_log(LOG_NOTICE
, "attempting to set the computer name to \"%@\"", name
);
240 SC_log(LOG_NOTICE
, "attempting to reset the computer name");
252 #pragma mark HostName
256 SCPreferencesGetHostName(SCPreferencesRef prefs
)
258 CFDictionaryRef dict
;
262 path
= CFStringCreateWithFormat(NULL
,
267 dict
= SCPreferencesPathGetValue(prefs
, path
);
270 if (!isA_CFDictionary(dict
)) {
271 _SCErrorSet(kSCStatusNoKey
);
275 name
= isA_CFString(CFDictionaryGetValue(dict
, kSCPropSystemHostName
));
277 _SCErrorSet(kSCStatusNoKey
);
286 SCPreferencesSetHostName(SCPreferencesRef prefs
,
289 CFDictionaryRef dict
;
290 CFMutableDictionaryRef newDict
;
297 if (!isA_CFString(name
)) {
298 _SCErrorSet(kSCStatusInvalidArgument
);
302 len
= CFStringGetLength(name
);
308 path
= CFStringCreateWithFormat(NULL
,
314 dict
= SCPreferencesPathGetValue(prefs
, path
);
316 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
318 newDict
= CFDictionaryCreateMutable(NULL
,
320 &kCFTypeDictionaryKeyCallBacks
,
321 &kCFTypeDictionaryValueCallBacks
);
325 CFDictionarySetValue(newDict
, kSCPropSystemHostName
, name
);
327 CFDictionaryRemoveValue(newDict
, kSCPropSystemHostName
);
330 if (CFDictionaryGetCount(newDict
) > 0) {
331 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
333 ok
= SCPreferencesPathRemoveValue(prefs
, path
);
338 SC_log(LOG_NOTICE
, "attempting to set the host name to \"%@\"", name
);
340 SC_log(LOG_NOTICE
, "attempting to reset the host name");
352 #pragma mark LocalHostName
356 _SCPreferencesCopyLocalHostName(SCPreferencesRef prefs
)
358 CFDictionaryRef dict
;
359 CFStringRef name
= NULL
;
361 Boolean tempPrefs
= FALSE
;
364 prefs
= SCPreferencesCreate(NULL
, CFSTR("_SCPreferencesCopyLocalHostName"), NULL
);
371 path
= CFStringCreateWithFormat(NULL
,
377 dict
= SCPreferencesPathGetValue(prefs
, path
);
381 if (isA_CFDictionary(dict
)) {
382 name
= CFDictionaryGetValue(dict
, kSCPropNetLocalHostName
);
383 name
= isA_CFString(name
);
390 if (tempPrefs
) CFRelease(prefs
);
391 _SCErrorSet(name
!= NULL
? kSCStatusOK
: kSCStatusNoKey
);
397 SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator
)
399 return SCDynamicStoreKeyCreate(allocator
,
401 kSCDynamicStoreDomainSetup
,
408 SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store
)
410 CFDictionaryRef dict
= NULL
;
412 CFStringRef name
= NULL
;
414 key
= SCDynamicStoreKeyCreateHostNames(NULL
);
415 dict
= SCDynamicStoreCopyValue(store
, key
);
419 * Let's try looking in the preferences.plist file until
420 * (a) we add an API to retrieve the name regardless of
421 * where it is stored and
422 * (b) this API is deprecated
424 name
= _SCPreferencesCopyLocalHostName(NULL
);
427 if (!isA_CFDictionary(dict
)) {
428 _SCErrorSet(kSCStatusNoKey
);
432 name
= isA_CFString(CFDictionaryGetValue(dict
, kSCPropNetLocalHostName
));
434 _SCErrorSet(kSCStatusNoKey
);
439 _SCErrorSet(kSCStatusOK
);
444 if (dict
!= NULL
) CFRelease(dict
);
450 _SC_stringIsValidDNSName(const char *name
)
453 size_t len
= strlen(name
);
461 for (scan
= name
, i
= 0; i
< len
; i
++, scan
++) {
463 char next
= *(scan
+ 1);
465 if (prev
== '.' || prev
== '\0') {
466 if (isalnum(ch
) == 0) {
467 /* a label must begin with a letter or digit */
470 } else if (next
== '\0' || next
== '.') {
471 if (isalnum(ch
) == 0) {
472 /* a label must end with a letter or digit */
475 } else if (isalnum(ch
) == 0) {
478 /* a label separator */
481 /* hyphens are OK within a label */
484 /* an invalid character */
497 _SC_CFStringIsValidDNSName(CFStringRef name
)
499 Boolean clean
= FALSE
;
502 if (!isA_CFString(name
)) {
506 str
= _SC_cfstring_to_cstring(name
, NULL
, 0, kCFStringEncodingASCII
);
511 clean
= _SC_stringIsValidDNSName(str
);
513 if (str
!= NULL
) CFAllocatorDeallocate(NULL
, str
);
519 SCPreferencesSetLocalHostName(SCPreferencesRef prefs
,
522 CFDictionaryRef dict
;
523 CFMutableDictionaryRef newDict
;
530 if (!isA_CFString(name
)) {
531 _SCErrorSet(kSCStatusInvalidArgument
);
535 len
= CFStringGetLength(name
);
537 if (!_SC_CFStringIsValidDNSName(name
)) {
538 _SCErrorSet(kSCStatusInvalidArgument
);
542 if (CFStringFindWithOptions(name
, CFSTR("."), CFRangeMake(0, len
), 0, NULL
)) {
543 _SCErrorSet(kSCStatusInvalidArgument
);
551 path
= CFStringCreateWithFormat(NULL
,
558 dict
= SCPreferencesPathGetValue(prefs
, path
);
560 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
562 newDict
= CFDictionaryCreateMutable(NULL
,
564 &kCFTypeDictionaryKeyCallBacks
,
565 &kCFTypeDictionaryValueCallBacks
);
569 CFDictionarySetValue(newDict
, kSCPropNetLocalHostName
, name
);
571 CFDictionaryRemoveValue(newDict
, kSCPropNetLocalHostName
);
574 if (CFDictionaryGetCount(newDict
) > 0) {
575 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
577 ok
= SCPreferencesPathRemoveValue(prefs
, path
);
582 SC_log(LOG_NOTICE
, "attempting to set the local host name to \"%@\"", name
);
584 SC_log(LOG_NOTICE
, "attempting to reset the local host name");
596 _SC_CFStringIsValidNetBIOSName(CFStringRef name
)
598 if (!isA_CFString(name
)) {
602 if (CFStringGetLength(name
) > 15) {