Fixed fortify scan Locale changes are reappearing - java

I have one J2EE application and for that application, fortify scan shows Locale dependent issues.
I have fixed those issues where using Locale.ENGLISH in toUpperCase(Locale.ENGLISH) and toLowerCase(Locale.ENGLISH) functions while comparing the Strings,
Earlier,
firstName.trim().toLowerCase();
Now
firstName.trim().toLowerCase(Locale.ENGLISH);
and I again run fortify scan on the application. However, second time, fortify scan shows Locale error at same place.
How can I fix these kind of issues?

The issue category "Portability Flaw: Locale Dependent Comparison" (RULEGUID=D8E9ED3B-22EC-4CBA-98C8-7C67F73CCF4C) belongs to the "Code Quality" kingdom and is a LOW RISK issue. I usually leave it un-remediated.
RATIONALE
When "java.lang.String.toUpperCase()/toLowerCase()" used without setting a locale, it will use the default locale. This may cause security checking being bypassed. For example, we want to exclude "script" from user input; if the default language is Turkish, the tag.toUpperCase() returns "T\u0130TLE", where "\u0130" is the "LATIN CAPITAL LETTER I WITH DOT ABOVE" character. Therefor the "script" checking is bypassed.
if (tag.toUpperCase().equals("SCRIPT")){
return null;}
REMEDIATION
(1) you can set language when start VM, and mark the issue "Not an Issue"
java -Duser.language=en -Duser.country=US -Duser.variant=US MainClass
(2) or, set language by code
import java.util.Locale;
//be aware that Locale.setDefault is global, below set locale to en_US_WIN
Locale.setDefault(new Locale("en", "US", "WIN"));
(3) or, if clients use different languages, use HttpServletRequest.getLocale
// see sample code here

Related

How to use String.format(Locale, ...)?

I am new in Android development and I'm trying this code:
String hms = String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(milliSeconds),
TimeUnit.MILLISECONDS.toMinutes(milliSeconds) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milliSeconds)),
TimeUnit.MILLISECONDS.toSeconds(milliSeconds) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliSeconds)));
I get the message :
Implicitly using the default locale is a common source of bugs:
Use String.format(Locale, ...) instead
I have no idea how to modify the code in order to implement the recommendation.
Most likely you don't need to do anything. That's a warning telling you that you didn't specify a locale for String.format, so it's using the default locale. That can cause a bug in some circumstances, but it's unlikely to in yours. If you want to be careful you can pass in an explicit locale, or you can just ignore the warning. Formatting numbers like this without any type of currency is fairly safe.
(The bugs you'll see are if the locale your device is in has specific formatting rules for things. The big one I know of that's hit me is that Turkish has a letter i who's capital symbol is different than the english letter I.)

How to use unsupported Locale in Java 11 and numbers in String.format()

How can I use an unsupported Locale (eg. ar-US) in JAVA 11 when I output a number via String.format()?
In Java 8 this worked just fine (try jdoodle, select JDK 1.8.0_66):
Locale locale = Locale.forLanguageTag("ar-US");
System.out.println(String.format(locale, "Output: %d", 120));
// Output: 120
Since Java 11 the output is in Eastern Arabic numerals (try jdoodle, use default JDK 11.0.4):
Locale locale = Locale.forLanguageTag("ar-US");
System.out.println(String.format(locale, "Output: %d", 120));
// Output: ١٢٠
It seems, this problem comes from the switch in the Locale Data Providers form JRE to CLDR (source: Localization Changes in Java 9 by #mcarth). Here is a list of supported locales: JDK 11 Supported Locales
UPDATE
I updated the questions example to ar-US, as my example before didn't make sense. The idea is to have a format which makes sense in that given country. In the example it would be the United States (US).
The behavior conforms to the CLDR being treated as the preferred Locale. To confirm this, the same snippet in Java-8 could be executed with
-Djava.locale.providers=CLDR
If you step back to look at the JEP 252: Use CLDR Locale Data by Default, the details follow :
The default lookup order will be CLDR, COMPAT, SPI, where COMPAT
designates the JRE's locale data in JDK 9. If a particular provider
cannot offer the requested locale data, the search will proceed to the
next provider in order.
So, in short if you really don't want the default behaviour to be that of Java-11, you can change the order of lookup with the VM argument
-Djava.locale.providers=COMPAT,CLDR,SPI
What might help further is understanding more about picking the right language using CLDR!
I'm sure I'm missing some nuance, but the problem is with your tag, so fix that. Specifically:
ar-EN makes no sense. That's short for:
language = arabic
country = ?? nobody knows.
EN is not a country. en is certainly a language code (for english), but the second part in a language tag is for country, and EN is not a country. (for context, there is en-GB for british english and en-US for american english).
Thus, this is as good as ar (as in, language = arabic, not tied to any particular country). Even if you did tie it to some country, that is mostly immaterial here; that would affect things like 'what is the first day of the week' ,'which currency symbol is to be presumed' and 'should temperatures be stated in Kelvin or Fahrenheit' perhaps. It has no bearing on how to show digits, because that's all based on language.
And language is arabic, thus, ١٢٠ is what you get when you try ar as a language tag when printing the number 120. The problem is that you expect this to return "120" which is a bizarre wish1, combined with the fact that java, unfortunately, shipped with a bug for a long long time that made it act in this bizarre fashion, thinking that rendering the number 120 in arabic is best done with "120", which is wrong.
So, with that context, in order of preference:
Best solution
Find out why your system ends up with ar-EN and nevertheless expects '120', and fix this. Also fix ar-EN in general; EN is not a country.
More generally, 'unsupported locale' isn't really a thing. the ar part is supported, and it's the only relevant part of the tag for rendering digits.
Alternatives
The most likely best answer if the above is not possible is to explicitly work around it. Detect the tag yourself, and write code that will just respond with the result of formatting this number using Locale.ENGLISH instead, guaranteeing that you get Output: 120. The rest seems considerably worse: You could try to write a localization provider which is a ton of work, or you can try to tell java to use the JRE version of the provider, but that one is obsoleted and will not be updated, so you're kicking the can down the road and setting yourself up for a maintenance burden later.
1.) Given that the JRE variant actually printed 120, and you're also indicating you want this, I get that nagging feeling I'm missing some political or historical info and the expectation that ar-EN results in rendering the number 120 as "120" is not so crazy. I'd love to hear that story if you care to provide it!

what is the difference between freemarker 2.3.21 and freemarker 2.3.26-incubating

I want to update Freemarker from 2.3.21 to 2.3.26-incubating. but, I do not know what features have improved or added or edited. I need to write an article about main improvement between these tow version. what should I write?
I want main improvement between tow versions 2.3.21 and 2.3.26-incubating of Freemarker. please, help me:
As #StephaneM said, there's a detailed change log. And it will be long for such a huge version range, but all changes should be backward compatible. But the most popular new features were probably these: Automatic escaping (i.e. "output formats"), new #list features (key-value listing, #items, #else, #sep), loop variable built-ins, ?api (to work around historical issues with Map-s...), custom number- and date formats, += and ++ operators in assignments, possibility of escaping of - (and : and .) in identifiers with \.

How to get the script from a Locale object on Android?

From what I see the Android Locale class doesn't mention anything about the script, only the language, country and variant.
Whereas the Java SE Locale class mentions language, country, script, variant and extensions, and of course has a method getScript() to get the script.
So, my question is: How to get the script from a Locale object on Android?
or is there another way to get the script?
I need this to be able to differentiate between Chinese Traditional (zho-Hant) and Chinese Simplified (zho-Hans), for that I need to be able to get the script from the Locale, e.g. Hant or Hans for the language zho
script =
ISO 15924 alpha-4 script code. You can find a full list of valid
script codes in the IANA Language Subtag Registry (search for "Type:
script"). The script field is case insensitive, but Locale always
canonicalizes to title case (the first letter is upper case and the
rest of the letters are lower case).
Well-formed script values have the form [a-zA-Z]{4}
Example: "Latn" (Latin), "Cyrl" (Cyrillic)
This feature is not built into the Android SDK. Instead, I wrote a version you can use, available here. Basically, it takes the table in the above answer and ports it to a Map<String, Map<String, String>> containing the useful information, then a simple lookup method is used. To use this class in your project, just call:
String script = LocaleUtilities.getScript(Locale.getDefault());
to get the script for the default locale.

How to get styled language/country code from the Java Locale

I was wondering if anyone knows how to get formatted or styled codes from the Locale class. What i would like to see is "en_US" for English for US. For example, if i detect a language from Firefox it comes back as "en-us,en;q=0.5". Later when I want to output it (using getLanguage() or toString()) it comes back as "en-us,en;q=0.5" instead of "en_US". I tried various functions, but they all seem to return the string that was used to generate the Locale in the first place.
These values go into various UI elements and config files, so it would be nicer to have them looking the same regardless of who or how it was generated and also comparison is not easy when they are converted to strings (have to be).
Cheers and Thanks!
NOTE: I am asking this because we have legacy code that does alot (and i really mean most) of things when data is in string/xml format, so formatting is crucial.
Locale#toString() returns what you want.
Here's the thing: the languages you detect from Firefox use the format specified in RFC 2616, which is the HTTP specification. This is a different format from anything you'll see in a Java Locale because that format is very much HTTP-specific.
The problem is the meaning on what you are trying to print.
en-us,en;q=0.5
Means that the preference quality of the english language is 50% and it can be identified as en-us or en.
In the case you get in an http request
Accept-Language: da, en-gb;q=0.8, en;q=0.7
it means: "I prefer Danish, but will accept British English and other types of English"
so first you will have to decode your http request according to the specification and then get the Locales

Categories