// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)

package org.xbill.DNS;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

/**
 * A class that tries to locate name servers and the search path to
 * be appended to unqualified names.
 *
 * The following are attempted, in order, until one succeeds.
 * <UL>
 *   <LI>The properties 'dns.server' and 'dns.search' (comma delimited lists)
 *       are checked.  The servers can either be IP addresses or hostnames
 *       (which are resolved using Java's built in DNS support).
 *   <LI>The sun.net.dns.ResolverConfiguration class is queried.
 *   <LI>On Unix, /etc/resolv.conf is parsed.
 *   <LI>On Windows, ipconfig/winipcfg is called and its output parsed.  This
 *       may fail for non-English versions on Windows.
 *   <LI>"localhost" is used as the nameserver, and the search path is empty.
 * </UL>
 *
 * These routines will be called internally when creating Resolvers/Lookups
 * without explicitly specifying server names, and can also be called
 * directly if desired.
 *
 * @author Brian Wellington
 * @author <a href="mailto:yannick@meudal.net">Yannick Meudal</a>
 * @author <a href="mailto:arnt@gulbrandsen.priv.no">Arnt Gulbrandsen</a>
 */

public class ResolverConfig {

private String [] servers = null;
private Name [] searchlist = null;
private int ndots = -1;

private static ResolverConfig currentConfig;

static {
	refresh();
}

public
ResolverConfig() {
	if (findProperty())
		return;
	if (findSunJVM())
		return;
	if (servers == null || searchlist == null) {
		String OS = System.getProperty("os.name");
		String vendor = System.getProperty("java.vendor");
		if (OS.indexOf("Windows") != -1) {
			if (OS.indexOf("95") != -1 ||
			    OS.indexOf("98") != -1 ||
			    OS.indexOf("ME") != -1)
				find95();
			else
				findNT();
		} else if (OS.indexOf("NetWare") != -1) {
			findNetware();
		} else if (vendor.indexOf("Android") != -1) {
			findAndroid();
		} else {
			findUnix();
		}
	}
}

private void
addServer(String server, List list) {
	if (list.contains(server))
		return;
	if (Options.check("verbose"))
		System.out.println("adding server " + server);
	list.add(server);
}

private void
addSearch(String search, List list) {
	Name name;
	if (Options.check("verbose"))
		System.out.println("adding search " + search);
	try {
		name = Name.fromString(search, Name.root);
	}
	catch (TextParseException e) {
		return;
	}
	if (list.contains(name))
		return;
	list.add(name);
}

private int
parseNdots(String token) {
	token = token.substring(6);
	try {
		int ndots = Integer.parseInt(token);
		if (ndots >= 0) {
			if (Options.check("verbose"))
				System.out.println("setting ndots " + token);
			return ndots;
		}
	}
	catch (NumberFormatException e) {
	}
	return -1;
}

private void
configureFromLists(List lserver, List lsearch) {
	if (servers == null && lserver.size() > 0)
		servers = (String []) lserver.toArray(new String[0]);
	if (searchlist == null && lsearch.size() > 0)
		searchlist = (Name []) lsearch.toArray(new Name[0]);
}

private void
configureNdots(int lndots) {
	if (ndots < 0 && lndots > 0)
		ndots = lndots;
}

/**
 * Looks in the system properties to find servers and a search path.
 * Servers are defined by dns.server=server1,server2...
 * The search path is defined by dns.search=domain1,domain2...
 */
private boolean
findProperty() {
	String prop;
	List lserver = new ArrayList(0);
	List lsearch = new ArrayList(0);
	StringTokenizer st;

	prop = System.getProperty("dns.server");
	if (prop != null) {
		st = new StringTokenizer(prop, ",");
		while (st.hasMoreTokens())
			addServer(st.nextToken(), lserver);
	}

	prop = System.getProperty("dns.search");
	if (prop != null) {
		st = new StringTokenizer(prop, ",");
		while (st.hasMoreTokens())
			addSearch(st.nextToken(), lsearch);
	}
	configureFromLists(lserver, lsearch);
	return (servers != null && searchlist != null);
}

/**
 * Uses the undocumented Sun DNS implementation to determine the configuration.
 * This doesn't work or even compile with all JVMs (gcj, for example).
 */
private boolean
findSunJVM() {
	List lserver = new ArrayList(0);
	List lserver_tmp;
	List lsearch = new ArrayList(0);
	List lsearch_tmp;

	try {
		Class [] noClasses = new Class[0];
		Object [] noObjects = new Object[0];
		String resConfName = "sun.net.dns.ResolverConfiguration";
		Class resConfClass = Class.forName(resConfName);
		Object resConf;

		// ResolverConfiguration resConf = ResolverConfiguration.open();
		Method open = resConfClass.getDeclaredMethod("open", noClasses);
		resConf = open.invoke(null, noObjects);

		// lserver_tmp = resConf.nameservers();
		Method nameservers = resConfClass.getMethod("nameservers",
							    noClasses);
		lserver_tmp = (List) nameservers.invoke(resConf, noObjects);

		// lsearch_tmp = resConf.searchlist();
		Method searchlist = resConfClass.getMethod("searchlist",
							    noClasses);
		lsearch_tmp = (List) searchlist.invoke(resConf, noObjects);
	}
	catch (Exception e) {
		return false;
	}

	if (lserver_tmp.size() == 0)
		return false;

	if (lserver_tmp.size() > 0) {
		Iterator it = lserver_tmp.iterator();
		while (it.hasNext())
			addServer((String) it.next(), lserver);
	}

	if (lsearch_tmp.size() > 0) {
		Iterator it = lsearch_tmp.iterator();
		while (it.hasNext())
			addSearch((String) it.next(), lsearch);
	}
	configureFromLists(lserver, lsearch);
	return true;
}

/**
 * Looks in /etc/resolv.conf to find servers and a search path.
 * "nameserver" lines specify servers.  "domain" and "search" lines
 * define the search path.
 */
private void
findResolvConf(String file) {
	InputStream in = null;
	try {
		in = new FileInputStream(file);
	}
	catch (FileNotFoundException e) {
		return;
	}
	InputStreamReader isr = new InputStreamReader(in);
	BufferedReader br = new BufferedReader(isr);
	List lserver = new ArrayList(0);
	List lsearch = new ArrayList(0);
	int lndots = -1;
	try {
		String line;
		while ((line = br.readLine()) != null) {
			if (line.startsWith("nameserver")) {
				StringTokenizer st = new StringTokenizer(line);
				st.nextToken(); /* skip nameserver */
				addServer(st.nextToken(), lserver);
			}
			else if (line.startsWith("domain")) {
				StringTokenizer st = new StringTokenizer(line);
				st.nextToken(); /* skip domain */
				if (!st.hasMoreTokens())
					continue;
				if (lsearch.isEmpty())
					addSearch(st.nextToken(), lsearch);
			}
			else if (line.startsWith("search")) {
				if (!lsearch.isEmpty())
					lsearch.clear();
				StringTokenizer st = new StringTokenizer(line);
				st.nextToken(); /* skip search */
				while (st.hasMoreTokens())
					addSearch(st.nextToken(), lsearch);
			}
			else if(line.startsWith("options")) {
				StringTokenizer st = new StringTokenizer(line);
				st.nextToken(); /* skip options */
				while (st.hasMoreTokens()) {
					String token = st.nextToken();
					if (token.startsWith("ndots:")) {
						lndots = parseNdots(token);
					}
				}
			}
		}
		br.close();
	}
	catch (IOException e) {
	}

	configureFromLists(lserver, lsearch);
	configureNdots(lndots);
}

private void
findUnix() {
	findResolvConf("/etc/resolv.conf");
}

private void
findNetware() {
	findResolvConf("sys:/etc/resolv.cfg");
}

/**
 * Parses the output of winipcfg or ipconfig.
 */
private void
findWin(InputStream in, Locale locale) {
	String packageName = ResolverConfig.class.getPackage().getName();
	String resPackageName = packageName + ".windows.DNSServer";
	ResourceBundle res;
	if (locale != null)
		res = ResourceBundle.getBundle(resPackageName, locale);
	else
		res = ResourceBundle.getBundle(resPackageName);

	String host_name = res.getString("host_name");
	String primary_dns_suffix = res.getString("primary_dns_suffix");
	String dns_suffix = res.getString("dns_suffix");
	String dns_servers = res.getString("dns_servers");

	BufferedReader br = new BufferedReader(new InputStreamReader(in));
	try {
		List lserver = new ArrayList();
		List lsearch = new ArrayList();
		String line = null;
		boolean readingServers = false;
		boolean readingSearches = false;
		while ((line = br.readLine()) != null) {
			StringTokenizer st = new StringTokenizer(line);
			if (!st.hasMoreTokens()) {
				readingServers = false;
				readingSearches = false;
				continue;
			}
			String s = st.nextToken();
			if (line.indexOf(":") != -1) {
				readingServers = false;
				readingSearches = false;
			}
			
			if (line.indexOf(host_name) != -1) {
				while (st.hasMoreTokens())
					s = st.nextToken();
				Name name;
				try {
					name = Name.fromString(s, null);
				}
				catch (TextParseException e) {
					continue;
				}
				if (name.labels() == 1)
					continue;
				addSearch(s, lsearch);
			} else if (line.indexOf(primary_dns_suffix) != -1) {
				while (st.hasMoreTokens())
					s = st.nextToken();
				if (s.equals(":"))
					continue;
				addSearch(s, lsearch);
				readingSearches = true;
			} else if (readingSearches ||
				   line.indexOf(dns_suffix) != -1)
			{
				while (st.hasMoreTokens())
					s = st.nextToken();
				if (s.equals(":"))
					continue;
				addSearch(s, lsearch);
				readingSearches = true;
			} else if (readingServers ||
				   line.indexOf(dns_servers) != -1)
			{
				while (st.hasMoreTokens())
					s = st.nextToken();
				if (s.equals(":"))
					continue;
				addServer(s, lserver);
				readingServers = true;
			}
		}
		
		configureFromLists(lserver, lsearch);
	}
	catch (IOException e) {
	}
	return;
}

private void
findWin(InputStream in) {
	String property = "org.xbill.DNS.windows.parse.buffer";
	final int defaultBufSize = 8 * 1024;
	int bufSize = Integer.getInteger(property, defaultBufSize).intValue();
	BufferedInputStream b = new BufferedInputStream(in, bufSize);
	b.mark(bufSize);
	findWin(b, null);
	if (servers == null) {
		try {
			b.reset();
		} 
		catch (IOException e) {
			return;
		}
		findWin(b, new Locale("", ""));
	}
}

/**
 * Calls winipcfg and parses the result to find servers and a search path.
 */
private void
find95() {
	String s = "winipcfg.out";
	try {
		Process p;
		p = Runtime.getRuntime().exec("winipcfg /all /batch " + s);
		p.waitFor();
		File f = new File(s);
		findWin(new FileInputStream(f));
		new File(s).delete();
	}
	catch (Exception e) {
		return;
	}
}

/**
 * Calls ipconfig and parses the result to find servers and a search path.
 */
private void
findNT() {
	try {
		Process p;
		p = Runtime.getRuntime().exec("ipconfig /all");
		findWin(p.getInputStream());
		p.destroy();
	}
	catch (Exception e) {
		return;
	}
}

/**
 * Parses the output of getprop, which is the only way to get DNS
 * info on Android. getprop might disappear in future releases, so
 * this code comes with a use-by date.
 */
private void
findAndroid() {
	// This originally looked for all lines containing .dns; but
	// http://code.google.com/p/android/issues/detail?id=2207#c73
	// indicates that net.dns* should always be the active nameservers, so
	// we use those.
	String re1 = "^\\d+(\\.\\d+){3}$";
	String re2 = "^[0-9a-f]+(:[0-9a-f]*)+:[0-9a-f]+$";
	try { 
		ArrayList lserver = new ArrayList(); 
		ArrayList lsearch = new ArrayList(); 
		String line; 
		Process p = Runtime.getRuntime().exec("getprop"); 
		InputStream in = p.getInputStream();
		InputStreamReader isr = new InputStreamReader(in);
		BufferedReader br = new BufferedReader(isr);
		while ((line = br.readLine()) != null ) { 
			StringTokenizer t = new StringTokenizer(line, ":");
			String name = t.nextToken();
			if (name.indexOf( "net.dns" ) > -1) {
				String v = t.nextToken();
				v = v.replaceAll("[ \\[\\]]", "");
				if ((v.matches(re1) || v.matches(re2)) &&
				    !lserver.contains(v))
					lserver.add(v);
			}
		}
		configureFromLists(lserver, lsearch);
	} catch ( Exception e ) { 
		// ignore resolutely
	}
}

/** Returns all located servers */
public String []
servers() {
	return servers;
}

/** Returns the first located server */
public String
server() {
	if (servers == null)
		return null;
	return servers[0];
}

/** Returns all entries in the located search path */
public Name []
searchPath() {
	return searchlist;
}

/**
 * Returns the located ndots value, or the default (1) if not configured.
 * Note that ndots can only be configured in a resolv.conf file, and will only
 * take effect if ResolverConfig uses resolv.conf directly (that is, if the
 * JVM does not include the sun.net.dns.ResolverConfiguration class).
 */
public int
ndots() {
	if (ndots < 0)
		return 1;
	return ndots;
}

/** Gets the current configuration */
public static synchronized ResolverConfig
getCurrentConfig() {
	return currentConfig;
}

/** Gets the current configuration */
public static void
refresh() {
	ResolverConfig newConfig = new ResolverConfig();
	synchronized (ResolverConfig.class) {
		currentConfig = newConfig;
	}
}

}
