/*
 * Copyright (C) 2011, Google Inc. 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.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.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.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;

/**
 * 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, httpStatus);
		} else if (isUploadPack(req)) {
			sendUploadPackError(req, res, textForGit, httpStatus);
		} else if (isReceivePack(req)) {
			sendReceivePackError(req, res, textForGit, httpStatus);
		} else {
			if (httpStatus < 400)
				ServletUtils.consumeRequestBody(req);
			res.sendError(httpStatus, textForGit);
		}
	}

	private static void sendInfoRefsError(HttpServletRequest req,
			HttpServletResponse res, String textForGit, int httpStatus)
			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(), httpStatus);
	}

	private static void sendUploadPackError(HttpServletRequest req,
			HttpServletResponse res, String textForGit, int httpStatus)
			throws IOException {
		// Do not use sideband. Sideband is acceptable only while packfile is
		// being sent. Other places, like acknowledgement section, do not
		// support sideband. Use an error packet.
		ByteArrayOutputStream buf = new ByteArrayOutputStream(128);
		PacketLineOut pckOut = new PacketLineOut(buf);
		writePacket(pckOut, textForGit);
		send(req, res, UPLOAD_PACK_RESULT_TYPE, buf.toByteArray(), httpStatus);
	}

	private static void sendReceivePackError(HttpServletRequest req,
			HttpServletResponse res, String textForGit, int httpStatus)
			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(), httpStatus);
	}

	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("ERR " + textForGit);
	}

	private static void send(HttpServletRequest req, HttpServletResponse res,
			String type, byte[] buf, int httpStatus) throws IOException {
		ServletUtils.consumeRequestBody(req);
		res.setStatus(httpStatus);
		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() {
	}
}
