/*
 * The contents of this file are subject to the Mozilla Public 
 * License Version 1.1 (the "License"); you may not use this 
 * file except in compliance with the License. You may obtain 
 * a copy of the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an 
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express 
 * or implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 *
 * The Original Code is OIOSAML Java Service Provider.
 * 
 * The Initial Developer of the Original Code is Trifork A/S. Portions 
 * created by Trifork A/S are Copyright (C) 2008 Danish National IT 
 * and Telecom Agency (http://www.itst.dk). All Rights Reserved.
 * 
 * Contributor(s):
 *   Joakim Recht <jre@trifork.com>
 *   Rolf Njor Jensen <rolf@trifork.com>
 *
 */
package dk.itst.oiosaml.sp.model;

import java.security.PublicKey;
import java.util.List;

import org.opensaml.common.SAMLObject;
import org.opensaml.common.binding.BasicSAMLMessageContext;
import org.opensaml.common.binding.SAMLMessageContext;
import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
import org.opensaml.saml2.core.RequestAbstractType;
import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.validation.ValidationException;

/**
 * Base class for all SAML requests.
 * 
 * @author Joakim Recht <jre@trifork.com>
 *
 */
public abstract class OIORequest extends OIOSamlObject {

	private final RequestAbstractType request;

	public OIORequest(RequestAbstractType request) {
		super(request);
		this.request = request;
	}
	
	
	/**
	 * 
	 * @param destination The expected destination
	 * @return <code>true</code>, if the destination is match the destination in the &lt;SAMLRequest&gt; - otherwise <code>false</code>. 
	 * If there is no destination, <code>true</code> is returned.
	 */
	public boolean isDestinationOK(String destination) {
		if (request.getDestination() == null) return true;
		
		return request.getDestination() != null && request.getDestination().equals(destination);
	}
	
	/**
	 * @return true, if the issuer of the SAML Request match the expected
	 */
	public boolean isIssuerOK(String issuer) {
		return request.getIssuer() != null
				&& request.getIssuer().getValue() != null
				&& request.getIssuer().getValue().equals(
						issuer);
	}

	
	protected final void validateRequest(String expectedIssuer, String expectedDestination, PublicKey publicKey, List<String> errors) {
		try {
			request.validate(true);
		} catch (ValidationException e) {
			errors.add(e.getMessage());
		}
		if (!isDestinationOK(expectedDestination)) {
			errors.add("Wrong destination. Expected " + expectedDestination + " but was " + request.getDestination());
		}
		if (!isIssuerOK(expectedIssuer)) {
			errors.add("Wring issuer. Expected " + expectedIssuer + " but was " + request.getIssuer());
		}
		if (hasSignature()) {
			if (!verifySignature(publicKey)) {
				errors.add("Invalid signature in SAMLObject");
			}
		}
	}
	
	/**
	 * Get the request ID.
	 */
	public String getID() {
		return request.getID();
	}

	/**
	 * Get the request issuer.
	 * @return The issuer value or <code>null</code> if there is no issuer.
	 */
	public String getIssuer() {
		return request.getIssuer() != null ? request.getIssuer().getValue() : null;
	}
	
	protected class Encoder extends HTTPRedirectDeflateEncoder {
		public String buildRedirectURL(Credential signingCredential) throws MessageEncodingException {
			SAMLMessageContext<?, RequestAbstractType, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, RequestAbstractType, SAMLObject>();
			// Build the parameters for the request
			messageContext.setOutboundSAMLMessage(request);
			messageContext.setRelayState(request.getID());

			// Sign the parameters
			messageContext.setOutboundSAMLMessageSigningCredential(signingCredential);

			return super.buildRedirectURL(messageContext, request.getDestination(), deflateAndBase64Encode(request));
		}
	}

	public String getDestination() {
		return request.getDestination();
	}

}

@@ -914,49 +914,189 @@
 ava.
-security.PublicKey;%0Aimport java.util.List
+io.ByteArrayOutputStream;%0Aimport java.io.IOException;%0Aimport java.security.PublicKey;%0Aimport java.util.List;%0Aimport java.util.zip.Deflater;%0Aimport java.util.zip.DeflaterOutputStream
 ;%0A%0Ai
@@ -1492,16 +1492,93 @@
 ential;%0A
+import org.opensaml.xml.util.Base64;%0Aimport org.opensaml.xml.util.XMLHelper;%0A
 import o
@@ -4192,16 +4192,640 @@
 tial);%0A%0A
+            String messageStr = XMLHelper.nodeToString(marshallMessage(request));%0A%0A            ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();%0A            Deflater deflater = new Deflater(Deflater.DEFLATED, true);%0A            DeflaterOutputStream deflaterStream = new DeflaterOutputStream(bytesOut, deflater);%0A            try %7B%0A%09%09%09%09deflaterStream.write(messageStr.getBytes(%22UTF-8%22));%0A%09%09%09%09deflaterStream.finish();%0A%09%09%09%7D catch (IOException e) %7B%0A%09%09%09%09throw new RuntimeException(%22Unable to deflate message%22, e);%0A%09%09%09%7D%0A%0A            String encoded = Base64.encodeBytes(bytesOut.toByteArray(), Base64.DONT_BREAK_LINES);%0A
 %09%09%09retur
@@ -4895,39 +4895,15 @@
 (), 
-deflateAndBase64Encode(request)
+encoded
 );%0A%09

fix bug in SLO if nameid contains foreign characters