/*
 * 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 org.eclipse.jgit.transport.SshSessionFactory} via
 * {@link org.eclipse.jgit.transport.OpenSshConfig.Host} objects returned by
 * {@link #lookup(String)}, and implements a fully conforming
 * {@link com.jcraft.jsch.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 org.eclipse.jgit.transport.OpenSshConfig.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(File h, 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(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 (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(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(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(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(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(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 + "]";
		}
	}

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

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