<commit_before>package hudson.plugins.git;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.Util;
import hudson.model.*;
import hudson.plugins.git.extensions.impl.IgnoreNotifyCommit;
import hudson.scm.SCM;
import hudson.security.ACL;
import hudson.triggers.SCMTrigger;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import jenkins.model.Jenkins;
import jenkins.scm.api.SCMEvent;
import jenkins.triggers.SCMTriggerItem;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.lang.StringUtils;
import static org.apache.commons.lang.StringUtils.isNotEmpty;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
import org.kohsuke.stapler.*;


/**
 * Information screen for the use of Git in Hudson.
 */
@Extension
public class GitStatus extends AbstractModelObject implements UnprotectedRootAction {
    public String getDisplayName() {
        return "Git";
    }

    public String getSearchUrl() {
        return getUrlName();
    }

    public String getIconFileName() {
        // TODO
        return null;
    }

    public String getUrlName() {
        return "git";
    }

    /* Package protected - not part of API, needed for testing */
    /* package */
    static void setAllowNotifyCommitParameters(boolean allowed) {
        allowNotifyCommitParameters = allowed;
    }

    private String lastURL = "";        // Required query parameter
    private String lastBranches = null; // Optional query parameter
    private String lastSHA1 = null;     // Optional query parameter
    private List<ParameterValue> lastBuildParameters = null;
    private static List<ParameterValue> lastStaticBuildParameters = null;

    private static void clearLastStaticBuildParameters() {
        lastStaticBuildParameters = null;
    }

    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();

        s.append("URL: ");
        s.append(lastURL);

        if (lastSHA1 != null) {
            s.append(" SHA1: ");
            s.append(lastSHA1);
        }

        if (lastBranches != null) {
            s.append(" Branches: ");
            s.append(lastBranches);
        }

        if (lastBuildParameters != null && !lastBuildParameters.isEmpty()) {
            s.append(" Parameters: ");
            for (ParameterValue buildParameter : lastBuildParameters) {
                s.append(buildParameter.getName());
                s.append("='");
                s.append(buildParameter.getValue());
                s.append("',");
            }
            s.delete(s.length() - 1, s.length());
        }

        if (lastStaticBuildParameters != null && !lastStaticBuildParameters.isEmpty()) {
            s.append(" More parameters: ");
            for (ParameterValue buildParameter : lastStaticBuildParameters) {
                s.append(buildParameter.getName());
                s.append("='");
                s.append(buildParameter.getValue());
                s.append("',");
            }
            s.delete(s.length() - 1, s.length());
        }

        return s.toString();
    }

    public HttpResponse doNotifyCommit(HttpServletRequest request, @QueryParameter(required=true) String url,
                                       @QueryParameter(required=false) String branches,
                                       @QueryParameter(required=false) String sha1) throws ServletException, IOException {
        lastURL = url;
        lastBranches = branches;
        lastSHA1 = sha1;
        lastBuildParameters = null;
        GitStatus.clearLastStaticBuildParameters();
        URIish uri;
        List<ParameterValue> buildParameters = new ArrayList<>();

        try {
            uri = new URIish(url);
        } catch (URISyntaxException e) {
            return HttpResponses.error(SC_BAD_REQUEST, new Exception("Illegal URL: " + url, e));
        }

        if (allowNotifyCommitParameters || !safeParameters.isEmpty()) { // Allow SECURITY-275 bug
            final Map<String, String[]> parameterMap = request.getParameterMap();
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                if (!(entry.getKey().equals("url")) && !(entry.getKey().equals("branches")) && !(entry.getKey().equals("sha1")))
                    if (entry.getValue()[0] != null && (allowNotifyCommitParameters || safeParameters.contains(entry.getKey())))
                        buildParameters.add(new StringParameterValue(entry.getKey(), entry.getValue()[0]));
            }
        }
        lastBuildParameters = buildParameters;

        branches = Util.fixEmptyAndTrim(branches);

        String[] branchesArray;
        if (branches == null) {
            branchesArray = new String[0];
        } else {
            branchesArray = branches.split(",");
        }

        final List<ResponseContributor> contributors = new ArrayList<>();
        Jenkins jenkins = Jenkins.getInstance();
        if (jenkins == null) {
            return HttpResponses.error(SC_BAD_REQUEST, new Exception("Jenkins.getInstance() null for : " + url));
        }
        String origin = SCMEvent.originOf(request);
        for (Listener listener : jenkins.getExtensionList(Listener.class)) {
            contributors.addAll(listener.onNotifyCommit(origin, uri, sha1, buildParameters, branchesArray));
        }

        return new HttpResponse() {
            public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node)
                    throws IOException, ServletException {
                rsp.setStatus(SC_OK);
                rsp.setContentType("text/plain");
                for (int i = 0; i < contributors.size(); i++) {
                    if (i == MAX_REPORTED_CONTRIBUTORS) {
                        rsp.addHeader("Triggered", "<" + (contributors.size() - i) + " more>");
                        break;
                    } else {
                        contributors.get(i).addHeaders(req, rsp);
                    }
                }
                PrintWriter w = rsp.getWriter();
                for (ResponseContributor c : contributors) {
                    c.writeBody(req, rsp, w);
                }
            }
        };
    }

    /**
     * Used to test if what we have in the job configuration matches what was submitted to the notification endpoint.
     * It is better to match loosely and wastes a few polling calls than to be pedantic and miss the push notification,
     * especially given that Git tends to support multiple access protocols.
     * @param lhs left-hand side of comparison
     * @param rhs right-hand side of comparison
     * @return true if left-hand side loosely matches right-hand side
     */
    public static boolean looselyMatches(URIish lhs, URIish rhs) {<commit_msg>Add @Override annotation on GitStatus methods<commit_after>package hudson.plugins.git;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.Util;
import hudson.model.*;
import hudson.plugins.git.extensions.impl.IgnoreNotifyCommit;
import hudson.scm.SCM;
import hudson.security.ACL;
import hudson.triggers.SCMTrigger;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import jenkins.model.Jenkins;
import jenkins.scm.api.SCMEvent;
import jenkins.triggers.SCMTriggerItem;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.lang.StringUtils;
import static org.apache.commons.lang.StringUtils.isNotEmpty;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
import org.kohsuke.stapler.*;


/**
 * Information screen for the use of Git in Hudson.
 */
@Extension
public class GitStatus extends AbstractModelObject implements UnprotectedRootAction {
    @Override
    public String getDisplayName() {
        return "Git";
    }

    @Override
    public String getSearchUrl() {
        return getUrlName();
    }

    @Override
    public String getIconFileName() {
        // TODO
        return null;
    }

    @Override
    public String getUrlName() {
        return "git";
    }

    /* Package protected - not part of API, needed for testing */
    /* package */
    static void setAllowNotifyCommitParameters(boolean allowed) {
        allowNotifyCommitParameters = allowed;
    }

    private String lastURL = "";        // Required query parameter
    private String lastBranches = null; // Optional query parameter
    private String lastSHA1 = null;     // Optional query parameter
    private List<ParameterValue> lastBuildParameters = null;
    private static List<ParameterValue> lastStaticBuildParameters = null;

    private static void clearLastStaticBuildParameters() {
        lastStaticBuildParameters = null;
    }

    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();

        s.append("URL: ");
        s.append(lastURL);

        if (lastSHA1 != null) {
            s.append(" SHA1: ");
            s.append(lastSHA1);
        }

        if (lastBranches != null) {
            s.append(" Branches: ");
            s.append(lastBranches);
        }

        if (lastBuildParameters != null && !lastBuildParameters.isEmpty()) {
            s.append(" Parameters: ");
            for (ParameterValue buildParameter : lastBuildParameters) {
                s.append(buildParameter.getName());
                s.append("='");
                s.append(buildParameter.getValue());
                s.append("',");
            }
            s.delete(s.length() - 1, s.length());
        }

        if (lastStaticBuildParameters != null && !lastStaticBuildParameters.isEmpty()) {
            s.append(" More parameters: ");
            for (ParameterValue buildParameter : lastStaticBuildParameters) {
                s.append(buildParameter.getName());
                s.append("='");
                s.append(buildParameter.getValue());
                s.append("',");
            }
            s.delete(s.length() - 1, s.length());
        }

        return s.toString();
    }

    public HttpResponse doNotifyCommit(HttpServletRequest request, @QueryParameter(required=true) String url,
                                       @QueryParameter(required=false) String branches,
                                       @QueryParameter(required=false) String sha1) throws ServletException, IOException {
        lastURL = url;
        lastBranches = branches;
        lastSHA1 = sha1;
        lastBuildParameters = null;
        GitStatus.clearLastStaticBuildParameters();
        URIish uri;
        List<ParameterValue> buildParameters = new ArrayList<>();

        try {
            uri = new URIish(url);
        } catch (URISyntaxException e) {
            return HttpResponses.error(SC_BAD_REQUEST, new Exception("Illegal URL: " + url, e));
        }

        if (allowNotifyCommitParameters || !safeParameters.isEmpty()) { // Allow SECURITY-275 bug
            final Map<String, String[]> parameterMap = request.getParameterMap();
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                if (!(entry.getKey().equals("url")) && !(entry.getKey().equals("branches")) && !(entry.getKey().equals("sha1")))
                    if (entry.getValue()[0] != null && (allowNotifyCommitParameters || safeParameters.contains(entry.getKey())))
                        buildParameters.add(new StringParameterValue(entry.getKey(), entry.getValue()[0]));
            }
        }
        lastBuildParameters = buildParameters;

        branches = Util.fixEmptyAndTrim(branches);

        String[] branchesArray;
        if (branches == null) {
            branchesArray = new String[0];
        } else {
            branchesArray = branches.split(",");
        }

        final List<ResponseContributor> contributors = new ArrayList<>();
        Jenkins jenkins = Jenkins.getInstance();
        if (jenkins == null) {
            return HttpResponses.error(SC_BAD_REQUEST, new Exception("Jenkins.getInstance() null for : " + url));
        }
        String origin = SCMEvent.originOf(request);
        for (Listener listener : jenkins.getExtensionList(Listener.class)) {
            contributors.addAll(listener.onNotifyCommit(origin, uri, sha1, buildParameters, branchesArray));
        }

        return new HttpResponse() {
            @Override
            public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node)
                    throws IOException, ServletException {
                rsp.setStatus(SC_OK);
                rsp.setContentType("text/plain");
                for (int i = 0; i < contributors.size(); i++) {
                    if (i == MAX_REPORTED_CONTRIBUTORS) {
                        rsp.addHeader("Triggered", "<" + (contributors.size() - i) + " more>");
                        break;
                    } else {
                        contributors.get(i).addHeaders(req, rsp);
                    }
                }
                PrintWriter w = rsp.getWriter();
                for (ResponseContributor c : contributors) {
                    c.writeBody(req, rsp, w);
                }
            }
        };
    }

    /**
     * Used to test if what we have in the job configuration matches what was submitted to the notification endpoint.
     * It is better to match loosely and wastes a few polling calls than to be pedantic and miss the push notification,
     * especially given that Git tends to support multiple access protocols.
     * @param lhs left-hand side of comparison
     * @param rhs right-hand side of comparison
     * @return true if left-hand side loosely matches right-hand side
     */
    public static boolean looselyMatches(URIish lhs, URIish rhs) {
{'fraction_non_alphanumeric': 0.10590604026845638, 'fraction_numerical': 0.0024161073825503354, 'mean_word_length': 2.412182276162125, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2487071', 'n_tokens_mistral': 3951, 'n_tokens_neox': 3835, 'n_words': 924}