package servlet;

import proof.*;
import sdsi.*;
import jp.*;
import sdsi.sexp.*;
import Tools.*;

import com.mortbay.HTTP.*;

import java.io.*;
import java.net.*;
import java.util.*;
import java.security.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * ProtectedServlet is a
 * parent class for servlets that want to check Snowflake/SPKI-style
 * permissions on incoming requests.
 */
public class ProtectedServlet
	extends HttpServlet
	implements SfHttpProtocol { 

//	SDSIPrincipal serverPublicKey;
		// for now this may actually be a hash (in which case these two
		// are equal. (Happens if we're started with a
		// hash as a command-line argument.)
//	Hash serverPublicHash;
	Map hashToMac;
	SecureRandom random;
	Prover2 prover;
	ProofCache proofCache;
	ServletConfig saveConfig;	// for re-init()ing the server

	boolean debug = false;

	/**
	 * The standard servlet initialization method. This one stashes the
	 * configuration in an instance field {@link #saveConfig} for
	 * subclasses to inspect.
	 */
	public void init(ServletConfig config) {
		try {
			random = new SecureRandom();
			hashToMac = new HashMap();
			proofCache = new ProofCache();
			this.saveConfig = config;
		} catch (Exception ex) {
			System.err.println("Exception in initializer");
			ex.printStackTrace();
		}
	}

    /**
     * Handle the GET and HEAD methods by building a simple web page.
     * HEAD is just like GET, except that the server returns only the
     * headers (including content length), not the body we write.<p>
	 *
	 * This method simply instantiates a {@link PSHandler} and passes
	 * the request there.
     */
    public void doGet(HttpServletRequest request,
		HttpServletResponse response)
		throws ServletException, IOException {

		// System.err.println("-------------------------------------------");
		Memory mt = null;
		Timer t = null;
		boolean printDebug = false;
// if (debug) {
//		mt = new Memory();
//		t = new Timer();
//		printDebug = true;	// debug flag can (duh) change during request...
// }
		getHandler(request,response).doGet();
// if (debug && printDebug) {
//		System.err.println("---------- Total request time at server: "+t);
//		System.err.println("memory added this request: "+mt);
//		System.err.println("hashToMac: "+hashToMac.size());
//		System.err.println("proofCache: "+proofCache.size());
//		prover.stats();
// }
	}

	PSHandler getHandler(HttpServletRequest request,
		HttpServletResponse response) {
		throw new RuntimeException("I'd be abstract, if jdb weren't LAAAME!");
	}

	/**
	 * Extract a proof from an "Authorization: SnowflakeProof " header.
	 * This is a common step in the Snowflake HTTP-with-signed-requests
	 * protocol.
	 */
	public static Proof extractProof(String authHeader) {
		if (authHeader==null
			|| !authHeader.startsWith(SNOWFLAKEPROOF)) {
			return null;
		}
		try {
			String proofStr = authHeader.substring(SNOWFLAKEPROOF.length());
			byte[] buf = proofStr.getBytes();
			if (buf[0] != ((byte) '(')) {
				// hex-escaped canonical format -- take off the 'hex'
				buf = Hex.hexToBytes(buf);
			}
			SexpList authSexp = (SexpList) Sexp.parse(new PushbackInputStream(
				new ByteArrayInputStream(buf)));
			Proof proof = Proof.parse(authSexp);
			return proof;
		} catch (Exception ex) {
			ex.printStackTrace();
//		} catch (SexpParseException ex) {
//		} catch (SexpException ex) {
		}
		return null;
	}
}
