/*
 * Copyright (C) 2012, 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.http.server;

import static org.eclipse.jgit.http.server.ServletUtils.isChunked;

import javax.servlet.http.HttpServletRequest;

/**
 * Parses Git client User-Agent strings.
 */
public class ClientVersionUtil {
	private static final int[] v1_7_5 = { 1, 7, 5 };
	private static final int[] v1_7_8_6 = { 1, 7, 8, 6 };
	private static final int[] v1_7_9 = { 1, 7, 9 };

	/**
	 * An invalid version of Git
	 *
	 * @return maximum version array, indicating an invalid version of Git.
	 */
	public static int[] invalidVersion() {
		return new int[] { Integer.MAX_VALUE };
	}

	/**
	 * Parse a Git client User-Agent header value.
	 *
	 * @param version
	 *            git client version string, of the form "git/1.7.9".
	 * @return components of the version string. {@link #invalidVersion()} if
	 *         the version string cannot be parsed.
	 */
	public static int[] parseVersion(String version) {
		if (version != null && version.startsWith("git/"))
			return splitVersion(version.substring("git/".length()));
		return invalidVersion();
	}

	private static int[] splitVersion(String versionString) {
		char[] str = versionString.toCharArray();
		int[] ver = new int[4];
		int end = 0;
		int acc = 0;
		for (int i = 0; i < str.length; i++) {
			char c = str[i];
			if ('0' <= c && c <= '9') {
				acc *= 10;
				acc += c - '0';
			} else if (c == '.') {
				if (end == ver.length)
					ver = grow(ver);
				ver[end++] = acc;
				acc = 0;
			} else if (c == 'g' && 0 < i && str[i - 1] == '.' && 0 < end) {
				// Non-tagged builds may contain a mangled git describe output.
				// "1.7.6.1.45.gbe0cc". The 45 isn't a valid component. Drop it.
				ver[end - 1] = 0;
				acc = 0;
				break;
			} else if (c == '-' && (i + 2) < str.length
					&& str[i + 1] == 'r' && str[i + 2] == 'c') {
				// Release candidates aren't the same as a final release.
				if (acc > 0)
					acc--;
				break;
			} else
				break;
		}
		if (acc != 0) {
			if (end == ver.length)
				ver = grow(ver);
			ver[end++] = acc;
		} else {
			while (0 < end && ver[end - 1] == 0)
				end--;
		}
		if (end < ver.length) {
			int[] n = new int[end];
			System.arraycopy(ver, 0, n, 0, end);
			ver = n;
		}
		return ver;
	}

	private static int[] grow(int[] tmp) {
		int[] n = new int[tmp.length + 1];
		System.arraycopy(tmp, 0, n, 0, tmp.length);
		return n;
	}

	/**
	 * Compare two version strings for natural ordering.
	 *
	 * @param a
	 *            first parsed version string.
	 * @param b
	 *            second parsed version string.
	 * @return &lt; 0 if a is before b; 0 if a equals b; &gt;0 if a is after b.
	 */
	public static int compare(int[] a, int[] b) {
		for (int i = 0; i < a.length && i < b.length; i++) {
			int cmp = a[i] - b[i];
			if (cmp != 0)
				return cmp;
		}
		return a.length - b.length;
	}

	/**
	 * Convert a parsed version back to a string.
	 *
	 * @param ver
	 *            the parsed version array.
	 * @return a string, e.g. "1.6.6.0".
	 */
	public static String toString(int[] ver) {
		StringBuilder b = new StringBuilder();
		for (int v : ver) {
			if (b.length() > 0)
				b.append('.');
			b.append(v);
		}
		return b.toString();
	}

	/**
	 * Check if a Git client has the known push status bug.
	 * <p>
	 * These buggy clients do not display the status report from a failed push
	 * over HTTP.
	 *
	 * @param version
	 *            parsed version of the Git client software.
	 * @return true if the bug is present.
	 */
	public static boolean hasPushStatusBug(int[] version) {
		int cmp = compare(version, v1_7_8_6);
		if (cmp < 0)
			return true; // Everything before 1.7.8.6 is known broken.
		else if (cmp == 0)
			return false; // 1.7.8.6 contained the bug fix.

		if (compare(version, v1_7_9) <= 0)
			return true; // 1.7.9 shipped before 1.7.8.6 and has the bug.
		return false; // 1.7.9.1 and later are fixed.
	}

	/**
	 * Check if a Git client has the known chunked request body encoding bug.
	 * <p>
	 * Git 1.7.5 contains a unique bug where chunked requests are malformed.
	 * This applies to both fetch and push.
	 *
	 * @param version
	 *            parsed version of the Git client software.
	 * @param request
	 *            incoming HTTP request.
	 * @return true if the client has the chunked encoding bug.
	 */
	public static boolean hasChunkedEncodingRequestBug(
			int[] version, HttpServletRequest request) {
		return compare(version, v1_7_5) == 0 && isChunked(request);
	}

	private ClientVersionUtil() {
	}
}
