/*
 * Copyright (C) 2011, 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 javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SIDE_BAND_64K;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
import static org.eclipse.jgit.transport.SideBandOutputStream.CH_ERROR;
import static org.eclipse.jgit.transport.SideBandOutputStream.SMALL_BUF;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.internal.transport.parser.FirstCommand;
import org.eclipse.jgit.internal.transport.parser.FirstWant;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.transport.PacketLineIn;
import org.eclipse.jgit.transport.PacketLineOut;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.RequestNotYetReadException;
import org.eclipse.jgit.transport.SideBandOutputStream;
import org.eclipse.jgit.transport.UploadPack;

/**
 * Utility functions for handling the Git-over-HTTP protocol.
 */
public class GitSmartHttpTools {
	private static final String INFO_REFS = Constants.INFO_REFS;

	/** Name of the git-upload-pack service. */
	public static final String UPLOAD_PACK = "git-upload-pack";

	/** Name of the git-receive-pack service. */
	public static final String RECEIVE_PACK = "git-receive-pack";

	/** Content type supplied by the client to the /git-upload-pack handler. */
	public static final String UPLOAD_PACK_REQUEST_TYPE =
			"application/x-git-upload-pack-request";

	/** Content type returned from the /git-upload-pack handler. */
	public static final String UPLOAD_PACK_RESULT_TYPE =
			"application/x-git-upload-pack-result";

	/** Content type supplied by the client to the /git-receive-pack handler. */
	public static final String RECEIVE_PACK_REQUEST_TYPE =
			"application/x-git-receive-pack-request";

	/** Content type returned from the /git-receive-pack handler. */
	public static final String RECEIVE_PACK_RESULT_TYPE =
			"application/x-git-receive-pack-result";

	/** Git service names accepted by the /info/refs?service= handler. */
	public static final List<String> VALID_SERVICES =
			Collections.unmodifiableList(Arrays.asList(new String[] {
					UPLOAD_PACK, RECEIVE_PACK }));

	private static final String INFO_REFS_PATH = "/" + INFO_REFS;
	private static final String UPLOAD_PACK_PATH = "/" + UPLOAD_PACK;
	private static final String RECEIVE_PACK_PATH = "/" + RECEIVE_PACK;

	private static final List<String> SERVICE_SUFFIXES =
			Collections.unmodifiableList(Arrays.asList(new String[] {
					INFO_REFS_PATH, UPLOAD_PACK_PATH, RECEIVE_PACK_PATH }));

	/**
	 * Check a request for Git-over-HTTP indicators.
	 *
	 * @param req
	 *            the current HTTP request that may have been made by Git.
	 * @return true if the request is likely made by a Git client program.
	 */
	public static boolean isGitClient(HttpServletRequest req) {
		return isInfoRefs(req) || isUploadPack(req) || isReceivePack(req);
	}

	/**
	 * Send an error to the Git client or browser.
	 * <p>
	 * Server implementors may use this method to send customized error messages
	 * to a Git protocol client using an HTTP 200 OK response with the error
	 * embedded in the payload. If the request was not issued by a Git client,
	 * an HTTP response code is returned instead.
	 *
	 * @param req
	 *            current request.
	 * @param res
	 *            current response.
	 * @param httpStatus
	 *            HTTP status code to set if the client is not a Git client.
	 * @throws IOException
	 *             the response cannot be sent.
	 */
	public static void sendError(HttpServletRequest req,
			HttpServletResponse res, int httpStatus) throws IOException {
		sendError(req, res, httpStatus, null);
	}

	/**
	 * Send an error to the Git client or browser.
	 * <p>
	 * Server implementors may use this method to send customized error messages
	 * to a Git protocol client using an HTTP 200 OK response with the error
	 * embedded in the payload. If the request was not issued by a Git client,
	 * an HTTP response code is returned instead.
	 * <p>
	 * This method may only be called before handing off the request to
	 * {@link org.eclipse.jgit.transport.UploadPack#upload(java.io.InputStream, OutputStream, OutputStream)}
	 * or
	 * {@link org.eclipse.jgit.transport.ReceivePack#receive(java.io.InputStream, OutputStream, OutputStream)}.
	 *
	 * @param req
	 *            current request.
	 * @param res
	 *            current response.
	 * @param httpStatus
	 *            HTTP status code to set if the client is not a Git client.
	 * @param textForGit
	 *            plain text message to display on the user's console. This is
	 *            shown only if the client is likely to be a Git client. If null
	 *            or the empty string a default text is chosen based on the HTTP
	 *            response code.
	 * @throws IOException
	 *             the response cannot be sent.
	 */
	public static void sendError(HttpServletRequest req,
			HttpServletResponse res, int httpStatus, String textForGit)
			throws IOException {
		if (textForGit == null || textForGit.length() == 0) {
			switch (httpStatus) {
			case SC_FORBIDDEN:
				textForGit = HttpServerText.get().repositoryAccessForbidden;
				break;
			case SC_NOT_FOUND:
				textForGit = HttpServerText.get().repositoryNotFound;
				break;
			case SC_INTERNAL_SERVER_ERROR:
				textForGit = HttpServerText.get().internalServerError;
				break;
			default:
				textForGit = "HTTP " + httpStatus;
				break;
			}
		}

		if (isInfoRefs(req)) {
			sendInfoRefsError(req, res, textForGit);
		} else if (isUploadPack(req)) {
			sendUploadPackError(req, res, textForGit);
		} else if (isReceivePack(req)) {
			sendReceivePackError(req, res, textForGit);
		} else {
			if (httpStatus < 400)
				ServletUtils.consumeRequestBody(req);
			res.sendError(httpStatus, textForGit);
		}
	}

	private static void sendInfoRefsError(HttpServletRequest req,
			HttpServletResponse res, String textForGit) throws IOException {
		ByteArrayOutputStream buf = new ByteArrayOutputStream(128);
		PacketLineOut pck = new PacketLineOut(buf);
		String svc = req.getParameter("service");
		pck.writeString("# service=" + svc + "\n");
		pck.end();
		pck.writeString("ERR " + textForGit);
		send(req, res, infoRefsResultType(svc), buf.toByteArray());
	}

	private static void sendUploadPackError(HttpServletRequest req,
			HttpServletResponse res, String textForGit) throws IOException {
		ByteArrayOutputStream buf = new ByteArrayOutputStream(128);
		PacketLineOut pckOut = new PacketLineOut(buf);

		boolean sideband;
		UploadPack up = (UploadPack) req.getAttribute(ATTRIBUTE_HANDLER);
		if (up != null) {
			try {
				sideband = up.isSideBand();
			} catch (RequestNotYetReadException e) {
				sideband = isUploadPackSideBand(req);
			}
		} else
			sideband = isUploadPackSideBand(req);

		if (sideband)
			writeSideBand(buf, textForGit);
		else
			writePacket(pckOut, textForGit);
		send(req, res, UPLOAD_PACK_RESULT_TYPE, buf.toByteArray());
	}

	private static boolean isUploadPackSideBand(HttpServletRequest req) {
		try {
			// The client may be in a state where they have sent the sideband
			// capability and are expecting a response in the sideband, but we might
			// not have an UploadPack, or it might not have read any of the request.
			// So, cheat and read the first line.
			String line = new PacketLineIn(req.getInputStream()).readString();
			FirstWant parsed = FirstWant.fromLine(line);
			return (parsed.getCapabilities().contains(OPTION_SIDE_BAND)
					|| parsed.getCapabilities().contains(OPTION_SIDE_BAND_64K));
		} catch (IOException e) {
			// Probably the connection is closed and a subsequent write will fail, but
			// try it just in case.
			return false;
		}
	}

	private static void sendReceivePackError(HttpServletRequest req,
			HttpServletResponse res, String textForGit) throws IOException {
		ByteArrayOutputStream buf = new ByteArrayOutputStream(128);
		PacketLineOut pckOut = new PacketLineOut(buf);

		boolean sideband;
		ReceivePack rp = (ReceivePack) req.getAttribute(ATTRIBUTE_HANDLER);
		if (rp != null) {
			try {
				sideband = rp.isSideBand();
			} catch (RequestNotYetReadException e) {
				sideband = isReceivePackSideBand(req);
			}
		} else
			sideband = isReceivePackSideBand(req);

		if (sideband)
			writeSideBand(buf, textForGit);
		else
			writePacket(pckOut, textForGit);
		send(req, res, RECEIVE_PACK_RESULT_TYPE, buf.toByteArray());
	}

	private static boolean isReceivePackSideBand(HttpServletRequest req) {
		try {
			// The client may be in a state where they have sent the sideband
			// capability and are expecting a response in the sideband, but we might
			// not have a ReceivePack, or it might not have read any of the request.
			// So, cheat and read the first line.
			String line = new PacketLineIn(req.getInputStream()).readString();
			FirstCommand parsed = FirstCommand.fromLine(line);
			return parsed.getCapabilities().contains(CAPABILITY_SIDE_BAND_64K);
		} catch (IOException e) {
			// Probably the connection is closed and a subsequent write will fail, but
			// try it just in case.
			return false;
		}
	}

	private static void writeSideBand(OutputStream out, String textForGit)
			throws IOException {
		try (OutputStream msg = new SideBandOutputStream(CH_ERROR, SMALL_BUF,
				out)) {
			msg.write(Constants.encode("error: " + textForGit));
			msg.flush();
		}
	}

	private static void writePacket(PacketLineOut pckOut, String textForGit)
			throws IOException {
		pckOut.writeString("error: " + textForGit);
	}

	private static void send(HttpServletRequest req, HttpServletResponse res,
			String type, byte[] buf) throws IOException {
		ServletUtils.consumeRequestBody(req);
		res.setStatus(HttpServletResponse.SC_OK);
		res.setContentType(type);
		res.setContentLength(buf.length);
		try (OutputStream os = res.getOutputStream()) {
			os.write(buf);
		}
	}

	/**
	 * Get the response Content-Type a client expects for the request.
	 * <p>
	 * This method should only be invoked if
	 * {@link #isGitClient(HttpServletRequest)} is true.
	 *
	 * @param req
	 *            current request.
	 * @return the Content-Type the client expects.
	 * @throws IllegalArgumentException
	 *             the request is not a Git client request. See
	 *             {@link #isGitClient(HttpServletRequest)}.
	 */
	public static String getResponseContentType(HttpServletRequest req) {
		if (isInfoRefs(req))
			return infoRefsResultType(req.getParameter("service"));
		else if (isUploadPack(req))
			return UPLOAD_PACK_RESULT_TYPE;
		else if (isReceivePack(req))
			return RECEIVE_PACK_RESULT_TYPE;
		else
			throw new IllegalArgumentException();
	}

	static String infoRefsResultType(String svc) {
		return "application/x-" + svc + "-advertisement";
	}

	/**
	 * Strip the Git service suffix from a request path.
	 *
	 * Generally the suffix is stripped by the {@code SuffixPipeline} handling
	 * the request, so this method is rarely needed.
	 *
	 * @param path
	 *            the path of the request.
	 * @return the path up to the last path component before the service suffix;
	 *         the path as-is if it contains no service suffix.
	 */
	public static String stripServiceSuffix(String path) {
		for (String suffix : SERVICE_SUFFIXES) {
			if (path.endsWith(suffix))
				return path.substring(0, path.length() - suffix.length());
		}
		return path;
	}

	/**
	 * Check if the HTTP request was for the /info/refs?service= Git handler.
	 *
	 * @param req
	 *            current request.
	 * @return true if the request is for the /info/refs service.
	 */
	public static boolean isInfoRefs(HttpServletRequest req) {
		return req.getRequestURI().endsWith(INFO_REFS_PATH)
				&& VALID_SERVICES.contains(req.getParameter("service"));
	}

	/**
	 * Check if the HTTP request path ends with the /git-upload-pack handler.
	 *
	 * @param pathOrUri
	 *            path or URI of the request.
	 * @return true if the request is for the /git-upload-pack handler.
	 */
	public static boolean isUploadPack(String pathOrUri) {
		return pathOrUri != null && pathOrUri.endsWith(UPLOAD_PACK_PATH);
	}

	/**
	 * Check if the HTTP request was for the /git-upload-pack Git handler.
	 *
	 * @param req
	 *            current request.
	 * @return true if the request is for the /git-upload-pack handler.
	 */
	public static boolean isUploadPack(HttpServletRequest req) {
		return isUploadPack(req.getRequestURI())
				&& UPLOAD_PACK_REQUEST_TYPE.equals(req.getContentType());
	}

	/**
	 * Check if the HTTP request was for the /git-receive-pack Git handler.
	 *
	 * @param req
	 *            current request.
	 * @return true if the request is for the /git-receive-pack handler.
	 */
	public static boolean isReceivePack(HttpServletRequest req) {
		String uri = req.getRequestURI();
		return uri != null && uri.endsWith(RECEIVE_PACK_PATH)
				&& RECEIVE_PACK_REQUEST_TYPE.equals(req.getContentType());
	}

	private GitSmartHttpTools() {
	}
}
