package test.abnahme.A;

import java.io.OutputStream;
import java.net.URL;
import java.security.Security;
import java.util.Calendar;
import java.util.Vector;

import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;

import org.apache.axis.message.SOAPBodyElement;
import org.w3c.dom.Element;

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

import test.abnahme.AbnahmeTestCase;

import at.gv.egovernment.moa.id.proxy.builder.SAMLRequestBuilder;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.DateTimeUtils;
import at.gv.egovernment.moa.util.StreamUtils;
import at.gv.egovernment.moa.util.URLDecoder;
import at.gv.egovernment.moa.util.URLEncoder;

/**
 * @author Stefan Knirsch
 * @version $Id$
 */

public class Test600GetAuthenticationDataService extends AbnahmeTestCase {

  private String moaSessionID;
  private String samlArtifact;
  private static final QName SERVICE_QNAME = new QName("SignatureCreation");
   
  public Test600GetAuthenticationDataService(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 testA601() throws Exception {
    try {

      // Anmelden
      String URL = getURL("https://localhost:8443/moa-id-auth/", "gb", "https://localhost:9443/");
      HttpsURLConnection conn = giveConnection(URL, "GET");
      conn.connect();
      String result = new String(StreamUtils.readStream(conn.getInputStream()));
      String MOASessionID = parseSessionIDFromForm(result);
      conn.disconnect();
      
      URL = parseDataURL(result);
      // Verify Identity Link
      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");
      conn.disconnect();
      //Verify Auth Block
      conn = giveConnection(redirectLoc, "POST");
      String createXMLSignatureResponse = URLEncoder.encode(readXmldata("CreateXMLSignatureResponse.xml"), "UTF-8");
      out = conn.getOutputStream();
      out.write(("MOASessionID=" + moaSessionID + "&XMLResponse=" + createXMLSignatureResponse).getBytes("UTF-8"));
      out.flush();
      out.close();
      conn.connect();
      redirectLoc = conn.getHeaderField("Location");
      samlArtifact = parseSamlArtifact(redirectLoc);
      System.out.println("SamlArtifact: " + samlArtifact);
      conn.disconnect();
      
      assertTrue(redirectLoc.startsWith("https://localhost:9443/?Target=gb&SAMLArtifact="));

      conn = null;
  
  SAMLRequestBuilder srb = new SAMLRequestBuilder();
  
  Element erg = doCall(srb.build(moaSessionID,URLDecoder.decode(samlArtifact, "UTF-8")));
  result = DOMUtils.serializeNode(erg);
  result = killInclusive(result,"IssueInstant=\"","\"","");
  result = killInclusive(result,"AssertionID=\"","\"","");
  result = killInclusive(result,"ResponseID=\"","\"","");

//  writeXmldata("GetAuthenticationDataWebServiceResponse.xml", result.getBytes("UTF-8"));
  
  assertEquals(result,readXmldata("GetAuthenticationDataWebServiceResponse.xml"));

  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 testA651() throws Exception {
    try {

      // Anmelden
      String URL = getURL("https://localhost:8443/moa-id-auth/", "gb", "https://localhost:9443/");
      HttpsURLConnection conn = giveConnection(URL, "GET");
      conn.connect();
      String result = new String(StreamUtils.readStream(conn.getInputStream()));
      String MOASessionID = parseSessionIDFromForm(result);
      conn.disconnect();
      
      URL = parseDataURL(result);
      // Verify Identity Link
      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");
      conn.disconnect();
      //Verify Auth Block
      conn = giveConnection(redirectLoc, "POST");
      String createXMLSignatureResponse = URLEncoder.encode(readXmldata("CreateXMLSignatureResponse.xml"), "UTF-8");
      out = conn.getOutputStream();
      out.write(("MOASessionID=" + moaSessionID + "&XMLResponse=" + createXMLSignatureResponse).getBytes("UTF-8"));
      out.flush();
      out.close();
      conn.connect();
      redirectLoc = conn.getHeaderField("Location");
      samlArtifact = "AAGu1JFbyGKqJ+3NAonwMu5bNyUc7kooeMK6bxeXBbnK6NL0DfuVJsGi";
      System.out.println("SamlArtifact: " + samlArtifact);
      conn.disconnect();
      
      assertTrue(redirectLoc.startsWith("https://localhost:9443/?Target=gb&SAMLArtifact="));

      conn = null;
  
      SAMLRequestBuilder srb = new SAMLRequestBuilder();
      Element samlPRequest = srb.build(moaSessionID,samlArtifact);
    
      assertTrue(DOMUtils.serializeNode(doCall(samlPRequest)).indexOf("unbekanntes SAML-Artifakt")!=-1);

      System.out.println("-----------------------\nFehler in " + this.getName() + " erfolgreich abgefangen: Fehler beim Abholen der Anmeldedaten, unbekanntes SAML-Artifakt\n-----------------------");
    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN " + this.getName() + ":" + e.getLocalizedMessage());
      throw e;
    }
   }
   
 public void testA652() throws Exception {
    try {

      // Anmelden
      String URL = getURL("https://localhost:8443/moa-id-auth/", "gb", "https://localhost:9443/");
      HttpsURLConnection conn = giveConnection(URL, "GET");
      conn.connect();
      String result = new String(StreamUtils.readStream(conn.getInputStream()));
      String MOASessionID = parseSessionIDFromForm(result);
      conn.disconnect();
      
      URL = parseDataURL(result);
      // Verify Identity Link
      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");
      conn.disconnect();
      //Verify Auth Block
      conn = giveConnection(redirectLoc, "POST");
      String createXMLSignatureResponse = URLEncoder.encode(readXmldata("CreateXMLSignatureResponse.xml"), "UTF-8");
      out = conn.getOutputStream();
      out.write(("MOASessionID=" + moaSessionID + "&XMLResponse=" + createXMLSignatureResponse).getBytes("UTF-8"));
      out.flush();
      out.close();
      conn.connect();
      redirectLoc = conn.getHeaderField("Location");
      samlArtifact = parseSamlArtifact(redirectLoc);
      System.out.println("SamlArtifact: " + samlArtifact);
      conn.disconnect();
      
      assertTrue(redirectLoc.startsWith("https://localhost:9443/?Target=gb&SAMLArtifact="));

      conn = null;
      String request =       
      "<samlp:Request xmlns:samlp=\"urn:oasis:names:tc:SAML:1.0:protocol\" RequestID=\"" +
      moaSessionID + "\" MajorVersion=\"1\" MinorVersion=\"0\" IssueInstant=\"" +
      DateTimeUtils.buildDateTime(Calendar.getInstance())+"\">" +
      "</samlp:Request>";
      
      Element samlPRequest = DOMUtils.parseDocument(request, false, ALL_SCHEMA_LOCATIONS, null).getDocumentElement();

      assertTrue(DOMUtils.serializeNode(doCall(samlPRequest)).indexOf("Fehlerhaftes Requestformat")!=-1);
//  writeXmldata("GetAuthenticationDataWebServiceResponse.xml", result.getBytes("UTF-8"));
      System.out.println("-----------------------\nFehler in " + this.getName() + " erfolgreich abgefangen: Fehlerhaftes Requestformat\n-----------------------");    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN " + this.getName() + ":" + e.getLocalizedMessage());
      throw e;
    }
   }

  protected Element doCall(Element request)
    throws Exception {
    QName serviceName = new QName("GetAuthenticationData");
    String endPoint = "http://localhost:8080/moa-id-auth/services/GetAuthenticationData";
    Service service = ServiceFactory.newInstance().createService(serviceName);
    Call call = service.createCall();
    SOAPBodyElement body =
      new SOAPBodyElement(request);
    SOAPBodyElement[] params = new SOAPBodyElement[] {body};
    Vector responses;
    SOAPBodyElement response;
    
    call.setTargetEndpointAddress(endPoint);
    responses = (Vector) call.invoke(params);
    response = (SOAPBodyElement) responses.get(0);

    return response.getAsDOM();
  }

  private String parseDataURL(String input)
  {   
    return getSubString(input.substring(input.indexOf("DataURL"),input.length()),"value=\"","\"");        
  }
  private String parseSamlArtifact(String input)
  {
   return  getSubString(input+"@@@","SAMLArtifact=","@@@");
  }
  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 HttpsURLConnection giveConnection(String targetURL, String requestMethod) throws Exception {
    HttpsURLConnection conn = (HttpsURLConnection) new URL(targetURL).openConnection();
    conn.setRequestMethod(requestMethod);
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.setUseCaches(false);
    conn.setAllowUserInteraction(false);
    conn.setHostnameVerifier(new HostnameVerifierHack());
    return conn;
  }
 private class HostnameVerifierHack implements HostnameVerifier {
    public boolean verify(String arg0, String arg1) {
      return true;
    }
  }
}