package test.abnahme.A;

import java.io.OutputStream;
import java.net.URL;
import java.security.Security;

import javax.net.ssl.SSLSocketFactory;

import test.abnahme.AbnahmeTestCase;

import at.gv.egovernment.moa.util.StreamUtils;
import at.gv.egovernment.moa.util.URLEncoder;

import com.sun.net.ssl.HostnameVerifier;
import com.sun.net.ssl.HttpsURLConnection;

/**
 * @author Stefan Knirsch
 * @version $Id$
 * 
 */
public class Test500StartAuthenticationServlet extends AbnahmeTestCase {

  private String testdataRoot = TESTDATA_ROOT + "xmldata/standard/";
  SSLSocketFactory ssf;
  public Test500StartAuthenticationServlet(String name) {
    super(name);
  }
  protected void setUp() throws Exception {
    super.setUp();
    Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
    System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
    System.setProperty("javax.net.ssl.trustStore", "C:/Programme/ApacheGroup/abnahme/server.keystore");
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
  }

 public void testA501() throws Exception {
    //NUR einmal f�r alle folgenden Testf�lle
    //----------------------------------------

    //----------------------------------------

    try {
      String targetURL = getURL("https://localhost:8443/moa-id-auth/", "gb", "https://localhost:9443/");
      HttpsURLConnection conn = giveConnection(targetURL, "GET");
      conn.connect();
      int resultCode = conn.getResponseCode();
      String contentType = conn.getHeaderField("Content-Type");
      if (resultCode != 200)
        fail("Wrong HTTP-Code");
      if (!conn.getHeaderField("Content-Type").equalsIgnoreCase("text/html"))
        fail("Wrong contentType: expected text/html and was " + conn.getHeaderField("Content-Type"));
      conn.disconnect();
      System.out.println("-----------------------Testfall " + this.getName() + " erfolgreich abgearbeitet! -----------------------");
      
    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN " + this.getName() + ":" + e.getLocalizedMessage());
      throw e;
    }
  }

  public void testA502() throws Exception {
    try {
      String URL = getURL("https://localhost:8443/moa-id-auth/", "gb", "https://localhost:9443/");
      HttpsURLConnection conn = giveConnection(URL, "GET");
      conn.connect();
      int resultCode = conn.getResponseCode();
      String contentType = conn.getHeaderField("Content-Type");
      if (resultCode != 200)
        fail("Wrong HTTP-Code: expected '200' and was '" + resultCode + "'");
      if (!conn.getHeaderField("Content-Type").equalsIgnoreCase("text/html"))
        fail("Wrong contentType: expected text/html and was " + conn.getHeaderField("Content-Type"));
      String result = new String(StreamUtils.readStream(conn.getInputStream()));

      conn.disconnect();

      URL = parseDataURL(result);
      conn = giveConnection(URL, "POST");
      conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");

      String infoboxReadResponse = readXmldata("InfoboxReadResponse.xml");
      System.out.println("File gelesen, Daten in Outputstream einpflegen");
      OutputStream out = conn.getOutputStream();
      out.write(new String("XMLResponse=" + URLEncoder.encode(infoboxReadResponse, "UTF-8")).getBytes("UTF-8"));
      out.flush();
      out.close();

      System.out.println("Verbinden zu " + URL);
      conn.connect();
      resultCode = conn.getResponseCode();
      System.out.println("resultCode :" + resultCode);
      String redirectLoc = conn.getHeaderField("Location");
      System.out.println("redirectLoc :" + redirectLoc);
      // Austausch von VerifyIdentityLink in der POST-URL durch VerifyAuthBlock... rest MUSS gleich sein!
      if (!killInclusive(URL, "VerifyI", "Link", "VerifyAuthBlock").equals(redirectLoc))
        fail("Wrong Redirect-Location: expected " + URL + " and was " + conn.getHeaderField("Location"));
      if (!conn.getHeaderField("Content-Type").equalsIgnoreCase("text/xml"))
        fail("Wrong contentType: expected text/xml and was " + conn.getHeaderField("Content-Type"));
      conn.disconnect();
      System.out.println("-----------------------\nTestfall " + this.getName() + " erfolgreich abgearbeitet! \n-----------------------");
    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN " + this.getName() + ":" + e.getLocalizedMessage());
      throw e;
    }
  }

  public void testA503() throws Exception {
    try {
      String URL = getURL("https://localhost:8443/moa-id-auth/", "gb", "https://localhost:9443/");
      HttpsURLConnection conn = giveConnection(URL, "GET");
      conn.connect();

      assertEquals(200,conn.getResponseCode());
      if (!conn.getHeaderField("Content-Type").equalsIgnoreCase("text/html"))
        fail("Wrong contentType: expected text/html and was " + conn.getHeaderField("Content-Type"));
      String result = new String(StreamUtils.readStream(conn.getInputStream()));
      URL = parseDataURL(result);

      conn.disconnect();
      conn = giveConnection(URL, "POST");
      conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
      String infoboxReadResponse = readXmldata("InfoboxReadResponse.xml");
      OutputStream out = conn.getOutputStream();
      out.write(new String("XMLResponse=" + URLEncoder.encode(infoboxReadResponse, "UTF-8")).getBytes());
      out.flush();
      out.close();
      conn.connect();
      String redirectLoc = conn.getHeaderField("Location");
      // Austausch von VerifyIdentityLink in der POST-URL durch VerifyAuthBlock... rest MUSS gleich sein!
      if (!killInclusive(URL, "VerifyI", "Link", "VerifyAuthBlock").equals(redirectLoc))
        fail("Wrong Redirect-Location: expected " + URL + " and was " + conn.getHeaderField("Location"));
      if (!conn.getHeaderField("Content-Type").equalsIgnoreCase("text/xml"))
        fail("Wrong contentType: expected text/xml and was " + conn.getHeaderField("Content-Type"));
      conn.disconnect();

      conn = giveConnection(redirectLoc, "POST");
      System.out.println("Redirect Location: " + redirectLoc);
      String createXMLSignatureResponse =  URLEncoder.encode(readXmldata("CreateXMLSignatureResponse.xml"), "UTF-8");
      out = conn.getOutputStream();
      out.write(("XMLResponse=" +createXMLSignatureResponse).getBytes());
      out.flush();
      out.close();

      System.out.println("Sending Data to " + redirectLoc);
      conn.connect();

      redirectLoc = conn.getHeaderField("Location");
      System.out.println("redirectLoc: "  + redirectLoc);
     /* RandomAccessFile raf = new RandomAccessFile("C://503.xml", "rw");
      raf.write(StreamUtils.readStream(conn.getInputStream()));
      raf.close();*/
      conn.disconnect();
      assertEquals(302, conn.getResponseCode());
      assertTrue(redirectLoc.startsWith("https://localhost:9443/?Target=gb&SAMLArtifact="));
      System.out.println("-----------------------\nTestfall " + this.getName() + " erfolgreich abgearbeitet! \n-----------------------");

    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN " + this.getName() + ":" + e.getLocalizedMessage());
      throw e;
    }
  }
  public void testA551() throws Exception {
    try {
      String targetURL = getURL("https://localhost:8443/moa-id-auth/", "gb", "");
      HttpsURLConnection conn = giveConnection(targetURL, "GET");
      conn.connect();
      String result = new String(StreamUtils.readStream(conn.getInputStream()));
      assertTrue(result.indexOf("Die Angabe der Parameter ist unvollständig") >= 0);
      conn.disconnect();
      System.out.println("-----------------------\nFehler in " + this.getName() + " erfolgreich abgefangen: Die Angabe der Parameter ist unvollst�ndig.\n-----------------------");
    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN " + this.getName() + ":" + e.getLocalizedMessage());
      throw e;
    }
  }

  public void testA552() throws Exception {
    try {
      String URL = getURL("https://localhost:8443/moa-id-auth/", "gb", "https://localhost:9443/");
      HttpsURLConnection conn = giveConnection(URL, "GET");
      conn.connect();
      int resultCode = conn.getResponseCode();
      assertEquals(200, resultCode);
      if (!conn.getHeaderField("Content-Type").equalsIgnoreCase("text/html"))
        fail("Wrong contentType: expected text/html and was " + conn.getHeaderField("Content-Type"));
      conn.disconnect();
      URL = "https://localhost:8443/moa-id-auth/" + "VerifyIdentityLink?MOASessionID=0000";
      conn = giveConnection(URL, "POST");
      conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");

      String infoboxReadResponse = readXmldata("InfoboxReadResponse.xml");
      OutputStream out = conn.getOutputStream();
      out.write(new String("XMLResponse=" + URLEncoder.encode(infoboxReadResponse, "UTF-8")).getBytes());
      out.flush();
      out.close();

      conn.connect();
      String result = new String(StreamUtils.readStream(conn.getInputStream()));
      assertTrue(result.indexOf("MOASessionID ist unbekannt") >= 0);
      System.out.println("Fehler in testA552 erfolgreich abgefangen: MOASessionID ist unbekannt");
      conn.disconnect();
    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN " + this.getName() + ":" + e.getLocalizedMessage());
      throw e;
    }
  }
  public void testA553() throws Exception {
    try {
      String URL = getURL("https://localhost:8443/moa-id-auth/", "gb", "https://localhost:9443/");
      HttpsURLConnection conn = giveConnection(URL, "GET");
      conn.connect();
      int resultCode = conn.getResponseCode();
      assertEquals(200,resultCode);
      if (!conn.getHeaderField("Content-Type").equalsIgnoreCase("text/html"))
        fail("Wrong contentType: expected text/html and was " + conn.getHeaderField("Content-Type"));
      String result = new String(StreamUtils.readStream(conn.getInputStream()));
      String MOASessionID = parseSessionIDFromForm(result);
      URL = parseDataURL(result);
      conn.disconnect();

      conn = giveConnection(URL, "POST");
      conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");

      String infoboxReadResponse = readXmldata("InfoboxReadResponse.xml");
      OutputStream out = conn.getOutputStream();
      out.write(new String("XMLResponse=" + URLEncoder.encode(infoboxReadResponse, "UTF-8")).getBytes());
      out.flush();
      out.close();
      conn.connect();
      result = new String(StreamUtils.readStream(conn.getInputStream()));
      String redirectLoc = conn.getHeaderField("Location");
      // Austausch von VerifyIdentityLink in der POST-URL durch VerifyAuthBlock... rest MUSS gleich sein!
      if (!killInclusive(URL, "VerifyI", "Link", "VerifyAuthBlock").equals(redirectLoc))
        fail("Wrong Redirect-Location: expected " + URL + " and was " + conn.getHeaderField("Location"));
      if (!conn.getHeaderField("Content-Type").equalsIgnoreCase("text/xml"))
        fail("Wrong contentType: expected text/xml and was " + conn.getHeaderField("Content-Type"));
      conn.disconnect();
      conn = giveConnection(redirectLoc + "XXX", "POST");
      System.out.println("Redirect Location: " + redirectLoc + "XXX");
      String createXMLSignatureResponse = "XMLResponse=" + URLEncoder.encode(readXmldata("CreateXMLSignatureResponse.xml"), "UTF-8");

      out = conn.getOutputStream();
      out.write(new String("MOASessionID=" + MOASessionID + "&").getBytes());
      out.write(createXMLSignatureResponse.getBytes("UTF-8"));
      out.flush();
      out.close();
      System.out.println("Sending Data to " + redirectLoc);
      conn.connect();
      resultCode = conn.getResponseCode();

      result = new String(StreamUtils.readStream(conn.getInputStream()));
      conn.disconnect();
      assertEquals(200, resultCode);
      assertTrue(result.indexOf("MOASessionID ist unbekannt") >= 0);
      System.out.println("-----------------------\nTestfall " + this.getName() + " erfolgreich abgearbeitet! \n-----------------------");
    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN " + this.getName() + ":" + e.getLocalizedMessage());
      throw e;
    }
  }

  private String parseDataURL(String input) {
    String ret = getSubString(input.substring(input.indexOf("DataURL"), input.length()), "value=\"", "\"");
    return ret;
  }

  private String getSubString(String input, String startsWith, String endsWith) {
    return input.substring(input.indexOf(startsWith) + startsWith.length(), input.indexOf(endsWith, input.indexOf(startsWith) + startsWith.length()));
  }
  private String getURL(String authURL, String target, String oaURL) {
    return authURL + "StartAuthentication?Target=" + target + "&OA=" + oaURL;
  }
  private String parseSessionIDFromForm(String htmlForm) {
    String parName = "MOASessionID=";
    assertTrue("HTML Form enth�lt keine SessionID", htmlForm.indexOf(parName) >= 0);
    int i1 = htmlForm.indexOf(parName) + parName.length();
    int i2 = htmlForm.indexOf("\"", i1);
    assertTrue("HTML Form enth�lt keine g�ltige SessionID", i2 > i1);
    return htmlForm.substring(i1, i2);
  }

  private class HostnameVerifierHack implements HostnameVerifier {
    public boolean verify(String arg0, String arg1) {
      return true;
    }
  }
  private HttpsURLConnection giveConnection(String targetURL, String requestMethod) throws Exception {
    URL url = new URL(targetURL);
    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    conn.setRequestMethod(requestMethod);
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.setUseCaches(false);
    conn.setAllowUserInteraction(false);
    conn.setHostnameVerifier(new HostnameVerifierHack());
    return conn;
  }

}