X-Git-Url: https://git.saurik.com/apple/cf.git/blobdiff_plain/df7f3a2a3ea65443e9420245c8c2860a5aaa5a00..d89253836d02fdbaf48cc7f9e7d94de7adad229f:/String.subproj/CFStringDefaultEncoding.h diff --git a/String.subproj/CFStringDefaultEncoding.h b/String.subproj/CFStringDefaultEncoding.h new file mode 100644 index 0000000..976e06a --- /dev/null +++ b/String.subproj/CFStringDefaultEncoding.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* CFStringDefaultEncoding.h + Copyright (c) 1998-2005, Apple, Inc. All rights reserved. +*/ + +/* This file defines static inline functions used both by CarbonCore & CF. */ + +#include +#if defined(__MACH__) +#include +#include +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#define __kCFUserEncodingEnvVariableName ("__CF_USER_TEXT_ENCODING") +#define __kCFMaxDefaultEncodingFileLength (24) +#define __kCFUserEncodingFileName ("/.CFUserTextEncoding") + +/* This function is used to obtain users' default script/region code. + The function first looks at environment variable __kCFUserEncodingEnvVariableName, then, reads the configuration file in user's home directory. +*/ +CF_INLINE void __CFStringGetUserDefaultEncoding(UInt32 *oScriptValue, UInt32 *oRegionValue) { + char *stringValue; + char buffer[__kCFMaxDefaultEncodingFileLength]; + int uid = getuid(); + + if ((stringValue = getenv(__kCFUserEncodingEnvVariableName)) != NULL) { + if ((uid == strtol(stringValue, &stringValue, 0)) && (':' == *stringValue)) { + ++stringValue; + } else { + stringValue = NULL; + } + } + + if ((stringValue == NULL) && ((uid > 0) || getenv("HOME"))) { + struct passwd *passwdp; + + if ((passwdp = getpwuid((uid_t)uid))) { + char filename[MAXPATHLEN + 1]; + int fd; + + strcpy(filename, passwdp->pw_dir); + strcat(filename, __kCFUserEncodingFileName); + + if ((fd = open(filename, O_RDONLY, 0)) == -1) { + // Cannot open the file. Let's fallback to smRoman/verUS + snprintf(filename, sizeof(filename), "%s=0x%X:0:0", __kCFUserEncodingEnvVariableName, uid); + putenv(filename); + } else { + int readSize; + + // cjk: We do not turn on F_NOCACHE on the fd here, because + // many processes read this file on startup, and caching the + // is probably a good thing, for the system as a whole. + readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1); + buffer[(readSize < 0 ? 0 : readSize)] = '\0'; + close(fd); + stringValue = buffer; + + // Well, we already have a buffer, let's reuse it + snprintf(filename, sizeof(filename), "%s=0x%X:%s", __kCFUserEncodingEnvVariableName, uid, buffer); + putenv(filename); + } + } + } + + if (stringValue) { + *oScriptValue = strtol(stringValue, &stringValue, 0); + if (*stringValue == ':') { + if (oRegionValue) *oRegionValue = strtol(++stringValue, NULL, 0); + return; + } + } + + // Falling back + *oScriptValue = 0; // smRoman + if (oRegionValue) *oRegionValue = 0; // verUS +} + +CF_INLINE uint32_t __CFStringGetInstallationRegion() { + char *stringValue = NULL; + char buffer[__kCFMaxDefaultEncodingFileLength]; + struct passwd *passwdp; + + if ((passwdp = getpwuid((uid_t)0))) { + char filename[MAXPATHLEN + 1]; + int fd; + + strcpy(filename, passwdp->pw_dir); + strcat(filename, __kCFUserEncodingFileName); + + if ((fd = open(filename, O_RDONLY, 0)) != -1) { + int readSize; + + // cjk: We do not turn on F_NOCACHE on the fd here, because + // many processes read this file on startup, and caching the + // is probably a good thing, for the system as a whole. + readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1); + buffer[(readSize < 0 ? 0 : readSize)] = '\0'; + close(fd); + stringValue = buffer; + } + } + + if (stringValue) { + (void)strtol(stringValue, &stringValue, 0); + if (*stringValue == ':') return strtol(++stringValue, NULL, 0); + } + + return 0; // verUS +} + +CF_INLINE void __CFStringGetInstallationEncodingAndRegion(uint32_t *encoding, uint32_t *region) { + char *stringValue = NULL; + char buffer[__kCFMaxDefaultEncodingFileLength]; + struct passwd *passwdp; + + *encoding = 0; *region = 0; + + if ((passwdp = getpwuid((uid_t)0))) { + char filename[MAXPATHLEN + 1]; + int fd; + + strcpy(filename, passwdp->pw_dir); + strcat(filename, __kCFUserEncodingFileName); + + if ((fd = open(filename, O_RDONLY, 0)) != -1) { + int readSize; + + // cjk: We do not turn on F_NOCACHE on the fd here, because + // many processes read this file on startup, and caching the + // is probably a good thing, for the system as a whole. + readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1); + buffer[(readSize < 0 ? 0 : readSize)] = '\0'; + close(fd); + stringValue = buffer; + } + } + + if (stringValue) { + *encoding = strtol(stringValue, &stringValue, 0); + if (*stringValue == ':') *region = strtol(++stringValue, NULL, 0); + } +} + +CF_INLINE void __CFStringSaveUserDefaultEncoding(UInt32 iScriptValue, UInt32 iRegionValue) { + struct passwd *passwdp; + + if ((passwdp = getpwuid(getuid()))) { + char filename[MAXPATHLEN + 1]; + int fd; + + strcpy(filename, passwdp->pw_dir); + strcat(filename, __kCFUserEncodingFileName); + + // In case, file exists + (void)unlink(filename); + + if ((fd = open(filename, O_WRONLY|O_CREAT, 0400)) != -1) { + char buffer[__kCFMaxDefaultEncodingFileLength]; + unsigned int writeSize; + + writeSize = snprintf(buffer, __kCFMaxDefaultEncodingFileLength, "0x%X:0x%X", (unsigned int)iScriptValue, (unsigned int)iRegionValue); + (void)write(fd, buffer, (writeSize > __kCFMaxDefaultEncodingFileLength ? __kCFMaxDefaultEncodingFileLength : writeSize)); + close(fd); + } + } +} + +#if defined(__cplusplus) +} +#endif + +#endif /* __MACH__ */