/* * free (adj.): unencumbered; not under the control of others * Written by mihi in 2004 and released into the public domain * with no warranty of any kind, either expressed or implied. * It probably won't make your computer catch on fire, or eat * your children, but it might. Use at your own risk. */ package net.i2p.client.naming; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; import net.i2p.I2PAppContext; import net.i2p.data.Destination; /** * A naming service based on multiple "hosts.txt" files. * Supports .b32.i2p and {b64} lookups. * Supports caching. * All host names are converted to lower case. */ public class HostsTxtNamingService extends MetaNamingService { /** * The naming service should only be constructed and accessed through the * application context. This constructor should only be used by the * appropriate application context itself. * */ public HostsTxtNamingService(I2PAppContext context) { super(context, null); for (String name : getFilenames()) { addNamingService(new SingleFileNamingService(context, name), false); } } /** * If this system property is specified, the tunnel will read the * given file for hostname=destKey values when resolving names */ public final static String PROP_HOSTS_FILE = "i2p.hostsfilelist"; /** default hosts.txt filenames */ public final static String DEFAULT_HOSTS_FILE = "privatehosts.txt,userhosts.txt,hosts.txt"; private List<String> getFilenames() { String list = _context.getProperty(PROP_HOSTS_FILE, DEFAULT_HOSTS_FILE); StringTokenizer tok = new StringTokenizer(list, ","); List<String> rv = new ArrayList<String>(tok.countTokens()); while (tok.hasMoreTokens()) rv.add(tok.nextToken()); return rv; } @Override public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) { // If it's long, assume it's a key. if (hostname.length() >= DEST_SIZE) return lookupBase64(hostname); return super.lookup(hostname.toLowerCase(Locale.US), lookupOptions, storedOptions); } @Override public boolean put(String hostname, Destination d, Properties options) { return super.put(hostname.toLowerCase(Locale.US), d, options); } @Override public boolean putIfAbsent(String hostname, Destination d, Properties options) { return super.putIfAbsent(hostname.toLowerCase(Locale.US), d, options); } @Override public boolean remove(String hostname, Properties options) { return super.remove(hostname.toLowerCase(Locale.US), options); } /** * All services aggregated, unless options contains * the property "file", in which case only for that file */ @Override public Set<String> getNames(Properties options) { String file = null; if (options != null) file = options.getProperty("file"); if (file == null) return super.getNames(options); for (NamingService ns : _services) { String name = ns.getName(); if (name.equals(file) || name.endsWith('/' + file) || name.endsWith('\\' + file)) return ns.getNames(options); } return new HashSet<String>(0); } }