All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zaproxy.zap.utils.I18N Maven / Gradle / Ivy

Go to download

The Zed Attack Proxy (ZAP) is an easy to use integrated penetration testing tool for finding vulnerabilities in web applications. It is designed to be used by people with a wide range of security experience and as such is ideal for developers and functional testers who are new to penetration testing. ZAP provides automated scanners as well as a set of tools that allow you to find security vulnerabilities manually.

There is a newer version: 2.15.0
Show newest version
/*
 * Zed Attack Proxy (ZAP) and its related class files.
 *
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 *
 * Copyright 2012 The ZAP Development Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.zaproxy.zap.utils;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;

public class I18N {

    /*
     * Utility class for handling multiple message bundles.
     * This allows extensions to manage their own i18n files.
     */

    private ResourceBundle stdMessages = null;
    /**
     * Fallback resource bundle for when a resource is missing in the file system resource bundle.
     *
     * 

It uses the resource bundled in the JAR. * * @see #loadBundledResourceBundle(ZapResourceBundleControl) */ private ResourceBundle fallbackStdMessages; private Locale locale = null; private Map addonMessages = new HashMap<>(); /** * A set of missing keys, to {@link #handleMissingResourceException(MissingResourceException) * log an error} just once. * *

The keys are removed when the corresponding bundle is removed (e.g. same prefix) or if a * new bundle already defines it (e.g. contained in a resource bundle of an updated add-on), * still, it might be possible that some keys are kept in memory until ZAP is shutdown. */ private Set missingKeys = Collections.synchronizedSet(new HashSet<>()); /** * The class loader for file system Messages resource bundle. * * @see #createLangClassLoader() * @see #loadFsResourceBundle(ZapResourceBundleControl) */ private URLClassLoader langClassLoader; private static final Logger logger = Logger.getLogger(I18N.class); public I18N(Locale locale) { langClassLoader = createLangClassLoader(); setLocale(locale); } private static URLClassLoader createLangClassLoader() { Path langDir = Paths.get(Constant.getZapInstall(), Constant.LANG_DIR); if (Files.exists(langDir)) { try { return new URLClassLoader(new URL[] {langDir.toUri().toURL()}); } catch (MalformedURLException e) { logger.warn("Failed to convert path " + langDir, e); } } return null; } /** * Gets the core resource bundle. * * @return the core resource bundle, never {@code null}. * @since 2.7.0 */ public ResourceBundle getCoreResourceBundle() { return this.stdMessages; } public void addMessageBundle(String prefix, ResourceBundle bundle) { logger.debug("Adding message bundle with prefix: " + prefix); if (addonMessages.containsKey(prefix)) { logger.error("Adding message bundle with duplicate prefix: " + prefix); } addonMessages.put(prefix, bundle); } public void removeMessageBundle(String prefix) { missingKeys.removeIf(k -> k.startsWith(prefix)); logger.debug("Removing message bundle with prefix: " + prefix); if (addonMessages.containsKey(prefix)) { addonMessages.remove(prefix); } else { logger.debug("Message bundle not found, prefix: " + prefix); } } public ResourceBundle getMessageBundle(String prefix) { return this.addonMessages.get(prefix); } /** * Gets the message with the given key. * *

The message will be obtained either from the core {@link ResourceBundle} or a {@code * ResourceBundle} of an add-on (depending on the prefix of the key). * *

Note: Since 2.8.0 this method no longer throws a {@code * MissingResourceException} if the key does not exist, instead it logs an error and returns the * key itself. This avoids breaking ZAP when a resource message is accidentally missing. Use * {@link #containsKey(String)} instead to know if a message exists or not. * * @param key the key. * @return the message. * @see #getString(String, Object...) * @see #getMessageBundle(String) */ public String getString(String key) { try { return this.getStringImpl(key); } catch (MissingResourceException e) { return handleMissingResourceException(e); } } private String handleMissingResourceException(MissingResourceException e) { logger.error("Failed to load a message:", e); String key = e.getKey(); missingKeys.add(key); return missingKeyReplacement(key); } private static String missingKeyReplacement(String key) { return '!' + key + '!'; } private String getStringImpl(String key) { if (missingKeys.contains(key)) { if (!containsKey(key)) { return missingKeyReplacement(key); } missingKeys.remove(key); } if (key.indexOf(".") > 0) { String prefix = key.substring(0, key.indexOf(".")); ResourceBundle bundle = this.addonMessages.get(prefix); if (bundle != null && bundle.containsKey(key)) { return bundle.getString(key); } } try { return this.stdMessages.getString(key); } catch (MissingResourceException e) { if (fallbackStdMessages != null) { return fallbackStdMessages.getString(key); } throw e; } } /** * Gets the String with the given key surrounded by {@code

} tags. * * @param key the key of the string * @return the string read wrapped in HTML and paragraph tags */ public String getHtmlWrappedString(String key) { String values = getStringImpl(key); if (values == null) return null; return "

" + values + "

"; } /** * Returns the specified char from the language file. As these are typically used for mnemonics * the 'null' char is returned if the key is not defined * * @param key the key of the char * @return the char read, or null char if not found */ public char getChar(String key) { try { String str = this.getStringImpl(key); if (str.length() > 0) { return str.charAt(0); } } catch (Exception e) { // Not defined } return '\u0000'; } /** * Sets the current locale to the given one and gets a resource bundle for new locale. * *

The call to this method has no effect if the given locale is the same as the current one. * * @param locale the new locale * @see ResourceBundle#getBundle(String, Locale) */ public void setLocale(Locale locale) { if (locale.equals(this.locale)) { return; } this.locale = locale; ZapResourceBundleControl rbc = new ZapResourceBundleControl(); ResourceBundle fsRb = loadFsResourceBundle(rbc); if (fsRb != null) { this.stdMessages = fsRb; logger.debug("Using file system Messages resource bundle."); try { this.fallbackStdMessages = loadBundledResourceBundle(rbc); } catch (MissingResourceException e) { logger.warn("Failed to find bundled Messages resource bundle."); } } else { this.stdMessages = loadBundledResourceBundle(rbc); logger.debug("Using bundled Messages resource bundle."); } } private ResourceBundle loadFsResourceBundle(ZapResourceBundleControl rbc) { if (langClassLoader == null) { return null; } ResourceBundle.clearCache(langClassLoader); try { return loadResourceBundle(Constant.MESSAGES_PREFIX, langClassLoader, rbc); } catch (MissingResourceException e) { logger.debug("Failed to load file system Messages resource bundle.", e); } return null; } private ResourceBundle loadBundledResourceBundle(ZapResourceBundleControl rbc) { return loadResourceBundle("org.zaproxy.zap.resources." + Constant.MESSAGES_PREFIX, rbc); } private ResourceBundle loadResourceBundle(String path, ZapResourceBundleControl rbc) { return loadResourceBundle(path, getClass().getClassLoader(), rbc); } private ResourceBundle loadResourceBundle( String path, ClassLoader classLoader, ZapResourceBundleControl rbc) { return ResourceBundle.getBundle(path, locale, classLoader, rbc); } public Locale getLocal() { return this.locale; } public boolean containsKey(String key) { if (key.indexOf(".") > 0) { String prefix = key.substring(0, key.indexOf(".")); ResourceBundle bundle = this.addonMessages.get(prefix); if (bundle != null && bundle.containsKey(key)) { return true; } } return this.stdMessages.containsKey(key); } /** * Gets the message with the given key, formatted with the given parameters. * *

The message will be obtained either from the core {@link ResourceBundle} or a {@code * ResourceBundle} of an add-on (depending on the prefix of the key) and then {@link * MessageFormat#format(String, Object...) formatted}. * *

Note: This method does not throw a {@code MissingResourceException} if * the key does not exist, instead it logs an error and returns the key itself. This avoids * breaking ZAP when a resource message is accidentally missing. Use {@link * #containsKey(String)} instead to know if a message exists or not. * * @param key the key. * @param params the parameters to format the message. * @return the message formatted. * @see #getString(String) */ public String getString(String key, Object... params) { try { return MessageFormat.format(this.getStringImpl(key), params); } catch (MissingResourceException e) { return handleMissingResourceException(e); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy