/*
 * Copyright (C) 2008, 2017, 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.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

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;
import org.eclipse.jgit.util.SystemReader;

import com.jcraft.jsch.ConfigRepository;

/**
 * Fairly complete configuration parser for the OpenSSH ~/.ssh/config file.
 * <p>
 * JSch does have its own config file parser
 * {@link com.jcraft.jsch.OpenSSHConfig} since version 0.1.50, but it has a
 * number of problems:
 * <ul>
 * <li>it splits lines of the format "keyword = value" wrongly: you'd end up
 * with the value "= value".
 * <li>its "Host" keyword is not case insensitive.
 * <li>it doesn't handle quoted values.
 * <li>JSch's OpenSSHConfig doesn't monitor for config file changes.
 * </ul>
 * <p>
 * Therefore implement our own parser to read an OpenSSH configuration file. It
 * makes the critical options available to {@link SshSessionFactory} via
 * {@link Host} objects returned by {@link #lookup(String)}, and implements a
 * fully conforming {@link ConfigRepository} providing
 * {@link com.jcraft.jsch.ConfigRepository.Config}s via
 * {@link #getConfig(String)}.
 * </p>
 * <p>
 * Limitations compared to the full OpenSSH 7.5 parser:
 * </p>
 * <ul>
 * <li>This parser does not handle Match or Include keywords.
 * <li>This parser does not do host name canonicalization (Jsch ignores it
 * anyway).
 * </ul>
 * <p>
 * Note that OpenSSH's readconf.c is a validating parser; Jsch's
 * ConfigRepository OTOH treats all option values as plain strings, so any
 * validation must happen in Jsch outside of the parser. Thus this parser does
 * not validate option values, except for a few options when constructing a
 * {@link Host} object.
 * </p>
 * <p>
 * This config does %-substitutions for the following tokens:
 * </p>
 * <ul>
 * <li>%% - single %
 * <li>%C - short-hand for %l%h%p%r. See %p and %r below; the replacement may be
 * done partially only and may leave %p or %r or both unreplaced.
 * <li>%d - home directory path
 * <li>%h - remote host name
 * <li>%L - local host name without domain
 * <li>%l - FQDN of the local host
 * <li>%n - host name as specified in {@link #lookup(String)}
 * <li>%p - port number; replaced only if set in the config
 * <li>%r - remote user name; replaced only if set in the config
 * <li>%u - local user name
 * </ul>
 * <p>
 * If the config doesn't set the port or the remote user name, %p and %r remain
 * un-substituted. It's the caller's responsibility to replace them with values
 * obtained from the connection URI. %i is not handled; Java has no concept of a
 * "user ID".
 * </p>
 */
public class OpenSshConfig implements ConfigRepository {

	/** 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 it was last loaded. */
	private long lastModified;

	/**
	 * Encapsulates entries read out of the configuration file, and
	 * {@link Host}s created from that.
	 */
	private static class State {
		Map<String, HostEntry> entries = new LinkedHashMap<>();
		Map<String, Host> hosts = new HashMap<>();

		@Override
		@SuppressWarnings("nls")
		public String toString() {
			return "State [entries=" + entries + ", hosts=" + hosts + "]";
		}
	}

	/** State read from the config file, plus {@link Host}s created from it. */
	private State state;

	OpenSshConfig(final File h, final File cfg) {
		home = h;
		configFile = cfg;
		state = new State();
	}

	/**
	 * 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 State cache = refresh();
		Host h = cache.hosts.get(hostName);
		if (h != null) {
			return h;
		}
		HostEntry fullConfig = new HostEntry();
		// Initialize with default entries at the top of the file, before the
		// first Host block.
		fullConfig.merge(cache.entries.get(HostEntry.DEFAULT_NAME));
		for (final Map.Entry<String, HostEntry> e : cache.entries.entrySet()) {
			String key = e.getKey();
			if (isHostMatch(key, hostName)) {
				fullConfig.merge(e.getValue());
			}
		}
		fullConfig.substitute(hostName, home);
		h = new Host(fullConfig, hostName, home);
		cache.hosts.put(hostName, h);
		return h;
	}

	private synchronized State refresh() {
		final long mtime = configFile.lastModified();
		if (mtime != lastModified) {
			State newState = new State();
			try (FileInputStream in = new FileInputStream(configFile)) {
				newState.entries = parse(in);
			} catch (IOException none) {
				// Ignore -- we'll set and return an empty state
			}
			lastModified = mtime;
			state = newState;
		}
		return state;
	}

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

		// The man page doesn't say so, but the OpenSSH parser (readconf.c)
		// starts out in active mode and thus always applies any lines that
		// occur before the first host block. We gather those options in a
		// HostEntry for DEFAULT_NAME.
		HostEntry defaults = new HostEntry();
		current.add(defaults);
		m.put(HostEntry.DEFAULT_NAME, defaults);

		while ((line = br.readLine()) != null) {
			line = line.trim();
			if (line.isEmpty() || line.startsWith("#")) { //$NON-NLS-1$
				continue;
			}
			String[] parts = line.split("[ \t]*[= \t]", 2); //$NON-NLS-1$
			// Although the ssh-config man page doesn't say so, the OpenSSH
			// parser does allow quoted keywords.
			String keyword = dequote(parts[0].trim());
			// man 5 ssh-config says lines had the format "keyword arguments",
			// with no indication that arguments were optional. However, let's
			// not crap out on missing arguments. See bug 444319.
			String argValue = parts.length > 1 ? parts[1].trim() : ""; //$NON-NLS-1$

			if (StringUtils.equalsIgnoreCase("Host", keyword)) { //$NON-NLS-1$
				current.clear();
				for (String name : HostEntry.parseList(argValue)) {
					if (name == null || name.isEmpty()) {
						// null should not occur, but better be safe than sorry.
						continue;
					}
					HostEntry c = m.get(name);
					if (c == null) {
						c = new HostEntry();
						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 (HostEntry.isListKey(keyword)) {
				List<String> args = HostEntry.parseList(argValue);
				for (HostEntry entry : current) {
					entry.setValue(keyword, args);
				}
			} else if (!argValue.isEmpty()) {
				argValue = dequote(argValue);
				for (HostEntry entry : current) {
					entry.setValue(keyword, argValue);
				}
			}
		}

		return m;
	}

	private static boolean isHostMatch(final String pattern,
			final String name) {
		if (pattern.startsWith("!")) { //$NON-NLS-1$
			return !patternMatchesHost(pattern.substring(1), name);
		} else {
			return patternMatchesHost(pattern, name);
		}
	}

	private static boolean patternMatchesHost(final String pattern,
			final String name) {
		if (pattern.indexOf('*') >= 0 || pattern.indexOf('?') >= 0) {
			final FileNameMatcher fn;
			try {
				fn = new FileNameMatcher(pattern, null);
			} catch (InvalidPatternException e) {
				return false;
			}
			fn.append(name);
			return fn.isMatch();
		} else {
			// Not a pattern but a full host name
			return pattern.equals(name);
		}
	}

	private static String dequote(final String value) {
		if (value.startsWith("\"") && value.endsWith("\"") //$NON-NLS-1$ //$NON-NLS-2$
				&& value.length() > 1)
			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 static File toFile(String path, File home) {
		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);
	}

	private static int positive(final String value) {
		if (value != null) {
			try {
				return Integer.parseUnsignedInt(value);
			} catch (NumberFormatException e) {
				// Ignore
			}
		}
		return -1;
	}

	static String userName() {
		return AccessController.doPrivileged(new PrivilegedAction<String>() {
			@Override
			public String run() {
				return SystemReader.getInstance()
						.getProperty(Constants.OS_USER_NAME_KEY);
			}
		});
	}

	private static class HostEntry implements ConfigRepository.Config {

		/**
		 * "Host name" of the HostEntry for the default options before the first
		 * host block in a config file.
		 */
		public static final String DEFAULT_NAME = ""; //$NON-NLS-1$

		// See com.jcraft.jsch.OpenSSHConfig. Translates some command-line keys
		// to ssh-config keys.
		private static final Map<String, String> KEY_MAP = new HashMap<>();

		static {
			KEY_MAP.put("kex", "KexAlgorithms"); //$NON-NLS-1$//$NON-NLS-2$
			KEY_MAP.put("server_host_key", "HostKeyAlgorithms"); //$NON-NLS-1$ //$NON-NLS-2$
			KEY_MAP.put("cipher.c2s", "Ciphers"); //$NON-NLS-1$ //$NON-NLS-2$
			KEY_MAP.put("cipher.s2c", "Ciphers"); //$NON-NLS-1$ //$NON-NLS-2$
			KEY_MAP.put("mac.c2s", "Macs"); //$NON-NLS-1$ //$NON-NLS-2$
			KEY_MAP.put("mac.s2c", "Macs"); //$NON-NLS-1$ //$NON-NLS-2$
			KEY_MAP.put("compression.s2c", "Compression"); //$NON-NLS-1$ //$NON-NLS-2$
			KEY_MAP.put("compression.c2s", "Compression"); //$NON-NLS-1$ //$NON-NLS-2$
			KEY_MAP.put("compression_level", "CompressionLevel"); //$NON-NLS-1$ //$NON-NLS-2$
			KEY_MAP.put("MaxAuthTries", "NumberOfPasswordPrompts"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		/**
		 * Keys that can be specified multiple times, building up a list. (I.e.,
		 * those are the keys that do not follow the general rule of "first
		 * occurrence wins".)
		 */
		private static final Set<String> MULTI_KEYS = new HashSet<>();

		static {
			MULTI_KEYS.add("CERTIFICATEFILE"); //$NON-NLS-1$
			MULTI_KEYS.add("IDENTITYFILE"); //$NON-NLS-1$
			MULTI_KEYS.add("LOCALFORWARD"); //$NON-NLS-1$
			MULTI_KEYS.add("REMOTEFORWARD"); //$NON-NLS-1$
			MULTI_KEYS.add("SENDENV"); //$NON-NLS-1$
		}

		/**
		 * Keys that take a whitespace-separated list of elements as argument.
		 * Because the dequote-handling is different, we must handle those in
		 * the parser. There are a few other keys that take comma-separated
		 * lists as arguments, but for the parser those are single arguments
		 * that must be quoted if they contain whitespace, and taking them apart
		 * is the responsibility of the user of those keys.
		 */
		private static final Set<String> LIST_KEYS = new HashSet<>();

		static {
			LIST_KEYS.add("CANONICALDOMAINS"); //$NON-NLS-1$
			LIST_KEYS.add("GLOBALKNOWNHOSTSFILE"); //$NON-NLS-1$
			LIST_KEYS.add("SENDENV"); //$NON-NLS-1$
			LIST_KEYS.add("USERKNOWNHOSTSFILE"); //$NON-NLS-1$
		}

		private Map<String, String> options;

		private Map<String, List<String>> multiOptions;

		private Map<String, List<String>> listOptions;

		@Override
		public String getHostname() {
			return getValue("HOSTNAME"); //$NON-NLS-1$
		}

		@Override
		public String getUser() {
			return getValue("USER"); //$NON-NLS-1$
		}

		@Override
		public int getPort() {
			return positive(getValue("PORT")); //$NON-NLS-1$
		}

		private static String mapKey(String key) {
			String k = KEY_MAP.get(key);
			if (k == null) {
				k = key;
			}
			return k.toUpperCase(Locale.ROOT);
		}

		private String findValue(String key) {
			String k = mapKey(key);
			String result = options != null ? options.get(k) : null;
			if (result == null) {
				// Also check the list and multi options. Modern OpenSSH treats
				// UserKnownHostsFile and GlobalKnownHostsFile as list-valued,
				// and so does this parser. Jsch 0.1.54 in general doesn't know
				// about list-valued options (it _does_ know multi-valued
				// options, though), and will ask for a single value for such
				// options.
				//
				// Let's be lenient and return at least the first value from
				// a list-valued or multi-valued key for which Jsch asks for a
				// single value.
				List<String> values = listOptions != null ? listOptions.get(k)
						: null;
				if (values == null) {
					values = multiOptions != null ? multiOptions.get(k) : null;
				}
				if (values != null && !values.isEmpty()) {
					result = values.get(0);
				}
			}
			return result;
		}

		@Override
		public String getValue(String key) {
			// See com.jcraft.jsch.OpenSSHConfig.MyConfig.getValue() for this
			// special case.
			if (key.equals("compression.s2c") //$NON-NLS-1$
					|| key.equals("compression.c2s")) { //$NON-NLS-1$
				String foo = findValue(key);
				if (foo == null || foo.equals("no")) { //$NON-NLS-1$
					return "none,zlib@openssh.com,zlib"; //$NON-NLS-1$
				}
				return "zlib@openssh.com,zlib,none"; //$NON-NLS-1$
			}
			return findValue(key);
		}

		@Override
		public String[] getValues(String key) {
			String k = mapKey(key);
			List<String> values = listOptions != null ? listOptions.get(k)
					: null;
			if (values == null) {
				values = multiOptions != null ? multiOptions.get(k) : null;
			}
			if (values == null || values.isEmpty()) {
				return new String[0];
			}
			return values.toArray(new String[values.size()]);
		}

		public void setValue(String key, String value) {
			String k = key.toUpperCase(Locale.ROOT);
			if (MULTI_KEYS.contains(k)) {
				if (multiOptions == null) {
					multiOptions = new HashMap<>();
				}
				List<String> values = multiOptions.get(k);
				if (values == null) {
					values = new ArrayList<>(4);
					multiOptions.put(k, values);
				}
				values.add(value);
			} else {
				if (options == null) {
					options = new HashMap<>();
				}
				if (!options.containsKey(k)) {
					options.put(k, value);
				}
			}
		}

		public void setValue(String key, List<String> values) {
			if (values.isEmpty()) {
				// Can occur only on a missing argument: ignore.
				return;
			}
			String k = key.toUpperCase(Locale.ROOT);
			// Check multi-valued keys first; because of the replacement
			// strategy, they must take precedence over list-valued keys
			// which always follow the "first occurrence wins" strategy.
			//
			// Note that SendEnv is a multi-valued list-valued key. (It's
			// rather immaterial for JGit, though.)
			if (MULTI_KEYS.contains(k)) {
				if (multiOptions == null) {
					multiOptions = new HashMap<>(2 * MULTI_KEYS.size());
				}
				List<String> items = multiOptions.get(k);
				if (items == null) {
					items = new ArrayList<>(values);
					multiOptions.put(k, items);
				} else {
					items.addAll(values);
				}
			} else {
				if (listOptions == null) {
					listOptions = new HashMap<>(2 * LIST_KEYS.size());
				}
				if (!listOptions.containsKey(k)) {
					listOptions.put(k, values);
				}
			}
		}

		public static boolean isListKey(String key) {
			return LIST_KEYS.contains(key.toUpperCase(Locale.ROOT));
		}

		/**
		 * Splits the argument into a list of whitespace-separated elements.
		 * Elements containing whitespace must be quoted and will be de-quoted.
		 *
		 * @param argument
		 *            argument part of the configuration line as read from the
		 *            config file
		 * @return a {@link List} of elements, possibly empty and possibly
		 *         containing empty elements
		 */
		public static List<String> parseList(String argument) {
			List<String> result = new ArrayList<>(4);
			int start = 0;
			int length = argument.length();
			while (start < length) {
				// Skip whitespace
				if (Character.isSpaceChar(argument.charAt(start))) {
					start++;
					continue;
				}
				if (argument.charAt(start) == '"') {
					int stop = argument.indexOf('"', ++start);
					if (stop < start) {
						// No closing double quote: skip
						break;
					}
					result.add(argument.substring(start, stop));
					start = stop + 1;
				} else {
					int stop = start + 1;
					while (stop < length
							&& !Character.isSpaceChar(argument.charAt(stop))) {
						stop++;
					}
					result.add(argument.substring(start, stop));
					start = stop + 1;
				}
			}
			return result;
		}

		protected void merge(HostEntry entry) {
			if (entry == null) {
				// Can occur if we could not read the config file
				return;
			}
			if (entry.options != null) {
				if (options == null) {
					options = new HashMap<>();
				}
				for (Map.Entry<String, String> item : entry.options
						.entrySet()) {
					if (!options.containsKey(item.getKey())) {
						options.put(item.getKey(), item.getValue());
					}
				}
			}
			if (entry.listOptions != null) {
				if (listOptions == null) {
					listOptions = new HashMap<>(2 * LIST_KEYS.size());
				}
				for (Map.Entry<String, List<String>> item : entry.listOptions
						.entrySet()) {
					if (!listOptions.containsKey(item.getKey())) {
						listOptions.put(item.getKey(), item.getValue());
					}
				}

			}
			if (entry.multiOptions != null) {
				if (multiOptions == null) {
					multiOptions = new HashMap<>(2 * MULTI_KEYS.size());
				}
				for (Map.Entry<String, List<String>> item : entry.multiOptions
						.entrySet()) {
					List<String> values = multiOptions.get(item.getKey());
					if (values == null) {
						values = new ArrayList<>(item.getValue());
						multiOptions.put(item.getKey(), values);
					} else {
						values.addAll(item.getValue());
					}
				}
			}
		}

		private class Replacer {
			private final Map<Character, String> replacements = new HashMap<>();

			public Replacer(String originalHostName, File home) {
				replacements.put(Character.valueOf('%'), "%"); //$NON-NLS-1$
				replacements.put(Character.valueOf('d'), home.getPath());
				// Needs special treatment...
				String host = getValue("HOSTNAME"); //$NON-NLS-1$
				replacements.put(Character.valueOf('h'), originalHostName);
				if (host != null && host.indexOf('%') >= 0) {
					host = substitute(host, "h"); //$NON-NLS-1$
					options.put("HOSTNAME", host); //$NON-NLS-1$
				}
				if (host != null) {
					replacements.put(Character.valueOf('h'), host);
				}
				String localhost = SystemReader.getInstance().getHostname();
				replacements.put(Character.valueOf('l'), localhost);
				int period = localhost.indexOf('.');
				if (period > 0) {
					localhost = localhost.substring(0, period);
				}
				replacements.put(Character.valueOf('L'), localhost);
				replacements.put(Character.valueOf('n'), originalHostName);
				replacements.put(Character.valueOf('p'), getValue("PORT")); //$NON-NLS-1$
				replacements.put(Character.valueOf('r'), getValue("USER")); //$NON-NLS-1$
				replacements.put(Character.valueOf('u'), userName());
				replacements.put(Character.valueOf('C'),
						substitute("%l%h%p%r", "hlpr")); //$NON-NLS-1$ //$NON-NLS-2$
			}

			public String substitute(String input, String allowed) {
				if (input == null || input.length() <= 1
						|| input.indexOf('%') < 0) {
					return input;
				}
				StringBuilder builder = new StringBuilder();
				int start = 0;
				int length = input.length();
				while (start < length) {
					int percent = input.indexOf('%', start);
					if (percent < 0 || percent + 1 >= length) {
						builder.append(input.substring(start));
						break;
					}
					String replacement = null;
					char ch = input.charAt(percent + 1);
					if (ch == '%' || allowed.indexOf(ch) >= 0) {
						replacement = replacements.get(Character.valueOf(ch));
					}
					if (replacement == null) {
						builder.append(input.substring(start, percent + 2));
					} else {
						builder.append(input.substring(start, percent))
								.append(replacement);
					}
					start = percent + 2;
				}
				return builder.toString();
			}
		}

		private List<String> substitute(List<String> values, String allowed,
				Replacer r) {
			List<String> result = new ArrayList<>(values.size());
			for (String value : values) {
				result.add(r.substitute(value, allowed));
			}
			return result;
		}

		private List<String> replaceTilde(List<String> values, File home) {
			List<String> result = new ArrayList<>(values.size());
			for (String value : values) {
				result.add(toFile(value, home).getPath());
			}
			return result;
		}

		protected void substitute(String originalHostName, File home) {
			Replacer r = new Replacer(originalHostName, home);
			if (multiOptions != null) {
				List<String> values = multiOptions.get("IDENTITYFILE"); //$NON-NLS-1$
				if (values != null) {
					values = substitute(values, "dhlru", r); //$NON-NLS-1$
					values = replaceTilde(values, home);
					multiOptions.put("IDENTITYFILE", values); //$NON-NLS-1$
				}
				values = multiOptions.get("CERTIFICATEFILE"); //$NON-NLS-1$
				if (values != null) {
					values = substitute(values, "dhlru", r); //$NON-NLS-1$
					values = replaceTilde(values, home);
					multiOptions.put("CERTIFICATEFILE", values); //$NON-NLS-1$
				}
			}
			if (listOptions != null) {
				List<String> values = listOptions.get("GLOBALKNOWNHOSTSFILE"); //$NON-NLS-1$
				if (values != null) {
					values = replaceTilde(values, home);
					listOptions.put("GLOBALKNOWNHOSTSFILE", values); //$NON-NLS-1$
				}
				values = listOptions.get("USERKNOWNHOSTSFILE"); //$NON-NLS-1$
				if (values != null) {
					values = replaceTilde(values, home);
					listOptions.put("USERKNOWNHOSTSFILE", values); //$NON-NLS-1$
				}
			}
			if (options != null) {
				// HOSTNAME already done in Replacer constructor
				String value = options.get("IDENTITYAGENT"); //$NON-NLS-1$
				if (value != null) {
					value = r.substitute(value, "dhlru"); //$NON-NLS-1$
					value = toFile(value, home).getPath();
					options.put("IDENTITYAGENT", value); //$NON-NLS-1$
				}
			}
			// Match is not implemented and would need to be done elsewhere
			// anyway. ControlPath, LocalCommand, ProxyCommand, and
			// RemoteCommand are not used by Jsch.
		}

		@Override
		@SuppressWarnings("nls")
		public String toString() {
			return "HostEntry [options=" + options + ", multiOptions="
					+ multiOptions + ", listOptions=" + listOptions + "]";
		}
	}

	/**
	 * 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 {
		String hostName;

		int port;

		File identityFile;

		String user;

		String preferredAuthentications;

		Boolean batchMode;

		String strictHostKeyChecking;

		int connectionAttempts;

		private Config config;

		/**
		 * Creates a new uninitialized {@link Host}.
		 */
		public Host() {
			// For API backwards compatibility with pre-4.9 JGit
		}

		Host(Config config, String hostName, File homeDir) {
			this.config = config;
			complete(hostName, homeDir);
		}

		/**
		 * @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;
		}


		private void complete(String initialHostName, File homeDir) {
			// Try to set values from the options.
			hostName = config.getHostname();
			user = config.getUser();
			port = config.getPort();
			connectionAttempts = positive(
					config.getValue("ConnectionAttempts")); //$NON-NLS-1$
			strictHostKeyChecking = config.getValue("StrictHostKeyChecking"); //$NON-NLS-1$
			String value = config.getValue("BatchMode"); //$NON-NLS-1$
			if (value != null) {
				batchMode = yesno(value);
			}
			value = config.getValue("PreferredAuthentications"); //$NON-NLS-1$
			if (value != null) {
				preferredAuthentications = nows(value);
			}
			// Fill in defaults if still not set
			if (hostName == null) {
				hostName = initialHostName;
			}
			if (user == null) {
				user = OpenSshConfig.userName();
			}
			if (port <= 0) {
				port = OpenSshConfig.SSH_PORT;
			}
			if (connectionAttempts <= 0) {
				connectionAttempts = 1;
			}
			String[] identityFiles = config.getValues("IdentityFile"); //$NON-NLS-1$
			if (identityFiles != null && identityFiles.length > 0) {
				identityFile = toFile(identityFiles[0], homeDir);
			}
		}

		Config getConfig() {
			return config;
		}

		@Override
		@SuppressWarnings("nls")
		public String toString() {
			return "Host [hostName=" + hostName + ", port=" + port
					+ ", identityFile=" + identityFile + ", user=" + user
					+ ", preferredAuthentications=" + preferredAuthentications
					+ ", batchMode=" + batchMode + ", strictHostKeyChecking="
					+ strictHostKeyChecking + ", connectionAttempts="
					+ connectionAttempts + ", config=" + config + "]";
		}
	}

	/**
	 * Retrieves the full {@link com.jcraft.jsch.ConfigRepository.Config Config}
	 * for the given host name. Should be called only by Jsch and tests.
	 *
	 * @param hostName
	 *            to get the config for
	 * @return the configuration for the host
	 * @since 4.9
	 */
	@Override
	public Config getConfig(String hostName) {
		Host host = lookup(hostName);
		return host.getConfig();
	}

	@Override
	@SuppressWarnings("nls")
	public String toString() {
		return "OpenSshConfig [home=" + home + ", configFile=" + configFile
				+ ", lastModified=" + lastModified + ", state=" + state + "]";
	}
}
