Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/java/lang/java_props_macosx.c
32287 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 "TargetConditionals.h"2627#include <sys/socket.h>28#include <netinet/in.h>29#include <arpa/inet.h>30#include <objc/objc-runtime.h>3132#ifndef TARGET_OS_IOS33#include <Security/AuthSession.h>34#endif35#include <CoreFoundation/CoreFoundation.h>36#ifndef TARGET_OS_IOS37#include <SystemConfiguration/SystemConfiguration.h>38#else39#include <SystemConfiguration/OSXSCSchemaDefinitions.h>40#include <SystemConfiguration/SCDynamicStore.h>41CFDictionaryRef SCDynamicStoreCopyProxies(SCDynamicStoreRef store);42#endif43#include <Foundation/Foundation.h>4445#include "java_props_macosx.h"4647char *getPosixLocale(int cat) {48char *lc = setlocale(cat, NULL);49if ((lc == NULL) || (strcmp(lc, "C") == 0)) {50lc = getenv("LANG");51}52if (lc == NULL) return NULL;53return strdup(lc);54}5556#define LOCALEIDLENGTH 12857char *getMacOSXLocale(int cat) {58const char* retVal = NULL;59char languageString[LOCALEIDLENGTH];60char localeString[LOCALEIDLENGTH];6162switch (cat) {63case LC_MESSAGES:64{65// get preferred language code66CFArrayRef languages = CFLocaleCopyPreferredLanguages();67if (languages == NULL) {68return NULL;69}70if (CFArrayGetCount(languages) <= 0) {71CFRelease(languages);72return NULL;73}7475CFStringRef primaryLanguage = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);76if (primaryLanguage == NULL) {77CFRelease(languages);78return NULL;79}80if (CFStringGetCString(primaryLanguage, languageString,81LOCALEIDLENGTH, CFStringGetSystemEncoding()) == false) {82CFRelease(languages);83return NULL;84}85CFRelease(languages);8687retVal = languageString;8889// Special case for Portuguese in Brazil:90// The language code needs the "_BR" region code (to distinguish it91// from Portuguese in Portugal), but this is missing when using the92// "Portuguese (Brazil)" language.93// If language is "pt" and the current locale is pt_BR, return pt_BR.94if (strcmp(retVal, "pt") == 0 &&95CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),96localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding()) &&97strcmp(localeString, "pt_BR") == 0) {98retVal = localeString;99}100}101break;102default:103{104if (!CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),105localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {106return NULL;107}108retVal = localeString;109}110break;111}112113if (retVal != NULL) {114// Language IDs use the language designators and (optional) region115// and script designators of BCP 47. So possible formats are:116//117// "en" (language designator only)118// "haw" (3-letter lanuage designator)119// "en-GB" (language with alpha-2 region designator)120// "es-419" (language with 3-digit UN M.49 area code)121// "zh-Hans" (language with ISO 15924 script designator)122// "zh-Hans-US" (language with ISO 15924 script designator and region)123// "zh-Hans-419" (language with ISO 15924 script designator and UN M.49)124//125// In the case of region designators (alpha-2 and/or UN M.49), we convert126// to our locale string format by changing '-' to '_'. That is, if127// the '-' is followed by fewer than 4 chars.128char* scriptOrRegion = strchr(retVal, '-');129if (scriptOrRegion != NULL) {130int length = strlen(scriptOrRegion);131if (length > 5) {132// Region and script both exist. Honor the script for now133scriptOrRegion[5] = '\0';134} else if (length < 5) {135*scriptOrRegion = '_';136137assert((length == 3 &&138// '-' followed by a 2 character region designator139isalpha(scriptOrRegion[1]) &&140isalpha(scriptOrRegion[2])) ||141(length == 4 &&142// '-' followed by a 3-digit UN M.49 area code143isdigit(scriptOrRegion[1]) &&144isdigit(scriptOrRegion[2]) &&145isdigit(scriptOrRegion[3])));146}147}148149return strdup(retVal);150}151return NULL;152}153154char *setupMacOSXLocale(int cat) {155char * ret = getMacOSXLocale(cat);156157if (ret == NULL) {158return getPosixLocale(cat);159} else {160return ret;161}162}163164int isInAquaSession() {165// environment variable to bypass the aqua session check166char *ev = getenv("AWT_FORCE_HEADFUL");167if (ev && (strncasecmp(ev, "true", 4) == 0)) {168// if "true" then tell the caller we're in an Aqua session without actually checking169return 1;170}171#ifndef TARGET_OS_IOS172// Is the WindowServer available?173SecuritySessionId session_id;174SessionAttributeBits session_info;175OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info);176if (status == noErr) {177if (session_info & sessionHasGraphicAccess) {178return 1;179}180}181#endif182return 0;183}184185// 10.9 SDK does not include the NSOperatingSystemVersion struct.186// For now, create our own187typedef struct {188NSInteger majorVersion;189NSInteger minorVersion;190NSInteger patchVersion;191} OSVerStruct;192193void setOSNameAndVersion(java_props_t *sprops) {194// Hardcode os_name, and fill in os_version195sprops->os_name = strdup("Mac OS X");196197char* osVersionCStr = NULL;198// Mac OS 10.9 includes the [NSProcessInfo operatingSystemVersion] function,199// but it's not in the 10.9 SDK. So, call it via NSInvocation.200if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) {201OSVerStruct osVer;202NSMethodSignature *sig = [[NSProcessInfo processInfo] methodSignatureForSelector:203@selector(operatingSystemVersion)];204NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:sig];205invoke.selector = @selector(operatingSystemVersion);206[invoke invokeWithTarget:[NSProcessInfo processInfo]];207[invoke getReturnValue:&osVer];208209NSString *nsVerStr;210if (osVer.patchVersion == 0) { // Omit trailing ".0"211nsVerStr = [NSString stringWithFormat:@"%ld.%ld",212(long)osVer.majorVersion, (long)osVer.minorVersion];213} else {214nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld",215(long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion];216}217// Copy out the char*218osVersionCStr = strdup([nsVerStr UTF8String]);219}220// Fallback if running on pre-10.9 Mac OS221if (osVersionCStr == NULL) {222NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :223@"/System/Library/CoreServices/SystemVersion.plist"];224if (version != NULL) {225NSString *nsVerStr = [version objectForKey : @"ProductVersion"];226if (nsVerStr != NULL) {227osVersionCStr = strdup([nsVerStr UTF8String]);228}229}230}231if (osVersionCStr == NULL) {232osVersionCStr = strdup("Unknown");233}234sprops->os_version = osVersionCStr;235}236237238static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey,239CFStringRef inHostKey, CFStringRef inPortKey,240CFStringRef *outProxyHost, int *ioProxyPort) {241/* See if the proxy is enabled. */242CFNumberRef cf_enabled = CFDictionaryGetValue(inDict, inEnabledKey);243if (cf_enabled == NULL) {244return false;245}246247int isEnabled = false;248if (!CFNumberGetValue(cf_enabled, kCFNumberIntType, &isEnabled)) {249return isEnabled;250}251252if (!isEnabled) return false;253*outProxyHost = CFDictionaryGetValue(inDict, inHostKey);254255// If cf_host is null, that means the checkbox is set,256// but no host was entered. We'll treat that as NOT ENABLED.257// If cf_port is null or cf_port isn't a number, that means258// no port number was entered. Treat this as ENABLED with the259// protocol's default port.260if (*outProxyHost == NULL) {261return false;262}263264if (CFStringGetLength(*outProxyHost) == 0) {265return false;266}267268int newPort = 0;269CFNumberRef cf_port = NULL;270if ((cf_port = CFDictionaryGetValue(inDict, inPortKey)) != NULL &&271CFNumberGetValue(cf_port, kCFNumberIntType, &newPort) &&272newPort > 0) {273*ioProxyPort = newPort;274} else {275// bad port or no port - leave *ioProxyPort unchanged276}277278return true;279}280281static char *createUTF8CString(const CFStringRef theString) {282if (theString == NULL) return NULL;283284const CFIndex stringLength = CFStringGetLength(theString);285const CFIndex bufSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8) + 1;286char *returnVal = (char *)malloc(bufSize);287288if (CFStringGetCString(theString, returnVal, bufSize, kCFStringEncodingUTF8)) {289return returnVal;290}291292free(returnVal);293return NULL;294}295296// Return TRUE if str is a syntactically valid IP address.297// Using inet_pton() instead of inet_aton() for IPv6 support.298// len is only a hint; cstr must still be nul-terminated299static int looksLikeIPAddress(char *cstr, size_t len) {300if (len == 0 || (len == 1 && cstr[0] == '.')) return FALSE;301302char dst[16]; // big enough for INET6303return (1 == inet_pton(AF_INET, cstr, dst) ||3041 == inet_pton(AF_INET6, cstr, dst));305}306307308309// Convert Mac OS X proxy exception entry to Java syntax.310// See Radar #3441134 for details.311// Returns NULL if this exception should be ignored by Java.312// May generate a string with multiple exceptions separated by '|'.313static char * createConvertedException(CFStringRef cf_original) {314// This is done with char* instead of CFString because inet_pton()315// needs a C string.316char *c_exception = createUTF8CString(cf_original);317if (!c_exception) return NULL;318319int c_len = strlen(c_exception);320321// 1. sanitize exception prefix322if (c_len >= 1 && 0 == strncmp(c_exception, ".", 1)) {323memmove(c_exception, c_exception+1, c_len);324c_len -= 1;325} else if (c_len >= 2 && 0 == strncmp(c_exception, "*.", 2)) {326memmove(c_exception, c_exception+2, c_len-1);327c_len -= 2;328}329330// 2. pre-reject other exception wildcards331if (strchr(c_exception, '*')) {332free(c_exception);333return NULL;334}335336// 3. no IP wildcarding337if (looksLikeIPAddress(c_exception, c_len)) {338return c_exception;339}340341// 4. allow domain suffixes342// c_exception is now "str\0" - change to "str|*.str\0"343c_exception = reallocf(c_exception, c_len+3+c_len+1);344if (!c_exception) return NULL;345346strncpy(c_exception+c_len, "|*.", 3);347strncpy(c_exception+c_len+3, c_exception, c_len);348c_exception[c_len+3+c_len] = '\0';349return c_exception;350}351352/*353* Method for fetching the user.home path and storing it in the property list.354* For signed .apps running in the Mac App Sandbox, user.home is set to the355* app's sandbox container.356*/357void setUserHome(java_props_t *sprops) {358if (sprops == NULL) { return; }359NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];360sprops->user_home = createUTF8CString((CFStringRef)NSHomeDirectory());361[pool drain];362}363364/*365* Method for fetching proxy info and storing it in the property list.366*/367void setProxyProperties(java_props_t *sProps) {368if (sProps == NULL) return;369370char buf[16]; /* Used for %d of an int - 16 is plenty */371CFStringRef372cf_httpHost = NULL,373cf_httpsHost = NULL,374cf_ftpHost = NULL,375cf_socksHost = NULL,376cf_gopherHost = NULL;377int378httpPort = 80, // Default proxy port values379httpsPort = 443,380ftpPort = 21,381socksPort = 1080,382gopherPort = 70;383384CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);385if (dict == NULL) return;386387/* Read the proxy exceptions list */388CFArrayRef cf_list = CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList);389390CFMutableStringRef cf_exceptionList = NULL;391if (cf_list != NULL) {392CFIndex len = CFArrayGetCount(cf_list), idx;393394cf_exceptionList = CFStringCreateMutable(NULL, 0);395for (idx = (CFIndex)0; idx < len; idx++) {396CFStringRef cf_ehost;397if ((cf_ehost = CFArrayGetValueAtIndex(cf_list, idx))) {398/* Convert this exception from Mac OS X syntax to Java syntax.399See Radar #3441134 for details. This may generate a string400with multiple Java exceptions separated by '|'. */401char *c_exception = createConvertedException(cf_ehost);402if (c_exception) {403/* Append the host to the list of exclusions. */404if (CFStringGetLength(cf_exceptionList) > 0) {405CFStringAppendCString(cf_exceptionList, "|", kCFStringEncodingMacRoman);406}407CFStringAppendCString(cf_exceptionList, c_exception, kCFStringEncodingMacRoman);408free(c_exception);409}410}411}412}413414if (cf_exceptionList != NULL) {415if (CFStringGetLength(cf_exceptionList) > 0) {416sProps->exceptionList = createUTF8CString(cf_exceptionList);417}418CFRelease(cf_exceptionList);419}420421#define CHECK_PROXY(protocol, PROTOCOL) \422sProps->protocol##ProxyEnabled = \423getProxyInfoForProtocol(dict, kSCPropNetProxies##PROTOCOL##Enable, \424kSCPropNetProxies##PROTOCOL##Proxy, \425kSCPropNetProxies##PROTOCOL##Port, \426&cf_##protocol##Host, &protocol##Port); \427if (sProps->protocol##ProxyEnabled) { \428sProps->protocol##Host = createUTF8CString(cf_##protocol##Host); \429snprintf(buf, sizeof(buf), "%d", protocol##Port); \430sProps->protocol##Port = malloc(strlen(buf) + 1); \431strcpy(sProps->protocol##Port, buf); \432}433434CHECK_PROXY(http, HTTP);435CHECK_PROXY(https, HTTPS);436CHECK_PROXY(ftp, FTP);437CHECK_PROXY(socks, SOCKS);438CHECK_PROXY(gopher, Gopher);439440#undef CHECK_PROXY441442CFRelease(dict);443}444445446