Path: blob/jdk8u272-b10-aarch32-20201026/jdk/src/solaris/native/java/lang/java_props_macosx.c
48795 views
/*1* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <sys/socket.h>26#include <netinet/in.h>27#include <arpa/inet.h>28#include <objc/objc-runtime.h>2930#include <Security/AuthSession.h>31#include <CoreFoundation/CoreFoundation.h>32#include <SystemConfiguration/SystemConfiguration.h>33#include <Foundation/Foundation.h>3435#include "java_props_macosx.h"3637char *getPosixLocale(int cat) {38char *lc = setlocale(cat, NULL);39if ((lc == NULL) || (strcmp(lc, "C") == 0)) {40lc = getenv("LANG");41}42if (lc == NULL) return NULL;43return strdup(lc);44}4546#define LOCALEIDLENGTH 12847char *getMacOSXLocale(int cat) {48const char* retVal = NULL;49char languageString[LOCALEIDLENGTH];50char localeString[LOCALEIDLENGTH];5152switch (cat) {53case LC_MESSAGES:54{55// get preferred language code56CFArrayRef languages = CFLocaleCopyPreferredLanguages();57if (languages == NULL) {58return NULL;59}60if (CFArrayGetCount(languages) <= 0) {61CFRelease(languages);62return NULL;63}6465CFStringRef primaryLanguage = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);66if (primaryLanguage == NULL) {67CFRelease(languages);68return NULL;69}70if (CFStringGetCString(primaryLanguage, languageString,71LOCALEIDLENGTH, CFStringGetSystemEncoding()) == false) {72CFRelease(languages);73return NULL;74}75CFRelease(languages);7677retVal = languageString;7879// Special case for Portuguese in Brazil:80// The language code needs the "_BR" region code (to distinguish it81// from Portuguese in Portugal), but this is missing when using the82// "Portuguese (Brazil)" language.83// If language is "pt" and the current locale is pt_BR, return pt_BR.84if (strcmp(retVal, "pt") == 0 &&85CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),86localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding()) &&87strcmp(localeString, "pt_BR") == 0) {88retVal = localeString;89}90}91break;92default:93{94if (!CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),95localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {96return NULL;97}98retVal = localeString;99}100break;101}102103if (retVal != NULL) {104// Language IDs use the language designators and (optional) region105// and script designators of BCP 47. So possible formats are:106//107// "en" (language designator only)108// "haw" (3-letter lanuage designator)109// "en-GB" (language with alpha-2 region designator)110// "es-419" (language with 3-digit UN M.49 area code)111// "zh-Hans" (language with ISO 15924 script designator)112// "zh-Hans-US" (language with ISO 15924 script designator and region)113// "zh-Hans-419" (language with ISO 15924 script designator and UN M.49)114//115// In the case of region designators (alpha-2 and/or UN M.49), we convert116// to our locale string format by changing '-' to '_'. That is, if117// the '-' is followed by fewer than 4 chars.118char* scriptOrRegion = strchr(retVal, '-');119if (scriptOrRegion != NULL) {120int length = strlen(scriptOrRegion);121if (length > 5) {122// Region and script both exist. Honor the script for now123scriptOrRegion[5] = '\0';124} else if (length < 5) {125*scriptOrRegion = '_';126127assert((length == 3 &&128// '-' followed by a 2 character region designator129isalpha(scriptOrRegion[1]) &&130isalpha(scriptOrRegion[2])) ||131(length == 4 &&132// '-' followed by a 3-digit UN M.49 area code133isdigit(scriptOrRegion[1]) &&134isdigit(scriptOrRegion[2]) &&135isdigit(scriptOrRegion[3])));136}137}138139return strdup(retVal);140}141return NULL;142}143144char *setupMacOSXLocale(int cat) {145char * ret = getMacOSXLocale(cat);146147if (ret == NULL) {148return getPosixLocale(cat);149} else {150return ret;151}152}153154int isInAquaSession() {155// environment variable to bypass the aqua session check156char *ev = getenv("AWT_FORCE_HEADFUL");157if (ev && (strncasecmp(ev, "true", 4) == 0)) {158// if "true" then tell the caller we're in an Aqua session without actually checking159return 1;160}161// Is the WindowServer available?162SecuritySessionId session_id;163SessionAttributeBits session_info;164OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info);165if (status == noErr) {166if (session_info & sessionHasGraphicAccess) {167return 1;168}169}170return 0;171}172173// 10.9 SDK does not include the NSOperatingSystemVersion struct.174// For now, create our own175typedef struct {176NSInteger majorVersion;177NSInteger minorVersion;178NSInteger patchVersion;179} OSVerStruct;180181void setOSNameAndVersion(java_props_t *sprops) {182// Hardcode os_name, and fill in os_version183sprops->os_name = strdup("Mac OS X");184185char* osVersionCStr = NULL;186// Mac OS 10.9 includes the [NSProcessInfo operatingSystemVersion] function,187// but it's not in the 10.9 SDK. So, call it via objc_msgSend_stret.188if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) {189OSVerStruct (*procInfoFn)(id rec, SEL sel) = (OSVerStruct(*)(id, SEL))objc_msgSend_stret;190OSVerStruct osVer = procInfoFn([NSProcessInfo processInfo],191@selector(operatingSystemVersion));192NSString *nsVerStr;193if (osVer.patchVersion == 0) { // Omit trailing ".0"194nsVerStr = [NSString stringWithFormat:@"%ld.%ld",195(long)osVer.majorVersion, (long)osVer.minorVersion];196} else {197nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld",198(long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion];199}200// Copy out the char*201osVersionCStr = strdup([nsVerStr UTF8String]);202}203// Fallback if running on pre-10.9 Mac OS204if (osVersionCStr == NULL) {205NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :206@"/System/Library/CoreServices/SystemVersion.plist"];207if (version != NULL) {208NSString *nsVerStr = [version objectForKey : @"ProductVersion"];209if (nsVerStr != NULL) {210osVersionCStr = strdup([nsVerStr UTF8String]);211}212}213}214if (osVersionCStr == NULL) {215osVersionCStr = strdup("Unknown");216}217sprops->os_version = osVersionCStr;218}219220221static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey,222CFStringRef inHostKey, CFStringRef inPortKey,223CFStringRef *outProxyHost, int *ioProxyPort) {224/* See if the proxy is enabled. */225CFNumberRef cf_enabled = CFDictionaryGetValue(inDict, inEnabledKey);226if (cf_enabled == NULL) {227return false;228}229230int isEnabled = false;231if (!CFNumberGetValue(cf_enabled, kCFNumberIntType, &isEnabled)) {232return isEnabled;233}234235if (!isEnabled) return false;236*outProxyHost = CFDictionaryGetValue(inDict, inHostKey);237238// If cf_host is null, that means the checkbox is set,239// but no host was entered. We'll treat that as NOT ENABLED.240// If cf_port is null or cf_port isn't a number, that means241// no port number was entered. Treat this as ENABLED with the242// protocol's default port.243if (*outProxyHost == NULL) {244return false;245}246247if (CFStringGetLength(*outProxyHost) == 0) {248return false;249}250251int newPort = 0;252CFNumberRef cf_port = NULL;253if ((cf_port = CFDictionaryGetValue(inDict, inPortKey)) != NULL &&254CFNumberGetValue(cf_port, kCFNumberIntType, &newPort) &&255newPort > 0) {256*ioProxyPort = newPort;257} else {258// bad port or no port - leave *ioProxyPort unchanged259}260261return true;262}263264static char *createUTF8CString(const CFStringRef theString) {265if (theString == NULL) return NULL;266267const CFIndex stringLength = CFStringGetLength(theString);268const CFIndex bufSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8) + 1;269char *returnVal = (char *)malloc(bufSize);270271if (CFStringGetCString(theString, returnVal, bufSize, kCFStringEncodingUTF8)) {272return returnVal;273}274275free(returnVal);276return NULL;277}278279// Return TRUE if str is a syntactically valid IP address.280// Using inet_pton() instead of inet_aton() for IPv6 support.281// len is only a hint; cstr must still be nul-terminated282static int looksLikeIPAddress(char *cstr, size_t len) {283if (len == 0 || (len == 1 && cstr[0] == '.')) return FALSE;284285char dst[16]; // big enough for INET6286return (1 == inet_pton(AF_INET, cstr, dst) ||2871 == inet_pton(AF_INET6, cstr, dst));288}289290291292// Convert Mac OS X proxy exception entry to Java syntax.293// See Radar #3441134 for details.294// Returns NULL if this exception should be ignored by Java.295// May generate a string with multiple exceptions separated by '|'.296static char * createConvertedException(CFStringRef cf_original) {297// This is done with char* instead of CFString because inet_pton()298// needs a C string.299char *c_exception = createUTF8CString(cf_original);300if (!c_exception) return NULL;301302int c_len = strlen(c_exception);303304// 1. sanitize exception prefix305if (c_len >= 1 && 0 == strncmp(c_exception, ".", 1)) {306memmove(c_exception, c_exception+1, c_len);307c_len -= 1;308} else if (c_len >= 2 && 0 == strncmp(c_exception, "*.", 2)) {309memmove(c_exception, c_exception+2, c_len-1);310c_len -= 2;311}312313// 2. pre-reject other exception wildcards314if (strchr(c_exception, '*')) {315free(c_exception);316return NULL;317}318319// 3. no IP wildcarding320if (looksLikeIPAddress(c_exception, c_len)) {321return c_exception;322}323324// 4. allow domain suffixes325// c_exception is now "str\0" - change to "str|*.str\0"326c_exception = reallocf(c_exception, c_len+3+c_len+1);327if (!c_exception) return NULL;328329strncpy(c_exception+c_len, "|*.", 3);330strncpy(c_exception+c_len+3, c_exception, c_len);331c_exception[c_len+3+c_len] = '\0';332return c_exception;333}334335/*336* Method for fetching the user.home path and storing it in the property list.337* For signed .apps running in the Mac App Sandbox, user.home is set to the338* app's sandbox container.339*/340void setUserHome(java_props_t *sprops) {341if (sprops == NULL) { return; }342NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];343sprops->user_home = createUTF8CString((CFStringRef)NSHomeDirectory());344[pool drain];345}346347/*348* Method for fetching proxy info and storing it in the property list.349*/350void setProxyProperties(java_props_t *sProps) {351if (sProps == NULL) return;352353char buf[16]; /* Used for %d of an int - 16 is plenty */354CFStringRef355cf_httpHost = NULL,356cf_httpsHost = NULL,357cf_ftpHost = NULL,358cf_socksHost = NULL,359cf_gopherHost = NULL;360int361httpPort = 80, // Default proxy port values362httpsPort = 443,363ftpPort = 21,364socksPort = 1080,365gopherPort = 70;366367CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);368if (dict == NULL) return;369370/* Read the proxy exceptions list */371CFArrayRef cf_list = CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList);372373CFMutableStringRef cf_exceptionList = NULL;374if (cf_list != NULL) {375CFIndex len = CFArrayGetCount(cf_list), idx;376377cf_exceptionList = CFStringCreateMutable(NULL, 0);378for (idx = (CFIndex)0; idx < len; idx++) {379CFStringRef cf_ehost;380if ((cf_ehost = CFArrayGetValueAtIndex(cf_list, idx))) {381/* Convert this exception from Mac OS X syntax to Java syntax.382See Radar #3441134 for details. This may generate a string383with multiple Java exceptions separated by '|'. */384char *c_exception = createConvertedException(cf_ehost);385if (c_exception) {386/* Append the host to the list of exclusions. */387if (CFStringGetLength(cf_exceptionList) > 0) {388CFStringAppendCString(cf_exceptionList, "|", kCFStringEncodingMacRoman);389}390CFStringAppendCString(cf_exceptionList, c_exception, kCFStringEncodingMacRoman);391free(c_exception);392}393}394}395}396397if (cf_exceptionList != NULL) {398if (CFStringGetLength(cf_exceptionList) > 0) {399sProps->exceptionList = createUTF8CString(cf_exceptionList);400}401CFRelease(cf_exceptionList);402}403404#define CHECK_PROXY(protocol, PROTOCOL) \405sProps->protocol##ProxyEnabled = \406getProxyInfoForProtocol(dict, kSCPropNetProxies##PROTOCOL##Enable, \407kSCPropNetProxies##PROTOCOL##Proxy, \408kSCPropNetProxies##PROTOCOL##Port, \409&cf_##protocol##Host, &protocol##Port); \410if (sProps->protocol##ProxyEnabled) { \411sProps->protocol##Host = createUTF8CString(cf_##protocol##Host); \412snprintf(buf, sizeof(buf), "%d", protocol##Port); \413sProps->protocol##Port = malloc(strlen(buf) + 1); \414strcpy(sProps->protocol##Port, buf); \415}416417CHECK_PROXY(http, HTTP);418CHECK_PROXY(https, HTTPS);419CHECK_PROXY(ftp, FTP);420CHECK_PROXY(socks, SOCKS);421CHECK_PROXY(gopher, Gopher);422423#undef CHECK_PROXY424425CFRelease(dict);426}427428429