3636import javax .swing .text .html .parser .ParserDelegator ;
3737
3838import org .apache .commons .io .IOUtils ;
39+ import org .apache .commons .io .input .BOMInputStream ;
3940import org .apache .commons .text .StringEscapeUtils ;
4041import org .owasp .html .PolicyFactory ;
4142import org .owasp .html .Sanitizers ;
@@ -48,7 +49,8 @@ public class StringUtils {
4849 private static final String UPPERCASE_ALPHA = stringRange ('A' , 'Z' );
4950 private static final String LOWERCASE_ALPHA = stringRange ('a' , 'z' );
5051 private static final String DIGITS = stringRange ('0' , '9' );
51- private static final String SPECIAL = stringRange ('!' , '/' );
52+ // Used in tests as well
53+ static final String SPECIAL = stringRange ('!' , '/' );
5254 private static final String ALPHANUMERIC = UPPERCASE_ALPHA + LOWERCASE_ALPHA + DIGITS ;
5355
5456 static final Map <String , PolicyFactory > SANITIZER_POLICIES =
@@ -63,6 +65,12 @@ public class StringUtils {
6365
6466 public static final String HASH_ALGORITHM = "SHA-256" ;
6567
68+ public static String hash (String value ) throws NoSuchAlgorithmException , DigestException {
69+ int LENGTH = 32 ;
70+ return hash (value , LENGTH );
71+ }
72+
73+ @ Deprecated
6674 public static String hash (String value , int length ) throws NoSuchAlgorithmException , DigestException {
6775 byte [] inBytes = value .getBytes (StandardCharsets .UTF_8 );
6876 byte [] outBytes = new byte [length ];
@@ -215,10 +223,14 @@ public static String stringFromFile(IContext context, FileDocument source, Chars
215223 return null ;
216224 }
217225 try (InputStream f = Core .getFileDocumentContent (context , source .getMendixObject ())) {
218- return IOUtils . toString (f , charset );
226+ return stringFromInputStream (f , charset );
219227 }
220228 }
221229
230+ public static String stringFromInputStream (InputStream inputStream , Charset charset ) throws IOException {
231+ return IOUtils .toString (BOMInputStream .builder ().setInputStream (inputStream ).get (), charset );
232+ }
233+
222234 public static void stringToFile (IContext context , String value , FileDocument destination ) throws IOException {
223235 stringToFile (context , value , destination , StandardCharsets .UTF_8 );
224236 }
@@ -279,39 +291,63 @@ public void handleEndTag(HTML.Tag tag, int pos) {
279291 }
280292
281293 /**
282- * Returns a random strong password containing a specified minimum number of digits, uppercase
283- * and special characters.
294+ * Returns a random strong password containing a specified minimum number of uppercase, digits
295+ * and the exact number of special characters.
284296 *
285297 * @param minLen Minimum length
286298 * @param maxLen Maximum length
287- * @param noOfCAPSAlpha Number of capitals
288- * @param noOfDigits Number of digits
289- * @param noOfSplChars Number of special characters
290- * @return
299+ * @param noOfCAPSAlpha Minimum number of capitals
300+ * @param noOfDigits Minimum number of digits
301+ * @param noOfSplChars Exact number of special characters
302+ * @deprecated Use the overload randomStrongPassword instead
291303 */
304+ @ Deprecated
292305 public static String randomStrongPassword (int minLen , int maxLen , int noOfCAPSAlpha , int noOfDigits , int noOfSplChars ) {
293306 if (minLen > maxLen ) {
294307 throw new IllegalArgumentException ("Min. Length > Max. Length!" );
295308 }
296309 if ((noOfCAPSAlpha + noOfDigits + noOfSplChars ) > minLen ) {
297310 throw new IllegalArgumentException ("Min. Length should be atleast sum of (CAPS, DIGITS, SPL CHARS) Length!" );
298311 }
299- return generateCommonLangPassword (minLen , maxLen , noOfCAPSAlpha , noOfDigits , noOfSplChars );
312+ return generateCommonLangPassword (minLen , maxLen , noOfCAPSAlpha , 0 , noOfDigits , noOfSplChars );
313+ }
314+
315+ /**
316+ * Returns a random strong password containing a specified minimum number of uppercase, lowercase, digits
317+ * and the exact number of special characters.
318+ *
319+ * @param minLen Minimum length
320+ * @param maxLen Maximum length
321+ * @param noOfCAPSAlpha Minimum number of capitals
322+ * @param noOfLowercaseAlpha Minimum number of lowercase letters
323+ * @param noOfDigits Minimum number of digits
324+ * @param noOfSplChars Exact number of special characters
325+ */
326+ public static String randomStrongPassword (int minLen , int maxLen , int noOfCAPSAlpha , int noOfLowercaseAlpha , int noOfDigits , int noOfSplChars ) {
327+ if (minLen > maxLen ) {
328+ throw new IllegalArgumentException ("Min. Length > Max. Length!" );
329+ }
330+ if ((noOfCAPSAlpha + noOfLowercaseAlpha + noOfDigits + noOfSplChars ) > minLen ) {
331+ throw new IllegalArgumentException ("Min. Length should be atleast sum of (CAPS, LOWER, DIGITS, SPL CHARS) Length!" );
332+ }
333+ return generateCommonLangPassword (minLen , maxLen , noOfCAPSAlpha , noOfLowercaseAlpha , noOfDigits , noOfSplChars );
300334 }
301335
302336 // See https://www.baeldung.com/java-generate-secure-password
303337 // Implementation inspired by https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-string-apis (under MIT license)
304- private static String generateCommonLangPassword (int minLen , int maxLen , int noOfCapsAlpha , int noOfDigits , int noOfSplChars ) {
338+ private static String generateCommonLangPassword (int minLen , int maxLen , int noOfCapsAlpha , int noOfLowercaseAlpha , int noOfDigits , int noOfSplChars ) {
305339 String upperCaseLetters = randomStringFromCharArray (noOfCapsAlpha , UPPERCASE_ALPHA .toCharArray ());
340+ String lowerCaseLetters = randomStringFromCharArray (noOfLowercaseAlpha , LOWERCASE_ALPHA .toCharArray ());
306341 String numbers = randomStringFromCharArray (noOfDigits , DIGITS .toCharArray ());
307342 String specialChar = randomStringFromCharArray (noOfSplChars , SPECIAL .toCharArray ());
308343
309- final int fixedNumber = noOfCapsAlpha + noOfDigits + noOfSplChars ;
344+ final int fixedNumber = noOfCapsAlpha + noOfLowercaseAlpha + noOfDigits + noOfSplChars ;
310345 final int lowerBound = minLen - fixedNumber ;
311346 final int upperBound = maxLen - fixedNumber ;
312347 String totalChars = randomStringFromCharArray (lowerBound , upperBound , ALPHANUMERIC .toCharArray ());
313348
314349 String combinedChars = upperCaseLetters
350+ .concat (lowerCaseLetters )
315351 .concat (numbers )
316352 .concat (specialChar )
317353 .concat (totalChars );
@@ -462,7 +498,12 @@ public static String sanitizeHTML(String html, List<SanitizerPolicy> policyParam
462498 PolicyFactory policyFactory = null ;
463499
464500 for (SanitizerPolicy param : policyParams ) {
465- policyFactory = (policyFactory == null ) ? SANITIZER_POLICIES .get (param .name ()) : policyFactory .and (SANITIZER_POLICIES .get (param .name ()));
501+ PolicyFactory policyFactoryForParam = SANITIZER_POLICIES .get (param .name ());
502+ policyFactory = (policyFactory == null ) ? policyFactoryForParam : policyFactory .and (policyFactoryForParam );
503+ }
504+
505+ if (policyFactory == null ) {
506+ throw new IllegalArgumentException ("Sanitizer policy not found." );
466507 }
467508
468509 return sanitizeHTML (html , policyFactory );
0 commit comments