Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/macosx/native/libjava/java_props_macosx.c
41119 views
1
/*
2
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#ifndef TARGET_IOS
27
#include <sys/socket.h>
28
#include <netinet/in.h>
29
#include <arpa/inet.h>
30
#include <objc/objc-runtime.h>
31
32
#include <CoreFoundation/CoreFoundation.h>
33
#include <SystemConfiguration/SystemConfiguration.h>
34
#include <Foundation/Foundation.h>
35
36
#else
37
#include <stdlib.h>
38
#include <string.h>
39
#include <sys/param.h>
40
#include <objc/runtime.h>
41
#include <objc/objc.h>
42
#include <objc/message.h>
43
#include <CoreFoundation/CoreFoundation.h>
44
#include <CoreFoundation/CFlocale.h>
45
46
#endif
47
48
#include "java_props_macosx.h"
49
50
#ifndef TARGET_IOS
51
52
char *getPosixLocale(int cat) {
53
char *lc = setlocale(cat, NULL);
54
if ((lc == NULL) || (strcmp(lc, "C") == 0)) {
55
lc = getenv("LANG");
56
}
57
if (lc == NULL) return NULL;
58
return strdup(lc);
59
}
60
61
#define LOCALEIDLENGTH 128
62
#ifndef kCFCoreFoundationVersionNumber10_11_Max
63
#define kCFCoreFoundationVersionNumber10_11_Max 1299
64
#endif
65
char *getMacOSXLocale(int cat) {
66
const char* retVal = NULL;
67
char languageString[LOCALEIDLENGTH];
68
char localeString[LOCALEIDLENGTH];
69
70
// Since macOS 10.12, there is no separate language selection for
71
// "format" locale, e.g., date format. Use the preferred language
72
// for all LC_* categories.
73
if (kCFCoreFoundationVersionNumber >
74
kCFCoreFoundationVersionNumber10_11_Max) {
75
cat = LC_MESSAGES;
76
}
77
78
switch (cat) {
79
case LC_MESSAGES:
80
{
81
// get preferred language code
82
CFArrayRef languages = CFLocaleCopyPreferredLanguages();
83
if (languages == NULL) {
84
return NULL;
85
}
86
if (CFArrayGetCount(languages) <= 0) {
87
CFRelease(languages);
88
return NULL;
89
}
90
91
CFStringRef primaryLanguage = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);
92
if (primaryLanguage == NULL) {
93
CFRelease(languages);
94
return NULL;
95
}
96
if (CFStringGetCString(primaryLanguage, languageString,
97
LOCALEIDLENGTH, CFStringGetSystemEncoding()) == false) {
98
CFRelease(languages);
99
return NULL;
100
}
101
CFRelease(languages);
102
103
// Explicitly supply region, if there is none
104
char *hyphenPos = strchr(languageString, '-');
105
int langStrLen = strlen(languageString);
106
107
if (hyphenPos == NULL || // languageString contains ISO639 only, e.g., "en"
108
languageString + langStrLen - hyphenPos == 5) { // ISO639-ScriptCode, e.g., "en-Latn"
109
CFLocaleRef cflocale = CFLocaleCopyCurrent();
110
if (cflocale != NULL) {
111
CFStringGetCString(CFLocaleGetIdentifier(cflocale),
112
localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding());
113
char *underscorePos = strrchr(localeString, '_');
114
char *region = NULL;
115
116
if (underscorePos != NULL) {
117
region = underscorePos + 1;
118
}
119
120
if (region != NULL) {
121
strcat(languageString, "-");
122
strcat(languageString, region);
123
}
124
CFRelease(cflocale);
125
}
126
}
127
128
retVal = languageString;
129
}
130
break;
131
132
default:
133
{
134
CFLocaleRef cflocale = CFLocaleCopyCurrent();
135
if (cflocale != NULL) {
136
if (!CFStringGetCString(CFLocaleGetIdentifier(cflocale),
137
localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {
138
CFRelease(cflocale);
139
return NULL;
140
}
141
142
retVal = localeString;
143
CFRelease(cflocale);
144
} else {
145
return NULL;
146
}
147
}
148
break;
149
}
150
151
if (retVal != NULL) {
152
// convertToPOSIXLocale() does not expect any variant codes, so ignore
153
// '@' and anything following, if present.
154
char* rmAt = strchr(retVal, '@');
155
if (rmAt != NULL) {
156
*rmAt = '\0';
157
}
158
return strdup(convertToPOSIXLocale(retVal));
159
}
160
161
return NULL;
162
}
163
164
/* Language IDs use the language designators and (optional) region
165
* and script designators of BCP 47. So possible formats are:
166
*
167
* "en" (language designator only)
168
* "haw" (3-letter lanuage designator)
169
* "en-GB" (language with alpha-2 region designator)
170
* "es-419" (language with 3-digit UN M.49 area code)
171
* "zh-Hans" (language with ISO 15924 script designator)
172
* "zh-Hans-US" (language with ISO 15924 script designator and region)
173
* "zh-Hans-419" (language with ISO 15924 script designator and UN M.49)
174
*
175
* convert these tags into POSIX conforming locale string, i.e.,
176
* lang{_region}{@script}. e.g., for "zh-Hans-US" into "zh_US@Hans"
177
*/
178
const char * convertToPOSIXLocale(const char* src) {
179
char* scriptRegion = strchr(src, '-');
180
if (scriptRegion != NULL) {
181
int length = strlen(scriptRegion);
182
char* region = strchr(scriptRegion + 1, '-');
183
char* atMark = NULL;
184
185
if (region == NULL) {
186
// CFLocaleGetIdentifier() returns '_' before region
187
region = strchr(scriptRegion + 1, '_');
188
}
189
190
*scriptRegion = '_';
191
if (length > 5) {
192
// Region and script both exist.
193
char tmpScript[4];
194
int regionLength = length - 6;
195
atMark = scriptRegion + 1 + regionLength;
196
memcpy(tmpScript, scriptRegion + 1, 4);
197
memmove(scriptRegion + 1, region + 1, regionLength);
198
memcpy(atMark + 1, tmpScript, 4);
199
} else if (length == 5) {
200
// script only
201
atMark = scriptRegion;
202
}
203
204
if (atMark != NULL) {
205
*atMark = '@';
206
207
// assert script code
208
assert(isalpha(atMark[1]) &&
209
isalpha(atMark[2]) &&
210
isalpha(atMark[3]) &&
211
isalpha(atMark[4]));
212
}
213
214
assert(((length == 3 || length == 8) &&
215
// '_' followed by a 2 character region designator
216
isalpha(scriptRegion[1]) &&
217
isalpha(scriptRegion[2])) ||
218
((length == 4 || length == 9) &&
219
// '_' followed by a 3-digit UN M.49 area code
220
isdigit(scriptRegion[1]) &&
221
isdigit(scriptRegion[2]) &&
222
isdigit(scriptRegion[3])) ||
223
// '@' followed by a 4 character script code (already validated above)
224
(length == 5));
225
}
226
227
return src;
228
}
229
230
char *setupMacOSXLocale(int cat) {
231
char * ret = getMacOSXLocale(cat);
232
233
if (ret == NULL) {
234
return getPosixLocale(cat);
235
} else {
236
return ret;
237
}
238
}
239
240
// 10.9 SDK does not include the NSOperatingSystemVersion struct.
241
// For now, create our own
242
typedef struct {
243
NSInteger majorVersion;
244
NSInteger minorVersion;
245
NSInteger patchVersion;
246
} OSVerStruct;
247
248
void setOSNameAndVersion(java_props_t *sprops) {
249
// Hardcode os_name, and fill in os_version
250
sprops->os_name = strdup("Mac OS X");
251
252
char* osVersionCStr = NULL;
253
// Mac OS 10.9 includes the [NSProcessInfo operatingSystemVersion] function,
254
// but it's not in the 10.9 SDK. So, call it via NSInvocation.
255
if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) {
256
OSVerStruct osVer;
257
NSMethodSignature *sig = [[NSProcessInfo processInfo] methodSignatureForSelector:
258
@selector(operatingSystemVersion)];
259
NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:sig];
260
invoke.selector = @selector(operatingSystemVersion);
261
[invoke invokeWithTarget:[NSProcessInfo processInfo]];
262
[invoke getReturnValue:&osVer];
263
264
NSString *nsVerStr;
265
// Copy out the char* if running on version other than 10.16 Mac OS (10.16 == 11.x)
266
// or explicitly requesting version compatibility
267
if (!((long)osVer.majorVersion == 10 && (long)osVer.minorVersion >= 16) ||
268
(getenv("SYSTEM_VERSION_COMPAT") != NULL)) {
269
if (osVer.patchVersion == 0) { // Omit trailing ".0"
270
nsVerStr = [NSString stringWithFormat:@"%ld.%ld",
271
(long)osVer.majorVersion, (long)osVer.minorVersion];
272
} else {
273
nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld",
274
(long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion];
275
}
276
// Copy out the char*
277
osVersionCStr = strdup([nsVerStr UTF8String]);
278
} else {
279
// Version 10.16, without explicit env setting of SYSTEM_VERSION_COMPAT
280
// AKA 11.x; compute the version number from the letter in the ProductBuildVersion
281
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :
282
@"/System/Library/CoreServices/SystemVersion.plist"];
283
if (version != NULL) {
284
NSString *nsBuildVerStr = [version objectForKey : @"ProductBuildVersion"];
285
if (nsBuildVerStr != NULL && nsBuildVerStr.length >= 3) {
286
int letter = [nsBuildVerStr characterAtIndex:2];
287
if (letter >= 'B' && letter <= 'Z') {
288
int vers = letter - 'A' - 1;
289
asprintf(&osVersionCStr, "11.%d", vers);
290
}
291
}
292
}
293
}
294
}
295
// Fallback if running on pre-10.9 Mac OS
296
if (osVersionCStr == NULL) {
297
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :
298
@"/System/Library/CoreServices/SystemVersion.plist"];
299
if (version != NULL) {
300
NSString *nsVerStr = [version objectForKey : @"ProductVersion"];
301
if (nsVerStr != NULL) {
302
osVersionCStr = strdup([nsVerStr UTF8String]);
303
}
304
}
305
}
306
if (osVersionCStr == NULL) {
307
osVersionCStr = strdup("Unknown");
308
}
309
sprops->os_version = osVersionCStr;
310
}
311
312
313
static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey,
314
CFStringRef inHostKey, CFStringRef inPortKey,
315
CFStringRef *outProxyHost, int *ioProxyPort) {
316
/* See if the proxy is enabled. */
317
CFNumberRef cf_enabled = CFDictionaryGetValue(inDict, inEnabledKey);
318
if (cf_enabled == NULL) {
319
return false;
320
}
321
322
int isEnabled = false;
323
if (!CFNumberGetValue(cf_enabled, kCFNumberIntType, &isEnabled)) {
324
return isEnabled;
325
}
326
327
if (!isEnabled) return false;
328
*outProxyHost = CFDictionaryGetValue(inDict, inHostKey);
329
330
// If cf_host is null, that means the checkbox is set,
331
// but no host was entered. We'll treat that as NOT ENABLED.
332
// If cf_port is null or cf_port isn't a number, that means
333
// no port number was entered. Treat this as ENABLED with the
334
// protocol's default port.
335
if (*outProxyHost == NULL) {
336
return false;
337
}
338
339
if (CFStringGetLength(*outProxyHost) == 0) {
340
return false;
341
}
342
343
int newPort = 0;
344
CFNumberRef cf_port = NULL;
345
if ((cf_port = CFDictionaryGetValue(inDict, inPortKey)) != NULL &&
346
CFNumberGetValue(cf_port, kCFNumberIntType, &newPort) &&
347
newPort > 0) {
348
*ioProxyPort = newPort;
349
} else {
350
// bad port or no port - leave *ioProxyPort unchanged
351
}
352
353
return true;
354
}
355
356
static char *createUTF8CString(const CFStringRef theString) {
357
if (theString == NULL) return NULL;
358
359
const CFIndex stringLength = CFStringGetLength(theString);
360
const CFIndex bufSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8) + 1;
361
char *returnVal = (char *)malloc(bufSize);
362
363
if (CFStringGetCString(theString, returnVal, bufSize, kCFStringEncodingUTF8)) {
364
return returnVal;
365
}
366
367
free(returnVal);
368
return NULL;
369
}
370
371
// Return TRUE if str is a syntactically valid IP address.
372
// Using inet_pton() instead of inet_aton() for IPv6 support.
373
// len is only a hint; cstr must still be nul-terminated
374
static int looksLikeIPAddress(char *cstr, size_t len) {
375
if (len == 0 || (len == 1 && cstr[0] == '.')) return FALSE;
376
377
char dst[16]; // big enough for INET6
378
return (1 == inet_pton(AF_INET, cstr, dst) ||
379
1 == inet_pton(AF_INET6, cstr, dst));
380
}
381
382
383
384
// Convert Mac OS X proxy exception entry to Java syntax.
385
// See Radar #3441134 for details.
386
// Returns NULL if this exception should be ignored by Java.
387
// May generate a string with multiple exceptions separated by '|'.
388
static char * createConvertedException(CFStringRef cf_original) {
389
// This is done with char* instead of CFString because inet_pton()
390
// needs a C string.
391
char *c_exception = createUTF8CString(cf_original);
392
if (!c_exception) return NULL;
393
394
int c_len = strlen(c_exception);
395
396
// 1. sanitize exception prefix
397
if (c_len >= 1 && 0 == strncmp(c_exception, ".", 1)) {
398
memmove(c_exception, c_exception+1, c_len);
399
c_len -= 1;
400
} else if (c_len >= 2 && 0 == strncmp(c_exception, "*.", 2)) {
401
memmove(c_exception, c_exception+2, c_len-1);
402
c_len -= 2;
403
}
404
405
// 2. pre-reject other exception wildcards
406
if (strchr(c_exception, '*')) {
407
free(c_exception);
408
return NULL;
409
}
410
411
// 3. no IP wildcarding
412
if (looksLikeIPAddress(c_exception, c_len)) {
413
return c_exception;
414
}
415
416
// 4. allow domain suffixes
417
// c_exception is now "str\0" - change to "str|*.str\0"
418
c_exception = reallocf(c_exception, c_len+3+c_len+1);
419
if (!c_exception) return NULL;
420
421
strncpy(c_exception+c_len, "|*.", 3);
422
strncpy(c_exception+c_len+3, c_exception, c_len);
423
c_exception[c_len+3+c_len] = '\0';
424
return c_exception;
425
}
426
427
/*
428
* Method for fetching the user.home path and storing it in the property list.
429
* For signed .apps running in the Mac App Sandbox, user.home is set to the
430
* app's sandbox container.
431
*/
432
void setUserHome(java_props_t *sprops) {
433
if (sprops == NULL) { return; }
434
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
435
sprops->user_home = createUTF8CString((CFStringRef)NSHomeDirectory());
436
[pool drain];
437
}
438
439
/*
440
* Method for fetching proxy info and storing it in the property list.
441
*/
442
void setProxyProperties(java_props_t *sProps) {
443
if (sProps == NULL) return;
444
445
char buf[16]; /* Used for %d of an int - 16 is plenty */
446
CFStringRef
447
cf_httpHost = NULL,
448
cf_httpsHost = NULL,
449
cf_ftpHost = NULL,
450
cf_socksHost = NULL;
451
int
452
httpPort = 80, // Default proxy port values
453
httpsPort = 443,
454
ftpPort = 21,
455
socksPort = 1080;
456
457
CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
458
if (dict == NULL) return;
459
460
/* Read the proxy exceptions list */
461
CFArrayRef cf_list = CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList);
462
463
CFMutableStringRef cf_exceptionList = NULL;
464
if (cf_list != NULL) {
465
CFIndex len = CFArrayGetCount(cf_list), idx;
466
467
cf_exceptionList = CFStringCreateMutable(NULL, 0);
468
for (idx = (CFIndex)0; idx < len; idx++) {
469
CFStringRef cf_ehost;
470
if ((cf_ehost = CFArrayGetValueAtIndex(cf_list, idx))) {
471
/* Convert this exception from Mac OS X syntax to Java syntax.
472
See Radar #3441134 for details. This may generate a string
473
with multiple Java exceptions separated by '|'. */
474
char *c_exception = createConvertedException(cf_ehost);
475
if (c_exception) {
476
/* Append the host to the list of exclusions. */
477
if (CFStringGetLength(cf_exceptionList) > 0) {
478
CFStringAppendCString(cf_exceptionList, "|", kCFStringEncodingMacRoman);
479
}
480
CFStringAppendCString(cf_exceptionList, c_exception, kCFStringEncodingMacRoman);
481
free(c_exception);
482
}
483
}
484
}
485
}
486
487
if (cf_exceptionList != NULL) {
488
if (CFStringGetLength(cf_exceptionList) > 0) {
489
sProps->exceptionList = createUTF8CString(cf_exceptionList);
490
}
491
CFRelease(cf_exceptionList);
492
}
493
494
#define CHECK_PROXY(protocol, PROTOCOL) \
495
sProps->protocol##ProxyEnabled = \
496
getProxyInfoForProtocol(dict, kSCPropNetProxies##PROTOCOL##Enable, \
497
kSCPropNetProxies##PROTOCOL##Proxy, \
498
kSCPropNetProxies##PROTOCOL##Port, \
499
&cf_##protocol##Host, &protocol##Port); \
500
if (sProps->protocol##ProxyEnabled) { \
501
sProps->protocol##Host = createUTF8CString(cf_##protocol##Host); \
502
snprintf(buf, sizeof(buf), "%d", protocol##Port); \
503
sProps->protocol##Port = malloc(strlen(buf) + 1); \
504
strcpy(sProps->protocol##Port, buf); \
505
}
506
507
CHECK_PROXY(http, HTTP);
508
CHECK_PROXY(https, HTTPS);
509
CHECK_PROXY(ftp, FTP);
510
CHECK_PROXY(socks, SOCKS);
511
512
#undef CHECK_PROXY
513
514
CFRelease(dict);
515
}
516
#else
517
#define LOCALEIDLENGTH 128
518
char *getPosixLocale(int cat) {
519
char *lc = setlocale(cat, NULL);
520
if ((lc == NULL) || (strcmp(lc, "C") == 0)) {
521
lc = getenv("LANG");
522
}
523
if (lc == NULL) return NULL;
524
return strdup(lc);
525
}
526
527
char *getMacOSXLocale(int cat) {
528
char localeString[LOCALEIDLENGTH];
529
// Get current user locale.
530
CFLocaleRef loc = CFLocaleCopyCurrent();
531
char *localstr;
532
if (CFStringGetCString(CFLocaleGetIdentifier(loc),
533
localeString, LOCALEIDLENGTH,
534
kCFStringEncodingUTF8))
535
localstr = strdup(localeString);
536
else
537
localstr = NULL;
538
539
CFRelease(loc);
540
return (localstr);
541
}
542
543
#endif
544
545