/*
 * Copyright (C) 2008, 2010, Google Inc.
 * Copyright (C) 2017, Thomas Wolf <thomas.wolf@paranor.ch> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.transport;

import java.io.IOException;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.Set;
import java.util.function.Supplier;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A representation of the "http.*" config values in a git
 * {@link org.eclipse.jgit.lib.Config}. git provides for setting values for
 * specific URLs through "http.&lt;url&gt;.*" subsections. git always considers
 * only the initial original URL for such settings, not any redirected URL.
 *
 * @since 4.9
 */
public class HttpConfig {

	private static final Logger LOG = LoggerFactory.getLogger(HttpConfig.class);

	private static final String FTP = "ftp"; //$NON-NLS-1$

	/** git config section key for http settings. */
	public static final String HTTP = "http"; //$NON-NLS-1$

	/** git config key for the "followRedirects" setting. */
	public static final String FOLLOW_REDIRECTS_KEY = "followRedirects"; //$NON-NLS-1$

	/** git config key for the "maxRedirects" setting. */
	public static final String MAX_REDIRECTS_KEY = "maxRedirects"; //$NON-NLS-1$

	/** git config key for the "postBuffer" setting. */
	public static final String POST_BUFFER_KEY = "postBuffer"; //$NON-NLS-1$

	/** git config key for the "sslVerify" setting. */
	public static final String SSL_VERIFY_KEY = "sslVerify"; //$NON-NLS-1$

	/**
	 * git config key for the "cookieFile" setting.
	 *
	 * @since 5.4
	 */
	public static final String COOKIE_FILE_KEY = "cookieFile"; //$NON-NLS-1$

	/**
	 * git config key for the "saveCookies" setting.
	 *
	 * @since 5.4
	 */
	public static final String SAVE_COOKIES_KEY = "saveCookies"; //$NON-NLS-1$

	/**
	 * Custom JGit config key which holds the maximum number of cookie files to
	 * keep in the cache.
	 *
	 * @since 5.4
	 */
	public static final String COOKIE_FILE_CACHE_LIMIT_KEY = "cookieFileCacheLimit"; //$NON-NLS-1$

	private static final int DEFAULT_COOKIE_FILE_CACHE_LIMIT = 10;

	private static final String MAX_REDIRECT_SYSTEM_PROPERTY = "http.maxRedirects"; //$NON-NLS-1$

	private static final int DEFAULT_MAX_REDIRECTS = 5;

	private static final int MAX_REDIRECTS = (new Supplier<Integer>() {

		@Override
		public Integer get() {
			String rawValue = SystemReader.getInstance()
					.getProperty(MAX_REDIRECT_SYSTEM_PROPERTY);
			Integer value = Integer.valueOf(DEFAULT_MAX_REDIRECTS);
			if (rawValue != null) {
				try {
					value = Integer.valueOf(Integer.parseUnsignedInt(rawValue));
				} catch (NumberFormatException e) {
					LOG.warn(MessageFormat.format(
							JGitText.get().invalidSystemProperty,
							MAX_REDIRECT_SYSTEM_PROPERTY, rawValue, value));
				}
			}
			return value;
		}
	}).get().intValue();

	/**
	 * Config values for http.followRedirect.
	 */
	public enum HttpRedirectMode implements Config.ConfigEnum {

		/** Always follow redirects (up to the http.maxRedirects limit). */
		TRUE("true"), //$NON-NLS-1$
		/**
		 * Only follow redirects on the initial GET request. This is the
		 * default.
		 */
		INITIAL("initial"), //$NON-NLS-1$
		/** Never follow redirects. */
		FALSE("false"); //$NON-NLS-1$

		private final String configValue;

		private HttpRedirectMode(String configValue) {
			this.configValue = configValue;
		}

		@Override
		public String toConfigValue() {
			return configValue;
		}

		@Override
		public boolean matchConfigValue(String s) {
			return configValue.equals(s);
		}
	}

	private int postBuffer;

	private boolean sslVerify;

	private HttpRedirectMode followRedirects;

	private int maxRedirects;

	private String cookieFile;

	private boolean saveCookies;

	private int cookieFileCacheLimit;

	/**
	 * Get the "http.postBuffer" setting
	 *
	 * @return the value of the "http.postBuffer" setting
	 */
	public int getPostBuffer() {
		return postBuffer;
	}

	/**
	 * Get the "http.sslVerify" setting
	 *
	 * @return the value of the "http.sslVerify" setting
	 */
	public boolean isSslVerify() {
		return sslVerify;
	}

	/**
	 * Get the "http.followRedirects" setting
	 *
	 * @return the value of the "http.followRedirects" setting
	 */
	public HttpRedirectMode getFollowRedirects() {
		return followRedirects;
	}

	/**
	 * Get the "http.maxRedirects" setting
	 *
	 * @return the value of the "http.maxRedirects" setting
	 */
	public int getMaxRedirects() {
		return maxRedirects;
	}

	/**
	 * Get the "http.cookieFile" setting
	 *
	 * @return the value of the "http.cookieFile" setting
	 *
	 * @since 5.4
	 */
	public String getCookieFile() {
		return cookieFile;
	}

	/**
	 * Get the "http.saveCookies" setting
	 *
	 * @return the value of the "http.saveCookies" setting
	 *
	 * @since 5.4
	 */
	public boolean getSaveCookies() {
		return saveCookies;
	}

	/**
	 * Get the "http.cookieFileCacheLimit" setting (gives the maximum number of
	 * cookie files to keep in the LRU cache)
	 *
	 * @return the value of the "http.cookieFileCacheLimit" setting
	 *
	 * @since 5.4
	 */
	public int getCookieFileCacheLimit() {
		return cookieFileCacheLimit;
	}

	/**
	 * Creates a new {@link org.eclipse.jgit.transport.HttpConfig} tailored to
	 * the given {@link org.eclipse.jgit.transport.URIish}.
	 *
	 * @param config
	 *            to read the {@link org.eclipse.jgit.transport.HttpConfig} from
	 * @param uri
	 *            to get the configuration values for
	 */
	public HttpConfig(Config config, URIish uri) {
		init(config, uri);
	}

	/**
	 * Creates a {@link org.eclipse.jgit.transport.HttpConfig} that reads values
	 * solely from the user config.
	 *
	 * @param uri
	 *            to get the configuration values for
	 */
	public HttpConfig(URIish uri) {
		StoredConfig userConfig = null;
		try {
			userConfig = SystemReader.getInstance().getUserConfig();
		} catch (IOException | ConfigInvalidException e) {
			// Log it and then work with default values.
			LOG.error(e.getMessage(), e);
			init(new Config(), uri);
			return;
		}
		init(userConfig, uri);
	}

	private void init(Config config, URIish uri) {
		// Set defaults from the section first
		int postBufferSize = config.getInt(HTTP, POST_BUFFER_KEY,
				1 * 1024 * 1024);
		boolean sslVerifyFlag = config.getBoolean(HTTP, SSL_VERIFY_KEY, true);
		HttpRedirectMode followRedirectsMode = config.getEnum(
				HttpRedirectMode.values(), HTTP, null,
				FOLLOW_REDIRECTS_KEY, HttpRedirectMode.INITIAL);
		int redirectLimit = config.getInt(HTTP, MAX_REDIRECTS_KEY,
				MAX_REDIRECTS);
		if (redirectLimit < 0) {
			redirectLimit = MAX_REDIRECTS;
		}
		cookieFile = config.getString(HTTP, null, COOKIE_FILE_KEY);
		saveCookies = config.getBoolean(HTTP, SAVE_COOKIES_KEY, false);
		cookieFileCacheLimit = config.getInt(HTTP, COOKIE_FILE_CACHE_LIMIT_KEY,
				DEFAULT_COOKIE_FILE_CACHE_LIMIT);
		String match = findMatch(config.getSubsections(HTTP), uri);
		if (match != null) {
			// Override with more specific items
			postBufferSize = config.getInt(HTTP, match, POST_BUFFER_KEY,
					postBufferSize);
			sslVerifyFlag = config.getBoolean(HTTP, match, SSL_VERIFY_KEY,
					sslVerifyFlag);
			followRedirectsMode = config.getEnum(HttpRedirectMode.values(),
					HTTP, match, FOLLOW_REDIRECTS_KEY, followRedirectsMode);
			int newMaxRedirects = config.getInt(HTTP, match, MAX_REDIRECTS_KEY,
					redirectLimit);
			if (newMaxRedirects >= 0) {
				redirectLimit = newMaxRedirects;
			}
			String urlSpecificCookieFile = config.getString(HTTP, match,
					COOKIE_FILE_KEY);
			if (urlSpecificCookieFile != null) {
				cookieFile = urlSpecificCookieFile;
			}
			saveCookies = config.getBoolean(HTTP, match, SAVE_COOKIES_KEY,
					saveCookies);
		}
		postBuffer = postBufferSize;
		sslVerify = sslVerifyFlag;
		followRedirects = followRedirectsMode;
		maxRedirects = redirectLimit;
	}

	/**
	 * Determines the best match from a set of subsection names (representing
	 * prefix URLs) for the given {@link URIish}.
	 *
	 * @param names
	 *            to match against the {@code uri}
	 * @param uri
	 *            to find a match for
	 * @return the best matching subsection name, or {@code null} if no
	 *         subsection matches
	 */
	private String findMatch(Set<String> names, URIish uri) {
		String bestMatch = null;
		int bestMatchLength = -1;
		boolean withUser = false;
		String uPath = uri.getPath();
		boolean hasPath = !StringUtils.isEmptyOrNull(uPath);
		if (hasPath) {
			uPath = normalize(uPath);
			if (uPath == null) {
				// Normalization failed; warning was logged.
				return null;
			}
		}
		for (String s : names) {
			try {
				URIish candidate = new URIish(s);
				// Scheme and host must match case-insensitively
				if (!compare(uri.getScheme(), candidate.getScheme())
						|| !compare(uri.getHost(), candidate.getHost())) {
					continue;
				}
				// Ports must match after default ports have been substituted
				if (defaultedPort(uri.getPort(),
						uri.getScheme()) != defaultedPort(candidate.getPort(),
								candidate.getScheme())) {
					continue;
				}
				// User: if present in candidate, must match
				boolean hasUser = false;
				if (candidate.getUser() != null) {
					if (!candidate.getUser().equals(uri.getUser())) {
						continue;
					}
					hasUser = true;
				}
				// Path: prefix match, longer is better
				String cPath = candidate.getPath();
				int matchLength = -1;
				if (StringUtils.isEmptyOrNull(cPath)) {
					matchLength = 0;
				} else {
					if (!hasPath) {
						continue;
					}
					// Paths can match only on segments
					matchLength = segmentCompare(uPath, cPath);
					if (matchLength < 0) {
						continue;
					}
				}
				// A longer path match is always preferred even over a user
				// match. If the path matches are equal, a match with user wins
				// over a match without user.
				if (matchLength > bestMatchLength
						|| (!withUser && hasUser && matchLength >= 0
								&& matchLength == bestMatchLength)) {
					bestMatch = s;
					bestMatchLength = matchLength;
					withUser = hasUser;
				}
			} catch (URISyntaxException e) {
				LOG.warn(MessageFormat
						.format(JGitText.get().httpConfigInvalidURL, s));
			}
		}
		return bestMatch;
	}

	private boolean compare(String a, String b) {
		if (a == null) {
			return b == null;
		}
		return a.equalsIgnoreCase(b);
	}

	private int defaultedPort(int port, String scheme) {
		if (port >= 0) {
			return port;
		}
		if (FTP.equalsIgnoreCase(scheme)) {
			return 21;
		} else if (HTTP.equalsIgnoreCase(scheme)) {
			return 80;
		} else {
			return 443; // https
		}
	}

	static int segmentCompare(String uriPath, String m) {
		// Precondition: !uriPath.isEmpty() && !m.isEmpty(),and u must already
		// be normalized
		String matchPath = normalize(m);
		if (matchPath == null || !uriPath.startsWith(matchPath)) {
			return -1;
		}
		// We can match only on a segment boundary: either both paths are equal,
		// or if matchPath does not end in '/', there is a '/' in uriPath right
		// after the match.
		int uLength = uriPath.length();
		int mLength = matchPath.length();
		if (mLength == uLength || matchPath.charAt(mLength - 1) == '/'
				|| (mLength < uLength && uriPath.charAt(mLength) == '/')) {
			return mLength;
		}
		return -1;
	}

	static String normalize(String path) {
		// C-git resolves . and .. segments
		int i = 0;
		int length = path.length();
		StringBuilder builder = new StringBuilder(length);
		builder.append('/');
		if (length > 0 && path.charAt(0) == '/') {
			i = 1;
		}
		while (i < length) {
			int slash = path.indexOf('/', i);
			if (slash < 0) {
				slash = length;
			}
			if (slash == i || (slash == i + 1 && path.charAt(i) == '.')) {
				// Skip /. or also double slashes
			} else if (slash == i + 2 && path.charAt(i) == '.'
					&& path.charAt(i + 1) == '.') {
				// Remove previous segment if we have "/.."
				int l = builder.length() - 2; // Skip terminating slash.
				while (l >= 0 && builder.charAt(l) != '/') {
					l--;
				}
				if (l < 0) {
					LOG.warn(MessageFormat.format(
							JGitText.get().httpConfigCannotNormalizeURL, path));
					return null;
				}
				builder.setLength(l + 1);
			} else {
				// Include the slash, if any
				builder.append(path, i, Math.min(length, slash + 1));
			}
			i = slash + 1;
		}
		if (builder.length() > 1 && builder.charAt(builder.length() - 1) == '/'
				&& length > 0 && path.charAt(length - 1) != '/') {
			// . or .. normalization left a trailing slash when the original
			// path had none at the end
			builder.setLength(builder.length() - 1);
		}
		return builder.toString();
	}
}
