package org.jenkinsci.plugins.ghprb;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.github.GHEventPayload.IssueComment;
import org.kohsuke.github.GHEventPayload.PullRequest;
import org.kohsuke.github.GitHub;

public class GhprbWebHook {
    private static final Logger logger = Logger.getLogger(GhprbWebHook.class.getName());
    
    private final GhprbTrigger trigger;
    
    public GhprbWebHook(GhprbTrigger trigger) {
        this.trigger = trigger;
    }
    
    public GitHub getGitHub() throws IOException {
        return trigger.getGitHub();
    }

    public boolean matchRepo(String hookRepoName) {
        GhprbRepository ghprbRepo = trigger.getRepository();
        String jobRepoName = ghprbRepo.getName();
        logger.log(Level.FINE, "Comparing repository names: {0} to {1}, case is ignored", new Object[] { jobRepoName, hookRepoName });
        return jobRepoName.equalsIgnoreCase(hookRepoName);
    }

    public String getProjectName() {
        return trigger.getActualProject().getFullName();
    }

    public void handleComment(IssueComment issueComment) throws IOException {
        GhprbRepository repo = trigger.getRepository();
        
        logger.log(Level.INFO, "Checking comment on PR #{0} for job {1}", new Object[] {issueComment.getIssue().getNumber(), getProjectName()});

        repo.onIssueCommentHook(issueComment);
    }

    public void handlePR(PullRequest pr) throws IOException {
        GhprbRepository repo = trigger.getRepository();

        logger.log(Level.INFO, "Checking PR #{0} for job {1}", new Object[] {pr.getNumber(), getProjectName()});

        repo.onPullRequestHook(pr);
    }

    public boolean checkSignature(String body, String signature) {
        String secret = trigger.getGitHubApiAuth().getSecret();
        if (StringUtils.isEmpty(secret)) {
            return true;
        }
        
        if (signature != null && signature.startsWith("sha1=")) {
            String expected = signature.substring(5);
            String algorithm = "HmacSHA1";
            try {
                SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(), algorithm);
                Mac mac = Mac.getInstance(algorithm);
                mac.init(keySpec);
                byte[] localSignatureBytes = mac.doFinal(body.getBytes("UTF-8"));
                String localSignature = Hex.encodeHexString(localSignatureBytes);
                if (! localSignature.equals(expected)) {
                    logger.log(Level.SEVERE, "Local signature {0} does not match external signature {1}",
                            new Object[] {localSignature, expected});
                    return false;
                }
            } catch (Exception e) {
                logger.log(Level.SEVERE, "Couldn't match both signatures");
                return false;
            }
        } else {
            logger.log(Level.SEVERE, "Request doesn't contain a signature. Check that github has a secret that should be attached to the hook");
            return false;
        }

        logger.log(Level.INFO, "Signatures checking OK");
        return true;
    }

}

@@ -31,16 +31,54 @@
 ghprb;%0A%0A
+import hudson.model.AbstractProject;%0A%0A
 import j
@@ -1226,56 +1226,201 @@
     
-return trigger.getActualProject().getFullName();
+AbstractProject%3C?, ?%3E project = trigger.getActualProject();%0A        if (project != null) %7B%0A            return project.getFullName();%0A        %7D else %7B%0A            return %22NOT STARTED%22;%0A        %7D
 %0A   

Fix #212, Closes janinko/ghprb#341