Files
i2p.i2p-bote/src/main/java/i2p/bote/Configuration.java

742 lines
29 KiB
Java

/**
* Copyright (C) 2009 HungryHobo@mail.i2p
*
* The GPG fingerprint for HungryHobo@mail.i2p is:
* 6DD3 EAA2 9990 29BC 4AD2 7486 1E2C 7B61 76DC DC12
*
* This file is part of I2P-Bote.
* I2P-Bote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* I2P-Bote is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with I2P-Bote. If not, see <http://www.gnu.org/licenses/>.
*/
package i2p.bote;
import static i2p.bote.Util._t;
import i2p.bote.email.EmailIdentity.IdentityConfig;
import i2p.bote.packet.dht.Contact;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.crypto.KeyStoreUtil;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import net.i2p.util.SecureFile;
import net.i2p.util.SystemVersion;
public class Configuration implements IdentityConfig {
public static final String KEY_DERIVATION_PARAMETERS_FILE = "derivparams"; // name of the KDF parameter cache file, relative to I2P_BOTE_SUBDIR
private static final String I2P_BOTE_SUBDIR = "i2pbote"; // relative to the I2P app dir
private static final String CONFIG_FILE_NAME = "i2pbote.config";
private static final String DEST_KEY_FILE_NAME = "local_dest.key";
private static final String DHT_PEER_FILE_NAME = "dht_peers.txt";
private static final String RELAY_PEER_FILE_NAME = "relay_peers.txt";
private static final String IDENTITIES_FILE_NAME = "identities";
private static final String ADDRESS_BOOK_FILE_NAME = "addressBook";
private static final String MESSAGE_ID_CACHE_FILE = "msgidcache.txt";
private static final String PASSWORD_FILE = "password";
private static final String SSL_KEYSTORE_FILE = "i2p.bote.ssl.keystore.jks"; // relative to I2P_BOTE_SUBDIR
private static final String SSL_KEY_ALIAS = "botessl";
private static final String OUTBOX_DIR = "outbox"; // relative to I2P_BOTE_SUBDIR
private static final String RELAY_PKT_SUBDIR = "relay_pkt"; // relative to I2P_BOTE_SUBDIR
private static final String INCOMPLETE_SUBDIR = "incomplete"; // relative to I2P_BOTE_SUBDIR
private static final String EMAIL_DHT_SUBDIR = "dht_email_pkt"; // relative to I2P_BOTE_SUBDIR
private static final String INDEX_PACKET_DHT_SUBDIR = "dht_index_pkt"; // relative to I2P_BOTE_SUBDIR
private static final String DIRECTORY_ENTRY_DHT_SUBDIR = "dht_directory_pkt"; // relative to I2P_BOTE_SUBDIR
private static final String INBOX_SUBDIR = "inbox"; // relative to I2P_BOTE_SUBDIR
private static final String SENT_FOLDER_DIR = "sent"; // relative to I2P_BOTE_SUBDIR
private static final String TRASH_FOLDER_DIR = "trash"; // relative to I2P_BOTE_SUBDIR
private static final String MIGRATION_VERSION_FILE = "migratedVersion"; // relative to I2P_BOTE_SUBDIR
private static final List<Theme> BUILT_IN_THEMES = Arrays.asList(new Theme[] { // theme IDs correspond to a theme directory in the .war
new Theme("material", _t("Material")),
new Theme("lblue", _t("Light Blue")),
new Theme("vanilla", _t("Vanilla"))
});
private static final String THEME_SUBDIR = "themes"; // relative to I2P_BOTE_SUBDIR
// Parameter names in the config file
private static final String PARAMETER_I2CP_DOMAIN_SOCKET_ENABLED = "i2cpDomainSocketEnabled";
private static final String PARAMETER_STORAGE_SPACE_INBOX = "storageSpaceInbox";
private static final String PARAMETER_STORAGE_SPACE_RELAY = "storageSpaceRelay";
private static final String PARAMETER_STORAGE_TIME = "storageTime";
private static final String PARAMETER_HASHCASH_STRENGTH = "hashCashStrength";
private static final String PARAMETER_SMTP_PORT = "smtpPort";
private static final String PARAMETER_SMTP_ADDRESS = "smtpAddress";
private static final String PARAMETER_SMTP_ENABLED = "smtpEnabled";
private static final String PARAMETER_IMAP_PORT = "imapPort";
private static final String PARAMETER_IMAP_ADDRESS = "imapAddress";
private static final String PARAMETER_IMAP_ENABLED = "imapEnabled";
private static final String PARAMETER_SSL_KEYSTORE_PASSWORD = "sslKeystorePassword";
private static final String PARAMETER_MAX_CONCURRENT_IDENTITIES_CHECK_MAIL = "maxConcurIdCheckMail";
private static final String PARAMETER_AUTO_MAIL_CHECK = "autoMailCheckEnabled";
private static final String PARAMETER_DELIVERY_CHECK = "deliveryCheckEnabled";
private static final String PARAMETER_MAIL_CHECK_INTERVAL = "mailCheckInterval";
private static final String PARAMETER_OUTBOX_CHECK_INTERVAL = "outboxCheckInterval";
private static final String PARAMETER_DELIVERY_CHECK_INTERVAL = "deliveryCheckInterval";
private static final String PARAMETER_RELAY_SEND_PAUSE = "RelaySendPause";
private static final String PARAMETER_HIDE_LOCALE = "hideLocale";
private static final String PARAMETER_INCLUDE_SENT_TIME = "includeSentTime";
private static final String PARAMETER_MESSAGE_ID_CACHE_SIZE = "messageIdCacheSize";
private static final String PARAMETER_RELAY_REDUNDANCY = "relayRedundancy";
private static final String PARAMETER_RELAY_MIN_DELAY = "relayMinDelay";
private static final String PARAMETER_RELAY_MAX_DELAY = "relayMaxDelay";
private static final String PARAMETER_NUM_STORE_HOPS = "numSendHops";
private static final String PARAMETER_GATEWAY_DESTINATION = "gatewayDestination";
private static final String PARAMETER_GATEWAY_ENABLED = "gatewayEnabled";
private static final String PARAMETER_PASSWORD_CACHE_DURATION = "passwordCacheDuration";
private static final String PARAMETER_EEPROXY_HOST = "eeproxyHost";
private static final String PARAMETER_EEPROXY_PORT = "eeproxyPort";
private static final String PARAMETER_UPDATE_URL = "updateUrl";
private static final String PARAMETER_UPDATE_CHECK_INTERVAL = "updateCheckInterval";
private static final String PARAMETER_THEME = "theme";
// Defaults for each parameter
private static final boolean DEFAULT_I2CP_DOMAIN_SOCKET_ENABLED = false;
private static final int DEFAULT_STORAGE_SPACE_INBOX = 1024 * 1024 * 1024;
private static final int DEFAULT_STORAGE_SPACE_RELAY = 100 * 1024 * 1024;
private static final int DEFAULT_STORAGE_TIME = 31; // in days
private static final int DEFAULT_HASHCASH_STRENGTH = 10;
private static final int DEFAULT_SMTP_PORT = 7661;
private static final String DEFAULT_SMTP_ADDRESS = "localhost";
private static final boolean DEFAULT_SMTP_ENABLED = false;
private static final int DEFAULT_IMAP_PORT = 7662;
private static final String DEFAULT_IMAP_ADDRESS = "localhost";
private static final boolean DEFAULT_IMAP_ENABLED = false;
private static final int DEFAULT_MAX_CONCURRENT_IDENTITIES_CHECK_MAIL = 10;
private static final boolean DEFAULT_AUTO_MAIL_CHECK = true;
private static final int DEFAULT_MAIL_CHECK_INTERVAL = 30; // in minutes
private static final int DEFAULT_OUTBOX_CHECK_INTERVAL = 10; // in minutes
private static final boolean DEFAULT_DELIVERY_CHECK = true;
private static final int DEFAULT_DELIVERY_CHECK_INTERVAL = 60; // in minutes
private static final int DEFAULT_RELAY_SEND_PAUSE = 10; // in minutes, see RelayPacketSender.java
private static final boolean DEFAULT_HIDE_LOCALE = true;
private static final boolean DEFAULT_INCLUDE_SENT_TIME = true;
private static final int DEFAULT_MESSAGE_ID_CACHE_SIZE = 1000; // the maximum number of message IDs to cache
private static final int DEFAULT_RELAY_REDUNDANCY = 5; // lower than the DHT redundancy because only the highest-uptime peers are used for relaying
private static final int DEFAULT_RELAY_MIN_DELAY = 5; // in minutes
private static final int DEFAULT_RELAY_MAX_DELAY = 40; // in minutes
private static final int DEFAULT_NUM_STORE_HOPS = 0;
private static final String DEFAULT_GATEWAY_DESTINATION = "";
private static final boolean DEFAULT_GATEWAY_ENABLED = true;
private static final int DEFAULT_PASSWORD_CACHE_DURATION = 10; // in minutes
private static final String DEFAULT_EEPROXY_HOST = "localhost";
private static final int DEFAULT_EEPROXY_PORT = 4444;
private static final String DEFAULT_UPDATE_URL = "http://tjgidoycrw6s3guetge3kvrvynppqjmvqsosmtbmgqasa6vmsf6a.b32.i2p/i2pbote-update.xpi2p";
private static final int DEFAULT_UPDATE_CHECK_INTERVAL = 60; // in minutes
private static final String DEFAULT_THEME = "material";
private Log log = new Log(Configuration.class);
private Properties properties;
private File i2pBoteDir;
private File configFile;
/**
* Reads configuration settings from the <code>I2P_BOTE_SUBDIR</code> subdirectory under
* the I2P application directory. The I2P application directory can be changed via the
* <code>i2p.dir.app</code> system property.
* <p/>
* Logging is done through the I2P logger. I2P reads the log configuration from the
* <code>logger.config</code> file whose location is determined by the
* <code>i2p.dir.config</code> system property.
*/
public Configuration() {
properties = new Properties();
// get the I2PBote directory and make sure it exists
i2pBoteDir = getI2PBoteDirectory();
if (!i2pBoteDir.exists() && !i2pBoteDir.mkdirs())
log.error("Cannot create directory: <" + i2pBoteDir.getAbsolutePath() + ">");
// read the configuration file
configFile = new File(i2pBoteDir, CONFIG_FILE_NAME);
boolean configurationLoaded = false;
if (configFile.exists()) {
log.info("Loading config file <" + configFile.getAbsolutePath() + ">");
try {
DataHelper.loadProps(properties, configFile);
configurationLoaded = true;
} catch (IOException e) {
log.error("Error loading configuration file <" + configFile.getAbsolutePath() + ">", e);
}
}
if (!configurationLoaded)
log.info("Can't read configuration file <" + configFile.getAbsolutePath() + ">, using default settings.");
// Create SSL key if necessary
if (!SystemVersion.isAndroid()) {
File ks = getSSLKeyStoreFile();
if (!ks.exists())
createKeyStore(ks);
}
}
private boolean createKeyStore(File ks) {
// make a random 48 character password (30 * 8 / 5)
String keyStorePassword = KeyStoreUtil.randomString();
// and one for the cname
String cname = KeyStoreUtil.randomString() + ".ssl.bote.i2p";
boolean success = KeyStoreUtil.createKeys(
ks, keyStorePassword, SSL_KEY_ALIAS, cname, "I2P-Bote",
3652, "RSA", 2048, keyStorePassword);
if (success) {
success = ks.exists();
if (success) {
properties.setProperty(PARAMETER_SSL_KEYSTORE_PASSWORD, keyStorePassword);
save();
}
}
if (success) {
log.logAlways(Log.INFO, "Created self-signed certificate for " + cname + " in keystore: " + ks.getAbsolutePath() + "\n" +
"The certificate name was generated randomly, and is not associated with your " +
"IP address, host name, router identity, or destination keys.");
} else {
log.error("Failed to create I2P-Bote SSL keystore.\n" +
"This is for the Sun/Oracle keytool, others may be incompatible.\n" +
"If you create the keystore manually, you must add " + PARAMETER_SSL_KEYSTORE_PASSWORD +
" to " + (new File(i2pBoteDir, CONFIG_FILE_NAME)).getAbsolutePath() + "\n" +
"You must create the keystore using the same password for the keystore and the key.");
}
return success;
}
/**
* @param enabled ignored if not on Android.
* @since 0.2.10
*/
public void setI2CPDomainSocketEnabled(boolean enabled) {
if (SystemVersion.isAndroid())
properties.setProperty(
PARAMETER_I2CP_DOMAIN_SOCKET_ENABLED,
String.valueOf(enabled));
}
/**
* @return false if not on Android.
* @since 0.2.10
*/
public boolean isI2CPDomainSocketEnabled() {
return SystemVersion.isAndroid() ?
getBooleanParameter(
PARAMETER_I2CP_DOMAIN_SOCKET_ENABLED,
DEFAULT_I2CP_DOMAIN_SOCKET_ENABLED) :
false;
}
public File getDestinationKeyFile() {
return new File(i2pBoteDir, DEST_KEY_FILE_NAME);
}
public File getDhtPeerFile() {
return new File(i2pBoteDir, DHT_PEER_FILE_NAME);
}
public File getRelayPeerFile() {
return new File(i2pBoteDir, RELAY_PEER_FILE_NAME);
}
public File getIdentitiesFile() {
return new File(i2pBoteDir, IDENTITIES_FILE_NAME);
}
public File getAddressBookFile() {
return new File(i2pBoteDir, ADDRESS_BOOK_FILE_NAME);
}
public File getMessageIdCacheFile() {
return new File(i2pBoteDir, MESSAGE_ID_CACHE_FILE);
}
/**
* The file returned by this method does not contain the user's password,
* but a known string that is encrypted with the password. The purpose
* of this file is for checking if a password entered by the user is
* correct.
*/
public File getPasswordFile() {
return new File(i2pBoteDir, PASSWORD_FILE);
}
/**
* Returns the file that caches the parameters needed for generating a
* file encryption key from a password.
*/
public File getKeyDerivationParametersFile() {
return new File(i2pBoteDir, KEY_DERIVATION_PARAMETERS_FILE);
}
/**
* @return the keystore file containing the SSL server key.
* @since 0.2.10
*/
public File getSSLKeyStoreFile() {
return new File(i2pBoteDir, SSL_KEYSTORE_FILE);
}
public File getOutboxDir() {
return new File(i2pBoteDir, OUTBOX_DIR);
}
public File getRelayPacketDir() {
return new File(i2pBoteDir, RELAY_PKT_SUBDIR);
}
public File getSentFolderDir() {
return new File(i2pBoteDir, SENT_FOLDER_DIR);
}
public File getTrashFolderDir() {
return new File(i2pBoteDir, TRASH_FOLDER_DIR);
}
public File getInboxDir() {
return new File(i2pBoteDir, INBOX_SUBDIR);
}
public File getIncompleteDir() {
return new File(i2pBoteDir, INCOMPLETE_SUBDIR);
}
public File getEmailDhtStorageDir() {
return new File(i2pBoteDir, EMAIL_DHT_SUBDIR);
}
public File getIndexPacketDhtStorageDir() {
return new File(i2pBoteDir, INDEX_PACKET_DHT_SUBDIR);
}
/** Returns the directory where DHT packets of type {@link Contact} are stored. */
public File getDirectoryEntryDhtStorageDir() {
return new File(i2pBoteDir, DIRECTORY_ENTRY_DHT_SUBDIR);
}
private static File getI2PBoteDirectory() {
// the parent directory of the I2PBote directory ($HOME or the value of the i2p.dir.app property)
File i2pAppDir = I2PAppContext.getGlobalContext().getAppDir();
return new File(i2pAppDir, I2P_BOTE_SUBDIR);
}
/**
* Saves the configuration to a file.
*/
public void save() {
log.debug("Saving config file <" + configFile.getAbsolutePath() + ">");
try {
DataHelper.storeProps(properties, new SecureFile(configFile.getAbsolutePath()));
} catch (IOException e) {
log.error("Cannot save configuration to file <" + configFile.getAbsolutePath() + ">", e);
}
}
/**
* Returns the maximum size (in bytes) the inbox can take up.
*/
public int getStorageSpaceInbox() {
return getIntParameter(PARAMETER_STORAGE_SPACE_INBOX, DEFAULT_STORAGE_SPACE_INBOX);
}
/**
* Returns the maximum size (in bytes) all messages stored for relaying can take up.
*/
public int getStorageSpaceRelay() {
return getIntParameter(PARAMETER_STORAGE_SPACE_RELAY, DEFAULT_STORAGE_SPACE_RELAY);
}
/**
* Returns the time (in milliseconds) after which an email is deleted from the outbox if it cannot be sent or relayed.
*/
public long getStorageTime() {
return 24L * 3600 * 1000 * getIntParameter(PARAMETER_STORAGE_TIME, DEFAULT_STORAGE_TIME);
}
public int getHashCashStrength() {
return getIntParameter(PARAMETER_HASHCASH_STRENGTH, DEFAULT_HASHCASH_STRENGTH);
}
public void setSmtpPort(int port) {
properties.setProperty(PARAMETER_SMTP_PORT, String.valueOf(port));
}
public int getSmtpPort() {
return getIntParameter(PARAMETER_SMTP_PORT, DEFAULT_SMTP_PORT);
}
/** Returns the host name the SMTP server listens on. */
public String getSmtpAddress() {
return properties.getProperty(PARAMETER_SMTP_ADDRESS, DEFAULT_SMTP_ADDRESS);
}
public void setSmtpEnabled(boolean enabled) {
properties.setProperty(PARAMETER_SMTP_ENABLED, String.valueOf(enabled));
}
public boolean isSmtpEnabled() {
return getBooleanParameter(PARAMETER_SMTP_ENABLED, DEFAULT_SMTP_ENABLED);
}
public void setImapPort(int port) {
properties.setProperty(PARAMETER_IMAP_PORT, String.valueOf(port));
}
public int getImapPort() {
return getIntParameter(PARAMETER_IMAP_PORT, DEFAULT_IMAP_PORT);
}
/** Returns the host name the IMAP server listens on. */
public String getImapAddress() {
return properties.getProperty(PARAMETER_IMAP_ADDRESS, DEFAULT_IMAP_ADDRESS);
}
public void setImapEnabled(boolean enabled) {
properties.setProperty(PARAMETER_IMAP_ENABLED, String.valueOf(enabled));
}
public boolean isImapEnabled() {
return getBooleanParameter(PARAMETER_IMAP_ENABLED, DEFAULT_IMAP_ENABLED);
}
/**
* @return the password for the SSL keystore.
* @since 0.2.10
*/
public String getSSLKeyStorePassword() {
return properties.getProperty(PARAMETER_SSL_KEYSTORE_PASSWORD);
}
/**
* Returns the maximum number of email identities to retrieve new emails for at a time.
*/
public int getMaxConcurIdCheckMail() {
return getIntParameter(PARAMETER_MAX_CONCURRENT_IDENTITIES_CHECK_MAIL, DEFAULT_MAX_CONCURRENT_IDENTITIES_CHECK_MAIL);
}
public void setAutoMailCheckEnabled(boolean enabled) {
properties.setProperty(PARAMETER_AUTO_MAIL_CHECK, String.valueOf(enabled));
}
public boolean isAutoMailCheckEnabled() {
return getBooleanParameter(PARAMETER_AUTO_MAIL_CHECK, DEFAULT_AUTO_MAIL_CHECK);
}
public void setDeliveryCheckEnabled(boolean enabled) {
properties.setProperty(PARAMETER_DELIVERY_CHECK, String.valueOf(enabled));
}
public boolean isDeliveryCheckEnabled() {
return getBooleanParameter(PARAMETER_DELIVERY_CHECK, DEFAULT_DELIVERY_CHECK);
}
public void setMailCheckInterval(int minutes) {
properties.setProperty(PARAMETER_MAIL_CHECK_INTERVAL, String.valueOf(minutes));
}
/**
* Returns the number of minutes the application should wait before
* checking for mail again. This setting only has an effect if
* automatic mail checking is disabled.
* @see #isAutoMailCheckEnabled()
*/
public int getMailCheckInterval() {
return getIntParameter(PARAMETER_MAIL_CHECK_INTERVAL, DEFAULT_MAIL_CHECK_INTERVAL);
}
public void setOutboxCheckInterval(int minutes) {
properties.setProperty(PARAMETER_OUTBOX_CHECK_INTERVAL, String.valueOf(minutes));
}
/**
* Returns the wait time, in minutes, before processing the outbox folder again.
* @see i2p.bote.service.OutboxProcessor
*/
public int getOutboxCheckInterval() {
return getIntParameter(PARAMETER_OUTBOX_CHECK_INTERVAL, DEFAULT_OUTBOX_CHECK_INTERVAL);
}
public void getDeliveryCheckInterval(int minutes) {
properties.setProperty(PARAMETER_DELIVERY_CHECK_INTERVAL, String.valueOf(minutes));
}
/**
* Returns the wait time, in minutes, between checking the delivery status of sent emails.
* @see i2p.bote.service.DeliveryChecker
*/
public int getDeliveryCheckInterval() {
return getIntParameter(PARAMETER_DELIVERY_CHECK_INTERVAL, DEFAULT_DELIVERY_CHECK_INTERVAL);
}
public void setRelaySendPause(int minutes) {
properties.setProperty(PARAMETER_RELAY_SEND_PAUSE, String.valueOf(minutes));
}
/**
* Returns the number of minutes to wait before processing the relay packet folder again.
*/
public int getRelaySendPause() {
return getIntParameter(PARAMETER_RELAY_SEND_PAUSE, DEFAULT_RELAY_SEND_PAUSE);
}
/**
* Controls whether strings that are added to outgoing email, like "Re:" or "Fwd:",
* are translated or not.<br/>
* If <code>hideLocale</code> is <code>false</code>, the UI language is used.<br/>
* If <code>hideLocale</code> is <code>true</code>, the strings are left untranslated
* (which means they are in English).
* @param hideLocale
*/
public void setHideLocale(boolean hideLocale) {
properties.setProperty(PARAMETER_HIDE_LOCALE, String.valueOf(hideLocale));
}
public boolean getHideLocale() {
return getBooleanParameter(PARAMETER_HIDE_LOCALE, DEFAULT_HIDE_LOCALE);
}
/**
* Controls whether the send time is included in outgoing emails.
* @param includeSentTime
*/
public void setIncludeSentTime(boolean includeSentTime) {
properties.setProperty(PARAMETER_INCLUDE_SENT_TIME, String.valueOf(includeSentTime));
}
public boolean getIncludeSentTime() {
return getBooleanParameter(PARAMETER_INCLUDE_SENT_TIME, DEFAULT_INCLUDE_SENT_TIME);
}
public int getMessageIdCacheSize() {
return getIntParameter(PARAMETER_MESSAGE_ID_CACHE_SIZE, DEFAULT_MESSAGE_ID_CACHE_SIZE);
}
/**
* Returns the number of relay chains that should be used per Relay Request.
*/
public int getRelayRedundancy() {
return getIntParameter(PARAMETER_RELAY_REDUNDANCY, DEFAULT_RELAY_REDUNDANCY);
}
public void setRelayMinDelay(int minDelay) {
properties.setProperty(PARAMETER_RELAY_MIN_DELAY, String.valueOf(minDelay));
}
/**
* Returns the minimum amount of time in minutes that a Relay Request is delayed.
*/
public int getRelayMinDelay() {
return getIntParameter(PARAMETER_RELAY_MIN_DELAY, DEFAULT_RELAY_MIN_DELAY);
}
public void setRelayMaxDelay(int maxDelay) {
properties.setProperty(PARAMETER_RELAY_MAX_DELAY, String.valueOf(maxDelay));
}
/**
* Returns the maximum amount of time in minutes that a Relay Request is delayed.
*/
public int getRelayMaxDelay() {
return getIntParameter(PARAMETER_RELAY_MAX_DELAY, DEFAULT_RELAY_MAX_DELAY);
}
public void setNumStoreHops(int numHops) {
properties.setProperty(PARAMETER_NUM_STORE_HOPS, String.valueOf(numHops));
}
/**
* Returns the number of relays that should be used when sending a DHT store request.
* @return A non-negative number
*/
public int getNumStoreHops() {
return getIntParameter(PARAMETER_NUM_STORE_HOPS, DEFAULT_NUM_STORE_HOPS);
}
public void setGatewayDestination(String destination) {
properties.setProperty(PARAMETER_GATEWAY_DESTINATION, destination);
}
public String getGatewayDestination() {
return properties.getProperty(PARAMETER_GATEWAY_DESTINATION, DEFAULT_GATEWAY_DESTINATION);
}
public void setGatewayEnabled(boolean enable) {
properties.setProperty(PARAMETER_GATEWAY_ENABLED, String.valueOf(enable));
}
public boolean isGatewayEnabled() {
return getBooleanParameter(PARAMETER_GATEWAY_ENABLED, DEFAULT_GATEWAY_ENABLED);
}
public void setPasswordCacheDuration(int duration) {
properties.setProperty(PARAMETER_PASSWORD_CACHE_DURATION, String.valueOf(duration));
}
/**
* Returns the number of minutes the password is kept in memory
*/
public int getPasswordCacheDuration() {
return getIntParameter(PARAMETER_PASSWORD_CACHE_DURATION, DEFAULT_PASSWORD_CACHE_DURATION);
}
public String getEeproxyHost() {
return properties.getProperty(PARAMETER_EEPROXY_HOST, DEFAULT_EEPROXY_HOST);
}
public int getEeproxyPort() {
return getIntParameter(PARAMETER_EEPROXY_PORT, DEFAULT_EEPROXY_PORT);
}
/**
* Returns an HTTP URL pointing to the .xpi2p update file.
*/
public String getUpdateUrl() {
return properties.getProperty(PARAMETER_UPDATE_URL, DEFAULT_UPDATE_URL);
}
/**
* Returns the number of minutes to wait after checking for a new plugin version.
*/
public int getUpdateCheckInterval() {
return getIntParameter(PARAMETER_UPDATE_CHECK_INTERVAL, DEFAULT_UPDATE_CHECK_INTERVAL);
}
public void setThemeUrl(String url) {
properties.setProperty(PARAMETER_THEME, url);
}
/**
* Returns the name of the current UI theme.
*/
public String getTheme() {
return properties.getProperty(PARAMETER_THEME, DEFAULT_THEME);
}
/**
* Returns a list of all available UI themes.
*/
public List<Theme> getThemes() {
List<Theme> themes = new ArrayList<Theme>();
themes.addAll(getBuiltInThemes());
themes.addAll(getExternalThemes());
return themes;
}
/**
* Returns only the UI themes that are included in the application.
*/
public List<Theme> getBuiltInThemes() {
return BUILT_IN_THEMES;
}
/**
* Returns the directory where the application looks for additional UI themes.
*/
public File getExternalThemeDir() {
return new File(i2pBoteDir, THEME_SUBDIR);
}
private List<Theme> getExternalThemes() {
File[] dirs = new File(i2pBoteDir, THEME_SUBDIR).listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
List<Theme> themes = new ArrayList<Theme>();
if (dirs != null)
for (File dir: dirs) {
String themeId = dir.getName();
Theme theme = new Theme(themeId, themeId);
themes.add(theme);
}
return themes;
}
/**
* Returns the File that contains the version the I2P-Bote data directory was last
* successfully migrated to.
*/
public File getMigrationVersionFile() {
return new File(i2pBoteDir, MIGRATION_VERSION_FILE);
}
private boolean getBooleanParameter(String parameterName, boolean defaultValue) {
try {
return Util.getBooleanParameter(properties, parameterName, defaultValue);
} catch (IllegalArgumentException e) {
log.warn("getBooleanParameter failed, using default", e);
return defaultValue;
}
}
private int getIntParameter(String parameterName, int defaultValue) {
try {
return Util.getIntParameter(properties, parameterName, defaultValue);
} catch (NumberFormatException e) {
log.warn("getIntParameter failed, using default", e);
return defaultValue;
}
}
/** Simple class that represents a UI theme */
public static class Theme {
private String id;
private String displayName;
private Theme(String id, String displayName) {
this.id = id;
this.displayName = displayName;
}
public String getId() {
return id;
}
public String getDisplayName() {
return displayName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Theme other = (Theme) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
}