/*
 * Copyright (C) 2008, 2014, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.transport;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jgit.errors.InvalidPatternException;
import org.eclipse.jgit.fnmatch.FileNameMatcher;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.StringUtils;

/**
 * Simple configuration parser for the OpenSSH ~/.ssh/config file.
 * <p>
 * Since JSch does not (currently) have the ability to parse an OpenSSH
 * configuration file this is a simple parser to read that file and make the
 * critical options available to {@link SshSessionFactory}.
 */
public class OpenSshConfig {
	/** IANA assigned port number for SSH. */
	static final int SSH_PORT = 22;

	/**
	 * Obtain the user's configuration data.
	 * <p>
	 * The configuration file is always returned to the caller, even if no file
	 * exists in the user's home directory at the time the call was made. Lookup
	 * requests are cached and are automatically updated if the user modifies
	 * the configuration file since the last time it was cached.
	 *
	 * @param fs
	 *            the file system abstraction which will be necessary to
	 *            perform certain file system operations.
	 * @return a caching reader of the user's configuration file.
	 */
	public static OpenSshConfig get(FS fs) {
		File home = fs.userHome();
		if (home == null)
			home = new File(".").getAbsoluteFile(); //$NON-NLS-1$

		final File config = new File(new File(home, ".ssh"), Constants.CONFIG); //$NON-NLS-1$
		final OpenSshConfig osc = new OpenSshConfig(home, config);
		osc.refresh();
		return osc;
	}

	/** The user's home directory, as key files may be relative to here. */
	private final File home;

	/** The .ssh/config file we read and monitor for updates. */
	private final File configFile;

	/** Modification time of {@link #configFile} when {@link #hosts} loaded. */
	private long lastModified;

	/** Cached entries read out of the configuration file. */
	private Map<String, Host> hosts;

	OpenSshConfig(final File h, final File cfg) {
		home = h;
		configFile = cfg;
		hosts = Collections.emptyMap();
	}

	/**
	 * Locate the configuration for a specific host request.
	 *
	 * @param hostName
	 *            the name the user has supplied to the SSH tool. This may be a
	 *            real host name, or it may just be a "Host" block in the
	 *            configuration file.
	 * @return r configuration for the requested name. Never null.
	 */
	public Host lookup(final String hostName) {
		final Map<String, Host> cache = refresh();
		Host h = cache.get(hostName);
		if (h == null)
			h = new Host();
		if (h.patternsApplied)
			return h;

		for (final Map.Entry<String, Host> e : cache.entrySet()) {
			if (!isHostPattern(e.getKey()))
				continue;
			if (!isHostMatch(e.getKey(), hostName))
				continue;
			h.copyFrom(e.getValue());
		}

		if (h.hostName == null)
			h.hostName = hostName;
		if (h.user == null)
			h.user = OpenSshConfig.userName();
		if (h.port == 0)
			h.port = OpenSshConfig.SSH_PORT;
		if (h.connectionAttempts == 0)
			h.connectionAttempts = 1;
		h.patternsApplied = true;
		return h;
	}

	private synchronized Map<String, Host> refresh() {
		final long mtime = configFile.lastModified();
		if (mtime != lastModified) {
			try {
				final FileInputStream in = new FileInputStream(configFile);
				try {
					hosts = parse(in);
				} finally {
					in.close();
				}
			} catch (FileNotFoundException none) {
				hosts = Collections.emptyMap();
			} catch (IOException err) {
				hosts = Collections.emptyMap();
			}
			lastModified = mtime;
		}
		return hosts;
	}

	private Map<String, Host> parse(final InputStream in) throws IOException {
		final Map<String, Host> m = new LinkedHashMap<String, Host>();
		final BufferedReader br = new BufferedReader(new InputStreamReader(in));
		final List<Host> current = new ArrayList<Host>(4);
		String line;

		while ((line = br.readLine()) != null) {
			line = line.trim();
			if (line.length() == 0 || line.startsWith("#")) //$NON-NLS-1$
				continue;

			final String[] parts = line.split("[ \t]*[= \t]", 2); //$NON-NLS-1$
			final String keyword = parts[0].trim();
			final String argValue = parts[1].trim();

			if (StringUtils.equalsIgnoreCase("Host", keyword)) { //$NON-NLS-1$
				current.clear();
				for (final String pattern : argValue.split("[ \t]")) { //$NON-NLS-1$
					final String name = dequote(pattern);
					Host c = m.get(name);
					if (c == null) {
						c = new Host();
						m.put(name, c);
					}
					current.add(c);
				}
				continue;
			}

			if (current.isEmpty()) {
				// We received an option outside of a Host block. We
				// don't know who this should match against, so skip.
				//
				continue;
			}

			if (StringUtils.equalsIgnoreCase("HostName", keyword)) { //$NON-NLS-1$
				for (final Host c : current)
					if (c.hostName == null)
						c.hostName = dequote(argValue);
			} else if (StringUtils.equalsIgnoreCase("User", keyword)) { //$NON-NLS-1$
				for (final Host c : current)
					if (c.user == null)
						c.user = dequote(argValue);
			} else if (StringUtils.equalsIgnoreCase("Port", keyword)) { //$NON-NLS-1$
				try {
					final int port = Integer.parseInt(dequote(argValue));
					for (final Host c : current)
						if (c.port == 0)
							c.port = port;
				} catch (NumberFormatException nfe) {
					// Bad port number. Don't set it.
				}
			} else if (StringUtils.equalsIgnoreCase("IdentityFile", keyword)) { //$NON-NLS-1$
				for (final Host c : current)
					if (c.identityFile == null)
						c.identityFile = toFile(dequote(argValue));
			} else if (StringUtils.equalsIgnoreCase(
					"PreferredAuthentications", keyword)) { //$NON-NLS-1$
				for (final Host c : current)
					if (c.preferredAuthentications == null)
						c.preferredAuthentications = nows(dequote(argValue));
			} else if (StringUtils.equalsIgnoreCase("BatchMode", keyword)) { //$NON-NLS-1$
				for (final Host c : current)
					if (c.batchMode == null)
						c.batchMode = yesno(dequote(argValue));
			} else if (StringUtils.equalsIgnoreCase(
					"StrictHostKeyChecking", keyword)) { //$NON-NLS-1$
				String value = dequote(argValue);
				for (final Host c : current)
					if (c.strictHostKeyChecking == null)
						c.strictHostKeyChecking = value;
			} else if (StringUtils.equalsIgnoreCase(
					"ConnectionAttempts", keyword)) { //$NON-NLS-1$
				try {
					final int connectionAttempts = Integer.parseInt(dequote(argValue));
					if (connectionAttempts > 0) {
						for (final Host c : current)
							if (c.connectionAttempts == 0)
								c.connectionAttempts = connectionAttempts;
					}
				} catch (NumberFormatException nfe) {
					// ignore bad values
				}
			}
		}

		return m;
	}

	private static boolean isHostPattern(final String s) {
		return s.indexOf('*') >= 0 || s.indexOf('?') >= 0;
	}

	private static boolean isHostMatch(final String pattern, final String name) {
		final FileNameMatcher fn;
		try {
			fn = new FileNameMatcher(pattern, null);
		} catch (InvalidPatternException e) {
			return false;
		}
		fn.append(name);
		return fn.isMatch();
	}

	private static String dequote(final String value) {
		if (value.startsWith("\"") && value.endsWith("\"")) //$NON-NLS-1$ //$NON-NLS-2$
			return value.substring(1, value.length() - 1);
		return value;
	}

	private static String nows(final String value) {
		final StringBuilder b = new StringBuilder();
		for (int i = 0; i < value.length(); i++) {
			if (!Character.isSpaceChar(value.charAt(i)))
				b.append(value.charAt(i));
		}
		return b.toString();
	}

	private static Boolean yesno(final String value) {
		if (StringUtils.equalsIgnoreCase("yes", value)) //$NON-NLS-1$
			return Boolean.TRUE;
		return Boolean.FALSE;
	}

	private File toFile(final String path) {
		if (path.startsWith("~/")) //$NON-NLS-1$
			return new File(home, path.substring(2));
		File ret = new File(path);
		if (ret.isAbsolute())
			return ret;
		return new File(home, path);
	}

	static String userName() {
		return AccessController.doPrivileged(new PrivilegedAction<String>() {
			public String run() {
				return System.getProperty("user.name"); //$NON-NLS-1$
			}
		});
	}

	/**
	 * Configuration of one "Host" block in the configuration file.
	 * <p>
	 * If returned from {@link OpenSshConfig#lookup(String)} some or all of the
	 * properties may not be populated. The properties which are not populated
	 * should be defaulted by the caller.
	 * <p>
	 * When returned from {@link OpenSshConfig#lookup(String)} any wildcard
	 * entries which appear later in the configuration file will have been
	 * already merged into this block.
	 */
	public static class Host {
		boolean patternsApplied;

		String hostName;

		int port;

		File identityFile;

		String user;

		String preferredAuthentications;

		Boolean batchMode;

		String strictHostKeyChecking;

		int connectionAttempts;

		void copyFrom(final Host src) {
			if (hostName == null)
				hostName = src.hostName;
			if (port == 0)
				port = src.port;
			if (identityFile == null)
				identityFile = src.identityFile;
			if (user == null)
				user = src.user;
			if (preferredAuthentications == null)
				preferredAuthentications = src.preferredAuthentications;
			if (batchMode == null)
				batchMode = src.batchMode;
			if (strictHostKeyChecking == null)
				strictHostKeyChecking = src.strictHostKeyChecking;
			if (connectionAttempts == 0)
				connectionAttempts = src.connectionAttempts;
		}

		/**
		 * @return the value StrictHostKeyChecking property, the valid values
		 *         are "yes" (unknown hosts are not accepted), "no" (unknown
		 *         hosts are always accepted), and "ask" (user should be asked
		 *         before accepting the host)
		 */
		public String getStrictHostKeyChecking() {
			return strictHostKeyChecking;
		}

		/**
		 * @return the real IP address or host name to connect to; never null.
		 */
		public String getHostName() {
			return hostName;
		}

		/**
		 * @return the real port number to connect to; never 0.
		 */
		public int getPort() {
			return port;
		}

		/**
		 * @return path of the private key file to use for authentication; null
		 *         if the caller should use default authentication strategies.
		 */
		public File getIdentityFile() {
			return identityFile;
		}

		/**
		 * @return the real user name to connect as; never null.
		 */
		public String getUser() {
			return user;
		}

		/**
		 * @return the preferred authentication methods, separated by commas if
		 *         more than one authentication method is preferred.
		 */
		public String getPreferredAuthentications() {
			return preferredAuthentications;
		}

		/**
		 * @return true if batch (non-interactive) mode is preferred for this
		 *         host connection.
		 */
		public boolean isBatchMode() {
			return batchMode != null && batchMode.booleanValue();
		}

		/**
		 * @return the number of tries (one per second) to connect before
		 *         exiting. The argument must be an integer. This may be useful
		 *         in scripts if the connection sometimes fails. The default is
		 *         1.
		 * @since 3.4
		 */
		public int getConnectionAttempts() {
			return connectionAttempts;
		}
	}
}
