diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..7cd1553ad632602845af431176c1b841c00e3226
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,22 @@
+simpleSAMLphp is based on code from Sun OpenSSO Extensions (formerly known as Lightbulb).
+The initial versions of the SAML 2.0 part was written by Pat Patterson, Sun.
+
+The functionality have been extended and Andreas Ă…kre Solberg, UNINETT, has rewritten the
+library and added support for Shibboleth IdP/SP, and SAML 2.0 IdP. The product is used to 
+bridge AAI protocols in the GÉANT project, http://geant2.net
+
+----
+simpleSAMLphp is subject to the terms
+of the Common Development and Distribution License
+(the License). You may not use this file except in
+compliance with the License.
+
+You can obtain a copy of the License at
+https://opensso.dev.java.net/public/CDDLv1.0.html or
+opensso/legal/CDDLv1.0.txt
+See the License for the specific language governing
+permission and limitations under the License.
+
+When distributing Covered Code, include this CDDL
+Header Notice in each file and include the License file
+at opensso/legal/CDDLv1.0.txt.
diff --git a/cert/server.crt b/cert/server.crt
new file mode 100755
index 0000000000000000000000000000000000000000..b4147e516abfa3e611c86e5594af25bc9a38b727
--- /dev/null
+++ b/cert/server.crt
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMC
+Tk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYD
+VQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG
+9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4
+MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xi
+ZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2Zl
+aWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5v
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LO
+NoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHIS
+KOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d
+1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8
+BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7n
+bK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2Qar
+Q4/67OZfHd7R+POBXhophSMv1ZOo
+-----END CERTIFICATE-----
diff --git a/cert/server.pem b/cert/server.pem
new file mode 100755
index 0000000000000000000000000000000000000000..673196b177454e79a4c1668cf51201afb995da57
--- /dev/null
+++ b/cert/server.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9
+IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+
+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQAB
+AoGAD4/Z4LWVWV6D1qMIp1Gzr0ZmdWTE1SPdZ7Ej8glGnCzPdguCPuzbhGXmIg0V
+J5D+02wsqws1zd48JSMXXM8zkYZVwQYIPUsNn5FetQpwxDIMPmhHg+QNBgwOnk8J
+K2sIjjLPL7qY7Itv7LT7Gvm5qSOkZ33RCgXcgz+okEIQMYkCQQDzbTOyDL0c5WQV
+6A2k06T/azdhUdGXF9C0+WkWSfNaovmTgRXh1G+jMlr82Snz4p4/STt7P/XtyWzF
+3pkVgZr3AkEA7nPjXwHlttNEMo6AtxHd47nizK2NUN803ElIUT8P9KSCoERmSXq6
+6PDekGNic4ldpsSvOeYCk8MAYoDBy9kvVwJBAMLgX4xg6lzhv7hR5+pWjTb1rIY6
+rCHbrPfU264+UZXz9v2BT/VUznLF81WMvStD9xAPHpFS6R0OLghSZhdzhI0CQQDL
+8Duvfxzrn4b9QlmduV8wLERoT6rEVxKLsPVz316TGrxJvBZLk/cV0SRZE1cZf4uk
+XSWMfEcJ/0Zt+LdG1CqjAkEAqwLSglJ9Dy3HpgMz4vAAyZWzAxvyA1zW0no9GOLc
+PQnYaNUN/Fy2SYtETXTb0CQ9X1rt8ffkFP7ya+5TC83aMg==
+-----END RSA PRIVATE KEY-----
diff --git a/config/config-template.php b/config/config-template.php
new file mode 100644
index 0000000000000000000000000000000000000000..49833941a77ba83b978b2d88581f9b9ae5863d1d
--- /dev/null
+++ b/config/config-template.php
@@ -0,0 +1,48 @@
+<?php
+/* 
+ * The configuration of simpleSAMLphp
+ * 
+ * 
+ */
+
+$config = array (
+
+	/*
+	 * Setup the following parameters to match the directory of your installation.
+	 * See the user manual for more details.
+	 */
+	'basedir' 				=> '/var/www/simplesamlphp/',
+	'baseurlpath'			=> 'simplesamlphp/',
+	'templatedir'			=> '/var/www/simplesamlphp/templates',
+	'metadatadir'			=> '/var/www/simplesamlphp/metadata',
+	
+	/*
+	 * If you set the debug parameter to true, all SAML messages will be visible in the
+	 * browser, and require the user to click the submit button. If debug is set to false,
+	 * Browser/POST SAML messages will be automaticly submitted.
+	 */
+	'debug'					=>	false,
+	
+	/* 
+	 * This value is the duration of the session in seconds. Make sure that the time duration of
+	 * cookies both at the SP and the IdP exceeds this duration.
+	 */
+	'session.duration'		=>  8 * (60*60), // 8 hours.
+	
+	/*
+	 * Default IdPs. If you do not enter an idpentityid in the SSO initialization endpoints,
+	 * the default IdP configured here will be used.
+	 */
+	'default-saml20-idp'	=> 'sam.feide.no',
+	'default-shib13-idp'	=> 'urn:mace:switch.ch:aaitest:dukono.switch.ch',
+	
+	/*
+	 * LDAP configuration. This is only relevant if you use the LDAP authentication plugin.
+	 */
+	'auth.ldap.dnpattern'	=> 'uid=%username%,dc=feide,dc=no,ou=feide,dc=uninett,dc=no',
+	'auth.ldap.hostname'	=> 'ldap.uninett.no',
+	'auth.ldap.attributes'	=> 'objectclass=*'
+);
+
+
+?>
\ No newline at end of file
diff --git a/docs/README b/docs/README
new file mode 100644
index 0000000000000000000000000000000000000000..5c950331844e82e6e13487c2002df04b1cd28d03
--- /dev/null
+++ b/docs/README
@@ -0,0 +1,29 @@
+README
+
+
+Installation instructions:
+==========================
+
+Store the simplesamlphp directory somewhere...
+
+In there there is a www directory, it have to be accessible from web, on the root of a vhost. The www can be moved outside the simplesamlphp folder. You can in example drop the content of the www folder into your existing web site folder.
+
+IF you decide to move the www folder out of the simplesamlphp folder, then you need to update the www/_include.php file properly.
+
+Next, configure config.php:
+- set the path and hostnames.
+- Use sam.feide.no as default idp.
+- Set the default duration of a session to be in example 3 hours.
+
+
+Then, configure saml20-sp-hosted to match your SP metadata. Change dev.andreas.feide.no to your hostname. Contact feide to ensure that your meta data is added to the Feide IdP.
+
+Then configure the saml20-idp-remote to match Feide. If there exists an entry for sam.feide.no it is probably already there.
+
+Then test the /example-simple/saml2-example.php log in with the feide test user, and look at the attributes. then test sp initated logout.
+
+Look at the example code of how to integrate with a service.
+
+Contact Andreas for questions:
+andreas@uninett.no
+
diff --git a/docs/simplesamlphp-install.html b/docs/simplesamlphp-install.html
new file mode 100644
index 0000000000000000000000000000000000000000..3c13eb2c8a00d42a9ad1f2f0f55b39ce8d3bd2c5
--- /dev/null
+++ b/docs/simplesamlphp-install.html
@@ -0,0 +1,182 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>simpleSAMLphp Installation and Configuration</title><link rel="stylesheet" href="html.css" type="text/css" /><meta name="generator" content="DocBook XSL Stylesheets V1.69.1" /></head><body><div class="article" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a id="id721994"></a>simpleSAMLphp Installation and Configuration</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Andreas Ă…kre</span> <span class="surname">Solberg</span></h3><code class="email">&lt;<a href="mailto:andreas.solberg@uninett.no">andreas.solberg@uninett.no</a>&gt;</code></div></div><div><p class="pubdate">Fri Sep 14 10:49:49 2007</p></div></div><hr /></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id856632">The history of simpleSAMLphp</a></span></dt><dt><span class="section"><a href="#id856682">Changelog</a></span></dt><dd><dl><dt><span class="section"><a href="#id856693">Version 0.4</a></span></dt></dl></dd><dt><span class="section"><a href="#id856807">Download and get simpleSAMLphp</a></span></dt><dd><dl><dt><span class="section"><a href="#id856826">Getting a working copy of simpleSAMLphp from subversion</a></span></dt></dl></dd><dt><span class="section"><a href="#id856866">Installing simpleSAMLphp</a></span></dt><dd><dl><dt><span class="section"><a href="#id856941">The simpleSAMLphp installation webpage</a></span></dt></dl></dd><dt><span class="section"><a href="#id856967">Making configuration and metadata files</a></span></dt><dt><span class="section"><a href="#sect.config">Configuring simpleSAMLphp</a></span></dt><dd><dl><dt><span class="section"><a href="#id857037">Configuration for LDAP authentication plugin</a></span></dt></dl></dd><dt><span class="section"><a href="#id857095">Setting up a SAML 2.0 SP</a></span></dt><dd><dl><dt><span class="section"><a href="#id857107">Configuring metadata for a SAML 2.0 SP</a></span></dt><dt><span class="section"><a href="#id857190">Test the SAML 2.0 SP example</a></span></dt></dl></dd><dt><span class="section"><a href="#id857224">Setting up a Shibboleth 1.3 SP</a></span></dt><dd><dl><dt><span class="section"><a href="#id857235">Configuring metadata for Shibboleth 1.3 SP</a></span></dt><dt><span class="section"><a href="#id857296">Test the Shibboleth 1.3 SP example</a></span></dt></dl></dd><dt><span class="section"><a href="#id857331">Setting up a SAML 2.0 IdP</a></span></dt><dd><dl><dt><span class="section"><a href="#id857342">Configuring the SAML 2.0 IdP</a></span></dt><dt><span class="section"><a href="#id857376">Adding a SAML IdP signing certificate</a></span></dt><dt><span class="section"><a href="#id857440">Test SAML 2.0 IdP</a></span></dt></dl></dd><dt><span class="section"><a href="#id857453">Using the built-in SP WAYF functionality</a></span></dt><dt><span class="section"><a href="#id857466">Setting up WebSSO bridges</a></span></dt><dd><dl><dt><span class="section"><a href="#id857477">Bridging SAML 2.0 &lt;-&gt; SAML 2.0</a></span></dt><dt><span class="section"><a href="#id857522">Bridging Shibboleth 1.3 &lt;-&gt; Shibboleth 1.3</a></span></dt><dt><span class="section"><a href="#id857533">Bridging Shibboleth 1.3 &lt;-&gt; SAML 2.0</a></span></dt><dt><span class="section"><a href="#id857544">Bridging SAML 2.0 &lt;-&gt; Shibboleth 1.3</a></span></dt><dt><span class="section"><a href="#id857554">Bridging SAML 2.0 &lt;-&gt; OpenID</a></span></dt><dt><span class="section"><a href="#id857564">Bridging Shibboelth 1.3 &lt;-&gt; OpenID</a></span></dt></dl></dd><dt><span class="section"><a href="#id857576">Authentication API</a></span></dt></dl></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id856632"></a>The history of simpleSAMLphp</h2></div></div></div><p>simpleSAMLphp is based on code from <a href="https://opensso.dev.java.net/public/extensions/" target="_top">Sun OpenSSO
+    Extensions</a> (formerly known as Lightbulb).</p><p>The initial versions of the SAML 2.0 SP part was written by <a href="http://blogs.sun.com/superpat/" target="_top">Pat Patterson, Sun</a>.</p><p>The functionality has been extended and <a href="http://claimid.com/erlang" target="_top">Andreas Ă…kre Solberg</a>, <a href="http://uninett.no" target="_top">UNINETT</a>, has rewritten the library and
+    added support for Shibboleth. The product is used to bridge AAI protocols
+    in the GÉANT project, <a href="http://geant2.net" target="_top">http://geant2.net</a>.</p></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id856682"></a>Changelog</h2></div></div></div><p>Here is changes between simpleSAML versions. Look here if you are
+    upgrading, to see if there are any changes to the config format.</p><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id856693"></a>Version 0.4</h3></div></div></div><p>Released 2007-09-14. Revision X.</p><div class="itemizedlist"><ul type="disc"><li><p>Improved documentation</p></li><li><p>Authentication plugin API. Only LDAP authenticaiton plugin is
+          included, but it is now easier to implement your own plugin.</p></li><li><p>Added support for SAML 2.0 IdP to work with Google Apps for
+          Education. Tested.</p></li><li><p>Initial implementation of SAML 2.0 Single Log-Out
+          functionality both for SP and IdP. Seems to work, but not yet
+          well-tested.</p></li><li><p>Added support for bridging SAML 2.0 to SAML 2.0.</p></li><li><p>Added some time skew offset to the NotBefore timestamp on the
+          assertion, to allow some time skew between the SP and IdP.</p></li><li><p>Fixed Browser/POST page to automaticly submit, and have fall
+          back functionality for user agents with no javascript
+          support.</p></li><li><p>Fixed some bug with warning traversing Shibboleth 1.3
+          Assertions.</p></li><li><p>Fixed tabindex on the login page of the LDAP authentication
+          module to allow you to tab from username, to password and then to
+          submit.</p></li><li><p>Fixed bug on autodiscovering hostname in multihost
+          environments.</p></li><li><p>Cleaned out some debug messages, and added a debug option in
+          the configuration file. This debug option let's you turn on the
+          possibility of showing all SAML messages to users in the web
+          browser, and manually submit them.</p></li><li><p>Several minor bugfixes.</p></li></ul></div></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id856807"></a>Download and get simpleSAMLphp</h2></div></div></div><p>You can go to <a href="http://rnd.feide.no/category/simplesamlphp/" target="_top">http://rnd.feide.no/category/simplesamlphp/</a>
+    to find the most recent release of simpleSAMLphp. Download the zipped
+    file, and unzip it on your webserver. However I hightly reccomend running
+    from a subversion checkout instead.</p><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id856826"></a>Getting a working copy of simpleSAMLphp from subversion</h3></div></div></div><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Warning</h3><p>Right now the subversion repository is requiring a username /
+        password. I'll update the access control, so that everyone can get
+        read access without authentication. I'll announce it on the rnd blog
+        when it is ready.</p></div><p>If you want a working copy from subversion enter:</p><pre class="screen">svn co https://svn.uninett.no/svn/feidernd/simplesamlphp</pre><p>If you know subversion you know how to view logs and review
+      changes to the files. To update the version you have checked out,
+      enter:</p><pre class="screen">cd simplesamlphp
+svn up</pre></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id856866"></a>Installing simpleSAMLphp</h2></div></div></div><p>First find an appropriate place for the <code class="filename">simplesamlphp
+    </code>folder. In example
+    <code class="filename">/var/simplesamlphp</code>.</p><p>Of the folders inside simplesamlphp, only the www folder needs to be
+    accessible from the web. There are several ways of putting the
+    simpleSAMLphp depending on the way web sites are structured on your apache
+    web server. Here is what I believe is the best configuration.</p><p>Find the apache configuration file for the virtual hosts that you
+    want to run simpleSAML on. The configuration may look like this:</p><pre class="programlisting">&lt;VirtualHost  *&gt;
+        ServerName service.example.com
+        DocumentRoot /var/www/service.example.com
+
+        Alias /simplesamlphp /var/simplesamlphp/www
+&lt;/VirtualHost&gt;
+</pre><p>What is special is tha Alias directive. That directive will give
+    control to simplesamlphp to all urls that matches
+    <code class="literal">http(s)://service.example.com/simplesamlphp/*</code>.
+    SimpleSAML will need to have several SAML interfaces available on the web,
+    and all these interfaces are included in the www subdirectory of your
+    simplesamlphp installation. You can set the alias to whatever you want,
+    but this alias must be set in the config.php file of simpleSAML as
+    described in <a href="#sect.config" title="Configuring simpleSAMLphp">the section called “Configuring simpleSAMLphp”</a>. Here is an example of how
+    this configuration may look like in config.php:</p><pre class="programlisting">$config = array (
+	'basedir' 				=&gt; '/var/simplesamlphp/',
+	'baseurl'				=&gt; 'http://service.example.com',
+	'baseurlpath'			=&gt; 'simplesamlphp/',</pre><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id856941"></a>The simpleSAMLphp installation webpage</h3></div></div></div><p>When you have installed simpleSAMLphp, you can access the homepage
+      of your installation, which contains some information and a few links to
+      the test services. The url of an installation can be in example:</p><div class="literallayout"><p>https://service.example.com/simplesamlphp/</p></div><p>But it depends on how you set it up with apache.</p></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id856967"></a>Making configuration and metadata files</h2></div></div></div><p>Configuration and metadata files are stored in a template format,
+    you need to copy them to have your local copies. The reason why it is done
+    this way, is that when you upgrade you can do svn up in subversion or just
+    copy the whole directory over your installation, without replacing your
+    existing configuration. When you are updating, you should investigate
+    whether the config format is changed, this should be documented in the
+    changelog.</p><p>Here are the steps you need to do to create local configuration
+    files:</p><pre class="screen">cd /var/simplesamlphp
+cp config/config-template.php config/config.php
+cp -r metadata-templates/*.php metadata/
+</pre></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="sect.config"></a>Configuring simpleSAMLphp</h2></div></div></div><p>First configure all the paths in the beginning of the config file,
+    to correspond to your organization of the apache web server, and where you
+    place simpleSAMLphp.</p><p>You will need to set the entityid of a default IdP in
+    <code class="literal">default-saml20-idp</code> or
+    <code class="literal">default-shib13-idp</code> depending on whether you use
+    shibboleth or SAML 2.0.</p><p>There is one parameter debug that may be set to true or false. If
+    you set it to true, then all Browser/POST SAML messages will be printed to
+    the web browser, and the user will have to manually submit it. </p><p>The session.duration parameter says how many seconds that a session
+    should be valid. After this amont of time, the session is not valid
+    anymore.</p><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857037"></a>Configuration for LDAP authentication plugin</h3></div></div></div><p>If you want to perform local authentication on this server, and
+      you want to use the LDAP authenticaiton plugin, then you need to
+      configure the following parameters:</p><div class="itemizedlist"><ul type="disc"><li><p><code class="literal">auth.ldap.dnpattern</code>: What DN should you
+          bind to? Replacing %username% with the username the user types
+          in.</p></li><li><p><code class="literal">auth.ldap.hostname</code>: The hostname of the
+          LDAP server</p></li><li><p><code class="literal">auth.ldap.attributes</code>: Search parameter to
+          LDAP. What attributes should be extracted?
+          <code class="literal">objectclass=*</code> gives you all.</p></li></ul></div></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id857095"></a>Setting up a SAML 2.0 SP</h2></div></div></div><p>This functionality is relevant if you want to integrate SAML 2.0
+    authentication on a service of yours, and you know one or more IdPs that
+    you can connect to. You would need metadata for those IdPs.</p><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857107"></a>Configuring metadata for a SAML 2.0 SP</h3></div></div></div><p>To configure a SAML 2.0 SP, you first need to configure the SP
+      data for all your vhosts. If you run only one host, you need only one
+      entry. This metadata is stored in the
+      <code class="filename">metadata/saml20-sp-hosted.php</code> file. Here is an
+      example of a metadata:</p><pre class="programlisting">	"dev.andreas.feide.no" =&gt; array(
+		'host'							=&gt;	'dev.andreas.feide.no',
+ 		"assertionConsumerServiceURL"	=&gt;	"http://dev.andreas.feide.no/saml2/sp/AssertionConsumerService.php", 
+		"issuer"						=&gt;	"dev.andreas.feide.no",
+		"spNameQualifier" 				=&gt;	"dev.andreas.feide.no",
+		"ForceAuthn"					=&gt;	"false",
+		"NameIDFormat"					=&gt;	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+	),</pre><p>Note that you should fill in the host field matching the hostname
+      of your vhost. That way simpleSAMLphp can automatically detect what SP
+      metadata to use based on the <code class="literal">Host:</code> header sent by the
+      HTTP user agent.</p><p>You also need to configure the metadata for the IdP that you want
+      to use. Here is a metadata example for the Feide IdP:</p><pre class="programlisting">	"sam.feide.no" =&gt;  array( 
+			"SingleSignOnUrl"	=&gt;	"https://sam.feide.no/amserver/SSORedirect/metaAlias/idp",
+		 	"SingleLogOutUrl"	=&gt;	"https://sam.feide.no/amserver/IDPSloRedirect/metaAlias/idp",
+		 	"certFingerprint"	=&gt;	"3a:e7:d3:d3:06:ba:57:fd:7f:62:6a:4b:a8:64:b3:4a:53:d9:5d:d0",
+		 	"base64attributes"	=&gt;	true),</pre><p>The IdP metadata is stored in the
+      <code class="filename">metadata/saml20-idp-remote.php</code> file. Configure the
+      correct URLs of the endpoints, the hash of the certificate, and whether
+      the IdP is base64 encoding attributes or not. Most IdPs don't use
+      base64, so if you do not connect to Feide you should turn this parameter
+      to <code class="literal">false</code>. Notice that the key of the array is the
+      entity id of the IdP, in this example:
+      <code class="literal">sam.feide.no</code>.</p></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857190"></a>Test the SAML 2.0 SP example</h3></div></div></div><p>Go to the URL of the test page, similar to:</p><div class="literallayout"><p>http://service.example.com/simplesamlphp/example-simple/saml2-example.php</p></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The simpleSAMLphp installation homepage will link you to this
+        example, so you do not need to type in the full url.</p></div><p>You should be redirected to the IdP. Login, and you should be sent
+      back and shown all the attributes sent form the IdP.</p></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id857224"></a>Setting up a Shibboleth 1.3 SP</h2></div></div></div><p>If you want to configure a service with authentication towards an
+    external Shibboleth 1.3 IdP, this section describes you how to proceed.
+    </p><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857235"></a>Configuring metadata for Shibboleth 1.3 SP</h3></div></div></div><p>Configure Shibboleth 1.3 SP metadata for all your vhosts. If you
+      run only one host, you need only one entry. This metadata is stored in
+      the <code class="filename">metadata/shib13-sp-hosted.php</code> file. Here is an
+      example:</p><pre class="programlisting">	'http://dev.andreas.feide.no'	=&gt; array(
+		'AssertionConsumerService'	=&gt;	'http://dev.andreas.feide.no/shib13/sp/AssertionConsumerService.php',
+		'host'						=&gt;	'dev.andreas.feide.no'
+	),</pre><p>Note that you should fill in the host field matching the hostname
+      of your vhost. That way simpleSAMLphp can automatically detect what SP
+      metadata to use based on the <code class="literal">Host:</code> header sent by the
+      HTTP user agent.</p><p>You also need to configure the metadata for the Shibboleth 1.3
+      IdPs that you want to connect to. Here is an example:</p><pre class="programlisting">	'urn:mace:switch.ch:aaitest:dukono.switch.ch'	=&gt; array(
+		'SingleSignOnUrl'		=&gt;	'https://dukono.switch.ch/shibboleth-idp/SSO',
+		'certFingerprint'		=&gt;	'c7279a9f28f11380509e075441e3dc55fb9ab864' 
+	),</pre><p>Notice that the key of the array is the entity ID.</p></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857296"></a>Test the Shibboleth 1.3 SP example</h3></div></div></div><p>Go to the URL of the shibboleth test page, similar to:</p><div class="literallayout"><p>http://service.example.com/example-simple/shib13-example.php</p></div><p>You should be redirected to the IdP. Login, and you should be sent
+      back and shown all the attributes sent form the IdP.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>simpleSAMLphp does not support the attribute profile that
+        Shibboleth is using by default. To make attributes work, you need to
+        configure the IdP to perform attribute push.</p></div></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id857331"></a>Setting up a SAML 2.0 IdP</h2></div></div></div><p>If you have a user database and want to offer a SAML 2.0 IdP
+    functinoality towards external services, here is how you set it up.</p><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857342"></a>Configuring the SAML 2.0 IdP</h3></div></div></div><p>Setup idp metadata in saml20-idp-hosted. Then for all the SP the
+      IdP shold trust in saml20-sp-remote. Then configure in config.php, ldap
+      DN patterns, ldap host etc. Next add a certificate with openssl.</p><p>Example config.php:</p><pre class="programlisting">	'auth.ldap.dnpattern'	=&gt; 'uid=%username%,dc=feide,dc=no,ou=feide,dc=uninett,dc=no',
+	'auth.ldap.hostname'	=&gt; 'ldap.uninett.no',
+	'auth.ldap.attributes'	=&gt; 'objectclass=*'</pre><p>Example IdP Metadata saml20-idp-hosted:</p><pre class="programlisting">	'dev2.andreas.feide.no' =&gt; array(
+		'host'				=&gt;	'dev2.andreas.feide.no',
+		'SingleSignOnUrl'	=&gt;	"http://dev2.andreas.feide.no/saml2/idp/SSOService.php",
+		'SingleLogOutUrl'	=&gt;	"http://dev2.andreas.feide.no/saml2/idp/LogoutService.php",
+		'privatekey'		=&gt;	'server.pem',
+		'certificate'		=&gt;	'server.crt',
+		'base64attributes'	=&gt;	true,
+		'auth'				=&gt;	'auth/login.php'
+	)</pre><p>The server.pem and server.crt is an example certificate shipped
+      with the package, and be used for demo purposes, but you must generate
+      your own to use in production services.</p><p>You also need to configure metadata for trusted SPs, here is an
+      example:</p><pre class="programlisting">_	"dev.andreas.feide.no" =&gt; array(
+		'host'							=&gt;	'dev.andreas.feide.no',
+ 		"assertionConsumerServiceURL"	=&gt;	"http://dev.andreas.feide.no/saml2/sp/AssertionConsumerService.php", 
+		"issuer"						=&gt;	"dev.andreas.feide.no",
+		"spNameQualifier" 				=&gt;	"dev.andreas.feide.no",
+		"ForceAuthn"					=&gt;	"false",
+		"NameIDFormat"					=&gt;	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+	),</pre></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857376"></a>Adding a SAML IdP signing certificate</h3></div></div></div><p>You should generate a new certificate for your IdP.</p><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Warning</h3><p>There is a certificate that follows this package that you can
+        use for test purposes, but off course NEVER use this in production as
+        the private key is also included in the package and can be downloaded
+        by anyone.</p></div><p>Here is an examples of openssl commands to generate a new key and
+      a selfsigned certificate to use for signing SAML messages:</p><pre class="screen">openssl genrsa -des3 -out server2.key 1024 
+openssl rsa -in server2.key -out server2.pem
+openssl req -new -key server.key -out server2.csr
+openssl x509 -req -days 60 -in server2.csr -signkey server2.key -out server2.crt</pre><p>The certificate above will be valid for 60 days.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>simpleSAMLphp will only work with RSA and not DSA
+        certificates.</p></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857440"></a>Test SAML 2.0 IdP</h3></div></div></div><p>To test the SAML 2.0 IdP, it is best to configure two hosts with
+      simpleSAMLphp, and use the SAML 2.0 SP demo example to test the
+      IdP.</p></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id857453"></a>Using the built-in SP WAYF functionality</h2></div></div></div><p>The WAYF is not yet a part of the simpleSAMLphp release. This
+    functionality will be added soon.</p></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id857466"></a>Setting up WebSSO bridges</h2></div></div></div><p>simpleSAMLphp can be used to bridge between two WebSSO protocols.
+    Here is some short descriptions of how to setup the different bridge
+    configurations.</p><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857477"></a>Bridging SAML 2.0 &lt;-&gt; SAML 2.0</h3></div></div></div><p>In this setup you can bridge between two federations using SAML
+      2.0.</p><p>To approach this, you must configure both saml 2.0 IdP and SP
+      hosted metadata, and in the IdP hosted metadata configure the auth
+      parameter to be the SP initialization endpoint, like this:</p><pre class="screen">		'auth'				=&gt;	'saml2/sp/initSSO.php?idpentityid=sam.feide.no'</pre><p>As you can see you specify the IdP in the remote federation as a
+      parameter to the initalization endpoint.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>This section of the documentation is only a placeholder. There
+        will be more detailed information added later. For now, ask the author
+        if you want more details of such a setup.</p><p>Briding SAML 2.0 SLO is not implemented. Will be improved
+        soon.</p></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857522"></a>Bridging Shibboleth 1.3 &lt;-&gt; Shibboleth 1.3</h3></div></div></div><p>Will be supported soon.</p></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857533"></a>Bridging Shibboleth 1.3 &lt;-&gt; SAML 2.0</h3></div></div></div><p>Will be supported soon.</p></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857544"></a>Bridging SAML 2.0 &lt;-&gt; Shibboleth 1.3</h3></div></div></div><p>Will be supported soon.</p></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857554"></a>Bridging SAML 2.0 &lt;-&gt; OpenID</h3></div></div></div><p>Will be supported soon.</p></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id857564"></a>Bridging Shibboelth 1.3 &lt;-&gt; OpenID</h3></div></div></div><p>Will be supported soon.</p></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id857576"></a>Authentication API</h2></div></div></div><p>The authentication plugin should be placed in the auth directory.
+    </p><p>The following parameters must be accepted in the incomming
+    URL:</p><div class="itemizedlist"><ul type="disc"><li><p><code class="literal">RelayState</code>: This is the URL that the user
+        should be sent back to after authentication within the plugin.</p></li><li><p><code class="literal">RequestID</code>: This is the ID of an incomming
+        request.</p></li></ul></div><p>The initSSO.php takes in addition the following parameters:</p><div class="itemizedlist"><ul type="disc"><li><p><code class="literal">idpentityid</code>: This is the entityid of the IdP
+        to authenticate with. This parameter is optional, if not set the
+        default for this host will be used.</p></li><li><p><code class="literal">spentityid</code>: This is which SP config to use.
+        This parameter is optional, if not set the default for this host will
+        be used.</p></li></ul></div><p>In hosted IdP metadata there is a config parameter auth that will
+    tell simpleSAML which authentication plugin that can be used.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3><p>The authentication API is pretty basic. The easiest way to
+      understand how it works is to look at one of the existing plugins that
+      is located in the auth directory of your installation.</p></div></div></div></body></html>
diff --git a/docs/simplesamlphp-install.pdf b/docs/simplesamlphp-install.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..aecd7d045e1c15b4f8840ed6fb1ff8a9fc2d4b30
Binary files /dev/null and b/docs/simplesamlphp-install.pdf differ
diff --git a/docs/source/simplesamlphp-install.xml b/docs/source/simplesamlphp-install.xml
new file mode 100644
index 0000000000000000000000000000000000000000..69e644b30f221c112ee4136c8d0801ae695aee37
--- /dev/null
+++ b/docs/source/simplesamlphp-install.xml
@@ -0,0 +1,588 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<article>
+  <title>simpleSAMLphp Installation and Configuration</title>
+
+  <articleinfo>
+    <date>2007-08-30</date>
+
+    <pubdate>Fri Sep 14 10:49:49 2007</pubdate>
+
+    <author>
+      <firstname>Andreas Ă…kre</firstname>
+
+      <surname>Solberg</surname>
+
+      <email>andreas.solberg@uninett.no</email>
+    </author>
+  </articleinfo>
+
+  <section>
+    <title>The history of simpleSAMLphp</title>
+
+    <para>simpleSAMLphp is based on code from <ulink
+    url="https://opensso.dev.java.net/public/extensions/">Sun OpenSSO
+    Extensions</ulink> (formerly known as Lightbulb).</para>
+
+    <para>The initial versions of the SAML 2.0 SP part was written by <ulink
+    url="http://blogs.sun.com/superpat/">Pat Patterson, Sun</ulink>.</para>
+
+    <para>The functionality has been extended and <ulink
+    url="http://claimid.com/erlang">Andreas Ă…kre Solberg</ulink>, <ulink
+    url="http://uninett.no">UNINETT</ulink>, has rewritten the library and
+    added support for Shibboleth. The product is used to bridge AAI protocols
+    in the GÉANT project, <ulink
+    url="http://geant2.net">http://geant2.net</ulink>.</para>
+  </section>
+
+  <section>
+    <title>Changelog</title>
+
+    <para>Here is changes between simpleSAML versions. Look here if you are
+    upgrading, to see if there are any changes to the config format.</para>
+
+    <section>
+      <title>Version 0.4</title>
+
+      <para>Released 2007-09-14. Revision X.</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>Improved documentation</para>
+        </listitem>
+
+        <listitem>
+          <para>Authentication plugin API. Only LDAP authenticaiton plugin is
+          included, but it is now easier to implement your own plugin.</para>
+        </listitem>
+
+        <listitem>
+          <para>Added support for SAML 2.0 IdP to work with Google Apps for
+          Education. Tested.</para>
+        </listitem>
+
+        <listitem>
+          <para>Initial implementation of SAML 2.0 Single Log-Out
+          functionality both for SP and IdP. Seems to work, but not yet
+          well-tested.</para>
+        </listitem>
+
+        <listitem>
+          <para>Added support for bridging SAML 2.0 to SAML 2.0.</para>
+        </listitem>
+
+        <listitem>
+          <para>Added some time skew offset to the NotBefore timestamp on the
+          assertion, to allow some time skew between the SP and IdP.</para>
+        </listitem>
+
+        <listitem>
+          <para>Fixed Browser/POST page to automaticly submit, and have fall
+          back functionality for user agents with no javascript
+          support.</para>
+        </listitem>
+
+        <listitem>
+          <para>Fixed some bug with warning traversing Shibboleth 1.3
+          Assertions.</para>
+        </listitem>
+
+        <listitem>
+          <para>Fixed tabindex on the login page of the LDAP authentication
+          module to allow you to tab from username, to password and then to
+          submit.</para>
+        </listitem>
+
+        <listitem>
+          <para>Fixed bug on autodiscovering hostname in multihost
+          environments.</para>
+        </listitem>
+
+        <listitem>
+          <para>Cleaned out some debug messages, and added a debug option in
+          the configuration file. This debug option let's you turn on the
+          possibility of showing all SAML messages to users in the web
+          browser, and manually submit them.</para>
+        </listitem>
+
+        <listitem>
+          <para>Several minor bugfixes.</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+  </section>
+
+  <section>
+    <title>Download and get simpleSAMLphp</title>
+
+    <para>You can go to <ulink
+    url="http://rnd.feide.no/category/simplesamlphp/">http://rnd.feide.no/category/simplesamlphp/</ulink>
+    to find the most recent release of simpleSAMLphp. Download the zipped
+    file, and unzip it on your webserver. However I hightly reccomend running
+    from a subversion checkout instead.</para>
+
+    <section>
+      <title>Getting a working copy of simpleSAMLphp from subversion</title>
+
+      <warning>
+        <para>Right now the subversion repository is requiring a username /
+        password. I'll update the access control, so that everyone can get
+        read access without authentication. I'll announce it on the rnd blog
+        when it is ready.</para>
+      </warning>
+
+      <para>If you want a working copy from subversion enter:</para>
+
+      <screen>svn co https://svn.uninett.no/svn/feidernd/simplesamlphp</screen>
+
+      <para>If you know subversion you know how to view logs and review
+      changes to the files. To update the version you have checked out,
+      enter:</para>
+
+      <screen>cd simplesamlphp
+svn up</screen>
+    </section>
+  </section>
+
+  <section>
+    <title>Installing simpleSAMLphp</title>
+
+    <para>First find an appropriate place for the <filename>simplesamlphp
+    </filename>folder. In example
+    <filename>/var/simplesamlphp</filename>.</para>
+
+    <para>Of the folders inside simplesamlphp, only the www folder needs to be
+    accessible from the web. There are several ways of putting the
+    simpleSAMLphp depending on the way web sites are structured on your apache
+    web server. Here is what I believe is the best configuration.</para>
+
+    <para>Find the apache configuration file for the virtual hosts that you
+    want to run simpleSAML on. The configuration may look like this:</para>
+
+    <programlisting>&lt;VirtualHost  *&gt;
+        ServerName service.example.com
+        DocumentRoot /var/www/service.example.com
+
+        Alias /simplesamlphp /var/simplesamlphp/www
+&lt;/VirtualHost&gt;
+</programlisting>
+
+    <para>What is special is tha Alias directive. That directive will give
+    control to simplesamlphp to all urls that matches
+    <literal>http(s)://service.example.com/simplesamlphp/*</literal>.
+    SimpleSAML will need to have several SAML interfaces available on the web,
+    and all these interfaces are included in the www subdirectory of your
+    simplesamlphp installation. You can set the alias to whatever you want,
+    but this alias must be set in the config.php file of simpleSAML as
+    described in <xref linkend="sect.config" />. Here is an example of how
+    this configuration may look like in config.php:</para>
+
+    <programlisting>$config = array (
+	'basedir' 				=&gt; '/var/simplesamlphp/',
+	'baseurl'				=&gt; 'http://service.example.com',
+	'baseurlpath'			=&gt; 'simplesamlphp/',</programlisting>
+
+    <section>
+      <title>The simpleSAMLphp installation webpage</title>
+
+      <para>When you have installed simpleSAMLphp, you can access the homepage
+      of your installation, which contains some information and a few links to
+      the test services. The url of an installation can be in example:</para>
+
+      <literallayout>https://service.example.com/simplesamlphp/</literallayout>
+
+      <para>But it depends on how you set it up with apache.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>Making configuration and metadata files</title>
+
+    <para>Configuration and metadata files are stored in a template format,
+    you need to copy them to have your local copies. The reason why it is done
+    this way, is that when you upgrade you can do svn up in subversion or just
+    copy the whole directory over your installation, without replacing your
+    existing configuration. When you are updating, you should investigate
+    whether the config format is changed, this should be documented in the
+    changelog.</para>
+
+    <para>Here are the steps you need to do to create local configuration
+    files:</para>
+
+    <screen>cd /var/simplesamlphp
+cp config/config-template.php config/config.php
+cp -r metadata-templates/*.php metadata/
+</screen>
+  </section>
+
+  <section id="sect.config">
+    <title>Configuring simpleSAMLphp</title>
+
+    <para>First configure all the paths in the beginning of the config file,
+    to correspond to your organization of the apache web server, and where you
+    place simpleSAMLphp.</para>
+
+    <para>You will need to set the entityid of a default IdP in
+    <literal>default-saml20-idp</literal> or
+    <literal>default-shib13-idp</literal> depending on whether you use
+    shibboleth or SAML 2.0.</para>
+
+    <para>There is one parameter debug that may be set to true or false. If
+    you set it to true, then all Browser/POST SAML messages will be printed to
+    the web browser, and the user will have to manually submit it. </para>
+
+    <para>The session.duration parameter says how many seconds that a session
+    should be valid. After this amont of time, the session is not valid
+    anymore.</para>
+
+    <section>
+      <title>Configuration for LDAP authentication plugin</title>
+
+      <para>If you want to perform local authentication on this server, and
+      you want to use the LDAP authenticaiton plugin, then you need to
+      configure the following parameters:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><literal>auth.ldap.dnpattern</literal>: What DN should you
+          bind to? Replacing %username% with the username the user types
+          in.</para>
+        </listitem>
+
+        <listitem>
+          <para><literal>auth.ldap.hostname</literal>: The hostname of the
+          LDAP server</para>
+        </listitem>
+
+        <listitem>
+          <para><literal>auth.ldap.attributes</literal>: Search parameter to
+          LDAP. What attributes should be extracted?
+          <literal>objectclass=*</literal> gives you all.</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+  </section>
+
+  <section>
+    <title>Setting up a SAML 2.0 SP</title>
+
+    <para>This functionality is relevant if you want to integrate SAML 2.0
+    authentication on a service of yours, and you know one or more IdPs that
+    you can connect to. You would need metadata for those IdPs.</para>
+
+    <section>
+      <title>Configuring metadata for a SAML 2.0 SP</title>
+
+      <para>To configure a SAML 2.0 SP, you first need to configure the SP
+      data for all your vhosts. If you run only one host, you need only one
+      entry. This metadata is stored in the
+      <filename>metadata/saml20-sp-hosted.php</filename> file. Here is an
+      example of a metadata:</para>
+
+      <programlisting>	"dev.andreas.feide.no" =&gt; array(
+		'host'							=&gt;	'dev.andreas.feide.no',
+ 		"assertionConsumerServiceURL"	=&gt;	"http://dev.andreas.feide.no/saml2/sp/AssertionConsumerService.php", 
+		"issuer"						=&gt;	"dev.andreas.feide.no",
+		"spNameQualifier" 				=&gt;	"dev.andreas.feide.no",
+		"ForceAuthn"					=&gt;	"false",
+		"NameIDFormat"					=&gt;	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+	),</programlisting>
+
+      <para>Note that you should fill in the host field matching the hostname
+      of your vhost. That way simpleSAMLphp can automatically detect what SP
+      metadata to use based on the <literal>Host:</literal> header sent by the
+      HTTP user agent.</para>
+
+      <para>You also need to configure the metadata for the IdP that you want
+      to use. Here is a metadata example for the Feide IdP:</para>
+
+      <programlisting>	"sam.feide.no" =&gt;  array( 
+			"SingleSignOnUrl"	=&gt;	"https://sam.feide.no/amserver/SSORedirect/metaAlias/idp",
+		 	"SingleLogOutUrl"	=&gt;	"https://sam.feide.no/amserver/IDPSloRedirect/metaAlias/idp",
+		 	"certFingerprint"	=&gt;	"3a:e7:d3:d3:06:ba:57:fd:7f:62:6a:4b:a8:64:b3:4a:53:d9:5d:d0",
+		 	"base64attributes"	=&gt;	true),</programlisting>
+
+      <para>The IdP metadata is stored in the
+      <filename>metadata/saml20-idp-remote.php</filename> file. Configure the
+      correct URLs of the endpoints, the hash of the certificate, and whether
+      the IdP is base64 encoding attributes or not. Most IdPs don't use
+      base64, so if you do not connect to Feide you should turn this parameter
+      to <literal>false</literal>. Notice that the key of the array is the
+      entity id of the IdP, in this example:
+      <literal>sam.feide.no</literal>.</para>
+    </section>
+
+    <section>
+      <title>Test the SAML 2.0 SP example</title>
+
+      <para>Go to the URL of the test page, similar to:</para>
+
+      <literallayout>http://service.example.com/simplesamlphp/example-simple/saml2-example.php</literallayout>
+
+      <note>
+        <para>The simpleSAMLphp installation homepage will link you to this
+        example, so you do not need to type in the full url.</para>
+      </note>
+
+      <para>You should be redirected to the IdP. Login, and you should be sent
+      back and shown all the attributes sent form the IdP.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>Setting up a Shibboleth 1.3 SP</title>
+
+    <para>If you want to configure a service with authentication towards an
+    external Shibboleth 1.3 IdP, this section describes you how to proceed.
+    </para>
+
+    <section>
+      <title>Configuring metadata for Shibboleth 1.3 SP</title>
+
+      <para>Configure Shibboleth 1.3 SP metadata for all your vhosts. If you
+      run only one host, you need only one entry. This metadata is stored in
+      the <filename>metadata/shib13-sp-hosted.php</filename> file. Here is an
+      example:</para>
+
+      <programlisting>	'http://dev.andreas.feide.no'	=&gt; array(
+		'AssertionConsumerService'	=&gt;	'http://dev.andreas.feide.no/shib13/sp/AssertionConsumerService.php',
+		'host'						=&gt;	'dev.andreas.feide.no'
+	),</programlisting>
+
+      <para>Note that you should fill in the host field matching the hostname
+      of your vhost. That way simpleSAMLphp can automatically detect what SP
+      metadata to use based on the <literal>Host:</literal> header sent by the
+      HTTP user agent.</para>
+
+      <para>You also need to configure the metadata for the Shibboleth 1.3
+      IdPs that you want to connect to. Here is an example:</para>
+
+      <programlisting>	'urn:mace:switch.ch:aaitest:dukono.switch.ch'	=&gt; array(
+		'SingleSignOnUrl'		=&gt;	'https://dukono.switch.ch/shibboleth-idp/SSO',
+		'certFingerprint'		=&gt;	'c7279a9f28f11380509e075441e3dc55fb9ab864' 
+	),</programlisting>
+
+      <para>Notice that the key of the array is the entity ID.</para>
+    </section>
+
+    <section>
+      <title>Test the Shibboleth 1.3 SP example</title>
+
+      <para>Go to the URL of the shibboleth test page, similar to:</para>
+
+      <literallayout>http://service.example.com/example-simple/shib13-example.php</literallayout>
+
+      <para>You should be redirected to the IdP. Login, and you should be sent
+      back and shown all the attributes sent form the IdP.</para>
+
+      <note>
+        <para>simpleSAMLphp does not support the attribute profile that
+        Shibboleth is using by default. To make attributes work, you need to
+        configure the IdP to perform attribute push.</para>
+      </note>
+    </section>
+  </section>
+
+  <section>
+    <title>Setting up a SAML 2.0 IdP</title>
+
+    <para>If you have a user database and want to offer a SAML 2.0 IdP
+    functinoality towards external services, here is how you set it up.</para>
+
+    <section>
+      <title>Configuring the SAML 2.0 IdP</title>
+
+      <para>Setup idp metadata in saml20-idp-hosted. Then for all the SP the
+      IdP shold trust in saml20-sp-remote. Then configure in config.php, ldap
+      DN patterns, ldap host etc. Next add a certificate with openssl.</para>
+
+      <para>Example config.php:</para>
+
+      <programlisting>	'auth.ldap.dnpattern'	=&gt; 'uid=%username%,dc=feide,dc=no,ou=feide,dc=uninett,dc=no',
+	'auth.ldap.hostname'	=&gt; 'ldap.uninett.no',
+	'auth.ldap.attributes'	=&gt; 'objectclass=*'</programlisting>
+
+      <para>Example IdP Metadata saml20-idp-hosted:</para>
+
+      <programlisting>	'dev2.andreas.feide.no' =&gt; array(
+		'host'				=&gt;	'dev2.andreas.feide.no',
+		'SingleSignOnUrl'	=&gt;	"http://dev2.andreas.feide.no/saml2/idp/SSOService.php",
+		'SingleLogOutUrl'	=&gt;	"http://dev2.andreas.feide.no/saml2/idp/LogoutService.php",
+		'privatekey'		=&gt;	'server.pem',
+		'certificate'		=&gt;	'server.crt',
+		'base64attributes'	=&gt;	true,
+		'auth'				=&gt;	'auth/login.php'
+	)</programlisting>
+
+      <para>The server.pem and server.crt is an example certificate shipped
+      with the package, and be used for demo purposes, but you must generate
+      your own to use in production services.</para>
+
+      <para>You also need to configure metadata for trusted SPs, here is an
+      example:</para>
+
+      <programlisting>_	"dev.andreas.feide.no" =&gt; array(
+		'host'							=&gt;	'dev.andreas.feide.no',
+ 		"assertionConsumerServiceURL"	=&gt;	"http://dev.andreas.feide.no/saml2/sp/AssertionConsumerService.php", 
+		"issuer"						=&gt;	"dev.andreas.feide.no",
+		"spNameQualifier" 				=&gt;	"dev.andreas.feide.no",
+		"ForceAuthn"					=&gt;	"false",
+		"NameIDFormat"					=&gt;	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+	),</programlisting>
+    </section>
+
+    <section>
+      <title>Adding a SAML IdP signing certificate</title>
+
+      <para>You should generate a new certificate for your IdP.</para>
+
+      <warning>
+        <para>There is a certificate that follows this package that you can
+        use for test purposes, but off course NEVER use this in production as
+        the private key is also included in the package and can be downloaded
+        by anyone.</para>
+      </warning>
+
+      <para>Here is an examples of openssl commands to generate a new key and
+      a selfsigned certificate to use for signing SAML messages:</para>
+
+      <screen>openssl genrsa -des3 -out server2.key 1024 
+openssl rsa -in server2.key -out server2.pem
+openssl req -new -key server.key -out server2.csr
+openssl x509 -req -days 60 -in server2.csr -signkey server2.key -out server2.crt</screen>
+
+      <para>The certificate above will be valid for 60 days.</para>
+
+      <note>
+        <para>simpleSAMLphp will only work with RSA and not DSA
+        certificates.</para>
+      </note>
+    </section>
+
+    <section>
+      <title>Test SAML 2.0 IdP</title>
+
+      <para>To test the SAML 2.0 IdP, it is best to configure two hosts with
+      simpleSAMLphp, and use the SAML 2.0 SP demo example to test the
+      IdP.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>Using the built-in SP WAYF functionality</title>
+
+    <para>The WAYF is not yet a part of the simpleSAMLphp release. This
+    functionality will be added soon.</para>
+  </section>
+
+  <section>
+    <title>Setting up WebSSO bridges</title>
+
+    <para>simpleSAMLphp can be used to bridge between two WebSSO protocols.
+    Here is some short descriptions of how to setup the different bridge
+    configurations.</para>
+
+    <section>
+      <title>Bridging SAML 2.0 &lt;-&gt; SAML 2.0</title>
+
+      <para>In this setup you can bridge between two federations using SAML
+      2.0.</para>
+
+      <para>To approach this, you must configure both saml 2.0 IdP and SP
+      hosted metadata, and in the IdP hosted metadata configure the auth
+      parameter to be the SP initialization endpoint, like this:</para>
+
+      <screen>		'auth'				=&gt;	'saml2/sp/initSSO.php?idpentityid=sam.feide.no'</screen>
+
+      <para>As you can see you specify the IdP in the remote federation as a
+      parameter to the initalization endpoint.</para>
+
+      <note>
+        <para>This section of the documentation is only a placeholder. There
+        will be more detailed information added later. For now, ask the author
+        if you want more details of such a setup.</para>
+
+        <para>Briding SAML 2.0 SLO is not implemented. Will be improved
+        soon.</para>
+      </note>
+    </section>
+
+    <section>
+      <title>Bridging Shibboleth 1.3 &lt;-&gt; Shibboleth 1.3</title>
+
+      <para>Will be supported soon.</para>
+    </section>
+
+    <section>
+      <title>Bridging Shibboleth 1.3 &lt;-&gt; SAML 2.0</title>
+
+      <para>Will be supported soon.</para>
+    </section>
+
+    <section>
+      <title>Bridging SAML 2.0 &lt;-&gt; Shibboleth 1.3</title>
+
+      <para>Will be supported soon.</para>
+    </section>
+
+    <section>
+      <title>Bridging SAML 2.0 &lt;-&gt; OpenID</title>
+
+      <para>Will be supported soon.</para>
+    </section>
+
+    <section>
+      <title>Bridging Shibboelth 1.3 &lt;-&gt; OpenID</title>
+
+      <para>Will be supported soon.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>Authentication API</title>
+
+    <para>The authentication plugin should be placed in the auth directory.
+    </para>
+
+    <para>The following parameters must be accepted in the incomming
+    URL:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para><literal>RelayState</literal>: This is the URL that the user
+        should be sent back to after authentication within the plugin.</para>
+      </listitem>
+
+      <listitem>
+        <para><literal>RequestID</literal>: This is the ID of an incomming
+        request.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>The initSSO.php takes in addition the following parameters:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para><literal>idpentityid</literal>: This is the entityid of the IdP
+        to authenticate with. This parameter is optional, if not set the
+        default for this host will be used.</para>
+      </listitem>
+
+      <listitem>
+        <para><literal>spentityid</literal>: This is which SP config to use.
+        This parameter is optional, if not set the default for this host will
+        be used.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>In hosted IdP metadata there is a config parameter auth that will
+    tell simpleSAML which authentication plugin that can be used.</para>
+
+    <tip>
+      <para>The authentication API is pretty basic. The easiest way to
+      understand how it works is to look at one of the existing plugins that
+      is located in the auth directory of your installation.</para>
+    </tip>
+  </section>
+</article>
\ No newline at end of file
diff --git a/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php b/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php
new file mode 100644
index 0000000000000000000000000000000000000000..8d68c99f71007de1d05db650ba2a7b7fbace671e
--- /dev/null
+++ b/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php
@@ -0,0 +1,213 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnResponse.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_Bindings_SAML20_HTTPPost {
+
+	private $configuration = null;
+	private $metadata = null;
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	
+	public function sendResponseUnsigned($response, $idpentityid, $spentityid, $relayState = null, $endpoint = 'assertionConsumerServiceURL') {
+
+		$idpmd = $this->metadata->getMetaData($idpentityid, 'saml20-idp-hosted');
+		$spmd = $this->metadata->getMetaData($spentityid, 'saml20-sp-remote');
+		
+		$destination = $spmd[$endpoint];
+		
+		echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+				"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+		<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+		<head>
+			<meta http-equiv="content-type" content="text/html; charset=utf-8">
+			<title>Send SAML 2.0 Authentication Response</title>
+		</head>
+		<body>
+		<h1>Send SAML 2.0 Authentication Response</h1>
+		 
+		 <form style="border: 1px solid #777; margin: 2em; padding: 2em" method="post" action="' . $destination . '">
+			<input type="hidden" name="SAMLResponse" value="' . base64_encode($response) . '" />
+			<input type="hidden" name="RelayState" value="' . $relayState. '">
+			<input type="submit" value="Submit the SAML 1.1 Response" />
+		 </form>
+		 
+		<ul>
+			<li>From IdP: <tt>' . $idpentityid . '</tt></li>
+			<li>To SP: <tt>' . $spentityid . '</tt></li>
+			<li>SP Assertion Consumer Service URL: <tt>' . $destination . '</tt></li>
+			<li>RelayState: <tt>' . $relayState . '</tt></li>
+		</ul>
+		
+		<p>SAML Message: <pre>' .  htmlentities($response) . '</pre>
+		
+		
+		</body>
+		</html>';
+	}
+	
+	public function sendResponse($response, $idpentityid, $spentityid, $relayState = null) {
+
+		$idpmd = $this->metadata->getMetaData($idpentityid, 'saml20-idp-hosted');
+		$spmd = $this->metadata->getMetaData($spentityid, 'saml20-sp-remote');
+		
+		$destination = $spmd['assertionConsumerServiceURL'];
+	
+		/*
+		$privatekey = "/home/as/erlang/feide2/cert/edugain/server1Key.pem";
+		$publiccert = "/home/as/erlang/feide2/cert/edugain/server2chain.pem";
+		*/
+
+		$privatekey = "/home/as/erlang/feide2/cert/server.pem";
+		$publiccert = "/home/as/erlang/feide2/cert/server.crt";
+		
+		$privatekey = $this->configuration->getValue('basedir') . '/cert/' . $idpmd['privatekey'];
+		$publiccert = $this->configuration->getValue('basedir') . '/cert/' . $idpmd['certificate'];
+
+		if (!file_exists($privatekey))
+			throw new Exception('Could not find private key file [' . $privatekey . '] which is needed to sign the authentication response');
+
+		if (!file_exists($publiccert)) 
+			throw new Exception('Could not find certificate [' . $publiccert . '] to attach to the authentication resposne');
+
+		
+		/*
+		 * XMLDSig. Sign the complete request with the key stored in cert/server.pem
+		 */
+		$objXMLSecDSig = new XMLSecurityDSig();
+		//$objXMLSecDSig->idKeys[] = 'ResponseID';
+		#$objXMLSecDSig->idKeys = array('ResponseID');
+		
+		$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
+	
+	
+		try {
+			$responsedom = new DOMDocument();
+			$responsedom->loadXML(str_replace("\n", "", str_replace ("\r", "", $response)));
+		} catch (Exception $e) {
+			throw new Exception("foo");
+		}
+		$responseroot = $responsedom->getElementsByTagName('Response')->item(0);
+		
+		//$assertionroot = $responsedom->getElementsByTagName('Assertion')->item(1);
+		$firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
+		
+		//$objXMLSecDSig->addReferenceList(array($responseroot), XMLSecurityDSig::SHA1, //array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'));
+		
+		$objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature',
+			'http://www.w3.org/2001/10/xml-exc-c14n#'));
+		
+		#$objXMLSecDSig->addRefInternal($responseroot, $responseroot, XMLSecurityDSig::SHA1);
+		
+		/* create new XMLSecKey using RSA-SHA-1 and type is private key */
+		$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
+		
+		/* load the private key from file - last arg is bool if key in file (TRUE) or is string (FALSE) */
+		$objKey->loadKey($privatekey,TRUE);
+		
+		
+		
+		
+		
+		$objXMLSecDSig->sign($objKey);
+		
+		$public_cert = file_get_contents($publiccert);
+		$objXMLSecDSig->add509Cert($public_cert, true);
+		/*
+		$public_cert = file_get_contents("cert/edugain/public2.pem");
+		$objXMLSecDSig->add509Cert($public_cert, true);
+		
+		$public_cert = file_get_contents("cert/edugain/public3.pem");
+		$objXMLSecDSig->add509Cert($public_cert, true);
+		*/
+		
+		
+		$objXMLSecDSig->appendSignature($firstassertionroot, true, true);
+		//$objXMLSecDSig->appendSignature($responseroot, true, false);
+		
+		$response = $responsedom->saveXML();
+		
+		
+		# openssl genrsa -des3 -out server.key 1024 
+		# openssl rsa -in server.key -out server.pem
+		# openssl req -new -key server.key -out server.csr
+		# openssl x509 -req -days 60 -in server.csr -signkey server.key -out server.crt
+		
+		if ($this->configuration->getValue('debug')) {
+	
+			$p = new SimpleSAML_XHTML_Template($this->configuration, 'post-debug.php');
+			
+			$p->data['header'] = 'SAML Response Debug-mode';
+			$p->data['RelayStateName'] = 'RelayState';
+			$p->data['RelayState'] = $relayState;
+			$p->data['destination'] = $destination;
+			$p->data['response'] = str_replace("\n", "", base64_encode($response));
+			$p->data['responseHTML'] = htmlentities($responsedom->saveHTML());
+			
+			$p->show();
+
+		
+		} else {
+
+			$p = new SimpleSAML_XHTML_Template($this->configuration, 'post.php');
+	
+			$p->data['RelayStateName'] = 'RelayState';
+			$p->data['RelayState'] = $relayState;
+			$p->data['destination'] = $destination;
+			$p->data['response'] = base64_encode($response);
+			
+			$p->show();
+
+		
+		}
+		
+		
+	}
+	
+	public function decodeResponse($post) {
+		$rawResponse = 	$post["SAMLResponse"];
+		$relaystate = 	$post["RelayState"];
+		
+		$samlResponseXML = base64_decode( $rawResponse );
+		
+		//error_log("Response is: " . $samlResponseXML);
+        
+		$samlResponse = new SimpleSAML_XML_SAML20_AuthnResponse($this->configuration, $this->metadata);
+	
+		$samlResponse->setXML($samlResponseXML);
+		
+		if (isset($relaystate)) {
+			$samlResponse->setRelayState($relaystate);
+		}
+	
+        #echo("Authn response = " . $samlResponse );
+
+        return $samlResponse;
+        
+	}
+
+
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/Bindings/SAML20/HTTPRedirect.php b/lib/SimpleSAML/Bindings/SAML20/HTTPRedirect.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf12376a51bae104b8630cf7630205dee65702c5
--- /dev/null
+++ b/lib/SimpleSAML/Bindings/SAML20/HTTPRedirect.php
@@ -0,0 +1,125 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_Bindings_SAML20_HTTPRedirect {
+
+	private $configuration = null;
+	private $metadata = null;
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	public function sendMessage($request, $remoteentityid, $relayState = null, $endpoint = 'SingleSignOnUrl', $direction = 'SAMLRequest', $mode = 'SP') {
+		if (!in_array($mode, array('SP', 'IdP'))) {
+			throw new Exception('mode parameter of sendMessage() must be either SP or IdP');
+		}
+		$metadataset = 'saml20-idp-remote';
+		if ($mode == 'IdP') {
+			$metadataset = 'saml20-sp-remote';
+		}
+
+		$md = $this->metadata->getMetaData($remoteentityid, $metadataset);
+		$idpTargetUrl = $md[$endpoint];
+	
+		$encodedRequest = urlencode( base64_encode( gzdeflate( $request ) ));
+		
+		$redirectURL = $idpTargetUrl . "?" . $direction . "=" . $encodedRequest;
+		if (isset($relayState)) {
+			$redirectURL .= "&RelayState=" . urlencode($relayState);
+		}
+		
+
+		header("Location: " . $redirectURL);
+		
+	}
+
+
+
+	public function decodeRequest($get) {
+		if (!isset($get['SAMLRequest'])) {
+			throw new Exception('SAMLRequest parameter not set in paramter (on SAML 2.0 HTTP Redirect binding endpoint)');
+		}
+		$rawRequest = 	$get["SAMLRequest"];
+		$relaystate = isset($get["RelayState"]) ? $get["RelayState"] : null;
+		
+		$samlRequestXML = gzinflate(base64_decode( $rawRequest ));
+         
+		$samlRequest = new SimpleSAML_XML_SAML20_AuthnRequest($this->configuration, $this->metadata);
+	
+		$samlRequest->setXML($samlRequestXML);
+		
+		if (isset($relaystate)) {
+			$samlRequest->setRelayState($relaystate);
+		}
+	
+        #echo("Authn response = " . $samlResponse );
+
+        return $samlRequest;
+        
+	}
+	
+	public function decodeLogoutRequest($get) {
+		if (!isset($get['SAMLRequest'])) {
+			throw new Exception('SAMLRequest parameter not set in paramter (on SAML 2.0 HTTP Redirect binding endpoint)');
+		}
+		$rawRequest = 	$get["SAMLRequest"];
+		$relaystate = isset($get["RelayState"]) ? $get["RelayState"] : null;
+		
+		$samlRequestXML = gzinflate(base64_decode( $rawRequest ));
+         
+		$samlRequest = new SimpleSAML_XML_SAML20_LogoutRequest($this->configuration, $this->metadata);
+	
+		$samlRequest->setXML($samlRequestXML);
+		
+		if (isset($relaystate)) {
+			$samlRequest->setRelayState($relaystate);
+		}
+	
+        #echo("Authn response = " . $samlResponse );
+
+        return $samlRequest;
+	}
+	
+	public function decodeLogoutResponse($get) {
+		if (!isset($get['SAMLResponse'])) {
+			throw new Exception('SAMLResponse parameter not set in paramter (on SAML 2.0 HTTP Redirect binding endpoint)');
+		}
+		$rawRequest = 	$get["SAMLResponse"];
+		$relaystate = isset($get["RelayState"]) ? $get["RelayState"] : null;
+		
+		$samlRequestXML = gzinflate(base64_decode( $rawRequest ));
+         
+		$samlRequest = new SimpleSAML_XML_SAML20_LogoutResponse($this->configuration, $this->metadata);
+	
+		$samlRequest->setXML($samlRequestXML);
+		
+		if (isset($relaystate)) {
+			$samlRequest->setRelayState($relaystate);
+		}
+	
+        #echo("Authn response = " . $samlResponse );
+
+        return $samlRequest;
+	}
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php b/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php
new file mode 100644
index 0000000000000000000000000000000000000000..cbe2a19a3d0f026f39f70b7c74017d72cb25d619
--- /dev/null
+++ b/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php
@@ -0,0 +1,198 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/Shib13/AuthnResponse.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_Bindings_Shib13_HTTPPost {
+
+	private $configuration = null;
+	private $metadata = null;
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	
+	public function sendResponseUnsigned($response, $idpentityid, $spentityid, $relayState = null, $endpoint = 'assertionConsumerServiceURL') {
+
+		$idpmd = $this->metadata->getMetaData($idpentityid, 'saml20-idp-hosted');
+		$spmd = $this->metadata->getMetaData($spentityid, 'saml20-sp-remote');
+		
+		$destination = $spmd[$endpoint];
+		
+		echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+				"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+		<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+		<head>
+			<meta http-equiv="content-type" content="text/html; charset=utf-8">
+			<title>Send SAML 2.0 Authentication Response</title>
+		</head>
+		<body>
+		<h1>Send SAML 2.0 Authentication Response</h1>
+		 
+		 <form style="border: 1px solid #777; margin: 2em; padding: 2em" method="post" action="' . $destination . '">
+			<input type="hidden" name="SAMLResponse" value="' . base64_encode($response) . '" />
+			<input type="hidden" name="TARGET" value="' . $relayState. '">
+			<input type="submit" value="Submit the SAML 1.1 Response" />
+		 </form>
+		 
+		<ul>
+			<li>From IdP: <tt>' . $idpentityid . '</tt></li>
+			<li>To SP: <tt>' . $spentityid . '</tt></li>
+			<li>SP Assertion Consumer Service URL: <tt>' . $destination . '</tt></li>
+			<li>RelayState: <tt>' . $relayState . '</tt></li>
+		</ul>
+		
+		<p>SAML Message: <pre>' .  htmlentities($response) . '</pre>
+		
+		
+		</body>
+		</html>';
+	}
+	
+	public function sendResponse($response, $idpentityid, $spentityid, $relayState = null) {
+
+		$idpmd = $this->metadata->getMetaData($idpentityid, 'saml20-idp-hosted');
+		$spmd = $this->metadata->getMetaData($spentityid, 'saml20-sp-remote');
+		
+		$destination = $spmd['assertionConsumerServiceURL'];
+	
+		/*
+		$privatekey = "/home/as/erlang/feide2/cert/edugain/server1Key.pem";
+		$publiccert = "/home/as/erlang/feide2/cert/edugain/server2chain.pem";
+		*/
+
+		$privatekey = "/home/as/erlang/feide2/cert/server.pem";
+		$publiccert = "/home/as/erlang/feide2/cert/server.crt";
+
+		
+		/*
+		 * XMLDSig. Sign the complete request with the key stored in cert/server.pem
+		 */
+		$objXMLSecDSig = new XMLSecurityDSig();
+		//$objXMLSecDSig->idKeys[] = 'ResponseID';
+		#$objXMLSecDSig->idKeys = array('ResponseID');
+		
+		$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
+		
+		$responsedom = new DOMDocument();
+		$responsedom->loadXML(str_replace ("\r", "", $response));
+		
+		$responseroot = $responsedom->getElementsByTagName('Response')->item(0);
+		
+		//$assertionroot = $responsedom->getElementsByTagName('Assertion')->item(1);
+		$firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
+		
+		#$objXMLSecDSig->addReferenceList(array($responseroot), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'));
+		$objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature',
+			'http://www.w3.org/2001/10/xml-exc-c14n#'));
+		
+		#$objXMLSecDSig->addRefInternal($responseroot, $responseroot, XMLSecurityDSig::SHA1);
+		
+		/* create new XMLSecKey using RSA-SHA-1 and type is private key */
+		$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
+		
+		/* load the private key from file - last arg is bool if key in file (TRUE) or is string (FALSE) */
+		$objKey->loadKey($privatekey,TRUE);
+		
+		
+		
+		
+		
+		$objXMLSecDSig->sign($objKey);
+		
+		$public_cert = file_get_contents($publiccert);
+		$objXMLSecDSig->add509Cert($public_cert, true);
+		/*
+		$public_cert = file_get_contents("cert/edugain/public2.pem");
+		$objXMLSecDSig->add509Cert($public_cert, true);
+		
+		$public_cert = file_get_contents("cert/edugain/public3.pem");
+		$objXMLSecDSig->add509Cert($public_cert, true);
+		*/
+		
+		
+		$objXMLSecDSig->appendSignature($firstassertionroot, true);
+		
+		$response = $responsedom->saveXML();
+		
+		
+		# openssl genrsa -des3 -out server.key 1024 
+		# openssl rsa -in server.key -out server.pem
+		# openssl req -new -key server.key -out server.csr
+		# openssl x509 -req -days 60 -in server.csr -signkey server.key -out server.crt
+		
+		
+		
+		echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+				"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+		<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+		<head>
+			<meta http-equiv="content-type" content="text/html; charset=utf-8">
+			<title>Send SAML 2.0 Authentication Response</title>
+		</head>
+		<body>
+		<h1>Send SAML 2.0 Authentication Response</h1>
+		 
+		 <form style="border: 1px solid #777; margin: 2em; padding: 2em" method="post" action="' . $destination . '">
+			<input type="hidden" name="SAMLResponse" value="' . base64_encode($response) . '" />
+			<input type="hidden" name="TARGET" value="' . $relayState. '">
+			<input type="submit" value="Submit the SAML 1.1 Response" />
+		 </form>
+		 
+		<ul>
+			<li>From IdP: <tt>' . $idpentityid . '</tt></li>
+			<li>To SP: <tt>' . $spentityid . '</tt></li>
+			<li>SP Assertion Consumer Service URL: <tt>' . $destination . '</tt></li>
+			<li>RelayState: <tt>' . $relayState . '</tt></li>
+		</ul>
+		
+		<p>SAML Message: <pre>' .  htmlentities($responsedom->saveHTML()) . '</pre>
+		
+		
+		</body>
+		</html>';
+		
+	}
+	
+	public function decodeResponse($post) {
+		$rawResponse = 	$post["SAMLResponse"];
+		$relaystate = 	$post["TARGET"];
+		
+		$samlResponseXML = base64_decode( $rawResponse );
+        
+		$samlResponse = new SimpleSAML_XML_Shib13_AuthnResponse($this->configuration, $this->metadata);
+	
+		$samlResponse->setXML($samlResponseXML);
+		
+		if (isset($relaystate)) {
+			$samlResponse->setRelayState($relaystate);
+		}
+	
+        #echo("Authn response = " . $samlResponse );
+
+        return $samlResponse;
+        
+	}
+
+
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/Configuration.php b/lib/SimpleSAML/Configuration.php
new file mode 100644
index 0000000000000000000000000000000000000000..116c018a8478d86659aa4129a5e25c0b093e964a
--- /dev/null
+++ b/lib/SimpleSAML/Configuration.php
@@ -0,0 +1,53 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_Configuration {
+
+	private static $instance = null;
+
+	private $configpath = null;	
+	private $configuration = null;
+
+	// private constructor restricts instantiaton to getInstance()
+	private function __construct($configpath) {
+
+		$this->configpath = $configpath;
+
+	}
+	
+	public function getInstance() {
+		return self::$instance;
+	}
+	
+	public static function init($path) {
+		self::$instance = new SimpleSAML_Configuration($path);
+	}
+
+	private function loadConfig() {
+		require_once($this->configpath . '/config.php');
+		$this->configuration = $config;
+	}
+
+	public function getValue($name) {
+		if (!isset($this->configuration)) {
+			$this->loadConfig();
+		}
+		return $this->configuration[$name];
+	}
+
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php
new file mode 100644
index 0000000000000000000000000000000000000000..03befb7c6c8787e8c63bacb84e5c5584f7f512f4
--- /dev/null
+++ b/lib/SimpleSAML/Session.php
@@ -0,0 +1,223 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+
+
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
+require_once('SimpleSAML/XML/AuthnResponse.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+
+/**
+ * A class representing a session.
+ */
+class SimpleSAML_Session {
+
+	const STATE_ONLINE = 1;
+	const STATE_LOGOUTINPROGRESS = 2;
+	const STATE_LOGGEDOUT = 3;
+
+	private static $instance = null;
+
+	private $configuration = null;
+	
+	private $authnrequests = array();
+	private $authnresponse = null;
+	
+	private $logoutrequest = null;
+	
+	private $authenticated = null;
+	private $protocol = null;
+	private $attributes = null;
+	
+	
+	private $sessionindex = null;
+	private $nameid = null;
+	private $nameidformat = null;
+	
+	private $sp_at_idpsessions = array();
+	
+	// Session duration parameters
+	private $sessionstarted = null;
+	private $sessionduration = null;
+
+	// private constructor restricts instantiaton to getInstance()
+	private function __construct($protocol, SimpleSAML_XML_AuthnResponse $message = null, $authenticated = true) {
+
+		$this->configuration = SimpleSAML_Configuration::getInstance();
+
+		$this->protocol = $protocol;
+		$this->authnresponse = $message;
+		
+		$this->authenticated = $authenticated;
+		if ($authenticated) {
+			$this->sessionstarted = time();
+		}
+		
+		$this->sessionduration = $this->configuration->getValue('session.duration');
+	}
+	
+	public function add_sp_session($entityid) {
+		$this->sp_at_idpsessions[$entityid] = self::STATE_ONLINE;
+	}
+	
+	public function get_next_sp_logout() {
+		
+		if (!$this->sp_at_idpsessions) return null;
+		
+		foreach ($this->sp_at_idpsessions AS $entityid => $sp) {
+			if ($sp == self::STATE_ONLINE) {
+				$this->sp_at_idpsessions[$entityid] = self::STATE_LOGOUTINPROGRESS;
+				return $entityid;
+			}
+		}
+		return null;
+	}
+	
+	public function set_sp_logout_completed($entityid) {
+		$this->sp_at_idpsessions[$entityid] = self::STATE_LOGGEDOUT;
+	}
+	
+	
+	public function dump_sp_sessions() {
+		foreach ($this->sp_at_idpsessions AS $entityid => $sp) {
+			error_log('Dump sp sessions: ' . $entityid . ' status: ' . $sp);
+		}
+	}
+	
+	public function getInstance() {
+		if (isset(self::$instance)) {
+			return self::$instance;
+		} elseif(isset($_SESSION['SimpleSAMLphp_SESSION'])) {
+			self::$instance = $_SESSION['SimpleSAMLphp_SESSION'];
+			return self::$instance;
+		}
+		return null;
+	}
+	
+	public static function init($protocol, $message = null, $authenticated = true) {
+		
+		$preinstance = self::getInstance();
+		
+		if (isset($preinstance)) {
+			if (isset($message)) $preinstance->authnresponse = $message;
+			if (isset($authenticated)) $preinstance->setAuthenticated($authenticated);
+		} else {	
+			self::$instance = new SimpleSAML_Session($protocol, $message, $authenticated);
+			$_SESSION['SimpleSAMLphp_SESSION'] = self::$instance;
+		}
+	}
+
+	public function setAuthnRequest($requestid, SimpleSAML_XML_SAML20_AuthnRequest $xml) {	
+		$this->authnrequests[$requestid] = $xml;
+	}
+	
+	public function getAuthnRequest($requestid) {
+		return $this->authnrequests[$requestid];
+	}
+	
+	public function setAuthnResponse(SimpleSAML_XML_AuthnResponse $xml) {
+		$this->authnresponse = $xml;
+	}
+	
+	public function getAuthnResposne() {
+		return $this->authnresponse;
+	}
+	
+	public function setLogoutRequest(SimpleSAML_XML_SAML20_LogoutRequest $lr) {
+		$this->logoutrequest = $lr;
+	}
+	
+	public function getLogoutRequest() {
+		return $this->logoutrequest;
+	}
+
+	public function setSessionIndex($sessionindex) {
+		$this->sessionindex = $sessionindex;
+	}
+	public function getSessionIndex() {
+		return $this->sessionindex;
+	}
+	public function setNameID($nameid) {
+		$this->nameid = $nameid;
+	}
+	public function getNameID() {
+		return $this->nameid;
+	}
+	public function setNameIDformat($nameidformat) {
+		$this->nameidformat = $nameidformat;
+	}
+	public function getNameIDformat() {
+		return $this->nameidformat;
+	}
+
+	public function setAuthenticated($auth) {
+		$this->authenticated = $auth;
+		if ($auth) {
+			$this->sessionstarted = time();
+		}
+	}
+	
+	public function setSessionDuration($duration) {
+		$this->sessionduration = $duration;
+	}
+	
+	
+	/*
+	 * Is the session representing an authenticated user, and is the session still alive.
+	 * This function will return false after the user has timed out.
+	 */
+
+	public function isValid() {
+		if (!$this->isAuthenticated()) return false;
+		return $this->remainingTime() > 0;
+	}
+	
+	/*
+	 * If the user is authenticated, how much time is left of the session.
+	 */
+	public function remainingTime() {
+		return $this->sessionduration - (time() - $this->sessionstarted);
+	}
+
+	/* 
+	 * Is the user authenticated. This function does not check the session duration.
+	 */
+	public function isAuthenticated() {
+		return $this->authenticated;
+	}
+	
+	
+	
+	
+	public function getProtocol() {
+		return $this->protocol;
+	}
+	
+	public function getAttributes() {
+		return $this->attributes;
+	}
+
+	public function getAttribute($name) {
+		return $this->attributes[$name];
+	}
+
+	public function setAttributes($attributes) {
+		$this->attributes = $attributes;
+	}
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b6af783eaf5e1d8b54008e09cbfc2fc98409c1d
--- /dev/null
+++ b/lib/SimpleSAML/Utilities.php
@@ -0,0 +1,92 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_Utilities {
+
+
+	public static function selfURLNoQuery() {
+	
+		$s = empty($_SERVER["HTTPS"]) ? ''
+			: ($_SERVER["HTTPS"] == "on") ? "s"
+			: "";
+		$protocol = self::strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
+		$port = ($_SERVER["SERVER_PORT"] == "80") ? ""
+			: (":".$_SERVER["SERVER_PORT"]);
+		$querystring = '';
+		return $protocol."://".$_SERVER['HTTP_HOST'].$port . $_SERVER['SCRIPT_NAME'];
+	
+	}
+
+	public static function selfURL() {
+	
+		$s = empty($_SERVER["HTTPS"]) ? ''
+			: ($_SERVER["HTTPS"] == "on") ? "s"
+			: "";
+		$protocol = self::strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
+		$port = ($_SERVER["SERVER_PORT"] == "80") ? ""
+			: (":".$_SERVER["SERVER_PORT"]);
+		$querystring = '';
+		return $protocol."://".$_SERVER['HTTP_HOST'].$port.$_SERVER['REQUEST_URI'];
+	
+	}
+	
+	public static function addURLparameter($url, $parameter) {
+		if (strstr($url, '?')) {
+			return $url . '&' . $parameter;
+		} else {
+			return $url . '?' . $parameter;
+		}
+	}
+	
+	public static function strleft($s1, $s2) {
+		return substr($s1, 0, strpos($s1, $s2));
+	}
+	
+	public static function checkDateConditions($start=NULL, $end=NULL) {
+		$currentTime = time();
+	
+		if (! empty($start)) {
+			$startTime = strtotime($start);
+			/* Allow for a 10 minute difference in Time */
+			if (($startTime < 0) || (($startTime - 600) > $currentTime)) {
+				return FALSE;
+			}
+		}
+		if (! empty($end)) {
+			$endTime = strtotime($end);
+			if (($endTime < 0) || ($endTime <= $currentTime)) {
+				return FALSE;
+			}
+		}
+		return TRUE;
+	}
+	
+	public static function generateID() {
+	
+		$length = 42;
+		$key = "_";
+		for ( $i=0; $i < $length; $i++ )
+		{
+			 $key .= dechex( rand(0,15) );
+		}
+		return $key;
+	}
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XHTML/Template.php b/lib/SimpleSAML/XHTML/Template.php
new file mode 100644
index 0000000000000000000000000000000000000000..11e845ee4478ead9b48d5799cd540193f5cee39c
--- /dev/null
+++ b/lib/SimpleSAML/XHTML/Template.php
@@ -0,0 +1,45 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_XHTML_Template {
+
+	private $configuration = null;
+	private $template = 'default.php';
+	
+	public $data = null;
+
+	function __construct(SimpleSAML_Configuration $configuration, $template) {
+		$this->configuration = $configuration;
+		$this->template = $template;
+		
+		$this->data['baseurlpath'] = $this->configuration->getValue('baseurlpath');
+	}
+	
+	public function show() {
+		$data = $this->data;
+		$filename = $this->configuration->getValue('templatedir') . '/' . $this->template;
+		if (!file_exists($filename)) {
+			throw new Exception('Could not find template file [' . $this->template . '] at [' . $filename . ']');
+		}
+		require_once($filename);
+	}
+	
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XML/AuthnResponse.php b/lib/SimpleSAML/XML/AuthnResponse.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2cd28d46996773fe9ce9b4a54b5b67c3d5c4e73
--- /dev/null
+++ b/lib/SimpleSAML/XML/AuthnResponse.php
@@ -0,0 +1,115 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+
+require_once('xmlseclibs.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+abstract class SimpleSAML_XML_AuthnResponse {
+
+	private $configuration = null;
+	private $metadata = 'default.php';
+	
+	private $message = null;
+	private $dom;
+	private $relayState = null;
+	
+	private $validIDs = null;
+	
+	const PROTOCOL = 'urn:oasis:names:tc:SAML:2.0';
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	
+	abstract public function validate();
+
+	abstract public function createSession();
+
+	
+	
+	abstract public function getAttributes();
+
+	
+	abstract public function getIssuer();
+	
+	abstract public function getNameID();
+	
+	
+	public function setXML($xml) {
+		$this->message = $xml;
+	}
+	
+	public function getXML() {
+		return $this->message;
+	}
+	
+	public function setRelayState($relayState) {
+		$this->relayState = $relayState;
+	}
+	
+	public function getRelayState() {
+		return $this->relayState;
+	}
+	
+	public function getDOM() {
+		if (isset($this->message) ) {
+			
+			/*
+			if (isset($this->dom)) {
+				return $this->dom;
+			}
+			*/
+		
+			$token = new DOMDocument();
+			$token->loadXML(str_replace ("\r", "", $this->message));
+			if (empty($token)) {
+				throw new Exception("Unable to load token");
+			}
+			$this->dom = $token;
+			return $this->dom;
+		
+		} 
+		
+		return null;
+	}
+	
+
+
+	
+	public static function generateID() {
+	
+		$length = 42;
+		$key = "_";
+		for ( $i=0; $i < $length; $i++ )
+		{
+			 $key .= dechex( rand(0,15) );
+		}
+		return $key;
+	}
+	
+	public static function generateIssueInstant($offset = 0) {
+		return gmdate("Y-m-d\TH:i:s\Z", time() + $offset);
+	}
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XML/MetaDataStore.php b/lib/SimpleSAML/XML/MetaDataStore.php
new file mode 100644
index 0000000000000000000000000000000000000000..8d15a3ed8c71c18a7eb3c9988af71d295b19d8ae
--- /dev/null
+++ b/lib/SimpleSAML/XML/MetaDataStore.php
@@ -0,0 +1,105 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+
+require_once('SimpleSAML/Configuration.php');
+
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_XML_MetaDataStore {
+
+	private $configuration = null;
+	private $metadata = null;
+	private $hostmap = null;
+
+	function __construct(SimpleSAML_Configuration $configuration) {
+		$this->configuration = $configuration;
+	}
+
+	public function load($set) {
+		$metadata = null;
+		if (!in_array($set, array(
+			'saml20-sp-hosted', 'saml20-sp-remote','saml20-idp-hosted', 'saml20-idp-remote',
+			'shib13-sp-hosted', 'shib13-sp-remote', 'shib13-idp-hosted', 'shib13-idp-remote'))) {
+				throw new Exception('Trying to load illegal set of Meta data [' . $set . ']');
+		}
+		
+		$metadatasetfile = $this->configuration->getValue('metadatadir') . '/' . $set . '.php';
+		
+		if (!file_exists($metadatasetfile)) {
+			throw new Exception('Could not open file: ' . $metadatasetfile);
+		}
+		include($metadatasetfile);
+		
+		if (!is_array($metadata)) {
+			throw new Exception('Could not load metadata set [' . $set . '] from file: ' . $metadatasetfile);
+		}
+		foreach ($metadata AS $key => $entry) { 
+			$this->metadata[$set][$key] = $entry;
+			$this->metadata[$set][$key]['entityid'] = $key;
+			
+			if (isset($entry['host'])) {
+				$this->hostmap[$set][$entry['host']] = $key;
+			}
+			
+		}
+		/*
+		echo '<pre>';
+		print_r();
+		echo '</pre>';
+		*/
+	}
+
+	public function getMetaDataCurrentEntityID($set = 'saml20-sp-hosted') {
+	
+		if (!isset($this->metadata[$set])) {
+			$this->load($set);
+		}
+		$currenthost = $_SERVER['HTTP_HOST'];
+		if (!isset($this->hostmap[$set])) {
+			throw new Exception('No default entities defined for metadata set [' . $set . ']');
+		}
+		if (!isset($currenthost)) {
+			throw new Exception('Could not get HTTP_HOST, in order to resolve default entity ID');
+		}
+		if (!isset($this->hostmap[$set][$currenthost])) {
+			throw new Exception('Could not find any default metadata entities in set [' . $set . '] for host [' . $currenthost . ']');
+		}
+		if (!$this->hostmap[$set][$currenthost]) throw new Exception('Could not find default metadata for current host');
+		return $this->hostmap[$set][$currenthost];
+	}
+
+	public function getMetaDataCurrent($set = 'saml20-sp-hosted') {
+		return $this->getMetaData($this->getMetaDataCurrentEntityID($set), $set);
+	}
+	
+	public function getMetaData($entityid = null, $set = 'saml20-sp-hosted') {
+		if (!isset($entityid)) {
+			return $this->getMetaDataCurrent($set);
+		}
+		
+		//echo 'find metadata for entityid [' . $entityid . '] in metadata set [' . $set . ']';
+		
+		if (!isset($this->metadata[$set])) {
+			$this->load($set);
+		}
+		if (!isset($this->metadata[$set][$entityid]) ) {
+			throw new Exception('Could not find metadata for entityid [' . $entityid . '] in metadata set [' . $set . ']');
+		}
+		return $this->metadata[$set][$entityid];
+	}
+	
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XML/SAML20/AuthnRequest.php b/lib/SimpleSAML/XML/SAML20/AuthnRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..83986d75b202df026f720cca65c5db2787f4bba2
--- /dev/null
+++ b/lib/SimpleSAML/XML/SAML20/AuthnRequest.php
@@ -0,0 +1,195 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_XML_SAML20_AuthnRequest {
+
+	private $configuration = null;
+	private $metadata = 'default.php';
+	
+	private $message = null;
+	private $dom;
+	private $relayState = null;
+	
+	
+	const PROTOCOL = 'urn:oasis:names:tc:SAML:2.0';
+
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	public function setXML($xml) {
+		$this->message = $xml;
+	}
+	
+	public function getXML() {
+		return $this->message;
+	}
+	
+	public function setRelayState($relayState) {
+		$this->relayState = $relayState;
+	}
+	
+	public function getRelayState() {
+		return $this->relayState;
+	}
+	
+	public function getDOM() {
+		if (isset($this->message) ) {
+		
+			/* if (isset($this->dom) && $this->dom != null ) {
+				return $this->dom;
+			} */
+		
+			$token = new DOMDocument();
+			$token->loadXML(str_replace ("\r", "", $this->message));
+			if (empty($token)) {
+				throw new Exception("Unable to load token");
+			}
+			$this->dom = $token;
+			return $this->dom;
+		
+		} 
+		
+		return null;
+	}
+	
+	
+	public function getIssuer() {
+		$dom = $this->getDOM();
+		$issuer = null;
+		
+		if (!$dom instanceof DOMDocument) {
+			throw new Exception("Could not get message DOM in AuthnRequest object");
+		}
+		
+		//print_r($dom->saveXML());
+		
+		if ($issuerNodes = $dom->getElementsByTagName('Issuer')) {
+			if ($issuerNodes->length > 0) {
+				$issuer = $issuerNodes->item(0)->textContent;
+			}
+		}
+		return $issuer;
+	}
+	
+	public function getRequestID() {
+		$dom = $this->getDOM();
+		$requestid = null;
+		
+		if (empty($dom)) {
+			throw new Exception("Could not get message DOM in AuthnRequest object");
+		}
+		
+		$requestelement = $dom->getElementsByTagName('AuthnRequest')->item(0);
+		$requestid = $requestelement->getAttribute('ID');
+		return $requestid;
+		/*
+		if ($issuerNodes = $dom->getElementsByTagName('Issuer')) {
+			if ($issuerNodes->length > 0) {
+				$requestid = $issuerNodes->item(0)->textContent;
+			}
+		}
+		return $requestid;	
+		*/
+	}
+	
+	public function createSession() {
+	
+		
+		$session = SimpleSAML_Session::getInstance();
+		
+		if (!isset($session)) {
+			SimpleSAML_Session::init(self::PROTOCOL, null, false);
+			$session = SimpleSAML_Session::getInstance();
+		}
+
+		$session->setAuthnRequest($this->getRequestID(), $this);
+		
+		/*
+		if (isset($this->relayState)) {
+			$session->setRelayState($this->relayState);
+		}
+		*/
+		return $session;
+	}
+	
+
+	public function generate($spentityid) {
+		$md = $this->metadata->getMetaData($spentityid);
+		
+		$id = self::generateID();
+		$issueInstant = self::generateIssueInstant();
+
+		$assertionConsumerServiceURL = $md['assertionConsumerServiceURL'];
+		$spNameQualifier = $md['spNameQualifier'];
+		$nameidformat = isset($md['NameIDformat']) ? 
+			$md['NameIDformat'] : 
+			'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent';
+		
+		$authnRequest = "<samlp:AuthnRequest  " .
+		  "xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"\n" .
+		  "ID=\"" . $id . "\" " .
+		  "Version=\"2.0\" " .
+		  "IssueInstant=\"" . $issueInstant . "\" " .
+		  "ForceAuthn=\"false\" " .
+		  "IsPassive=\"false\" " .
+		  "ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" " .
+		  "AssertionConsumerServiceURL=\"" . $assertionConsumerServiceURL . "\">\n" .
+			"<saml:Issuer " .
+			"xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" .
+			  $spentityid .
+			"</saml:Issuer>\n" .
+			"<samlp:NameIDPolicy  " .
+			"xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" " .
+			"Format=\"" . $nameidformat. "\" " .
+			"SPNameQualifier=\"" . $spNameQualifier . "\" " .
+			"AllowCreate=\"true\" />\n" . 
+			"<samlp:RequestedAuthnContext " .
+			"xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" " .
+			"Comparison=\"exact\">" .
+			  "<saml:AuthnContextClassRef " .
+			  "xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" .
+				"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" .
+			  "</saml:AuthnContextClassRef>" .
+			"</samlp:RequestedAuthnContext>\n" .
+		  "</samlp:AuthnRequest>";
+		  
+		return $authnRequest;
+	}
+	
+	public static function generateID() {
+	
+		$length = 42;
+		$key = "_";
+		for ( $i=0; $i < $length; $i++ )
+		{
+			 $key .= dechex( rand(0,15) );
+		}
+		return $key;
+	}
+	
+	public static function generateIssueInstant() {
+		return gmdate("Y-m-d\TH:i:s\Z");
+	}
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
new file mode 100644
index 0000000000000000000000000000000000000000..1e7b18920d997c4d09658853ab8c94958da09c73
--- /dev/null
+++ b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
@@ -0,0 +1,528 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ă…kre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/AuthnResponse.php');
+
+require_once('xmlseclibs.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
+
+	private $configuration = null;
+	private $metadata = 'default.php';
+	
+	private $message = null;
+	private $dom;
+	private $relayState = null;
+	
+	private $validIDs = null;
+	
+	const PROTOCOL = 'urn:oasis:names:tc:SAML:2.0';
+	
+	const TRANSIENT 	= 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient';
+	const EMAIL 		= 'urn:oasis:names:tc:SAML:2.0:nameid-format:email';
+	
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+
+	
+	public function validate() {
+	
+		$dom = $this->getDOM();
+		
+		/* Create an XML security object, and register ID as the id attribute for sig references. */
+		$objXMLSecDSig = new XMLSecurityDSig();
+		$objXMLSecDSig->idKeys[] = 'ID';
+		
+		/* Locate the signature element to be used. */
+		$objDSig = $objXMLSecDSig->locateSignature($dom);
+		
+
+		/* If no signature element was found, throw an error */
+		if (!$objDSig) {
+			throw new Exception("Could not locate XML Signature element in Authentication Response");
+		}
+		
+		
+		/* Must check certificate fingerprint now - validateReference removes it */        
+		// TODO FIX"!!!
+		if ( ! $this->validateCertFingerprint($objDSig) ) {
+			throw new Exception("Fingerprint Validation Failed");
+		}
+
+		/* Get information about canoncalization in to the xmlsec library. Read from the siginfo part. */
+		$objXMLSecDSig->canonicalizeSignedInfo();
+		
+		$refids = $objXMLSecDSig->getRefIDs();
+		
+		
+		
+		/* Validate refrences */
+		$retVal = $objXMLSecDSig->validateReference();
+		if (! $retVal) {
+			throw new Exception("XMLsec: digest validation failed");
+		}
+
+		$key = NULL;
+		$objKey = $objXMLSecDSig->locateKey();
+	
+		if ($objKey) {
+			if ($objKeyInfo = XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig)) {
+				/* Handle any additional key processing such as encrypted keys here */
+			}
+		}
+	
+		if (empty($objKey)) {
+			throw new Exception("Error loading key to handle Signature");
+		}
+
+		if (! $objXMLSecDSig->verify($objKey)) {
+			throw new Exception("Unable to validate Signature");
+		}
+		
+		$this->validIDs = $refids;
+		return true;
+	}
+	
+	
+	
+	
+	function validateCertFingerprint($dom) {
+//		$dom = $this->getDOM();
+		$fingerprint = "";
+		
+		
+		// Find the certificate in the document.
+		if ($x509certNodes = $dom->getElementsByTagName('X509Certificate')) {
+			if ($x509certNodes->length > 0) {
+				$x509cert = $x509certNodes->item(0)->textContent;
+				$x509data = base64_decode( $x509cert );
+				$fingerprint = strtolower( sha1( $x509data ) );
+			}
+		}
+	
+		// Get the issuer of the assertion.
+		$issuer = $this->getIssuer();
+		$md = $this->metadata->getMetaData($issuer, 'saml20-idp-remote');
+		
+		/*
+		 * Get fingerprint from saml20-idp-remote metadata...
+		 * 
+		 * Accept fingerprints with or without colons, case insensitive
+		 */
+		$issuerFingerprint = strtolower( str_replace(":", "", $md['certFingerprint']) );
+	
+
+		
+		if (empty($issuerFingerprint)) {
+			throw new Exception("Certificate finger print for entity ID [" . $issuer . "] in metadata was empty.");
+		}
+		if (empty($fingerprint)) {
+			throw new Exception("Certificate finger print in message was empty.");
+		}
+
+		if ($fingerprint != $issuerFingerprint) {
+			echo "Expecting fingerprint $issuerFingerprint but got fingerprint $fingerprint .st";
+		}
+	
+		return ($fingerprint == $issuerFingerprint);
+	}
+	
+	
+	public function createSession() {
+	
+	//($protocol, $message = null, $authenticated = true) {
+		SimpleSAML_Session::init(self::PROTOCOL, $this, true);
+		$session = SimpleSAML_Session::getInstance();
+		$session->setAttributes($this->getAttributes());
+		
+		
+		$nameid = $this->getNameID();
+		
+		$session->setNameID($nameid['NameID']);
+		$session->setNameIDFormat($nameid['Format']);
+		$session->setSessionIndex($this->getSessionIndex());
+		/*
+		$nameID["NameID"] = $node->nodeValue;
+		
+				$nameID["NameQualifier"] = $node->getAttribute('NameQualifier');
+				$nameID["SPNameQualifier"] = $node->getAttribute('SPNameQualifier');
+		*/
+		return $session;
+	}
+	
+	//TODO
+	function getSessionIndex() {
+		$token = $this->getDOM();
+		if ($token instanceof DOMDocument) {
+			$xPath = new DOMXpath($token);
+			$xPath->registerNamespace('mysaml', SAML2_ASSERT_NS);
+			$xPath->registerNamespace('mysamlp', SAML2_PROTOCOL_NS);
+	
+			$query = '/mysamlp:Response/mysaml:Assertion/mysaml:AuthnStatement';
+			$nodelist = $xPath->query($query);
+			if ($node = $nodelist->item(0)) {
+				return $node->getAttribute('SessionIndex');
+			}
+		}
+		return NULL;
+	}
+
+	
+	public function getAttributes() {
+
+
+		$md = $this->metadata->getMetadata($this->getIssuer(), 'saml20-idp-remote');
+		
+		$base64 = isset($md['base64attributes']) ? $md['base64attributes'] : false;
+		
+		define('SAML2_ASSERT_NS', 'urn:oasis:names:tc:SAML:2.0:assertion');
+		define('SAML2_PROTOCOL_NS', 'urn:oasis:names:tc:SAML:2.0:protocol');
+		
+		define('SAML2_BINDINGS_POST', 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST');
+		
+		define('SAML2_STATUS_SUCCESS', 'urn:oasis:names:tc:SAML:2.0:status:Success');
+		
+		/*
+		echo 'Validids<pre>';
+		print_r($this->validIDs);
+		echo '</pre>';
+		*/
+
+		$attributes = array();
+		$token = $this->getDOM();
+		
+		
+		//echo '<pre>' . $this->getXML() . '</pre>';
+		
+		
+		if ($token instanceof DOMDocument) {
+		
+			/*
+			echo "<PRE>token:";
+			echo htmlentities($token->saveXML());
+			echo ":</PRE>";
+			*/
+			
+			$xPath = new DOMXpath($token);
+			$xPath->registerNamespace("mysaml", SAML2_ASSERT_NS);
+			$xPath->registerNamespace("mysamlp", SAML2_PROTOCOL_NS);
+			$query = "/mysamlp:Response/mysaml:Assertion/mysaml:Conditions";
+			$nodelist = $xPath->query($query);
+		
+			if ($node = $nodelist->item(0)) {
+		
+				$start = $node->getAttribute("NotBefore");
+				$end = $node->getAttribute("NotOnOrAfter");
+	
+				if (! SimpleSAML_Utilities::checkDateConditions($start, $end)) {
+					error_log( " Date check failed ... (from $start to $end)");
+		
+					return $attributes;
+				}
+			}
+	
+			$valididqueries = array();
+			foreach ($this->validIDs AS $vid) {
+				$valididqueries[] = "@ID='" . $vid . "'";
+			}
+			$valididquery = join(' or ', $valididqueries);
+			
+	
+			foreach (
+				array(
+					"/mysamlp:Response[" . $valididquery . "]/mysaml:Assertion/mysaml:AttributeStatement/mysaml:Attribute",
+					"/mysamlp:Response/mysaml:Assertion[" . $valididquery . "]/mysaml:AttributeStatement/mysaml:Attribute") AS $query) {
+		
+//				echo 'performing query : ' . $query;
+		
+//				$query = "/mysamlp:Response[" . $valididquery . "]/mysaml:Assertion/mysaml:AttributeStatement/mysaml:Attribute";
+				$nodelist = $xPath->query($query);
+				
+
+				
+//				if (is_array($nodelist)) {
+					
+
+					foreach ($nodelist AS $node) {
+
+						if ($name = $node->getAttribute("Name")) {
+//							echo "Name ";
+							$value = array();
+							foreach ($node->childNodes AS $child) {
+								if ($child->localName == "AttributeValue") {
+									$newvalue = $child->textContent;
+									if ($base64) {
+										$values = explode('_', $newvalue);
+										foreach($values AS $v) {
+											$value[] = base64_decode($v);
+										}
+									} else {
+		
+										$value[] = $newvalue;
+									}
+								}
+							}
+							$attributes[$name] = $value;
+						}
+					}
+					
+//				}
+				
+			}
+			
+			
+			
+		}
+/*
+		echo '<p>Attributes<pre>';
+		print_r($attributes);
+		echo '</pre>';
+*/
+		return $attributes;
+	}
+
+	
+	public function getIssuer() {
+		$dom = $this->getDOM();
+		$issuer = null;
+		if ($issuerNodes = $dom->getElementsByTagName('Issuer')) {
+			if ($issuerNodes->length > 0) {
+				$issuer = $issuerNodes->item(0)->textContent;
+			}
+		}
+		return $issuer;
+	}
+	
+	public function getNameID() {
+		
+		$dom = $this->getDOM();
+		$nameID = array();
+		
+		if ($dom instanceof DOMDocument) {
+			$xPath = new DOMXpath($dom);
+			$xPath->registerNamespace('mysaml', SAML2_ASSERT_NS);
+			$xPath->registerNamespace('mysamlp', SAML2_PROTOCOL_NS);
+	
+			$query = '/mysamlp:Response/mysaml:Assertion/mysaml:Subject/mysaml:NameID';
+			$nodelist = $xPath->query($query);
+			if ($node = $nodelist->item(0)) {
+
+				$nameID["NameID"] = $node->nodeValue;
+				$nameID["NameQualifier"] = $node->getAttribute('NameQualifier');
+				$nameID["SPNameQualifier"] = $node->getAttribute('SPNameQualifier');
+				$nameID["Format"] = $node->getAttribute('Format');
+			}
+		}
+		//echo '<pre>'; print_r($nameID); echo '</pre>';
+		return $nameID;
+	}
+	
+
+	// Not updated for response. from request.
+	public function generate($idpentityid, $spentityid, $inresponseto, $nameid, $attributes) {
+	
+		//echo 'idp:' . $idpentityid . ' sp:' . $spentityid .' inresponseto:' .  $inresponseto . ' namid:' . $nameid;
+	
+		$idpmd 	= $this->metadata->getMetaData($idpentityid, 'saml20-idp-hosted');
+		$spmd 	= $this->metadata->getMetaData($spentityid, 'saml20-sp-remote');
+		
+		$id = self::generateID();
+		$issueInstant = self::generateIssueInstant();
+		$assertionExpire = self::generateIssueInstant(60 * 5); # 5 minutes
+		$notBefore = self::generateIssueInstant(-30);
+		
+		$assertionid = self::generateID();
+		$sessionindex = self::generateID();
+		
+
+		$issuer = $idpentityid;
+
+		$assertionConsumerServiceURL = $spmd['assertionConsumerServiceURL'];
+		$spNameQualifier = $spmd['spNameQualifier'];
+		
+		$destination = $spmd['assertionConsumerServiceURL'];
+		
+		$base64 = isset($idpmd['base64attributes']) ? $idpmd['base64attributes'] : false;
+		
+		$encodedattributes = '';
+		foreach ($attributes AS $name => $value) {
+			$encodedattributes .= $this->enc_attribute($name, $value[0], $base64);
+		}
+		$attributestatement = '<saml:AttributeStatement>' . $encodedattributes . '</saml:AttributeStatement>';
+		
+		if (!$spmd['simplesaml.attributes']) 
+			$attributestatement = '';
+		
+		$namid = null;
+		if ($spmd['NameIDFormat'] == self::EMAIL) {
+			$nameid = $this->generateNameID($spmd['NameIDFormat'], $attributes[$spmd['simplesaml.nameidattribute']][0]);
+		} else {
+			$nameid = $this->generateNameID($spmd['NameIDFormat'], self::generateID(), $issuer, $spNameQualifier);
+		}
+		
+		/*
+		$authnResponse = '<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+    ID="' . $id . '"
+    InResponseTo="' . $inresponseto. '" Version="2.0"
+    IssueInstant="' . $issueInstant . '"
+    Destination="' . $destination . '">
+    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">' . $issuer . '</saml:Issuer>
+    <samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
+        <samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+            Value="urn:oasis:names:tc:SAML:2.0:status:Success"> </samlp:StatusCode>
+    </samlp:Status>
+    <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0"
+        ID="' . $assertionid . '" IssueInstant="' . $issueInstant . '">
+        <saml:Issuer>' . $issuer . '</saml:Issuer>
+        <saml:Subject>
+            <saml:NameID NameQualifier="' . $issuer . '" SPNameQualifier="'. $spentityid. '"
+                Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+                >' . $nameid. '</saml:NameID>
+            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+                <saml:SubjectConfirmationData NotOnOrAfter="' . $assertionExpire . '"
+                    InResponseTo="' . $inresponseto. '"
+                    Recipient="' . $destination . '"/>
+            </saml:SubjectConfirmation>
+        </saml:Subject>
+        <saml:Conditions NotBefore="' . $issueInstant. '" NotOnOrAfter="' . $assertionExpire. '">
+            <saml:AudienceRestriction>
+                <saml:Audience>' . $spentityid . '</saml:Audience>
+            </saml:AudienceRestriction>
+        </saml:Conditions>
+        <saml:AuthnStatement AuthnInstant="' . $issueInstant . '"
+            SessionIndex="' . $sessionindex . '">
+            <saml:AuthnContext>
+                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
+            </saml:AuthnContext>
+        </saml:AuthnStatement>
+        <saml:AttributeStatement>
+            ' . $encodedattributes . '
+        </saml:AttributeStatement>
+    </saml:Assertion>
+</samlp:Response>
+';
+
+		
+		$authnResponse = '<samlp:Response 
+    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
+    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
+    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" 
+    ID="' . $id . '" 
+    IssueInstant="' . $issueInstant . '" 
+Version="2.0"> 
+
+    <samlp:Status>
+       <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> 
+    </samlp:Status> 
+    <saml:Assertion ID="' . $assertionid . '" 
+       IssueInstant="' . $issueInstant . '" 
+       Version="2.0"> 
+        <saml:Issuer>' . $issuer . '</saml:Issuer>
+       <saml:Subject> 
+          <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test</saml:NameID> 
+          <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer" /> 
+       </saml:Subject> 
+       <saml:Conditions NotBefore="' . $notBefore. '" NotOnOrAfter="' . $assertionExpire. '"></saml:Conditions> 
+       <saml:AuthnStatement AuthnInstant="' . $issueInstant. '"> 
+          <saml:AuthnContext> 
+             <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> 
+          </saml:AuthnContext> 
+       </saml:AuthnStatement>
+    </saml:Assertion>
+</samlp:Response> 
+';
+*/
+		$authnResponse = '<samlp:Response 
+			xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
+			xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
+			ID="' . $id . '"
+			InResponseTo="' . $inresponseto. '" Version="2.0"
+			IssueInstant="' . $issueInstant . '"
+			Destination="' . $destination . '">
+	<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">' . $issuer . '</saml:Issuer>
+	<samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
+		<samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+			Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
+	</samlp:Status>
+	<saml:Assertion Version="2.0"
+		ID="' . $assertionid . '" IssueInstant="' . $issueInstant . '">
+		<saml:Issuer>' . $issuer . '</saml:Issuer>
+		<saml:Subject>
+			' . $nameid . ' 
+			<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+				<saml:SubjectConfirmationData NotOnOrAfter="' . $assertionExpire . '"
+					InResponseTo="' . $inresponseto. '"
+					Recipient="' . $destination . '"/>
+			</saml:SubjectConfirmation>
+		</saml:Subject>
+		<saml:Conditions NotBefore="' . $notBefore. '" NotOnOrAfter="' . $assertionExpire. '">
+            <saml:AudienceRestriction>
+                <saml:Audience>' . $spentityid . '</saml:Audience>
+            </saml:AudienceRestriction>
+		</saml:Conditions> 
+		<saml:AuthnStatement AuthnInstant="' . $issueInstant . '"
+			SessionIndex="' . $sessionindex . '">
+			<saml:AuthnContext>
+				<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
+			</saml:AuthnContext>
+        </saml:AuthnStatement>
+        ' . $attributestatement. '
+    </saml:Assertion>
+</samlp:Response>
+';
+
+
+//echo $authnResponse;
+
+
+		//  echo $authnResponse; exit(0);
+		return $authnResponse;
+	}
+
+
+	private function generateNameID($type = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', 
+			$value = 'anonymous', $namequalifier = null, $spnamequalifier = null) {
+			
+		if ($type == self::EMAIL) {
+			return '<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">' . $value . '</saml:NameID>';
+
+		} else {
+			return '<saml:NameID NameQualifier="' . $namequalifier . '" SPNameQualifier="'. $spnamequalifier. '"
+                Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+                >' . $value. '</saml:NameID>';
+		}
+		
+	}
+
+	
+	private function enc_attribute($name,$value, $base64 = false) {
+		return '<saml:Attribute Name="' . $name. '">
+                <saml:AttributeValue xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+                >' . ($base64 ? base64_encode($value) : htmlspecialchars($value) ) . '</saml:AttributeValue>
+            </saml:Attribute>';
+	}
+	
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XML/SAML20/LogoutRequest.php b/lib/SimpleSAML/XML/SAML20/LogoutRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8dfb35d6ac8e2ccdc927f80b486f441d6e1ba4f7
--- /dev/null
+++ b/lib/SimpleSAML/XML/SAML20/LogoutRequest.php
@@ -0,0 +1,182 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_XML_SAML20_LogoutRequest {
+
+	private $configuration = null;
+	private $metadata = null;
+	
+	private $message = null;
+	private $dom;
+	private $relayState = null;
+	
+	
+	const PROTOCOL = 'urn:oasis:names:tc:SAML:2.0';
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	public function setXML($xml) {
+		$this->message = $xml;
+	}
+	
+	public function getXML() {
+		return $this->message;
+	}
+	
+	public function setRelayState($relayState) {
+		$this->relayState = $relayState;
+	}
+	
+	public function getRelayState() {
+		return $this->relayState;
+	}
+	
+	public function getDOM() {
+		if (isset($this->message) ) {
+		
+			/* if (isset($this->dom) && $this->dom != null ) {
+				return $this->dom;
+			} */
+		
+			$token = new DOMDocument();
+			$token->loadXML(str_replace ("\r", "", $this->message));
+			if (empty($token)) {
+				throw new Exception("Unable to load token");
+			}
+			$this->dom = $token;
+			return $this->dom;
+		
+		} 
+		
+		return null;
+	}
+	
+	
+	public function getIssuer() {
+		$dom = $this->getDOM();
+		$issuer = null;
+		
+		if (!$dom instanceof DOMDocument) {
+			throw new Exception("Could not get message DOM in AuthnRequest object");
+		}
+		
+		//print_r($dom->saveXML());
+		
+		if ($issuerNodes = $dom->getElementsByTagName('Issuer')) {
+			if ($issuerNodes->length > 0) {
+				$issuer = $issuerNodes->item(0)->textContent;
+			}
+		}
+		return $issuer;
+	}
+	
+	public function getRequestID() {
+		$dom = $this->getDOM();
+		$requestid = null;
+		
+		if (empty($dom)) {
+			throw new Exception("Could not get message DOM in AuthnRequest object");
+		}
+		
+		$requestelement = $dom->getElementsByTagName('LogoutRequest')->item(0);
+		$requestid = $requestelement->getAttribute('ID');
+		return $requestid;
+		/*
+		if ($issuerNodes = $dom->getElementsByTagName('Issuer')) {
+			if ($issuerNodes->length > 0) {
+				$requestid = $issuerNodes->item(0)->textContent;
+			}
+		}
+		return $requestid;	
+		*/
+	}
+	
+
+
+	public function generate($issuer, $receiver, $nameid, $nameidformat, $sessionindex, $mode) {
+	
+		if (!in_array($mode, array('SP', 'IdP'))) {
+			throw new Exception('mode parameter of generate() must be either SP or IdP');
+		}
+		if ($mode == 'IdP') {
+			$issuerset = 'saml20-idp-hosted';
+			$receiverset = 'saml20-sp-remote';
+		} else {
+			$issuerset = 'saml20-sp-hosted';
+			$receiverset = 'saml20-idp-remote';
+		}
+	
+		$issuermd 	= $this->metadata->getMetaData($issuer, $issuerset);
+		$receivermd = $this->metadata->getMetaData($receiver, $receiverset);
+		
+		$id = self::generateID();
+		$issueInstant = self::generateIssueInstant();
+
+		$destination = $receivermd['SingleLogOutUrl'];
+
+/*
+		$spNameQualifier = $md['spNameQualifier'];
+		$nameidformat = isset($md['NameIDformat']) ? 
+			$md['NameIDformat'] : 
+			'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent';
+	*/	
+		$logoutRequest = "<samlp:LogoutRequest " .
+      "xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" " . 
+      "ID=\"" . $id . "\" " .
+      "Version=\"2.0\" " .
+      "IssueInstant=\"" . $issueInstant . "\"> " .
+        "<saml:Issuer " . 
+        "xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" .
+          $issuer .
+        "</saml:Issuer>" .
+        "<saml:NameID " . 
+        "xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" " . 
+//        "NameQualifier=\"" . $nameId["NameQualifier"] . "\" " . 
+//        "SPNameQualifier=\"" . $nameId["SPNameQualifier"] . "\" " . 
+        "Format=\"" .  $nameidformat. "\">" . 
+          $nameid . 
+        "</saml:NameID>" . 
+        "<samlp:SessionIndex " .
+        "xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">" . 
+          $sessionindex .
+        "</samlp:SessionIndex>" .
+      "</samlp:LogoutRequest>";
+		  
+		return $logoutRequest;
+	}
+	
+	public static function generateID() {
+	
+		$length = 42;
+		$key = "_";
+		for ( $i=0; $i < $length; $i++ )
+		{
+			 $key .= dechex( rand(0,15) );
+		}
+		return $key;
+	}
+	
+	public static function generateIssueInstant() {
+		return gmdate("Y-m-d\TH:i:s\Z");
+	}
+
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XML/SAML20/LogoutResponse.php b/lib/SimpleSAML/XML/SAML20/LogoutResponse.php
new file mode 100644
index 0000000000000000000000000000000000000000..c83cde7198ae95b864e1308f6afa486668a3d751
--- /dev/null
+++ b/lib/SimpleSAML/XML/SAML20/LogoutResponse.php
@@ -0,0 +1,152 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+
+require_once('xmlseclibs.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_XML_SAML20_LogoutResponse {
+
+	private $configuration = null;
+	private $metadata = null;
+	
+	private $message = null;
+	private $dom;
+	private $relayState = null;
+	
+	const PROTOCOL = 'urn:oasis:names:tc:SAML:2.0';
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	public function setXML($xml) {
+		$this->message = $xml;
+	}
+	
+	public function getXML() {
+		return $this->message;
+	}
+	
+	public function setRelayState($relayState) {
+		$this->relayState = $relayState;
+	}
+	
+	public function getRelayState() {
+		return $this->relayState;
+	}
+	
+	public function getDOM() {
+		if (isset($this->message) ) {
+			
+			/*
+			if (isset($this->dom)) {
+				return $this->dom;
+			}
+			*/
+		
+			$token = new DOMDocument();
+			$token->loadXML(str_replace ("\r", "", $this->message));
+			if (empty($token)) {
+				throw new Exception("Unable to load token");
+			}
+			$this->dom = $token;
+			return $this->dom;
+		
+		} 
+		
+		return null;
+	}
+	
+
+	
+	public function getIssuer() {
+		$dom = $this->getDOM();
+		$issuer = null;
+		if ($issuerNodes = $dom->getElementsByTagName('Issuer')) {
+			if ($issuerNodes->length > 0) {
+				$issuer = $issuerNodes->item(0)->textContent;
+			}
+		}
+		return $issuer;
+	}
+
+
+	// Not updated for response. from request.
+	public function generate($issuer, $receiver, $inresponseto, $mode ) {
+		if (!in_array($mode, array('SP', 'IdP'))) {
+			throw new Exception('mode parameter of generate() must be either SP or IdP');
+		}
+		if ($mode == 'IdP') {
+			$issuerset = 'saml20-idp-hosted';
+			$receiverset = 'saml20-sp-remote';
+		} else {
+			$issuerset = 'saml20-sp-hosted';
+			$receiverset = 'saml20-idp-remote';
+		}
+		
+	
+		//echo 'idp:' . $idpentityid . ' sp:' . $spentityid .' inresponseto:' .  $inresponseto . ' namid:' . $nameid;
+	
+		$issuermd 	= $this->metadata->getMetaData($issuer, $issuerset);
+		$receivermd = $this->metadata->getMetaData($receiver, $receiverset);
+		
+		$id = self::generateID();
+		$issueInstant = self::generateIssueInstant();
+
+		$destination = $receivermd['SingleLogOutUrl'];
+		
+		$samlResponse = '<samlp:LogoutResponse  xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+ID="_' . $id . '" Version="2.0" IssueInstant="' . $issueInstant . '" Destination="'. $destination. '" InResponseTo="' . $inresponseto . '">
+<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">' . $issuer . '</saml:Issuer>
+<samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
+<samlp:StatusCode  xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+Value="urn:oasis:names:tc:SAML:2.0:status:Success">
+</samlp:StatusCode>
+<samlp:StatusMessage xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
+Successfully logged out from service ' . $issuer . '
+</samlp:StatusMessage>
+</samlp:Status>
+</samlp:LogoutResponse>';
+
+		return $samlResponse;
+	}
+
+
+	
+	
+	public static function generateID() {
+	
+		$length = 42;
+		$key = "_";
+		for ( $i=0; $i < $length; $i++ )
+		{
+			 $key .= dechex( rand(0,15) );
+		}
+		return $key;
+	}
+	
+	public static function generateIssueInstant($offset = 0) {
+		return gmdate("Y-m-d\TH:i:s\Z", time() + $offset);
+	}
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XML/Shib13/AuthnRequest.php b/lib/SimpleSAML/XML/Shib13/AuthnRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef7c0c9aa034b0af09f749899da580df8e7c7a3b
--- /dev/null
+++ b/lib/SimpleSAML/XML/Shib13/AuthnRequest.php
@@ -0,0 +1,114 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_XML_Shib13_AuthnRequest {
+
+	private $configuration = null;
+	private $metadata = null;
+	
+	private $issuer = null;
+	private $relayState = null;
+	
+	private $requestid = null;
+	
+	
+	const PROTOCOL = 'shibboleth';
+
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	public function setRelayState($relayState) {
+		$this->relayState = $relayState;
+	}
+	
+	public function getRelayState() {
+		return $this->relayState;
+	}
+	
+	public function setIssuer($issuer) {
+		$this->issuer = $issuer;
+	}
+	public function getIssuer() {
+		return $this->issuer;
+	}
+	
+
+
+	public function parseGet($get) {
+		return null;
+	}
+	
+	public function setNewRequestID() {	
+		$this->requestid = $this->generateID();
+	}
+	
+	public function getRequestID() {
+		return $this->requestid;
+	}
+	
+	public function createSession() {
+		
+		$session = SimpleSAML_Session::getInstance();
+		
+		if (!isset($session)) {
+			SimpleSAML_Session::init(self::PROTOCOL);
+			$session = SimpleSAML_Session::getInstance();
+		}
+
+		$session->setAuthnRequest($this->getRequestID(), $this);
+		
+		/*
+		if (isset($this->relayState)) {
+			$session->setRelayState($this->relayState);
+		}
+		*/
+		return $session;
+	}
+	
+	public function createRedirect($destination) {
+		$idpmetadata = $this->metadata->getMetaData($destination, 'shib13-idp-remote');
+		$spmetadata = $this->metadata->getMetaData($this->getIssuer(), 'shib13-sp-hosted');
+	
+		$desturl = $idpmetadata['SingleSignOnUrl'];
+		$shire = $spmetadata['AssertionConsumerService'];
+		$target = $this->getRelayState();
+		
+		$url = $desturl . '?' .
+	    	'providerId=' . urlencode($this->getIssuer()) .
+		    '&shire=' . urlencode($shire) .
+		    (isset($target) ? '&target=' . urlencode($target) : '');
+		return $url;
+	}
+	
+	public static function generateID() {
+		$length = 42;
+		$key = "_";
+		for ( $i=0; $i < $length; $i++ ) {
+			 $key .= dechex( rand(0,15) );
+		}
+		return $key;
+	}
+	
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/XML/Shib13/AuthnResponse.php b/lib/SimpleSAML/XML/Shib13/AuthnResponse.php
new file mode 100644
index 0000000000000000000000000000000000000000..22412500c8d8432a5520edbc4447ddfc637b6ad4
--- /dev/null
+++ b/lib/SimpleSAML/XML/Shib13/AuthnResponse.php
@@ -0,0 +1,398 @@
+<?php
+
+
+/**
+ * SimpleSAMLphp
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ */
+ 
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/AuthnResponse.php');
+
+require_once('xmlseclibs.php');
+ 
+/**
+ * Configuration of SimpleSAMLphp
+ */
+class SimpleSAML_XML_Shib13_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
+
+	private $configuration = null;
+	private $metadata = 'default.php';
+	
+	private $message = null;
+	private $dom;
+	private $relayState = null;
+	
+	private $validIDs = null;
+	
+	const PROTOCOL = 'urn:oasis:names:tc:SAML:2.0';
+	const SHIB_PROTOCOL_NS = 'urn:oasis:names:tc:SAML:1.0:protocol';
+	const SHIB_ASSERT_NS = 'urn:oasis:names:tc:SAML:1.0:assertion';
+
+	function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_XML_MetaDataStore $metadatastore) {
+		$this->configuration = $configuration;
+		$this->metadata = $metadatastore;
+	}
+	
+	// Inhereted public function setXML($xml) {
+	// Inhereted public function getXML() {
+	// Inhereted public function setRelayState($relayState) {
+	// Inhereted public function getRelayState() {
+
+	
+	public function validate() {
+	
+		$dom = $this->getDOM();
+		
+		/* Create an XML security object, and register ID as the id attribute for sig references. */
+		$objXMLSecDSig = new XMLSecurityDSig();
+		$objXMLSecDSig->idKeys[] = 'ResponseID';
+		
+		/* Locate the signature element to be used. */
+		$objDSig = $objXMLSecDSig->locateSignature($dom);
+		
+
+		/* If no signature element was found, throw an error */
+		if (!$objDSig) {
+			throw new Exception("Could not locate XML Signature element in Authentication Response");
+		}
+		
+		
+		/* Must check certificate fingerprint now - validateReference removes it */        
+		// TODO FIX"!!!
+		if ( ! $this->validateCertFingerprint($objDSig) ) {
+			throw new Exception("Fingerprint Validation Failed");
+		}
+
+		/* Get information about canoncalization in to the xmlsec library. Read from the siginfo part. */
+		$objXMLSecDSig->canonicalizeSignedInfo();
+		
+		$refids = $objXMLSecDSig->getRefIDs();
+		
+		
+		
+		/* Validate refrences */
+		$retVal = $objXMLSecDSig->validateReference();
+		if (! $retVal) {
+			throw new Exception("XMLsec: digest validation failed");
+		}
+
+		$key = NULL;
+		$objKey = $objXMLSecDSig->locateKey();
+	
+		if ($objKey) {
+			if ($objKeyInfo = XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig)) {
+				/* Handle any additional key processing such as encrypted keys here */
+			}
+		}
+	
+		if (empty($objKey)) {
+			throw new Exception("Error loading key to handle Signature");
+		}
+
+		if (! $objXMLSecDSig->verify($objKey)) {
+			throw new Exception("Unable to validate Signature");
+		}
+		
+		$this->validIDs = $refids;
+		return true;
+	}
+	
+	
+	
+	
+	function validateCertFingerprint($dom) {
+//		$dom = $this->getDOM();
+		$fingerprint = "";
+		
+		
+		// Find the certificate in the document.
+		if ($x509certNodes = $dom->getElementsByTagName('X509Certificate')) {
+			if ($x509certNodes->length > 0) {
+				$x509cert = $x509certNodes->item(0)->textContent;
+				$x509data = base64_decode( $x509cert );
+				$fingerprint = strtolower( sha1( $x509data ) );
+			}
+		}
+	
+		// Get the issuer of the assertion.
+		$issuer = $this->getIssuer();
+		
+		//echo 'found issuer: ' . $this->getIssuer();
+		$md = $this->metadata->getMetaData($issuer, 'shib13-idp-remote');
+		
+		/*
+		 * Get fingerprint from saml20-idp-remote metadata...
+		 * 
+		 * Accept fingerprints with or without colons, case insensitive
+		 */
+		$issuerFingerprint = strtolower( str_replace(":", "", $md['certFingerprint']) );
+	
+		//echo 'issuer fingerprint: ' . $issuerFingerprint;
+		
+		if (empty($issuerFingerprint)) {
+			throw new Exception("Certificate finger print for entity ID [" . $issuer . "] in metadata was empty.");
+		}
+		if (empty($fingerprint)) {
+			throw new Exception("Certificate finger print in message was empty.");
+		}
+
+		if ($fingerprint != $issuerFingerprint) {
+			throw new Exception("Expecting certificate fingerprint [$issuerFingerprint] but got [$fingerprint]");
+		}
+	
+		return ($fingerprint == $issuerFingerprint);
+	}
+	
+	
+	public function createSession() {
+	
+		SimpleSAML_Session::init(self::PROTOCOL, $this, true);
+		$session = SimpleSAML_Session::getInstance();
+		$session->setAttributes($this->getAttributes());
+		
+		$nameid = $this->getNameID();
+		
+		$session->setNameID($nameid['NameID']);
+		$session->setNameIDFormat($nameid['Format']);
+		$session->setSessionIndex($this->getSessionIndex());
+		/*
+		$nameID["NameID"] = $node->nodeValue;
+		
+				$nameID["NameQualifier"] = $node->getAttribute('NameQualifier');
+				$nameID["SPNameQualifier"] = $node->getAttribute('SPNameQualifier');
+		*/
+		return $session;
+	}
+	
+	//TODO
+	function getSessionIndex() {
+		$token = $this->getDOM();
+		if ($token instanceof DOMDocument) {
+			$xPath = new DOMXpath($token);
+			$xPath->registerNamespace('mysamlp', self::SHIB_PROTOCOL_NS);
+			$xPath->registerNamespace('mysaml', self::SHIB_ASSERT_NS);
+			
+			$query = '/mysamlp:Response/mysaml:Assertion/mysaml:AuthnStatement';
+			$nodelist = $xPath->query($query);
+			if ($node = $nodelist->item(0)) {
+				return $node->getAttribute('SessionIndex');
+			}
+		}
+		return NULL;
+	}
+
+	
+	public function getAttributes() {
+
+
+		$md = $this->metadata->getMetadata($this->getIssuer(), 'shib13-idp-remote');
+		
+		//$base64 = isset($md['base64attributes']) ? $md['base64attributes'] : false;
+		
+		/*
+		define('SAML2_BINDINGS_POST', 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST');
+		define('SAML2_STATUS_SUCCESS', 'urn:oasis:names:tc:SAML:2.0:status:Success');
+		*/
+		
+		/*
+		echo 'Validids<pre>';
+		print_r($this->validIDs);
+		echo '</pre>';
+		*/
+
+		$attributes = array();
+		$token = $this->getDOM();
+			
+		
+		//echo $this->getXML();
+		
+		$attributes = array();
+		
+		if ($token instanceof DOMDocument) {
+		
+			$sxml = simplexml_import_dom($token);
+			
+			$sxml->registerXPathNamespace('samlp', self::SHIB_PROTOCOL_NS);
+			$sxml->registerXPathNamespace('saml', self::SHIB_ASSERT_NS);
+			
+
+			
+			$assertions = $sxml->xpath('/samlp:Response[@ResponseID="' . $this->validIDs[0] . '"]/saml:Assertion');
+
+			foreach ($assertions AS $assertion) {				
+
+				if ($assertion->Conditions) {
+
+					if (($start = (string)$assertion->Conditions['NotBefore']) &&
+						($end = (string)$assertion->Conditions['NotOnOrAfter'])) {
+	
+						if (! SimpleSAML_Utilities::checkDateConditions($start, $end)) {
+							error_log( " Date check failed ... (from $start to $end)");
+							next;
+						} 
+
+					}
+
+				}
+				
+				if (isset($assertion->AttributeStatement->Attribute)) {
+					foreach ($assertion->AttributeStatement->Attribute AS $attribute) {
+						$values = array();
+						foreach ($attribute->AttributeValue AS $val) {
+							$values[] = (string) $val;
+						}
+						
+						$attributes[(string)$attribute['AttributeName']] = $values;
+					}
+				}
+				
+			}
+		
+		
+			/*
+			echo "<PRE>token:";
+			echo htmlentities($token->saveXML());
+			echo ":</PRE>";
+			*/
+			/*
+			echo '<pre>Attributes: ';
+			print_r($attributes);
+			echo '</pre>';
+	*/
+		}
+		return $attributes;
+		
+		
+	}
+
+	
+	public function getIssuer() {
+	
+		$token = $this->getDOM();
+		$xPath = new DOMXpath($token);
+		$xPath->registerNamespace('mysamlp', self::SHIB_PROTOCOL_NS);
+		$xPath->registerNamespace('mysaml', self::SHIB_ASSERT_NS);
+
+		$query = '/mysamlp:Response/mysaml:Assertion/@Issuer';
+		$nodelist = $xPath->query($query);
+
+		if ($attr = $nodelist->item(0)) {
+			return $attr->value;
+		} else {
+			throw Exception('Could not find Issuer field in Authentication response');
+		}
+
+	}
+	
+	public function getNameID() {
+		
+		
+		$token = $this->getDOM();
+		$nameID = array();
+		if ($token instanceof DOMDocument) {
+			$xPath = new DOMXpath($token);
+			$xPath->registerNamespace('mysamlp', self::SHIB_PROTOCOL_NS);
+			$xPath->registerNamespace('mysaml', self::SHIB_ASSERT_NS);
+	
+			$query = '/mysamlp:Response/mysaml:Assertion/mysaml:AuthenticationStatement/mysaml:Subject/mysaml:NameIdentifier';
+			$nodelist = $xPath->query($query);
+			if ($node = $nodelist->item(0)) {
+				$nameID["NameID"] = $node->nodeValue;
+				$nameID["Format"] = $node->getAttribute('Format');
+				$nameID["NameQualifier"] = $node->getAttribute('NameQualifier');
+			}
+		}
+		return $nameID;
+
+	}
+	
+
+	// Not updated for response. from request.
+	public function generate($idpentityid, $spentityid, $inresponseto, $nameid, $attributes) {
+	
+		//echo 'idp:' . $idpentityid . ' sp:' . $spentityid .' inresponseto:' .  $inresponseto . ' namid:' . $nameid;
+	
+		$idpmd 	= $this->metadata->getMetaData($idpentityid, 'saml20-idp-hosted');
+		$spmd 	= $this->metadata->getMetaData($spentityid, 'saml20-sp-remote');
+		
+		$id = self::generateID();
+		$issueInstant = self::generateIssueInstant();
+		$assertionExpire = self::generateIssueInstant(60 * 5); # 5 minutes
+		
+		$assertionid = self::generateID();
+		$sessionindex = self::generateID();
+		
+		if (is_null($nameid)) {
+			$nameid = self::generateID();
+		}
+
+		$issuer = $idpentityid;
+
+		$assertionConsumerServiceURL = $spmd['assertionConsumerServiceURL'];
+		$spNameQualifier = $spmd['spNameQualifier'];
+		
+		$destination = $spmd['assertionConsumerServiceURL'];
+		
+		$encodedattributes = '';
+		foreach ($attributes AS $name => $value) {
+			$encodedattributes .= $this->enc_attribute($name, $value[0], true);
+		}
+		
+		$authnResponse = '<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+    ID="' . $id . '"
+    InResponseTo="' . $inresponseto. '" Version="2.0"
+    IssueInstant="' . $issueInstant . '"
+    Destination="' . $destination . '">
+    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">' . $issuer . '</saml:Issuer>
+    <samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
+        <samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+            Value="urn:oasis:names:tc:SAML:2.0:status:Success"> </samlp:StatusCode>
+    </samlp:Status>
+    <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0"
+        ID="' . $assertionid . '" IssueInstant="' . $issueInstant . '">
+        <saml:Issuer>' . $issuer . '</saml:Issuer>
+        <saml:Subject>
+            <saml:NameID NameQualifier="' . $issuer . '" SPNameQualifier="'. $spentityid. '"
+                Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+                >' . $nameid. '</saml:NameID>
+            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+                <saml:SubjectConfirmationData NotOnOrAfter="' . $assertionExpire . '"
+                    InResponseTo="' . $inresponseto. '"
+                    Recipient="' . $destination . '"/>
+            </saml:SubjectConfirmation>
+        </saml:Subject>
+        <saml:Conditions NotBefore="' . $issueInstant. '" NotOnOrAfter="' . $assertionExpire. '">
+            <saml:AudienceRestriction>
+                <saml:Audience>' . $spentityid . '</saml:Audience>
+            </saml:AudienceRestriction>
+        </saml:Conditions>
+        <saml:AuthnStatement AuthnInstant="' . $issueInstant . '"
+            SessionIndex="' . $sessionindex . '">
+            <saml:AuthnContext>
+                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
+            </saml:AuthnContext>
+        </saml:AuthnStatement>
+        <saml:AttributeStatement>
+            ' . $encodedattributes . '
+        </saml:AttributeStatement>
+    </saml:Assertion>
+</samlp:Response>
+';
+		  
+		return $authnResponse;
+	}
+
+
+	
+
+	
+}
+
+?>
\ No newline at end of file
diff --git a/lib/xmlseclibs.php b/lib/xmlseclibs.php
new file mode 100644
index 0000000000000000000000000000000000000000..f441eafd9040959ed0bb4aaa72a5bb00fe513911
--- /dev/null
+++ b/lib/xmlseclibs.php
@@ -0,0 +1,1387 @@
+<?php 
+/**
+ * xmlseclibs.php
+ *
+ * Copyright (c) 2007, Robert Richards <rrichards@ctindustries.net>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ *   * Neither the name of Robert Richards nor the names of his
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author     Robert Richards <rrichards@ctindustries.net>
+ * @copyright  2007 Robert Richards <rrichards@ctindustries.net>
+ * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
+ * @version    1.0.0
+ */
+ 
+/*
+Functions to generate simple cases of Exclusive Canonical XML - Callable function is C14NGeneral() 
+i.e.: $canonical = C14NGeneral($domelement, TRUE);
+*/
+
+/* helper function */
+function sortAndAddAttrs($element, $arAtts) {
+   $newAtts = array();
+   foreach ($arAtts AS $attnode) {
+      $newAtts[$attnode->nodeName] = $attnode;
+   }
+   ksort($newAtts);
+   foreach ($newAtts as $attnode) {
+      $element->setAttribute($attnode->nodeName, $attnode->nodeValue);
+   }
+}
+
+/* helper function */
+function canonical($tree, $element, $withcomments) {
+	if ($tree->nodeType != XML_DOCUMENT_NODE) {
+		$dom = $tree->ownerDocument;
+	} else {
+		$dom = $tree;
+	}
+	if ($element->nodeType != XML_ELEMENT_NODE) {
+		if ($element->nodeType == XML_COMMENT_NODE && ! $withcomments) {
+			return;
+		}
+		$tree->appendChild($dom->importNode($element, TRUE));
+		return;
+	}
+	$arNS = array();
+	if ($element->namespaceURI != "") {
+		if ($element->prefix == "") {
+			$elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
+		} else {
+			$prefix = $tree->lookupPrefix($element->namespaceURI);
+			if ($prefix == $element->prefix) {
+				$elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
+			} else {
+				$elCopy = $dom->createElement($element->nodeName);
+				$arNS[$element->namespaceURI] = $element->prefix;
+			}
+		}
+	} else {
+		$elCopy = $dom->createElement($element->nodeName);
+	}
+	$tree->appendChild($elCopy);
+
+	/* Create DOMXPath based on original document */
+	$xPath = new DOMXPath($element->ownerDocument);
+
+	/* Get namespaced attributes */
+	$arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element);
+
+	/* Create an array with namespace URIs as keys, and sort them */
+	foreach ($arAtts AS $attnode) {
+		if (array_key_exists($attnode->namespaceURI, $arNS) && 
+			($arNS[$attnode->namespaceURI] == $attnode->prefix)) {
+			continue;
+		}
+		$prefix = $tree->lookupPrefix($attnode->namespaceURI);
+		if ($prefix != $attnode->prefix) {
+		   $arNS[$attnode->namespaceURI] = $attnode->prefix;
+		} else {
+			$arNS[$attnode->namespaceURI] = NULL;
+		}
+	}
+	if (count($arNS) > 0) {
+		asort($arNS);
+	}
+
+	/* Add namespace nodes */
+	foreach ($arNS AS $namespaceURI=>$prefix) {
+		if ($prefix != NULL) {
+	      	$elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/",
+                               "xmlns:".$prefix, $namespaceURI);
+		}
+	}
+	if (count($arNS) > 0) {
+		ksort($arNS);
+	}
+
+	/* Get attributes not in a namespace, and then sort and add them */
+	$arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element);
+	sortAndAddAttrs($elCopy, $arAtts);
+
+	/* Loop through the URIs, and then sort and add attributes within that namespace */
+	foreach ($arNS as $nsURI=>$prefix) {
+	   $arAtts = $xPath->query('attribute::*[namespace-uri(.) = "'.$nsURI.'"]', $element);
+	   sortAndAddAttrs($elCopy, $arAtts);
+	}
+
+	foreach ($element->childNodes AS $node) {
+		canonical($elCopy, $node, $withcomments);
+	}
+}
+
+/*
+$element - DOMElement for which to produce the canonical version of
+$exclusive - boolean to indicate exclusive canonicalization (must pass TRUE)
+$withcomments - boolean indicating wether or not to include comments in canonicalized form
+*/
+function C14NGeneral($element, $exclusive=FALSE, $withcomments=FALSE) {
+	/* IF PHP 5.2+ then use built in canonical functionality */
+	$php_version = explode('.', PHP_VERSION);
+	if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2) ) {
+		return $element->C14N($exclusive, $withcomments);
+	}
+
+	/* Must be element */
+	if (! $element instanceof DOMElement) {
+		return NULL;
+	}
+	/* Currently only exclusive XML is supported */
+	if ($exclusive == FALSE) {
+		throw new Exception("Only exclusive canonicalization is supported in this version of PHP");
+	}
+	
+	$copyDoc = new DOMDocument();
+	canonical($copyDoc, $element, $withcomments);
+	return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG);
+}
+
+class XMLSecurityKey {
+	const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
+	const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
+	const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
+	const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
+	const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
+	const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
+	const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
+	const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
+
+	private $cryptParams = array();
+	public $type = 0;
+	public $key = NULL;
+	public $passphrase = "";
+	public $iv = NULL;
+	public $name = NULL;
+	public $keyChain = NULL;
+	public $isEncrypted = FALSE;
+	public $encryptedCtx = NULL;
+	public $guid = NULL;
+
+	public function __construct($type, $params=NULL) {
+		switch ($type) {
+			case (XMLSecurityKey::TRIPLEDES_CBC):
+				$this->cryptParams['library'] = 'mcrypt';
+				$this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
+				break;
+			case (XMLSecurityKey::AES128_CBC):
+				$this->cryptParams['library'] = 'mcrypt';
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
+				break;
+			case (XMLSecurityKey::AES192_CBC):
+				$this->cryptParams['library'] = 'mcrypt';
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
+				break;
+			case (XMLSecurityKey::AES256_CBC):
+				$this->cryptParams['library'] = 'mcrypt';
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
+				break;
+			case (XMLSecurityKey::RSA_1_5):
+				$this->cryptParams['library'] = 'openssl';
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
+				if (is_array($params) && ! empty($params['type'])) {
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
+						$this->cryptParams['type'] = $params['type'];
+						break;
+					}
+				}
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+				return;
+			case (XMLSecurityKey::RSA_OAEP_MGF1P):
+				$this->cryptParams['library'] = 'openssl';
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
+				$this->cryptParams['hash'] = NULL;
+				if (is_array($params) && ! empty($params['type'])) {
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
+						$this->cryptParams['type'] = $params['type'];
+						break;
+					}
+				}
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+				return;
+			case (XMLSecurityKey::RSA_SHA1):
+				$this->cryptParams['library'] = 'openssl';
+				$this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
+				if (is_array($params) && ! empty($params['type'])) {
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
+						$this->cryptParams['type'] = $params['type'];
+						break;
+					}
+				}
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+				break;
+			default:
+				throw new Exception('Invalid Key Type');
+				return;
+		}
+		$this->type = $type;
+	}
+
+	public function generateSessionKey() {
+		$key = '';
+		if (! empty($this->cryptParams['cipher']) && ! empty($this->cryptParams['mode'])) {
+			$keysize = mcrypt_module_get_algo_key_size($this->cryptParams['cipher']);
+			/* Generating random key using iv generation routines */
+			if (($keysize > 0) && ($td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '',$this->cryptParams['mode'], ''))) {
+				if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
+					$keysize = 16;
+					if ($this->type == XMLSecurityKey::AES256_CBC) {
+						$keysize = 32;
+					} elseif ($this->type == XMLSecurityKey::AES192_CBC) {
+						$keysize = 24;
+					}
+				}
+				while (strlen($key) < $keysize) {
+					$key .= mcrypt_create_iv(mcrypt_enc_get_iv_size ($td),MCRYPT_RAND);
+				}
+				mcrypt_module_close($td);
+				$key = substr($key, 0, $keysize);
+				$this->key = $key;
+			}
+		}
+		return $key;
+	}
+
+	public function loadKey($key, $isFile=FALSE, $isCert = FALSE) {
+		if ($isFile) {
+			$this->key = file_get_contents($key);
+		} else {
+			$this->key = $key;
+		}
+		if ($isCert) {
+			$this->key = openssl_x509_read($this->key);
+			openssl_x509_export($this->key, $str_cert);
+			$this->key = $str_cert;
+		}
+		if ($this->cryptParams['library'] == 'openssl') {
+			if ($this->cryptParams['type'] == 'public') {
+				$this->key = openssl_get_publickey($this->key);
+			} else {
+				$this->key = openssl_get_privatekey($this->key, $this->passphrase);
+			}
+		} else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
+			/* Check key length */
+			switch ($this->type) {
+				case (XMLSecurityKey::AES256_CBC):
+					if (strlen($this->key) < 25) {
+						throw new Exception('Key must contain at least 25 characters for this cipher');
+					}
+					break;
+				case (XMLSecurityKey::AES192_CBC):
+					if (strlen($this->key) < 17) {
+						throw new Exception('Key must contain at least 17 characters for this cipher');
+					}
+					break;
+			}
+		}
+	}
+
+	private function encryptMcrypt($data) {
+    	$td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
+	    $this->iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
+	    mcrypt_generic_init($td, $this->key, $this->iv);
+    	$encrypted_data = $this->iv.mcrypt_generic($td, $data);
+	    mcrypt_generic_deinit($td);
+    	mcrypt_module_close($td);
+		return $encrypted_data;
+	}
+
+	private function decryptMcrypt($data) {
+    	$td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
+		$iv_length = mcrypt_enc_get_iv_size($td);
+
+		$this->iv = substr($data, 0, $iv_length);
+		$data = substr($data, $iv_length);
+
+	    mcrypt_generic_init($td, $this->key, $this->iv);
+    	$decrypted_data = mdecrypt_generic($td, $data);
+	    mcrypt_generic_deinit($td);
+    	mcrypt_module_close($td);
+		if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
+	        $dataLen = strlen($decrypted_data);
+			$paddingLength = substr($decrypted_data, $dataLen - 1, 1);
+        	$decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
+		}
+		return $decrypted_data;
+	}
+
+	private function encryptOpenSSL($data) {
+		if ($this->cryptParams['type'] == 'public') {
+			if (! openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
+				throw new Exception('Failure encrypting Data');
+				return;
+			}
+		} else {
+			if (! openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
+				throw new Exception('Failure encrypting Data');
+				return;
+			}
+		}
+		return $encrypted_data;
+	}
+
+	private function decryptOpenSSL($data) {
+		if ($this->cryptParams['type'] == 'public') {
+			if (! openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
+				throw new Exception('Failure decrypting Data');
+				return;
+			}
+		} else {
+			if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
+				throw new Exception('Failure decrypting Data');
+				return;
+			}
+		}
+		return $decrypted;
+	}
+
+	private function signOpenSSL($data) {
+		if (! openssl_sign ($data, $signature, $this->key)) {
+			throw new Exception('Failure Signing Data');
+			return;
+		}
+		return $signature;
+	}
+
+	private function verifyOpenSSL($data, $signature) {
+		return openssl_verify ($data, $signature, $this->key);
+	}
+
+	public function encryptData($data) {
+		switch ($this->cryptParams['library']) {
+			case 'mcrypt':
+				return $this->encryptMcrypt($data);
+				break;
+			case 'openssl':
+				return $this->encryptOpenSSL($data);
+				break;
+		}
+	}
+
+	public function decryptData($data) {
+		switch ($this->cryptParams['library']) {
+			case 'mcrypt':
+				return $this->decryptMcrypt($data);
+				break;
+			case 'openssl':
+				return $this->decryptOpenSSL($data);
+				break;
+		}
+	}
+
+	public function signData($data) {
+		switch ($this->cryptParams['library']) {
+			case 'openssl':
+				return $this->signOpenSSL($data);
+				break;
+		}
+	}
+
+	public function verifySignature($data, $signature) {
+		switch ($this->cryptParams['library']) {
+			case 'openssl':
+				return $this->verifyOpenSSL($data, $signature);
+				break;
+		}
+	}
+
+	public function getAlgorith() {
+		return $this->cryptParams['method'];
+	}
+
+	static function makeAsnSegment($type, $string) {
+		switch ($type){
+			case 0x02:
+				if (ord($string) > 0x7f)
+					$string = chr(0).$string;
+				break;
+			case 0x03:
+				$string = chr(0).$string;
+				break;
+		}
+	
+		$length = strlen($string);
+	
+		if ($length < 128){
+		   $output = sprintf("%c%c%s", $type, $length, $string);
+		} else if ($length < 0x0100){
+		   $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
+		} else if ($length < 0x010000) {
+		   $output = sprintf("%c%c%c%c%s", $type, 0x82, $length/0x0100, $length%0x0100, $string);
+		} else {
+			$output = NULL;
+		}
+		return($output);
+	}
+
+	/* Modulus and Exponent must already be base64 decoded */
+	static function convertRSA($modulus, $exponent) {
+		/* make an ASN publicKeyInfo */
+		$exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);    
+		$modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);    
+		$sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding.$exponentEncoding);
+		$bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
+		$rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500"); 
+		$publicKeyInfo = XMLSecurityKey::makeAsnSegment (0x30, $rsaAlgorithmIdentifier.$bitstringEncoding);
+
+		/* encode the publicKeyInfo in base64 and add PEM brackets */
+		$publicKeyInfoBase64 = base64_encode($publicKeyInfo);    
+		$encoding = "-----BEGIN PUBLIC KEY-----\n";
+		$offset = 0;
+		while ($segment=substr($publicKeyInfoBase64, $offset, 64)){
+		   $encoding = $encoding.$segment."\n";
+		   $offset += 64;
+		}
+		return $encoding."-----END PUBLIC KEY-----\n";
+	}
+	
+	public function serializeKey($parent) {
+		
+	}
+}
+
+class XMLSecurityDSig {
+	const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
+	const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
+	const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
+	const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
+	const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
+
+	const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
+	const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
+	const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
+	const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
+
+	const template = '<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+  <ds:SignedInfo>
+    <ds:SignatureMethod />
+  </ds:SignedInfo>
+</ds:Signature>';
+	
+	public $sigNode = NULL;
+	public $idKeys = array();
+	public $idNS = array();
+	private $signedInfo = NULL;
+	private $xPathCtx = NULL;
+	private $canonicalMethod = NULL;
+	private $prefix = 'ds';
+	private $searchpfx = 'secdsig';
+
+	public function __construct() {
+		$sigdoc = new DOMDocument();
+		$sigdoc->loadXML(XMLSecurityDSig::template);
+		$this->sigNode = $sigdoc->documentElement;
+	}
+
+	private function getXPathObj() {
+		if (empty($this->xPathCtx) && ! empty($this->sigNode)) {
+			$xpath = new DOMXPath($this->sigNode->ownerDocument);
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+
+			$this->xPathCtx = $xpath;
+		}
+		return $this->xPathCtx;
+	}
+
+	static function generate_GUID($prefix='_pfx') {
+		$uuid = md5(uniqid(rand(), true));
+		$guid =  $prefix.substr($uuid,0,8)."-".
+				substr($uuid,8,4)."-".
+				substr($uuid,12,4)."-".
+				substr($uuid,16,4)."-".
+				substr($uuid,20,12);
+		return $guid;
+	}
+
+	public function locateSignature($objDoc) {
+		if ($objDoc instanceof DOMDocument) {
+			$doc = $objDoc;
+		} else {
+			$doc = $objDoc->ownerDocument;
+		}
+		if ($doc) {
+			$xpath = new DOMXPath($doc);
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+			$query = ".//secdsig:Signature";
+			$nodeset = $xpath->query($query, $objDoc);
+			
+
+			$this->sigNode = $nodeset->item(0);
+			return $this->sigNode;
+		}
+		return NULL;
+	}
+
+	public function createNewSignNode($name, $value=NULL) {
+		$doc = $this->sigNode->ownerDocument;
+		if (! is_null($value)) {
+			$node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $this->prefix.':'.$name, $value);
+		} else {
+			$node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $this->prefix.':'.$name);
+		}
+		return $node;
+	}
+
+	public function setCanonicalMethod($method) {
+		switch ($method) {
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+				$this->canonicalMethod = $method;
+				break;
+			default:
+				throw new Exception('Invalid Canonical Method');
+		}
+		if ($xpath = $this->getXPathObj()) {
+			$query = './'.$this->searchpfx.':SignedInfo';
+			$nodeset = $xpath->query($query, $this->sigNode);
+			if ($sinfo = $nodeset->item(0)) {
+				$query = './'.$this->searchpfx.'CanonicalizationMethod';
+				$nodeset = $xpath->query($query, $sinfo);
+				if (! ($canonNode = $nodeset->item(0))) {
+					$canonNode = $this->createNewSignNode('CanonicalizationMethod');
+					$sinfo->insertBefore($canonNode, $sinfo->firstChild);
+				}
+				$canonNode->setAttribute('Algorithm', $this->canonicalMethod);
+			}
+		}
+	}
+
+	private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) {
+		$exclusive = FALSE;
+		$withComments = FALSE;
+		switch ($canonicalmethod) {
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+				$exclusive = FALSE;
+				$withComments = FALSE;
+				break;
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+				$withComments = TRUE;
+				break;
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+				$exclusive = TRUE;
+				break;
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+				$exclusive = TRUE;
+				$withComments = TRUE;
+				break;
+		}
+/* Support PHP versions < 5.2 not containing C14N methods in DOM extension */
+		$php_version = explode('.', PHP_VERSION);
+		if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2) ) {
+			if (! is_null($arXPath)) {
+				throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations");
+			}
+			return C14NGeneral($node, $exclusive, $withComments);
+		}
+		return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
+	}
+
+	public function canonicalizeSignedInfo() {
+
+		$doc = $this->sigNode->ownerDocument;
+		$canonicalmethod = NULL;
+		if ($doc) {
+			$xpath = $this->getXPathObj();
+			$query = "./secdsig:SignedInfo";
+			$nodeset = $xpath->query($query, $this->sigNode);
+			if ($signInfoNode = $nodeset->item(0)) {
+				$query = "./secdsig:CanonicalizationMethod";
+				$nodeset = $xpath->query($query, $signInfoNode);
+				if ($canonNode = $nodeset->item(0)) {
+					$canonicalmethod = $canonNode->getAttribute('Algorithm');
+				}
+				$this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
+				return $this->signedInfo;
+			}
+		}
+		return NULL;
+	}
+
+	public function calculateDigest ($digestAlgorithm, $data) {
+		switch ($digestAlgorithm) {
+			case XMLSecurityDSig::SHA1:
+				$alg = 'sha1';
+				break;
+			case XMLSecurityDSig::SHA256:
+				$alg = 'sha256';
+				break;
+			case XMLSecurityDSig::SHA512:
+				$alg = 'sha512';
+				break;
+			case XMLSecurityDSig::RIPEMD160:
+				$alg = 'ripemd160';
+				break;
+			default:
+				throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>");
+		}
+		return base64_encode(hash($alg, $data, TRUE));
+	}
+
+	public function validateDigest($refNode, $data) {
+		$xpath = new DOMXPath($refNode->ownerDocument);
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+		$query = 'string(./secdsig:DigestMethod/@Algorithm)';
+		$digestAlgorithm = $xpath->evaluate($query, $refNode);
+		$digValue = $this->calculateDigest($digestAlgorithm, $data);
+		$query = 'string(./secdsig:DigestValue)';
+		$digestValue = $xpath->evaluate($query, $refNode);
+		return ($digValue == $digestValue);
+	}
+
+	public function processTransforms($refNode, $objData) {
+		$data = $objData;
+		$xpath = new DOMXPath($refNode->ownerDocument);
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+		$query = './secdsig:Transforms/secdsig:Transform';
+		$nodelist = $xpath->query($query, $refNode);
+		$canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
+		$arXPath = NULL;
+		$prefixList = NULL;
+		foreach ($nodelist AS $transform) {
+			$algorithm = $transform->getAttribute("Algorithm");
+			switch ($algorithm) {
+				case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+				case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+					$node = $transform->firstChild;
+					while ($node) {
+						if ($node->localName == 'InclusiveNamespaces') {
+							if ($pfx = $node->getAttribute('PrefixList')) {
+								$arpfx = array();
+								$pfxlist = split(" ", $pfx);
+								foreach ($pfxlist AS $pfx) {
+									$val = trim($pfx);
+									if (! empty($val)) {
+										$arpfx[] = $val;
+									}
+								}
+								if (count($arpfx) > 0) {
+									$prefixList = $arpfx;
+								}
+							}
+							break;
+						}
+						$node = $node->nextSibling;
+					}
+				case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+				case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+					$canonicalMethod = $algorithm;
+					break;
+				case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
+					$node = $transform->firstChild;
+					while ($node) {
+						if ($node->localName == 'XPath') {
+							$arXPath = array();
+							$arXPath['query'] = '(.//. | .//@* | .//namespace::*)['.$node->nodeValue.']';
+							$arXpath['namespaces'] = array();
+							$nslist = $xpath->query('./namespace::*', $node);
+							foreach ($nslist AS $nsnode) {
+								if ($nsnode->localName != "xml") {
+									$arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
+								}
+							}
+							break;
+						}
+						$node = $node->nextSibling;
+					}
+					break;
+			}
+		}
+		if ($data instanceof DOMNode) {
+			$data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
+		}
+		return $data;
+	}
+
+	public function processRefNode($refNode) {
+		$dataObject = NULL;
+		if ($uri = $refNode->getAttribute("URI")) {
+			$arUrl = parse_url($uri);
+			if (empty($arUrl['path'])) {
+				if ($identifier = $arUrl['fragment']) {
+					$xPath = new DOMXPath($refNode->ownerDocument);
+					if ($this->idNS && is_array($this->idNS)) {
+						foreach ($this->idNS AS $nspf=>$ns) {
+							$xPath->registerNamespace($nspf, $ns);
+						}
+					}
+					$iDlist = '@Id="'.$identifier.'"';
+					if (is_array($this->idKeys)) {
+						foreach ($this->idKeys AS $idKey) {
+							$iDlist .= " or @$idKey='$identifier'";
+						}
+					}
+					$query = '//*['.$iDlist.']';
+					$dataObject = $xPath->query($query)->item(0);
+				} else {
+					$dataObject = $refNode->ownerDocument;
+				}
+			} else {
+				$dataObject = file_get_contents($arUrl);
+			}
+		} else {
+			$dataObject = $refNode->ownerDocument;
+		}
+		$data = $this->processTransforms($refNode, $dataObject);
+		return $this->validateDigest($refNode, $data);
+	}
+	
+	public function getRefNodeID($refNode) {
+		if ($uri = $refNode->getAttribute("URI")) {
+			$arUrl = parse_url($uri);
+			if (empty($arUrl['path'])) {
+				if ($identifier = $arUrl['fragment']) {
+					return $identifier;
+				}
+			}
+		}
+		return null;
+	}
+	
+	public function getRefIDs() {
+		$refids = array();
+		$doc = $this->sigNode->ownerDocument;
+
+		$xpath = $this->getXPathObj();
+		$query = "./secdsig:SignedInfo/secdsig:Reference";
+		$nodeset = $xpath->query($query, $this->sigNode);
+		if ($nodeset->length == 0) {
+			throw new Exception("Reference nodes not found");
+		}
+		foreach ($nodeset AS $refNode) {
+			$refids[] = $this->getRefNodeID($refNode);
+		}
+		return $refids;
+	}
+
+	public function validateReference() {
+		$doc = $this->sigNode->ownerDocument;
+		if (! $doc->isSameNode($this->sigNode)) {
+			$this->sigNode->parentNode->removeChild($this->sigNode);
+		}
+		$xpath = $this->getXPathObj();
+		$query = "./secdsig:SignedInfo/secdsig:Reference";
+		$nodeset = $xpath->query($query, $this->sigNode);
+		if ($nodeset->length == 0) {
+			throw new Exception("Reference nodes not found");
+		}
+		foreach ($nodeset AS $refNode) {
+			if (! $this->processRefNode($refNode)) {
+				throw new Exception("Reference validation failed");
+			}
+		}
+		return TRUE;
+	}
+
+	private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL) {
+		$prefix = NULL;
+		$prefix_ns = NULL;
+		$id_name = 'ID';
+
+		if (is_array($options)) {
+			$prefix = empty($options['prefix'])?NULL:$options['prefix'];
+			$prefix_ns = empty($options['prefix_ns'])?NULL:$options['prefix_ns'];
+			$id_name = empty($options['id_name'])?'Id':$options['id_name'];
+		}
+
+		$refNode = $this->createNewSignNode('Reference');
+		$sinfoNode->appendChild($refNode);
+
+		if ($node instanceof DOMDocument) {
+			$uri = NULL;
+		} else {
+/* Do wer really need to set a prefix? */
+			$uri = XMLSecurityDSig::generate_GUID();
+			$refNode->setAttribute("URI", '#'.$uri);
+			//$refNode->setAttribute("URI", '');
+		}
+
+		$transNodes = $this->createNewSignNode('Transforms');
+		$refNode->appendChild($transNodes);
+
+		if (is_array($arTransforms)) {
+			foreach ($arTransforms AS $transform) {
+				$transNode = $this->createNewSignNode('Transform');
+				$transNodes->appendChild($transNode);
+				$transNode->setAttribute('Algorithm', $transform);
+			}
+		} elseif (! empty($this->canonicalMethod)) {
+			$transNode = $this->createNewSignNode('Transform');
+			$transNodes->appendChild($transNode);
+			$transNode->setAttribute('Algorithm', $this->canonicalMethod);
+		}
+		
+		if (! empty($uri)) {
+			$attname = $id_name;
+			if (! empty($prefix)) {
+				$attname = $prefix.':'.$attname;
+			}
+			$node->setAttributeNS($prefix_ns, $attname, $uri);
+		}
+		
+		$canonicalData = $this->processTransforms($refNode, $node);
+		$digValue = $this->calculateDigest($algorithm, $canonicalData);
+		
+		$digestMethod = $this->createNewSignNode('DigestMethod');
+		$refNode->appendChild($digestMethod);
+		$digestMethod->setAttribute('Algorithm', $algorithm);
+
+		$digestValue = $this->createNewSignNode('DigestValue', $digValue);
+		$refNode->appendChild($digestValue);
+	}
+
+	public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL) {
+		if ($xpath = $this->getXPathObj()) {
+			$query = "./secdsig:SignedInfo";
+			$nodeset = $xpath->query($query, $this->sigNode);
+			if ($sInfo = $nodeset->item(0)) {
+				$this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
+			}
+		}
+	}
+
+	public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL) {
+		if ($xpath = $this->getXPathObj()) {
+			$query = "./secdsig:SignedInfo";
+			$nodeset = $xpath->query($query, $this->sigNode);
+			if ($sInfo = $nodeset->item(0)) {
+				foreach ($arNodes AS $node) {
+					$this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
+				}
+			}
+		}
+	}
+
+   public function addObject($data, $mimetype=NULL, $encoding=NULL) {
+      $objNode = $this->createNewSignNode('Object');
+      $this->sigNode->appendChild($objNode);
+      if (! empty($mimetype)) {
+         $objNode->setAtribute('MimeType', $mimetype);
+      }
+      if (! empty($encoding)) {
+         $objNode->setAttribute('Encoding', $encoding);
+      }
+      
+      if ($data instanceof DOMElement) {
+         $newData = $this->sigNode->ownerDocument->importNode($data, TRUE);
+      } else {
+         $newData = $this->sigNode->ownerDocument->createTextNode($data);
+      }
+      $objNode->appendChild($newData);
+
+      return $objNode;
+   }
+
+	public function locateKey($node=NULL) {
+		if (empty($node)) {
+			$node = $this->sigNode;
+		}
+		if (! $node instanceof DOMNode) {
+			return NULL;
+		}
+		if ($doc = $node->ownerDocument) {
+			$xpath = new DOMXPath($doc);
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+			$query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
+			$algorithm = $xpath->evaluate($query, $node);
+			if ($algorithm) {
+				try {
+					$objKey = new XMLSecurityKey($algorithm, array('type'=>'public'));
+				} catch (Exception $e) {
+					return NULL;
+				}
+				return $objKey;
+			}
+		}
+		return NULL;
+	}
+	
+	public function verify($objKey) {
+		$doc = $this->sigNode->ownerDocument;
+		$xpath = new DOMXPath($doc);
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+		$query = "string(./secdsig:SignatureValue)";
+		$sigValue = $xpath->evaluate($query, $this->sigNode);
+		if (empty($sigValue)) {
+			throw new Exception("Unable to locate SignatureValue");
+		}
+		return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
+	}
+	
+	public function signData($objKey, $data) {
+		return $objKey->signData($data);
+	}
+	
+	public function sign($objKey) {
+		if ($xpath = $this->getXPathObj()) {
+			$query = "./secdsig:SignedInfo";
+			$nodeset = $xpath->query($query, $this->sigNode);
+			if ($sInfo = $nodeset->item(0)) {
+				$query = "./secdsig:SignatureMethod";
+				$nodeset = $xpath->query($query, $sInfo);
+				$sMethod = $nodeset->item(0);
+				$sMethod->setAttribute('Algorithm', $objKey->type);
+				$data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
+				$sigValue = base64_encode($this->signData($objKey, $data));
+				$sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
+				if ($infoSibling = $sInfo->nextSibling) {
+					$infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
+				} else {
+					$this->sigNode->appendChild($sigValueNode);
+				}
+			}
+		}
+	}
+
+	public function appendCert() {
+		
+	}
+
+	public function appendKey($objKey, $parent=NULL) {
+		$objKey->serializeKey($parent);
+	}
+
+	public function appendSignature($parentNode, $insertBefore = FALSE, $assertion = false) {
+		$baseDoc = ($parentNode instanceof DOMDocument)?$parentNode:$parentNode->ownerDocument;
+		$newSig = $baseDoc->importNode($this->sigNode, TRUE);
+
+	
+	
+		$xnode = null;
+		
+		$xpath = new DOMXPath($baseDoc);
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+		$xpath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol');
+		$xpath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:2.0:assertion');
+
+
+		if ($insertBefore && !$assertion) {
+
+			$query = "//samlp:Status";
+			$nodeset = $xpath->query($query, $parentNode);
+
+			$xnode = $nodeset->item(0);
+			if (!$xnode)
+				throw new Exception("Could not find node to sign before (Root signing mode)");
+		
+			$parentNode->insertBefore($newSig, $xnode);
+			
+		} elseif ($insertBefore) {
+			
+			$query = "//saml:Assertion/saml:Subject";
+			$nodeset = $xpath->query($query, $parentNode);
+
+			$xnode = $nodeset->item(0);
+			if (!$xnode)
+				throw new Exception("Could not find node to sign before (Assertion signing mode)");
+
+			$parentNode->insertBefore($newSig, $xnode);
+		} else {
+			$parentNode->appendChild($newSig);
+		}
+	}
+	
+	static function get509XCert($cert, $isPEMFormat=TRUE) {
+		if ($isPEMFormat) {
+			$data = '';
+			$arCert = explode("\n", $cert);
+			$inData = FALSE;
+			foreach ($arCert AS $curData) {
+				if (! $inData) {
+					if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
+						$inData = TRUE;
+					}
+				} else {
+					if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
+						break;
+					}
+					$data .= trim($curData);
+				}
+			}
+		} else {
+			$data = $cert;
+		}
+		return $data;
+	}
+	
+	static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL) {
+          if ($isURL) {
+            $cert = file_get_contents($cert);
+          }
+          if (! $parentRef instanceof DOMElement) {
+            throw new Exception('Invalid parent Node parameter');
+          }
+          $baseDoc = $parentRef->ownerDocument;
+
+          if (empty($xpath)) {
+              $xpath = new DOMXPath($parentRef->ownerDocument);
+              $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+          }
+          $data = XMLSecurityDSig::get509XCert($cert, $isPEMFormat);
+
+         $query = "./secdsig:KeyInfo";
+         $nodeset = $xpath->query($query, $parentRef);
+         $keyInfo = $nodeset->item(0);
+         if (! $keyInfo) {
+              $inserted = FALSE;
+              $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
+
+               $query = "./secdsig:Object";
+               $nodeset = $xpath->query($query, $parentRef);
+               if ($sObject = $nodeset->item(0)) {
+                    $sObject->parentNode->insertBefore($keyInfo, $sObject);
+                    $inserted = TRUE;
+               }
+
+              if (! $inserted) {
+                   $parentRef->appendChild($keyInfo);
+              }
+         }
+         $x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
+         $keyInfo->appendChild($x509DataNode);
+         $x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $data);
+         $x509DataNode->appendChild($x509CertNode);
+
+     }
+
+	public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False) {
+         if ($xpath = $this->getXPathObj()) {
+            self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath);
+         }
+	}
+}
+
+class XMLSecEnc {
+	const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
+   <xenc:CipherData>
+      <xenc:CipherValue></xenc:CipherValue>
+   </xenc:CipherData>
+</xenc:EncryptedData>";
+
+	const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
+	const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
+	const URI = 3;
+	const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
+
+	private $encdoc = NULL;
+	private $rawNode = NULL;
+	public $type = NULL;
+	public $encKey = NULL;
+	
+	public function __construct() {
+		$this->encdoc = new DOMDocument();
+		$this->encdoc->loadXML(XMLSecEnc::template);
+	}
+	
+	public function setNode($node) {
+		$this->rawNode = $node;
+	}
+
+	public function encryptNode($objKey, $replace=TRUE) {
+		$data = '';
+		if (empty($this->rawNode)) {
+			throw new Exception('Node to encrypt has not been set');
+		}
+		if (! $objKey instanceof XMLSecurityKey) {
+			throw new Exception('Invalid Key');
+		}
+		$doc = $this->rawNode->ownerDocument;
+		$xPath = new DOMXPath($this->encdoc);
+		$objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
+		$cipherValue = $objList->item(0);
+		if ($cipherValue == NULL) {
+			throw new Exception('Error locating CipherValue element within template');
+		}
+		switch ($this->type) {
+			case (XMLSecEnc::Element):
+				$data = $doc->saveXML($this->rawNode);
+				$this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
+				break;
+			case (XMLSecEnc::Content):
+				$children = $this->rawNode->childNodes;
+				foreach ($children AS $child) {
+					$data .= $doc->saveXML($child);
+				}
+				$this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
+				break;
+			default:
+				throw new Exception('Type is currently not supported');
+				return;
+		}
+		
+		$encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
+		$encMethod->setAttribute('Algorithm', $objKey->getAlgorith());
+		$cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode);
+		
+		$strEncrypt = base64_encode($objKey->encryptData($data));
+		$value = $this->encdoc->createTextNode($strEncrypt);
+		$cipherValue->appendChild($value);
+
+		if ($replace) {
+			switch ($this->type) {
+				case (XMLSecEnc::Element):
+					if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+						return $this->encdoc;
+					}
+					$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
+					$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
+					return $importEnc;
+					break;
+				case (XMLSecEnc::Content):
+					$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
+					while($this->rawNode->firstChild) {
+						$this->rawNode->removeChild($this->rawNode->firstChild);
+					}
+					$this->rawNode->appendChild($importEnc);
+					return $importEnc;
+					break;
+			}
+		}
+	}
+
+	public function decryptNode($objKey, $replace=TRUE) {
+		$data = '';
+		if (empty($this->rawNode)) {
+			throw new Exception('Node to decrypt has not been set');
+		}
+		if (! $objKey instanceof XMLSecurityKey) {
+			throw new Exception('Invalid Key');
+		}
+		$doc = $this->rawNode->ownerDocument;
+		$xPath = new DOMXPath($doc);
+		$xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
+		/* Only handles embedded content right now and not a reference */
+		$query = "./xmlencr:CipherData/xmlencr:CipherValue";
+		$nodeset = $xPath->query($query, $this->rawNode);
+
+		if ($node = $nodeset->item(0)) {
+			$encryptedData = base64_decode($node->nodeValue);
+			$decrypted = $objKey->decryptData($encryptedData);
+			if ($replace) {
+				switch ($this->type) {
+					case (XMLSecEnc::Element):
+						$newdoc = new DOMDocument();
+						$newdoc->loadXML($decrypted);
+						if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+							return $newdoc;
+						}
+						$importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE);
+						$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
+						return $importEnc;
+						break;
+					case (XMLSecEnc::Content):
+						if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+							$doc = $this->rawNode;
+						} else {
+							$doc = $this->rawNode->ownerDocument;
+						}
+						$newFrag = $doc->createDOMDocumentFragment();
+						$newFrag->appendXML($decrypted);
+						$this->rawNode->parentNode->replaceChild($newFrag, $this->rawNode);
+						return $this->rawNode->parentNode;
+						break;
+					default:
+						return $decrypted;
+				}
+			} else {
+				return $decrypted;
+			}
+		} else {
+			throw new Exception("Cannot locate encrypted data");
+		}
+	}
+
+	public function encryptKey($srcKey, $rawKey, $append=TRUE) {
+		if ((! $srcKey instanceof XMLSecurityKey) || (! $rawKey instanceof XMLSecurityKey)) {
+			throw new Exception('Invalid Key');
+		}
+		$strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
+		$root = $this->encdoc->documentElement;
+		$encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
+		if ($append) {
+			$keyInfo = $root->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
+			$keyInfo->appendChild($encKey);
+		} else {
+			$this->encKey = $encKey;
+		}
+		$encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
+		$encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
+		if (! empty($srcKey->name)) {
+			$keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
+			$keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
+		}
+		$cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
+		$cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
+		return;
+	}
+	
+	public function decryptKey($encKey) {
+		if (! $encKey->isEncrypted) {
+			throw new Exception("Key is not Encrypted");
+		}
+		if (empty($encKey->key)) {
+			throw new Exception("Key is missing data to perform the decryption");
+		}
+		return $this->decryptNode($encKey, FALSE);
+	}
+	
+	public function locateEncryptedData($element) {
+		if ($element instanceof DOMDocument) {
+			$doc = $element;
+		} else {
+			$doc = $element->ownerDocument;
+		}
+		if ($doc) {
+			$xpath = new DOMXPath($doc);
+			$query = "//*[local-name()='EncryptedData' and namespace-uri()='".XMLSecEnc::XMLENCNS."']";
+			$nodeset = $xpath->query($query);
+			return $nodeset->item(0);
+		}
+		return NULL;
+	}
+	
+	public function locateKey($node=NULL) {
+		if (empty($node)) {
+			$node = $this->rawNode;
+		}
+		if (! $node instanceof DOMNode) {
+			return NULL;
+		}
+		if ($doc = $node->ownerDocument) {
+			$xpath = new DOMXPath($doc);
+			$xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
+			$query = ".//xmlsecenc:EncryptionMethod";
+			$nodeset = $xpath->query($query, $node);
+			if ($encmeth = $nodeset->item(0)) {
+   				$attrAlgorithm = $encmeth->getAttribute("Algorithm");
+				try {
+					$objKey = new XMLSecurityKey($attrAlgorithm, array('type'=>'private'));
+				} catch (Exception $e) {
+					return NULL;
+				}
+				return $objKey;
+			}
+		}
+		return NULL;
+	}
+	
+	static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) {
+		if (empty($node) || (! $node instanceof DOMNode)) {
+			return NULL;
+		}
+		if ($doc = $node->ownerDocument) {
+			$xpath = new DOMXPath($doc);
+			$xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
+			$xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
+			$query = "./xmlsecdsig:KeyInfo";
+			$nodeset = $xpath->query($query, $node);
+			if ($encmeth = $nodeset->item(0)) {
+				foreach ($encmeth->childNodes AS $child) {
+					switch ($child->localName) {
+						case 'KeyName':
+							if (! empty($objBaseKey)) {
+								$objBaseKey->name = $child->nodeValue;
+							}
+							break;
+						case 'KeyValue':
+							foreach ($child->childNodes AS $keyval) {
+								switch ($keyval->localName) {
+									case 'DSAKeyValue':
+										throw new Exception("DSAKeyValue currently not supported");
+										break;
+									case 'RSAKeyValue':
+										$modulus = NULL;
+										$exponent = NULL;
+										if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
+											$modulus = base64_decode($modulusNode->nodeValue);
+										}
+										if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
+											$exponent = base64_decode($exponentNode->nodeValue);
+										}
+										if (empty($modulus) || empty($exponent)) {
+											throw new Exception("Missing Modulus or Exponent");
+										}
+										$publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
+										$objBaseKey->loadKey($publicKey);
+										break;
+								}
+							}
+							break;
+						case 'RetrievalMethod':
+							/* Not currently supported */
+							break;
+						case 'EncryptedKey':
+							$objenc = new XMLSecEnc();
+							$objenc->setNode($child);
+							if (! $objKey = $objenc->locateKey()) {
+								throw new Exception("Unable to locate algorithm for this Encrypted Key");
+							}
+							$objKey->isEncrypted = TRUE;
+							$objKey->encryptedCtx = $objenc;
+							XMLSecEnc::staticLocateKeyInfo($objKey, $child);
+							return $objKey;
+							break;
+						case 'X509Data':
+							if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
+								if ($x509certNodes->length > 0) {
+									$x509cert = $x509certNodes->item(0)->textContent;
+									$x509cert = str_replace(array("\r", "\n"), "", $x509cert);
+									$x509cert = "-----BEGIN CERTIFICATE-----\n".chunk_split($x509cert, 64, "\n")."-----END CERTIFICATE-----\n";
+									$objBaseKey->loadKey($x509cert);
+								}
+							}
+							break;
+					}
+				}
+			}
+			return $objBaseKey;
+		}
+		return NULL;
+	}
+	
+	public function locateKeyInfo($objBaseKey=NULL, $node=NULL) {
+		if (empty($node)) {
+			$node = $this->rawNode;
+		}
+		return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
+	}
+}
+?>
\ No newline at end of file
diff --git a/metadata-templates/saml20-idp-hosted.php b/metadata-templates/saml20-idp-hosted.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1eab5941a9035e4d0d77d482a0b8b9139a65c32
--- /dev/null
+++ b/metadata-templates/saml20-idp-hosted.php
@@ -0,0 +1,37 @@
+<?php
+/* 
+ * SAML 2.0 Meta data for simpleSAMLphp
+ *
+ * The SAML 2.0 IdP Hosted config is used by the SAML 2.0 IdP to identify itself.
+ *
+ */
+
+
+$metadata = array( 
+
+	// The SAML entity ID is the index of this config.
+	'dev2.andreas.feide.no' => array(
+	
+		// The hostname of the server (VHOST) that this SAML entity will use.
+		'host'				=>	'dev2.andreas.feide.no',
+		
+		// SAML endpoints.
+		'SingleSignOnUrl'	=>	"http://dev2.andreas.feide.no/saml2/idp/SSOService.php",
+		'SingleLogOutUrl'	=>	"http://dev2.andreas.feide.no/saml2/idp/LogoutService.php",
+		
+		// X.509 key and certificate. Relative to the cert directory.
+		'privatekey'		=>	'server.pem',
+		'certificate'		=>	'server.crt',
+		
+		/* If base64attributes is set to true, then all attributes will be base64 encoded. Make sure
+		 * that you set the SP to have the same value for this.
+		 */
+		'base64attributes'	=>	false,
+		
+		// Authentication plugin to use. login.php is the default one that uses LDAP.
+		'auth'				=>	'auth/login.php'
+	)
+
+);
+
+?>
diff --git a/metadata-templates/saml20-idp-remote.php b/metadata-templates/saml20-idp-remote.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f0afacb37aae6b1db2734ea0aa99e171a8126dc
--- /dev/null
+++ b/metadata-templates/saml20-idp-remote.php
@@ -0,0 +1,41 @@
+<?php
+/* 
+ * SAML 2.0 Meta data for simpleSAMLphp
+ *
+ * The SAML 2.0 IdP Remote config is used by the SAML 2.0 SP to identify trusted SAML 2.0 IdPs.
+ *
+ */
+
+
+
+$metadata = array( 
+	"feide2.erlang.no-saml2" => 
+		array(
+			"SingleSignOnUrl"	=>	"https://feide2.erlang.no/saml2/idp/SSOService.php",
+		 	"SingleLogOutUrl"	=>	"https://feide2.erlang.no/saml2/idp/LogoutService.php",
+		 	"certFingerprint"	=>	"afe71c28ef740bc87425be13a2263d37971da1f9",
+		 	"base64attributes"	=>	true),
+
+	'dev2.andreas.feide.no' => 
+		array(
+			"SingleSignOnUrl"	=>	"http://dev2.andreas.feide.no/saml2/idp/SSOService.php",
+		 	"SingleLogOutUrl"	=>	"http://dev2.andreas.feide.no/saml2/idp/LogoutService.php",
+		 	"certFingerprint"	=>	"afe71c28ef740bc87425be13a2263d37971da1f9",
+		 	"base64attributes"	=>	false),
+		 	
+	"sam.feide.no" => 
+		array( 
+			"SingleSignOnUrl"	=>	"https://sam.feide.no/amserver/SSORedirect/metaAlias/idp",
+		 	"SingleLogOutUrl"	=>	"https://sam.feide.no/amserver/IDPSloRedirect/metaAlias/idp",
+		 	"certFingerprint"	=>	"3a:e7:d3:d3:06:ba:57:fd:7f:62:6a:4b:a8:64:b3:4a:53:d9:5d:d0",
+		 	"base64attributes"	=>	true),
+		 	
+	"max.feide.no" => 
+		array(
+			"SingleSignOnUrl"	=>	"https://max.feide.no/amserver/SSORedirect/metaAlias/idp",
+		 	"SingleLogOutUrl"	=>	"https://max.feide.no/amserver/IDPSloRedirect/metaAlias/idp",
+		 	"certFingerprint"	=>	"d79b0e23c0833d2f5b8d94abd54ae693708b1eef",
+		 	"base64attributes"	=>	false )
+
+    );
+?>
diff --git a/metadata-templates/saml20-sp-hosted.php b/metadata-templates/saml20-sp-hosted.php
new file mode 100644
index 0000000000000000000000000000000000000000..d6357b0aa25ea9546b512bd7c89640dfc501eb84
--- /dev/null
+++ b/metadata-templates/saml20-sp-hosted.php
@@ -0,0 +1,37 @@
+<?php
+/* 
+ * SAML 2.0 Meta data for simpleSAMLphp
+ *
+ * The SAML 2.0 IdP Remote config is used by the SAML 2.0 SP to identify itself.
+ *
+ */
+ 
+$metadata = array( 
+	"dev.andreas.feide.no" => array(
+		'host'							=>	'dev.andreas.feide.no',
+ 		"assertionConsumerServiceURL"	=>	"http://dev.andreas.feide.no/saml2/sp/AssertionConsumerService.php", 
+		"issuer"						=>	"dev.andreas.feide.no",
+		"spNameQualifier" 				=>	"dev.andreas.feide.no",
+		"ForceAuthn"					=>	"false",
+		"NameIDFormat"					=>	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+	),
+	"feide2.erlang.no" => array(
+		'host'							=>	'feide2.erlang.no',
+ 		"assertionConsumerServiceURL"	=>	"https://feide2.erlang.no/saml2/sp/AssertionConsumerService.php", 
+		"issuer"						=>	"feide2.erlang.no",
+		"spNameQualifier" 				=>	"feide2.erlang.no",
+		"ForceAuthn"					=>	"false",
+		"NameIDFormat"					=>	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+	),
+	"feide3.erlang.no" => array(
+		'host'							=>	'feide3.erlang.no',
+ 		"assertionConsumerServiceURL"	=>	"https://feide3.erlang.no/saml2/sp/AssertionConsumerService.php", //
+		"issuer"						=>	"feide3.erlang.no",
+		"spNameQualifier" 				=>	"feide3.erlang.no",
+		"ForceAuthn"					=>	"false",
+		"NameIDFormat"					=>	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+	)
+);
+
+
+?>
diff --git a/metadata-templates/saml20-sp-remote.php b/metadata-templates/saml20-sp-remote.php
new file mode 100644
index 0000000000000000000000000000000000000000..78fc98b301c723353bdb9e6ca47a0f5a2c048b02
--- /dev/null
+++ b/metadata-templates/saml20-sp-remote.php
@@ -0,0 +1,84 @@
+<?php
+/* 
+ * SAML 2.0 Meta data for simpleSAMLphp
+ *
+ * The SAML 2.0 SP Remote config is used by the SAML 2.0 IdP to identify trusted SAML 2.0 SPs.
+ *
+ *	Required parameters:
+ * 
+ *		assertionConsumerServiceURL
+ *		spNameQualifier
+ *		NameIDFormat
+ *		simplesaml.attributes (Will you send an attributestatement [true/false])
+ *
+ *	Optional parameters:
+ *
+ *		ForceAuthn (default: "false")
+ *		simplesaml.nameidattribute (only needed when you are using NameID format email.
+ *
+ */
+
+$metadata = array( 
+
+	'dev.andreas.feide.no' => array(
+ 		'assertionConsumerServiceURL'	=>	'http://dev.andreas.feide.no/saml2/sp/AssertionConsumerService.php', 
+		'spNameQualifier' 				=>	'dev.andreas.feide.no',
+		'ForceAuthn'					=>	'false',
+		'NameIDFormat'					=>	'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
+		'simplesaml.attributes'			=>	true
+	),
+	
+	/*
+	 * This example shows an example config that works with Google Apps for education.
+	 * What is important is that you have an attribute in your IdP that maps to the local part of the email address
+	 * at Google Apps. In example, if your google account is foo.com, and you have a user that has an email john@foo.com, then you
+	 * must set the simplesaml.nameidattribute to be the name of an attribute that for this user has the value of 'john'.
+	 */
+	'google.com' => array(
+ 		'assertionConsumerServiceURL'	=>	'https://www.google.com/a/foo.com/acs', 
+		'spNameQualifier' 				=>	'google.com',
+		'ForceAuthn'					=>	'false',
+		'NameIDFormat'					=>	'urn:oasis:names:tc:SAML:2.0:nameid-format:email',
+		'simplesaml.nameidattribute'	=>	'uid',
+		'simplesaml.attributes'			=>	false
+	),
+	
+	"feide2.erlang.no" => array(
+ 		"assertionConsumerServiceURL"	=>	"https://feide2.erlang.no/saml2/sp/AssertionConsumerService.php", 
+		"spNameQualifier" 				=>	"feide2.erlang.no",
+		"ForceAuthn"					=>	"false",
+		"NameIDFormat"					=>	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
+		'simplesaml.nameidattribute'	=>	'uid',
+		'simplesaml.attributes'			=>	true
+	),
+		
+	"feide3.erlang.no" => array(
+ 		"assertionConsumerServiceURL"	=>	"https://feide3.erlang.no/saml2/sp/AssertionConsumerService.php", //
+		"spNameQualifier" 				=>	"feide3.erlang.no",
+		"ForceAuthn"					=>	"false",
+		"NameIDFormat"					=>	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
+		'simplesaml.attributes'			=>	true
+	),
+	
+	"skjak.uninett.no" => array(
+ 		"assertionConsumerServiceURL"	=>	"https://skjak.uninett.no/Shibboleth.sso/SAML2/POST", //
+		"spNameQualifier" 				=>	"skjak.uninett.no",
+		"ForceAuthn"					=>	"false",
+		"NameIDFormat"					=>	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
+		'simplesaml.attributes'			=>	true
+		),
+	"skjak.uninett.no" => array(
+// 		"assertionConsumerServiceURL"	=>	"https://skjak2.uninett.no:443/fam/Consumer/metaAlias/sp_meta_alias", //
+ 		"assertionConsumerServiceURL"	=>	"https://skjak.uninett.no/Shibboleth.sso/SAML2/POST", //
+		"spNameQualifier" 				=>	"skjak.uninett.no",
+		"ForceAuthn"					=>	"false",
+		"NameIDFormat"					=>	"urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
+		'simplesaml.attributes'			=>	true
+		)
+		
+		
+
+);
+
+
+?>
diff --git a/metadata-templates/shib13-idp-hosted.php b/metadata-templates/shib13-idp-hosted.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce175ddb88481d08e3581d3fac35b9a398a466d6
--- /dev/null
+++ b/metadata-templates/shib13-idp-hosted.php
@@ -0,0 +1,16 @@
+<?php
+/* 
+ * SAML 2.0 Meta data for simpleSAMLphp
+ *
+ */
+
+
+$metadata = array(
+	'feide.erlang.no-shib13'	=> array(
+		'issuer'						=>	'feide.erlang.no',
+		'assertionDurationMinutes'		=>	10,
+		'audience'						=> 'urn:mace:feide:shiblab'
+	)
+);
+
+?>
\ No newline at end of file
diff --git a/metadata-templates/shib13-idp-remote.php b/metadata-templates/shib13-idp-remote.php
new file mode 100644
index 0000000000000000000000000000000000000000..aba114a16777d6d7904e26cae2d710f3345e33e3
--- /dev/null
+++ b/metadata-templates/shib13-idp-remote.php
@@ -0,0 +1,29 @@
+<?php
+/* 
+ * SAML 2.0 Meta data for simpleSAMLphp
+ *
+ */
+
+
+$metadata = array(
+
+	'urn:mace:switch.ch:aaitest:dukono.switch.ch'	=> array(
+		'SingleSignOnUrl'		=>	'https://dukono.switch.ch/shibboleth-idp/SSO',
+		'certFingerprint'		=>	'c7279a9f28f11380509e075441e3dc55fb9ab864' 
+//		'certFingerprint'		=>	'4e730f327ce8d9fe6269298d8f777a4bd0937ba5'
+//		c7279a9f28f11380509e075441e3dc55fb9ab864
+		// "SingleLogOutUrl" => "https://mars.feide.no/amserver/IDPSloRedirect/metaAlias/idp",
+	),
+	
+	'feide.erlang.no-shib13'	=> array(
+		'issuer'						=>	'feide.erlang.no',
+		'assertionDurationMinutes'		=>	10,
+		'audience'						=> 'urn:mace:feide:shiblab'
+	),
+	
+	'urn:mace:dfnwayf'	=> array(
+		'SingleSignOnUrl'		=>	'https://dfn.wayf.com/WAYF'
+	)
+);
+
+?>
\ No newline at end of file
diff --git a/metadata-templates/shib13-sp-hosted.php b/metadata-templates/shib13-sp-hosted.php
new file mode 100644
index 0000000000000000000000000000000000000000..70c78d23531c2aa51b7a367cdb9265e5bf08c027
--- /dev/null
+++ b/metadata-templates/shib13-sp-hosted.php
@@ -0,0 +1,35 @@
+<?php
+/* 
+ * SAML 2.0 Meta data for simpleSAMLphp
+ *
+ */
+
+$metadata = array(
+	'http://dev.andreas.feide.no'	=> array(
+		'AssertionConsumerService'	=>	'http://dev.andreas.feide.no/shib13/sp/AssertionConsumerService.php',
+		'host'						=>	'dev.andreas.feide.no'
+	),
+	'https://sp.shiblab.feide.no'	=> array(
+		'shire'				=>	'http://sp.shiblab.feide.no/Shibboleth.sso/SAML/POST',
+		'spnamequalifier'	=>	'urn:feide.no',
+		'audience'			=>	'urn:mace:feide:shiblab'
+	),
+	'urn:geant:edugain:component:be:switchaai-test:central' => array(
+		'shire'				=>	'https://edugain-login.switch.ch/ShiBE-R/WebSSOResponseListener',
+		'spnamequalifier'	=>	'urn:geant:edugain:component:be:rediris:rediris.es',
+		'audience'			=>	'urn:geant:edugain:component:be:switchaai-test:central'
+	),
+	'urn:geant:edugain:component:be:rediris:rediris.es' => array(
+		'shire'				=>	'http://serrano.rediris.es:8080/PAPIWebSSOResponseListener/request',
+		'spnamequalifier'	=>	'urn:geant:edugain:component:be:rediris:rediris.es',
+		'audience'			=>	'urn:geant:edugain:component:be:rediris:rediris.es'
+	),
+	'https://skjak.uninett.no/shibboleth/target' => array(
+		'shire'				=>	'https://skjak.uninett.no/Shibboleth.shire',
+		'spnamequalifier'	=>	'https://skjak.uninett.no/shibboleth/target',
+		'audience'			=>	'https://skjak.uninett.no/shibboleth/target'
+	)
+
+);
+
+?>
\ No newline at end of file
diff --git a/metadata-templates/shib13-sp-remote.php b/metadata-templates/shib13-sp-remote.php
new file mode 100644
index 0000000000000000000000000000000000000000..f79d904bf87f75deadd7b170b4190bbdbcc09dec
--- /dev/null
+++ b/metadata-templates/shib13-sp-remote.php
@@ -0,0 +1,32 @@
+<?php
+/* 
+ * SAML 2.0 Meta data for simpleSAMLphp
+ *
+ */
+
+
+$metadata = array(
+	'https://sp.shiblab.feide.no'	=> array(
+		'shire'				=>	'http://sp.shiblab.feide.no/Shibboleth.sso/SAML/POST',
+		'spnamequalifier'	=>	'urn:feide.no',
+		'audience'			=>	'urn:mace:feide:shiblab'
+	),
+	'urn:geant:edugain:component:be:switchaai-test:central' => array(
+		'shire'				=>	'https://edugain-login.switch.ch/ShiBE-R/WebSSOResponseListener',
+		'spnamequalifier'	=>	'urn:geant:edugain:component:be:rediris:rediris.es',
+		'audience'			=>	'urn:geant:edugain:component:be:switchaai-test:central'
+	),
+	'urn:geant:edugain:component:be:rediris:rediris.es' => array(
+		'shire'				=>	'http://serrano.rediris.es:8080/PAPIWebSSOResponseListener/request',
+		'spnamequalifier'	=>	'urn:geant:edugain:component:be:rediris:rediris.es',
+		'audience'			=>	'urn:geant:edugain:component:be:rediris:rediris.es'
+	),
+	'https://skjak.uninett.no/shibboleth/target' => array(
+		'shire'				=>	'https://skjak.uninett.no/Shibboleth.shire',
+		'spnamequalifier'	=>	'https://skjak.uninett.no/shibboleth/target',
+		'audience'			=>	'https://skjak.uninett.no/shibboleth/target'
+	)
+
+);
+
+?>
\ No newline at end of file
diff --git a/templates/error.php b/templates/error.php
new file mode 100644
index 0000000000000000000000000000000000000000..8d46001449f1c014126cfdf392542ea122e57c3d
--- /dev/null
+++ b/templates/error.php
@@ -0,0 +1,97 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title><?php echo $data['header']; ?></title>
+
+<style type="text/css">
+
+/* these styles are in the head of this page because this is a unique page */
+
+/* THE BIG GUYS */
+* {margin:0;padding:0}
+body {text-align:center;padding: 20px 0;background: #222;color:#333;font:83%/1.5 arial,tahoma,verdana,sans-serif}
+img {border:none;display:block}
+hr {margin: 1em 0;background:#eee;height:1px;color:#eee;border:none;clear:both}
+
+/* LINKS */
+a,a:link,a:link,a:link,a:hover {font-weight:bold;background:transparent;text-decoration:underline;cursor:pointer} 
+a:link {color:#c00} 
+a:visited {color:#999} 
+a:hover,a:active {color:#069} 
+
+/* LISTS */
+ul {margin: .3em 0 1.5em 2em}
+	ul.related {margin-top:-1em}
+li {margin-left:2em}
+dt {font-weight:bold}
+#wrap {border: 1px solid #fff;position:relative;background:#fff;width:600px;margin: 0 auto;text-align:left}
+#header {background: #666 url("/<?php echo $data['baseurlpath']; ?>resources/sprites.gif") repeat-x 0 100%;margin: 0 0 25px;padding: 0 0 8px}
+#header h1 {color:#fff;font-size: 145%;padding:20px 20px 12px}
+#poweredby {width:96px;height:63px;position:absolute;top:0;right:0}
+#content {padding: 0 20px}
+
+/* TYPOGRAPHY */
+p, ul, ol {margin: 0 0 1.5em}
+h1, h2, h3, h4, h5, h6 {letter-spacing: -1px;font-family: arial,verdana,sans-serif;margin: 1.2em 0 .3em;color:#000;border-bottom: 1px solid #eee;padding-bottom: .1em}
+h1 {font-size: 196%;margin-top:0;border:none}
+h2 {font-size: 136%}
+h3 {font-size: 126%}
+h4 {font-size: 116%}
+h5 {font-size: 106%}
+h6 {font-size: 96%}
+
+.old {text-decoration:line-through}
+</style>
+</head>
+<body>
+
+<div id="wrap">
+
+	<div id="header">
+		<h1>simpleSAMLphp error page</h1>
+		<div id="poweredby"><img src="/<?php echo $data['baseurlpath']; ?>resources/icons/bomb_l.png" alt="Login screen" /></div>
+	</div>
+	
+	<div id="content">
+	
+
+
+
+		<h2><?php if (isset($data['header'])) { echo $data['header']; } else { echo "Some error occured"; } ?></h2>
+		
+		<p>
+			
+			<?php echo $data['message']; ?>
+
+		</p>
+
+		
+		<p>The debug information below may be interesting for the administrator / help desk:</p>
+		
+		<div style="border: 1px solid #eee; padding: 1em; font-size: x-small">
+			<p style="margin: 1px"><?php echo htmlentities($data['e']->getMessage()); ?></p>
+			<div style=" padding: 1em; font-family: monospace; ">
+				<?php echo htmlentities($data['e']->getTraceAsString()); ?>
+			</div>
+		</div>
+		
+		<h2 style="clear: both">How to get help</h2>
+		
+		
+		<p>This error probably is due to some unexpected behaviour or to misconfiguration of simpleSAMLphp. Contact the administrator of this login service, and send them the error message above.</p>
+		
+
+
+		<hr />
+		
+		Copyright &copy; 2007 <a href="http://rnd.feide.no/">Feide RnD</a>
+		
+		<hr />
+	
+	</div>
+
+</div>
+
+</body>
+</html>
diff --git a/templates/login.php b/templates/login.php
new file mode 100644
index 0000000000000000000000000000000000000000..756e37f62d402f6e14606ac6f68e9fb71c0d0ff9
--- /dev/null
+++ b/templates/login.php
@@ -0,0 +1,124 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title><?php echo $data['header']; ?></title>
+<script>
+<!--
+function sf(){document.f.username.focus();}
+// -->
+</script>
+<style type="text/css">
+
+/* these styles are in the head of this page because this is a unique page */
+
+/* THE BIG GUYS */
+* {margin:0;padding:0}
+body {text-align:center;padding: 20px 0;background: #222;color:#333;font:83%/1.5 arial,tahoma,verdana,sans-serif}
+img {border:none;display:block}
+hr {margin: 1em 0;background:#eee;height:1px;color:#eee;border:none;clear:both}
+
+/* LINKS */
+a,a:link,a:link,a:link,a:hover {font-weight:bold;background:transparent;text-decoration:underline;cursor:pointer} 
+a:link {color:#c00} 
+a:visited {color:#999} 
+a:hover,a:active {color:#069} 
+
+/* LISTS */
+ul {margin: .3em 0 1.5em 2em}
+	ul.related {margin-top:-1em}
+li {margin-left:2em}
+dt {font-weight:bold}
+#wrap {border: 1px solid #fff;position:relative;background:#fff;width:600px;margin: 0 auto;text-align:left}
+#header {background: #666 url("/<?php echo $data['baseurlpath']; ?>resources/sprites.gif") repeat-x 0 100%;margin: 0 0 25px;padding: 0 0 8px}
+#header h1 {color:#fff;font-size: 145%;padding:20px 20px 12px}
+#poweredby {width:96px;height:63px;position:absolute;top:0;right:0}
+#content {padding: 0 20px}
+
+/* TYPOGRAPHY */
+p, ul, ol {margin: 0 0 1.5em}
+h1, h2, h3, h4, h5, h6 {letter-spacing: -1px;font-family: arial,verdana,sans-serif;margin: 1.2em 0 .3em;color:#000;border-bottom: 1px solid #eee;padding-bottom: .1em}
+h1 {font-size: 196%;margin-top:0;border:none}
+h2 {font-size: 136%}
+h3 {font-size: 126%}
+h4 {font-size: 116%}
+h5 {font-size: 106%}
+h6 {font-size: 96%}
+
+.old {text-decoration:line-through}
+</style>
+</head>
+<body onload="sf();">
+
+<div id="wrap">
+
+	<div id="header">
+		<h1>simpleSAMLphp authentication</h1>
+		<div id="poweredby"><img src="/<?php echo $data['baseurlpath']; ?>resources/icons/lock.png" alt="Login screen" /></div>
+	</div>
+	
+	<div id="content">
+	
+		<?php if (isset($data['error'])) { ?>
+		<div style="border-left: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8; background: #f5f5f5"
+		<img src="/<?php echo $data['baseurlpath']; ?>resources/icons/bomb.png" style="float: left; margin: 15px " />
+		<h2>What you entered was not accepted!</h2>
+		
+		<p><?php echo $data['error']; ?> </p>
+		</div>
+		<?php } ?>
+	
+		<h2 style="break: both">Enter your username and password</h2>
+		
+		<p>
+			A service has requested you to authenticate your self. That means you need to enter your username and password in the form below.
+		</p>
+		
+		<form action="?" method="post" name="f">
+
+		<table>
+			<tr>
+				<td rowspan="2"><img src="/<?php echo $data['baseurlpath']; ?>resources/icons/pencil.png" /></td>
+				<td style="padding: .3em;">Username</td>
+				<td><input type="text" tabindex="1" name="username" 
+					<?php if (isset($data['username'])) {
+						echo 'value="' . $data['username'] . '"';
+					} ?> /></td>
+				<td style="padding: .4em; rowspan="2">
+					<input type="submit" tabindex="3" value="Login" />
+					<input type="hidden" name="RelayState" value="<?php echo $data['relaystate']; ?>" />
+				</td>
+			</tr>
+			<tr>
+				<td style="padding: .3em;">Password</td>
+				<td><input type="password" tabindex="2" name="password" /></td>
+			</tr>
+		</table>
+		
+		
+		</form>
+		
+		
+		<h2>Help! I don't remember my password.</h2>
+		
+		
+		<p>Too bad! - Without your username and password you cannot authenticate your self and access the service.
+		There may be someone that can help you. Contact the help desk at your university!</p>
+		
+		<h2>About simpleSAMLphp</h2>
+		<p>Hey! This simpleSAMLphp thing is pretty cool, where can I read more about it?
+		You can find more information about simpleSAMLphp at <a href="http://rnd.feide.no">the Feide RnD blog</a> over at <a href="http://uninett.no">UNINETT</a>.</p>
+		
+
+		<hr />
+		
+		Copyright &copy; 2007 <a href="http://rnd.feide.no/">Feide RnD</a>
+		
+		<hr />
+	
+	</div>
+
+</div>
+
+</body>
+</html>
diff --git a/templates/post-debug.php b/templates/post-debug.php
new file mode 100644
index 0000000000000000000000000000000000000000..b3dfebf1105cbc198cd21eceafd9ecb0a1bb36df
--- /dev/null
+++ b/templates/post-debug.php
@@ -0,0 +1,91 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title><?php echo $data['header']; ?></title>
+<script>
+<!--
+function sf(){document.f.username.focus();}
+// -->
+</script>
+<style type="text/css">
+
+/* these styles are in the head of this page because this is a unique page */
+
+/* THE BIG GUYS */
+* {margin:0;padding:0}
+body {text-align:center;padding: 20px 0;background: #222;color:#333;font:83%/1.5 arial,tahoma,verdana,sans-serif}
+img {border:none;display:block}
+hr {margin: 1em 0;background:#eee;height:1px;color:#eee;border:none;clear:both}
+
+/* LINKS */
+a,a:link,a:link,a:link,a:hover {font-weight:bold;background:transparent;text-decoration:underline;cursor:pointer} 
+a:link {color:#c00} 
+a:visited {color:#999} 
+a:hover,a:active {color:#069} 
+
+/* LISTS */
+ul {margin: .3em 0 1.5em 2em}
+	ul.related {margin-top:-1em}
+li {margin-left:2em}
+dt {font-weight:bold}
+#wrap {border: 1px solid #fff;position:relative;background:#fff;width:600px;margin: 0 auto;text-align:left}
+#header {background: #666 url("/<?php echo $data['baseurlpath']; ?>resources/sprites.gif") repeat-x 0 100%;margin: 0 0 25px;padding: 0 0 8px}
+#header h1 {color:#fff;font-size: 145%;padding:20px 20px 12px}
+#poweredby {width:96px;height:63px;position:absolute;top:0;right:0}
+#content {padding: 0 20px}
+
+/* TYPOGRAPHY */
+p, ul, ol {margin: 0 0 1.5em}
+h1, h2, h3, h4, h5, h6 {letter-spacing: -1px;font-family: arial,verdana,sans-serif;margin: 1.2em 0 .3em;color:#000;border-bottom: 1px solid #eee;padding-bottom: .1em}
+h1 {font-size: 196%;margin-top:0;border:none}
+h2 {font-size: 136%}
+h3 {font-size: 126%}
+h4 {font-size: 116%}
+h5 {font-size: 106%}
+h6 {font-size: 96%}
+
+.old {text-decoration:line-through}
+</style>
+</head>
+<body onload="sf();">
+
+<div id="wrap">
+
+	<div id="header">
+		<h1>simpleSAMLphp authentication</h1>
+		<div id="poweredby"><img src="/<?php echo $data['baseurlpath']; ?>resources/icons/debug.png" alt="Debug" /></div>
+	</div>
+	
+	<div id="content">
+	
+
+
+		<h2>Sending a SAML response to the service</h2>
+	
+		<p>You are about to send a SAML response back to the service. Hit the send response button to continue.</p>
+		
+		<form method="post" action="<?php echo $data['destination']; ?>">
+			<input type="hidden" name="SAMLResponse" value="<?php echo $data['response']; ?>" />
+			<input type="hidden" name="<?php echo $data['RelayStateName']; ?>" value="<?php echo $data['RelayState']; ?>">
+			<input type="submit" value="Submit the response to the service" />
+		</form>
+
+		<h2>Debug mode</h2>
+		
+		<p>As you are in debug mode you are lucky to see the content of the response you are sending:</p>
+		
+		<pre style="overflow: scroll; border: 1px solid #eee"><?php echo $data['responseHTML']; ?></pre>
+
+		<hr />
+		
+		Copyright &copy; 2007 <a href="http://rnd.feide.no/">Feide RnD</a>
+		
+		<hr />
+	
+	</div>
+
+</div>
+
+</body>
+</html>
diff --git a/templates/post.php b/templates/post.php
new file mode 100644
index 0000000000000000000000000000000000000000..2329cdbca7059cb3722bfd793a6c29c399c6e17f
--- /dev/null
+++ b/templates/post.php
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+	<title>SAML 2.0 POST</title>
+</head>
+<body onload="document.forms[0].submit()">
+
+	<noscript>
+		<p><strong>Note:</strong> Since your browser does not support JavaScript, you must press the button below once to proceed.</p> 
+	</noscript> 
+	
+	<form method="post" action="<?php echo $data['destination']; ?>">
+		<input type="hidden" name="SAMLResponse" value="<?php echo $data['response']; ?>" />
+		<input type="hidden" name="<?php echo $data['RelayStateName']; ?>" value="<?php echo $data['RelayState']; ?>">
+		
+		<noscript>
+			<input type="submit" value="Submit the response to the service" />
+		</noscript>
+	</form>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/templates/status.php b/templates/status.php
new file mode 100644
index 0000000000000000000000000000000000000000..609c043612b80a3a3b14eae8d6bcf53d2a14be07
--- /dev/null
+++ b/templates/status.php
@@ -0,0 +1,111 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title><?php echo $data['header']; ?></title>
+
+<style type="text/css">
+
+/* these styles are in the head of this page because this is a unique page */
+
+/* THE BIG GUYS */
+* {margin:0;padding:0}
+body {text-align:center;padding: 20px 0;background: #222;color:#333;font:83%/1.5 arial,tahoma,verdana,sans-serif}
+img {border:none;display:block}
+hr {margin: 1em 0;background:#eee;height:1px;color:#eee;border:none;clear:both}
+
+/* LINKS */
+a,a:link,a:link,a:link,a:hover {font-weight:bold;background:transparent;text-decoration:underline;cursor:pointer} 
+a:link {color:#c00} 
+a:visited {color:#999} 
+a:hover,a:active {color:#069} 
+
+/* LISTS */
+ul {margin: .3em 0 1.5em 2em}
+	ul.related {margin-top:-1em}
+li {margin-left:2em}
+dt {font-weight:bold}
+#wrap {border: 1px solid #fff;position:relative;background:#fff;width:600px;margin: 0 auto;text-align:left}
+#header {background: #666 url("/<?php echo $data['baseurlpath']; ?>resources/sprites.gif") repeat-x 0 100%;margin: 0 0 25px;padding: 0 0 8px}
+#header h1 {color:#fff;font-size: 145%;padding:20px 20px 12px}
+#poweredby {width:96px;height:63px;position:absolute;top:0;right:0}
+#content {padding: 0 20px}
+
+/* TYPOGRAPHY */
+p, ul, ol {margin: 0 0 1.5em}
+h1, h2, h3, h4, h5, h6 {letter-spacing: -1px;font-family: arial,verdana,sans-serif;margin: 1.2em 0 .3em;color:#000;border-bottom: 1px solid #eee;padding-bottom: .1em}
+h1 {font-size: 196%;margin-top:0;border:none}
+h2 {font-size: 136%}
+h3 {font-size: 126%}
+h4 {font-size: 116%}
+h5 {font-size: 106%}
+h6 {font-size: 96%}
+
+.old {text-decoration:line-through}
+</style>
+</head>
+<body>
+
+<div id="wrap">
+
+	<div id="header">
+		<h1>simpleSAMLphp status page</h1>
+		<div id="poweredby"><img src="/<?php echo $data['baseurlpath']; ?>resources/icons/bino.png" alt="Bino" /></div>
+	</div>
+	
+	<div id="content">
+
+		<h2><?php if (isset($data['header'])) { echo $data['header']; } else { echo "Some error occured"; } ?></h2>
+		
+		<p>Hi, this is the status page of simpleSAMLphp. Here you can see if your session is timed out, how long it lasts until it times out and all the attributes that is attached to your session.</p>
+		
+		<p><?php echo $data['valid']; ?>. Your session is valid for <?php echo $data['remaining']; ?> seconds from now.</p>
+		
+		<h2>Your attributes</h2>
+		
+
+			<table>
+			<?php
+			
+			$attributes = $data['attributes'];
+			foreach ($attributes AS $name => $value) {
+				if (sizeof($value) > 1) {
+					echo '<tr><td>' . $name . '</td><td><ul>';
+					foreach ($value AS $v) {
+						echo '<li>' . $v . '</li>';
+					}
+					echo '</ul></td></tr>';
+				} else {
+					echo '<tr><td>' . $name . '</td><td>' . $value[0] . '</td></tr>';
+				}
+			}
+			
+			#echo "\n\n\n" . $session->getMessage() . "\n\n\n";
+			
+			?>
+			</table>
+
+		<h2>Logout</h2>
+
+			<p><?php echo $data['logout']; ?></p>
+		
+		<h2>About simpleSAMLphp</h2>
+		<p>Hey! This simpleSAMLphp thing is pretty cool, where can I read more about it?
+		You can find more information about simpleSAMLphp at <a href="http://rnd.feide.no">the Feide RnD blog</a> over at <a href="http://uninett.no">UNINETT</a>.</p>
+		
+
+		
+
+
+		<hr />
+		
+		Copyright &copy; 2007 <a href="http://rnd.feide.no/">Feide RnD</a>
+		
+		<hr />
+	
+	</div>
+
+</div>
+
+</body>
+</html>
diff --git a/www/_include.php b/www/_include.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab5e7dcab22bc81bf2339bd474412a5844728c09
--- /dev/null
+++ b/www/_include.php
@@ -0,0 +1,18 @@
+<?php
+
+
+
+$path_extra = dirname(dirname(__FILE__)) . '/lib';
+
+$path = ini_get('include_path');
+$path = $path_extra . PATH_SEPARATOR . $path;
+ini_set('include_path', $path);
+
+require_once('SimpleSAML/Configuration.php');
+
+SimpleSAML_Configuration::init(dirname(dirname(__FILE__)) . '/config');
+
+
+
+
+?>
\ No newline at end of file
diff --git a/www/auth/login-auto.php b/www/auth/login-auto.php
new file mode 100644
index 0000000000000000000000000000000000000000..f06c29baf86510e6b9f90dfc71c1379f410ded86
--- /dev/null
+++ b/www/auth/login-auto.php
@@ -0,0 +1,95 @@
+<?php
+
+
+require_once('../../www/_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+require_once('SimpleSAML/XHTML/Template.php');
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+	
+$session = SimpleSAML_Session::getInstance();
+
+$error = null;
+$attributes = array();
+	
+if (isset($_POST['username'])) {
+
+
+	$dn = str_replace('%username%', $_POST['username'], $config->getValue('auth.ldap.dnpattern'));
+	$pwd = $_POST['password'];
+
+	$ds = ldap_connect($config->getValue('auth.ldap.hostname'));
+	
+	if ($ds) {
+	
+		if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
+			echo "Failed to set LDAP Protocol version to 3";
+			exit;
+		}
+		/*
+		if (!ldap_start_tls($ds)) {
+		echo "Failed to start TLS";
+		exit;
+		}
+		*/
+		if (!ldap_bind($ds, $dn, $pwd)) {
+			$error = "Bind failed, wrong username or password. Tried with DN=[" . $dn . "] DNPattern=[" . $config->getValue('auth.ldap.dnpattern') . "]";
+			
+			
+		} else {
+			$sr = ldap_read($ds, $dn, $config->getValue('auth.ldap.attributes'));
+			$ldapentries = ldap_get_entries($ds, $sr);
+			
+
+			for ($i = 0; $i < $ldapentries[0]['count']; $i++) {
+				$values = array();
+				if ($ldapentries[0][$i] == 'jpegphoto') continue;
+				for ($j = 0; $j < $ldapentries[0][$ldapentries[0][$i]]['count']; $j++) {
+					$values[] = $ldapentries[0][$ldapentries[0][$i]][$j];
+				}
+				
+				$attributes[$ldapentries[0][$i]] = $values;
+			}
+
+			// generelt ldap_next_entry for flere, men bare ett her
+			//print_r($ldapentries);
+			//print_r($attributes);
+			
+			$session->setAuthenticated(true);
+			$session->setAttributes($attributes);
+			$returnto = $_SESSION['webssourl']. '?RequestID=' . $_REQUEST['RequestID'];
+			header("Location: " . $returnto);
+
+		}
+	// ldap_close() om du vil, men frigjoeres naar skriptet slutter
+	}
+	
+
+	
+	
+}
+
+
+$t = new SimpleSAML_XHTML_Template($config, 'login.php');
+
+$t->data['header'] = 'simpleSAMLphp: Enter username and password';	
+$t->data['requestid'] = $_REQUEST['RequestID'];
+$t->data['error'] = $error;
+if (isset($error)) {
+	$t->data['username'] = $_POST['username'];
+}
+
+$t->show();
+
+
+?>
diff --git a/www/auth/login-radius.php b/www/auth/login-radius.php
new file mode 100644
index 0000000000000000000000000000000000000000..49ceee2e9e72d19bf9a4adad606e31f159e590a8
--- /dev/null
+++ b/www/auth/login-radius.php
@@ -0,0 +1,95 @@
+<?php
+
+
+require_once('../../www/_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+require_once('SimpleSAML/XHTML/Template.php');
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+	
+$session = SimpleSAML_Session::getInstance();
+
+$error = null;
+$attributes = array();
+	
+if (isset($_POST['username'])) {
+
+
+	$dn = str_replace('%username%', $_POST['username'], $config->getValue('auth.ldap.dnpattern'));
+	$pwd = $_POST['password'];
+
+	$ds = ldap_connect($config->getValue('auth.ldap.hostname'));
+	
+	if ($ds) {
+	
+		if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
+			echo "Failed to set LDAP Protocol version to 3";
+			exit;
+		}
+		/*
+		if (!ldap_start_tls($ds)) {
+		echo "Failed to start TLS";
+		exit;
+		}
+		*/
+		if (!ldap_bind($ds, $dn, $pwd)) {
+			$error = "Bind failed, wrong username or password. Tried with DN=[" . $dn . "] DNPattern=[" . $config->getValue('auth.ldap.dnpattern') . "]";
+			
+			
+		} else {
+			$sr = ldap_read($ds, $dn, $config->getValue('auth.ldap.attributes'));
+			$ldapentries = ldap_get_entries($ds, $sr);
+			
+
+			for ($i = 0; $i < $ldapentries[0]['count']; $i++) {
+				$values = array();
+				if ($ldapentries[0][$i] == 'jpegphoto') continue;
+				for ($j = 0; $j < $ldapentries[0][$ldapentries[0][$i]]['count']; $j++) {
+					$values[] = $ldapentries[0][$ldapentries[0][$i]][$j];
+				}
+				
+				$attributes[$ldapentries[0][$i]] = $values;
+			}
+
+			// generelt ldap_next_entry for flere, men bare ett her
+			//print_r($ldapentries);
+			//print_r($attributes);
+			
+			$session->setAuthenticated(true);
+			$session->setAttributes($attributes);
+			$returnto = $_REQUEST['RelayState'];
+			header("Location: " . $returnto);
+
+		}
+	// ldap_close() om du vil, men frigjoeres naar skriptet slutter
+	}
+	
+
+	
+	
+}
+
+
+$t = new SimpleSAML_XHTML_Template($config, 'login.php');
+
+$t->data['header'] = 'simpleSAMLphp: Enter username and password';	
+$t->data['requestid'] = $_REQUEST['RequestID'];
+$t->data['error'] = $error;
+if (isset($error)) {
+	$t->data['username'] = $_POST['username'];
+}
+
+$t->show();
+
+
+?>
diff --git a/www/auth/login.php b/www/auth/login.php
new file mode 100644
index 0000000000000000000000000000000000000000..31f05dfbd8453cc65351e8d3e33c22fd07bf83f2
--- /dev/null
+++ b/www/auth/login.php
@@ -0,0 +1,98 @@
+<?php
+
+
+require_once('../../www/_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+require_once('SimpleSAML/XHTML/Template.php');
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+	
+$session = SimpleSAML_Session::getInstance();
+
+$error = null;
+$attributes = array();
+	
+if (isset($_POST['username'])) {
+
+
+	$dn = str_replace('%username%', $_POST['username'], $config->getValue('auth.ldap.dnpattern'));
+	$pwd = $_POST['password'];
+
+	$ds = ldap_connect($config->getValue('auth.ldap.hostname'));
+	
+	if ($ds) {
+	
+		if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
+			echo "Failed to set LDAP Protocol version to 3";
+			exit;
+		}
+		/*
+		if (!ldap_start_tls($ds)) {
+		echo "Failed to start TLS";
+		exit;
+		}
+		*/
+		if (!ldap_bind($ds, $dn, $pwd)) {
+			$error = "Bind failed, wrong username or password. Tried with DN=[" . $dn . "] DNPattern=[" . $config->getValue('auth.ldap.dnpattern') . "]";
+			
+			
+		} else {
+			$sr = ldap_read($ds, $dn, $config->getValue('auth.ldap.attributes'));
+			$ldapentries = ldap_get_entries($ds, $sr);
+			
+
+			for ($i = 0; $i < $ldapentries[0]['count']; $i++) {
+				$values = array();
+				if ($ldapentries[0][$i] == 'jpegphoto') continue;
+				for ($j = 0; $j < $ldapentries[0][$ldapentries[0][$i]]['count']; $j++) {
+					$values[] = $ldapentries[0][$ldapentries[0][$i]][$j];
+				}
+				
+				$attributes[$ldapentries[0][$i]] = $values;
+			}
+
+			// generelt ldap_next_entry for flere, men bare ett her
+			//print_r($ldapentries);
+			//print_r($attributes);
+			
+			$session->setAuthenticated(true);
+			$session->setAttributes($attributes);
+			
+			$session->setNameID(SimpleSAML_Utilities::generateID());
+			$session->setNameIDFormat('urn:oasis:names:tc:SAML:2.0:nameid-format:transient');
+			
+			$returnto = $_REQUEST['RelayState'];
+			header("Location: " . $returnto);
+			exit(0);
+
+		}
+	// ldap_close() om du vil, men frigjoeres naar skriptet slutter
+	}
+
+	
+}
+
+
+$t = new SimpleSAML_XHTML_Template($config, 'login.php');
+
+$t->data['header'] = 'simpleSAMLphp: Enter username and password';	
+$t->data['relaystate'] = $_REQUEST['RelayState'];
+$t->data['error'] = $error;
+if (isset($error)) {
+	$t->data['username'] = $_POST['username'];
+}
+
+$t->show();
+
+
+?>
diff --git a/www/example-simple/saml2-example.php b/www/example-simple/saml2-example.php
new file mode 100644
index 0000000000000000000000000000000000000000..7da667c980c341758109721c7706a80661c17125
--- /dev/null
+++ b/www/example-simple/saml2-example.php
@@ -0,0 +1,52 @@
+<?php
+
+require_once('../_include.php');
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
+require_once('SimpleSAML/XML/SAML20/AuthnResponse.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+require_once('SimpleSAML/XHTML/Template.php');
+
+session_start();
+
+/* Load simpleSAMLphp, configuration and metadata */
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+$session = SimpleSAML_Session::getInstance();
+
+/* Check if valid local session exists.. */
+if (!isset($session) || !$session->isValid() ) {
+	header('Location: /' . $config->getValue('baseurlpath') . 'saml2/sp/initSSO.php?RelayState=' . urlencode(SimpleSAML_Utilities::selfURL()));
+	exit(0);
+}
+
+$attributes = $session->getAttributes();
+
+/*
+ * The attributes variable now contains all the attributes. So this variable is basicly all you need to perform integration in 
+ * your PHP application.
+ * 
+ * To debug the content of the attributes variable, do something like:
+ *
+ * print_r($attributes);
+ *
+ */
+
+
+
+$et = new SimpleSAML_XHTML_Template($config, 'status.php');
+
+$et->data['header'] = 'SAML 2.0 SP Demo Example';
+$et->data['remaining'] = $session->remainingTime();
+$et->data['attributes'] = $attributes;
+$et->data['valid'] = $session->isValid() ? 'Session is valid' : 'Session is invalid';
+$et->data['logout'] = '[ <a href="https://sam.feide.no/amserver/saml2/jsp/idpSingleLogoutInit.jsp?binding=urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect">IdP intiated logout from Feide (only if you are connected to the Feide IdP)</a> ]</p>
+			<p>[ <a href="/' . $config->getValue('baseurlpath') . 'saml2/sp/initSLO.php?RelayState=' .  urlencode(SimpleSAML_Utilities::selfURL()) . '">SP initated logout</a> ]';
+$et->show();
+
+
+?>
\ No newline at end of file
diff --git a/www/example-simple/shib13-example.php b/www/example-simple/shib13-example.php
new file mode 100644
index 0000000000000000000000000000000000000000..377816a7f8b39cbc9e011553f3836aa26e5e5345
--- /dev/null
+++ b/www/example-simple/shib13-example.php
@@ -0,0 +1,35 @@
+<?php
+
+require_once('../_include.php');
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XHTML/Template.php');
+session_start();
+
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+$session = SimpleSAML_Session::getInstance();
+
+if (!isset($session) || !$session->isValid() ) {
+	
+	header('Location: ' . $config->getValue('baseurlpath') . '/shib13/sp/initSSO.php?RelayState=' . urlencode(SimpleSAML_Utilities::selfURL()));
+		// . '&idpentityid=' . $idpentityid );
+	exit(0);
+}
+
+$et = new SimpleSAML_XHTML_Template($config, 'status.php');
+
+$et->data['header'] = 'Shibboleth demo';
+$et->data['remaining'] = $session->remainingTime();
+$et->data['attributes'] = $session->getAttributes();
+$et->data['valid'] = $session->isValid() ? 'Session is valid' : 'Session is invalid';
+$et->data['logout'] = 'Shibboleth logout not implemented yet.';
+
+$et->show();
+
+
+?>
diff --git a/www/index.html b/www/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..9940b30d51a94789e77ecf1688bf695e46b1e2fb
--- /dev/null
+++ b/www/index.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>simpleSAMLphp</title>
+
+<style type="text/css">
+
+/* these styles are in the head of this page because this is a unique page */
+
+/* THE BIG GUYS */
+* {margin:0;padding:0}
+body {text-align:center;padding: 20px 0;background: #222;color:#333;font:83%/1.5 arial,tahoma,verdana,sans-serif}
+img {border:none;display:block}
+hr {margin: 1em 0;background:#eee;height:1px;color:#eee;border:none;clear:both}
+
+/* LINKS */
+a,a:link,a:link,a:link,a:hover {font-weight:bold;background:transparent;text-decoration:underline;cursor:pointer} 
+a:link {color:#c00} 
+a:visited {color:#999} 
+a:hover,a:active {color:#069} 
+
+/* LISTS */
+ul {margin: .3em 0 1.5em 2em}
+	ul.related {margin-top:-1em}
+li {margin-left:2em}
+dt {font-weight:bold}
+#wrap {border: 1px solid #fff;position:relative;background:#fff;width:600px;margin: 0 auto;text-align:left}
+#header {background: #666 url("resources/sprites.gif") repeat-x 0 100%;margin: 0 0 25px;padding: 0 0 8px}
+#header h1 {color:#fff;font-size: 145%;padding:20px 20px 12px}
+#poweredby {width:96px;height:63px;position:absolute;top:0;right:0}
+#content {padding: 0 20px}
+
+/* TYPOGRAPHY */
+p, ul, ol {margin: 0 0 1.5em}
+h1, h2, h3, h4, h5, h6 {letter-spacing: -1px;font-family: arial,verdana,sans-serif;margin: 1.2em 0 .3em;color:#000;border-bottom: 1px solid #eee;padding-bottom: .1em}
+h1 {font-size: 196%;margin-top:0;border:none}
+h2 {font-size: 136%}
+h3 {font-size: 126%}
+h4 {font-size: 116%}
+h5 {font-size: 106%}
+h6 {font-size: 96%}
+
+.old {text-decoration:line-through}
+</style>
+</head>
+<body>
+
+<div id="wrap">
+
+	<div id="header">
+		<h1>simpleSAMLphp is installed</h1>
+		<div id="poweredby"><img src="resources/icons/compass_l.png" alt="Bino" /></div>
+	</div>
+	
+	<div id="content">
+
+		<h2>Welcome to simpleSAMlphp</h2>
+		
+		<p>You have installed simpleSAMLphp on this web host.</p>
+		
+		<p>After you have configured it properly as described in the documentation you may want to test one of the two examples:
+			<ul>
+				<li><a href="example-simple/saml2-example.php">SAML 2.0 SP example</a></li>
+				<li><a href="example-simple/shib13-example.php">Shibboleth 1.3 SP example</a></li>
+			</ul>
+		</p>
+
+		<h2>About simpleSAMLphp</h2>
+		<p>Hey! This simpleSAMLphp thing is pretty cool, where can I read more about it?
+		You can find more information about simpleSAMLphp at <a href="http://rnd.feide.no">the Feide RnD blog</a> over at <a href="http://uninett.no">UNINETT</a>.</p>
+		
+
+		
+
+
+		<hr />
+		
+		Copyright &copy; 2007 <a href="http://rnd.feide.no/">Feide RnD</a>
+		
+		<hr />
+	
+	</div>
+
+</div>
+
+</body>
+</html>
diff --git a/www/resources/icons/bino.png b/www/resources/icons/bino.png
new file mode 100644
index 0000000000000000000000000000000000000000..8708a439c91d39ac5a195d1af6d87178663775c8
Binary files /dev/null and b/www/resources/icons/bino.png differ
diff --git a/www/resources/icons/bomb.png b/www/resources/icons/bomb.png
new file mode 100644
index 0000000000000000000000000000000000000000..35811006b5cabde251612955aa1f6385c71829da
Binary files /dev/null and b/www/resources/icons/bomb.png differ
diff --git a/www/resources/icons/bomb_l.png b/www/resources/icons/bomb_l.png
new file mode 100644
index 0000000000000000000000000000000000000000..901409504180b295662068d599aa85e7f5482003
Binary files /dev/null and b/www/resources/icons/bomb_l.png differ
diff --git a/www/resources/icons/compass_l.png b/www/resources/icons/compass_l.png
new file mode 100644
index 0000000000000000000000000000000000000000..2ad574a7b38e661b462e0ad8d72207234cd8e827
Binary files /dev/null and b/www/resources/icons/compass_l.png differ
diff --git a/www/resources/icons/debug.png b/www/resources/icons/debug.png
new file mode 100644
index 0000000000000000000000000000000000000000..5b78608a21cb1649da11ad6599a4f3c0821b9be1
Binary files /dev/null and b/www/resources/icons/debug.png differ
diff --git a/www/resources/icons/lock.png b/www/resources/icons/lock.png
new file mode 100644
index 0000000000000000000000000000000000000000..11073e2969f6ada809e80a322549f19197cd288c
Binary files /dev/null and b/www/resources/icons/lock.png differ
diff --git a/www/resources/icons/pencil.png b/www/resources/icons/pencil.png
new file mode 100644
index 0000000000000000000000000000000000000000..e79a164dc3d1699bafa050caa2d4a644dffa6f6d
Binary files /dev/null and b/www/resources/icons/pencil.png differ
diff --git a/www/resources/sprites.gif b/www/resources/sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ae69d83412dc91ea11333eeca56f19d5aef833db
Binary files /dev/null and b/www/resources/sprites.gif differ
diff --git a/www/saml2/idp/SSOService.php b/www/saml2/idp/SSOService.php
new file mode 100644
index 0000000000000000000000000000000000000000..4d744c4facdd3d6459f9aafd98be03673a3c13f3
--- /dev/null
+++ b/www/saml2/idp/SSOService.php
@@ -0,0 +1,140 @@
+<?php
+
+
+require_once('../../../www/_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
+require_once('SimpleSAML/XML/SAML20/AuthnResponse.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+require_once('SimpleSAML/XHTML/Template.php');
+
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+$idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted');
+$idpmeta = $metadata->getMetaDataCurrent('saml20-idp-hosted');
+
+$requestid = null;
+$session = null;
+
+
+if (isset($_GET['SAMLRequest'])) {
+
+
+	try {
+		$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+		$authnrequest = $binding->decodeRequest($_GET);
+		
+		$session = $authnrequest->createSession();
+	
+		$requestid = $authnrequest->getRequestID();
+		
+	
+		
+		$session->setAuthnRequest($requestid, $authnrequest);
+	
+	} catch(Exception $exception) {
+		
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+		
+		$et->data['header'] = 'Error getting incomming request';
+		$et->data['message'] = 'Something bad happened when simpleSAML got the incomming authentication request';	
+		$et->data['e'] = $exception;
+		
+		$et->show();
+
+	}
+
+} elseif(isset($_GET['RequestID'])) {
+
+	try {
+
+		$requestid = $_GET['RequestID'];
+		$session = SimpleSAML_Session::getInstance();
+		$authnrequest = $session->getAuthnRequest($requestid);
+		
+		if (!$authnrequest) throw new Exception('Could not retrieve cached RequestID = ' . $requestid);
+		
+	} catch(Exception $exception) {
+		
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+		
+		$et->data['header'] = 'Error retrieving authnrequest cache';
+		$et->data['message'] = 'simpleSAML cannot find the authnrequest that it earlier stored.';	
+		$et->data['e'] = $exception;
+		
+		$et->show();
+
+	}
+	
+	
+	/*	
+	$authnrequest = new SimpleSAML_XML_SAML20_AuthnRequest($config, $metadata);
+	$authnrequest->setXML($authnrequestXML);
+	*/
+	
+
+
+} else {
+
+	echo 'You must either provide a SAML Request message or a RequestID on this interface.';
+	exit(0);
+
+}
+
+
+
+
+if (!$session->isAuthenticated() ) {
+
+	$relaystate = SimpleSAML_Utilities::selfURLNoQuery() . '?RelayState=' . urlencode($_GET['RelayState']) .
+		'&RequestID=' . urlencode($requestid);
+	$authurl = SimpleSAML_Utilities::addURLparameter('/' . $config->getValue('baseurlpath') . $idpmeta['auth'], 
+		'RelayState=' . urlencode($relaystate));
+	header('Location: ' . $authurl);
+	exit(0);
+} else {
+
+	try {
+	
+		$session->add_sp_session($authnrequest->getIssuer());
+
+		$ar = new SimpleSAML_XML_SAML20_AuthnResponse($config, $metadata);
+		$authnResponseXML = $ar->generate($idpentityid, $authnrequest->getIssuer(), 
+			$requestid, null, $session->getAttributes());
+		
+		#echo $authnResponseXML;
+		#print_r($session);
+		
+		//sendResponse($response, $idpentityid, $spentityid, $relayState = null) {
+		$httppost = new SimpleSAML_Bindings_SAML20_HTTPPost($config, $metadata);
+		
+		//echo 'Relaystate[' . $authnrequest->getRelayState() . ']';
+		
+		$httppost->sendResponse($authnResponseXML, 
+			$idpentityid, $authnrequest->getIssuer(), $authnrequest->getRelayState());
+			
+	} catch(Exception $exception) {
+		
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+		
+		$et->data['header'] = 'Error sending response to service';
+		$et->data['message'] = 'Some error occured when trying to issue the authentication response, and send it back to the SP.';	
+		$et->data['e'] = $exception;
+		
+		$et->show();
+
+	}
+	
+}
+
+
+?>
\ No newline at end of file
diff --git a/www/saml2/idp/SingleLogoutService.php b/www/saml2/idp/SingleLogoutService.php
new file mode 100644
index 0000000000000000000000000000000000000000..39ba55d17db729771c45ac6017e8336945f122fd
--- /dev/null
+++ b/www/saml2/idp/SingleLogoutService.php
@@ -0,0 +1,146 @@
+<?php
+
+
+require_once('../../../www/_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/LogoutRequest.php');
+require_once('SimpleSAML/XML/SAML20/LogoutResponse.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+//require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+require_once('SimpleSAML/XHTML/Template.php');
+
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+$idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted');
+
+$session = SimpleSAML_Session::getInstance();
+
+$session->dump_sp_sessions();
+
+/*
+ * If we get an LogoutRequest then we initiate the logout process.
+ */
+if (isset($_GET['SAMLRequest'])) {
+
+	$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+	$logoutrequest = $binding->decodeLogoutRequest($_GET);
+	
+	$session->setAuthenticated(false);
+
+	//$requestid = $authnrequest->getRequestID();
+	//$session->setAuthnRequest($requestid, $authnrequest);
+	
+	//echo '<pre>' . htmlentities($logoutrequest->getXML()) . '</pre>';
+	
+	error_log('IdP LogoutService: got Logoutrequest from ' . $logoutrequest->getIssuer() . '  ');
+	
+	$session->set_sp_logout_completed($logoutrequest->getIssuer() );
+	$session->setLogoutRequest($logoutrequest);
+
+/*
+ * We receive a Logout Response to a Logout Request that we have issued earlier.
+ */
+} elseif (isset($_GET['SAMLResponse'])) {
+
+	$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+	$loginresponse = $binding->decodeLogoutResponse($_GET);
+	
+	$session->set_sp_logout_completed($loginresponse->getIssuer());
+	
+	error_log('IdP LogoutService: got LogoutResponse from ' . $loginresponse->getIssuer() . '  ');
+}
+
+/*
+ * We proceed to send logout requests to all remaining SPs.
+ */
+$spentityid = $session->get_next_sp_logout();
+if ($spentityid) {
+
+	error_log('IdP LogoutService: next SP ' . $spentityid);
+
+	try {
+		$lr = new SimpleSAML_XML_SAML20_LogoutRequest($config, $metadata);
+	
+		// ($issuer, $receiver, $nameid, $nameidformat, $sessionindex, $mode) {
+		$req = $lr->generate($idpentityid, $spentityid, $session->getNameID(), $session->getNameIDFormat(), $session->getSessionIndex(), 'IdP');
+		
+		$httpredirect = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+		
+		$relayState = SimpleSAML_Utilities::selfURL();
+		if (isset($_GET['RelayState'])) {
+			$relayState = $_GET['RelayState'];
+		}
+		
+		//$request, $remoteentityid, $relayState = null, $endpoint = 'SingleSignOnUrl', $direction = 'SAMLRequest', $mode = 'SP'
+		$httpredirect->sendMessage($req, $spentityid, $relayState, 'SingleLogOutUrl', 'SAMLRequest', 'IdP');
+		
+		exit();
+
+	} catch(Exception $exception) {
+		
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+		
+		$et->data['header'] = 'Error sending logout request to service';
+		$et->data['message'] = 'Some error occured when trying to issue the logout response, and send it to the SP.';	
+		$et->data['e'] = $exception;
+		
+		$et->show();
+		exit(0);
+	}
+
+
+}
+
+/*
+ * Logout procedure is done and we send a Logout Response back to the SP
+ */
+error_log('IdP LogoutService:  SPs done ');
+try {
+
+	$logoutrequest = $session->getLogoutRequest();
+	if (!$logoutrequest) {
+		throw new Exception('Could not get reference to the logout request.');
+	}
+
+	$rg = new SimpleSAML_XML_SAML20_LogoutResponse($config, $metadata);
+	
+	// generate($issuer, $receiver, $inresponseto, $mode )
+	
+	$logoutResponseXML = $rg->generate($idpentityid, $logoutrequest->getIssuer(), $logoutrequest->getRequestID(), 'IdP');
+	
+	//	echo '<pre>' . htmlentities($logoutResponseXML) . '</pre>';
+	//	exit();
+	
+	$httpredirect = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+	
+	$relayState = SimpleSAML_Utilities::selfURL();
+	if (isset($_GET['RelayState'])) {
+		$relayState = $_GET['RelayState'];
+	}
+	
+	//$request, $remoteentityid, $relayState = null, $endpoint = 'SingleSignOnUrl', $direction = 'SAMLRequest', $mode = 'SP'
+	$httpredirect->sendMessage($logoutResponseXML, $logoutrequest->getIssuer(), $relayState, 'SingleLogOutUrl', 'SAMLResponse', 'IdP');
+
+} catch(Exception $exception) {
+	
+	$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+	
+	$et->data['header'] = 'Error sending response to service';
+	$et->data['message'] = 'Some error occured when trying to issue the logout response, and send it to the SP.';	
+	$et->data['e'] = $exception;
+	
+	$et->show();
+
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/www/saml2/sp/AssertionConsumerService.php b/www/saml2/sp/AssertionConsumerService.php
new file mode 100644
index 0000000000000000000000000000000000000000..2c2d99066e241b36c29b2b80eee62903d8ff496c
--- /dev/null
+++ b/www/saml2/sp/AssertionConsumerService.php
@@ -0,0 +1,52 @@
+<?php
+
+require_once('../../_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+require_once('SimpleSAML/XHTML/Template.php');
+
+session_start();
+
+try {
+	
+	$config = SimpleSAML_Configuration::getInstance();	
+	$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+	$binding = new SimpleSAML_Bindings_SAML20_HTTPPost($config, $metadata);
+	$authnResponse = $binding->decodeResponse($_POST);
+	
+	$authnResponse->validate();
+	
+	$session = $authnResponse->createSession();
+	if (isset($session)) {
+	
+		$relayState = $authnResponse->getRelayState();
+		if (isset($relayState)) {
+			header("Location: " . $relayState);
+			exit(0);
+		} else {
+			echo 'Could not find RelayState parameter, you are stucked here.';
+		}
+	} else {
+		throw new Exception('Unkown error. Could not get session.');
+	}
+
+} catch(Exception $exception) {
+
+	$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+
+	$et->data['header'] = 'Error receiving response from IdP';
+	$et->data['message'] = 'Some error occured when trying to issue the authentication request to the IdP.';	
+	$et->data['e'] = $exception;
+	
+	$et->show();
+
+}
+
+
+?>
\ No newline at end of file
diff --git a/www/saml2/sp/SingleLogoutService.php b/www/saml2/sp/SingleLogoutService.php
new file mode 100644
index 0000000000000000000000000000000000000000..c31ebd5462a04f6339181b5e87e346bf968c7403
--- /dev/null
+++ b/www/saml2/sp/SingleLogoutService.php
@@ -0,0 +1,78 @@
+<?php
+
+require_once('../../_include.php');
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/LogoutRequest.php');
+require_once('SimpleSAML/XML/SAML20/LogoutResponse.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+
+
+
+
+// Get the local session
+$session = SimpleSAML_Session::getInstance();
+
+
+// Destroy local session if exists.
+if (isset($session) && $session->isAuthenticated() ) {	
+	$session->setAuthenticated(false);
+}
+
+
+
+
+if (isset($_GET['SAMLRequest'])) {
+		
+	// Create a HTTPRedirect binding
+	$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+	
+	// Decode the LogoutRequest using the HTTP Redirect binding.
+	$logoutrequest = $binding->decodeLogoutRequest($_GET);
+	
+	// Extract some parameters from the logout request
+	$requestid = $logoutrequest->getRequestID();
+	$requester = $logoutrequest->getIssuer();
+	$relayState = $logoutrequest->getRelayState();
+	
+	
+	//$responder = $config->getValue('saml2-hosted-sp');
+	$responder = $metadata->getMetaDataCurrentEntityID();
+	
+
+	
+	// Create a logout response
+	$lr = new SimpleSAML_XML_SAML20_LogoutResponse($config, $metadata);
+	$logoutResponseXML = $lr->generate($responder, $requester, $requestid, 'SP');
+	
+	
+	// Create a HTTP Redirect binding.
+	$httpredirect = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+	
+	// Send the Logout response using HTTP POST binding.
+	$httpredirect->sendMessage($logoutResponseXML, $requester, $logoutrequest->getRelayState(), 'SingleLogOutUrl', 'SAMLResponse');
+
+} elseif(isset($_GET['SAMLResponse'])) {
+	
+
+	if (isset($_GET['RelayState'])) {
+		header('Location: ' . $_GET['RelayState']);
+	} else {
+		
+		echo 'You are now successfully logged out.';
+		
+	}
+
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/www/saml2/sp/initSLO.php b/www/saml2/sp/initSLO.php
new file mode 100644
index 0000000000000000000000000000000000000000..e3aae4e175cbe4cc208545c9eb2e222ce7dd020e
--- /dev/null
+++ b/www/saml2/sp/initSLO.php
@@ -0,0 +1,66 @@
+<?php
+
+require_once('../../_include.php');
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/LogoutRequest.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+//require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+$session = SimpleSAML_Session::getInstance();
+
+$idpentityid = isset($_GET['idpentityid']) ? $_GET['idpentityid'] : $config->getValue('default-saml20-idp') ;
+$spentityid = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID();
+
+
+if (isset($session) ) {
+	
+	try {
+		$lr = new SimpleSAML_XML_SAML20_LogoutRequest($config, $metadata);
+	
+		// ($issuer, $receiver, $nameid, $nameidformat, $sessionindex, $mode) {
+		$req = $lr->generate($spentityid, $idpentityid, $session->getNameID(), $session->getNameIDFormat(), $session->getSessionIndex(), 'SP');
+		
+		$httpredirect = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+		
+		$relayState = SimpleSAML_Utilities::selfURL();
+		if (isset($_GET['RelayState'])) {
+			$relayState = $_GET['RelayState'];
+		}
+		
+		//$request, $remoteentityid, $relayState = null, $endpoint = 'SingleSignOnUrl', $direction = 'SAMLRequest', $mode = 'SP'
+		$httpredirect->sendMessage($req, $idpentityid, $relayState, 'SingleLogOutUrl', 'SAMLRequest', 'SP');
+
+	} catch(Exception $exception) {
+		
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+
+		$et->$data['message'] = 'Some error occured when trying to issue the logout request to the IdP.';	
+		$et->$data['e'] = $exception;
+		
+		$et->show();
+
+	}
+
+} else {
+
+	
+	$relaystate = $session->getRelayState();
+	
+	header('Location: ' . $relaystate );
+	
+	#print_r($metadata->getMetaData('sam.feide.no'));
+	#print_r($req);
+
+}
+
+
+?>
\ No newline at end of file
diff --git a/www/saml2/sp/initSSO.php b/www/saml2/sp/initSSO.php
new file mode 100644
index 0000000000000000000000000000000000000000..a5d5a403ded30de293c13e4759191747c7722123
--- /dev/null
+++ b/www/saml2/sp/initSSO.php
@@ -0,0 +1,97 @@
+<?php
+
+require_once('../../_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XHTML/Template.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
+//require_once('SimpleSAML/XML/SAML20/AuthnResponse.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+//require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+
+$session = SimpleSAML_Session::getInstance();
+		
+try {
+
+	$idpentityid = isset($_GET['idpentityid']) ? $_GET['idpentityid'] : $config->getValue('default-saml20-idp') ;
+	$spentityid = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID();
+
+} catch (Exception $exception) {
+
+	$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+	$et->data['message'] = 'Error loading SAML 2.0 metadata';	
+	$et->data['e'] = $exception;	
+	$et->show();
+	exit(0);
+}
+
+if (!isset($session) || !$session->isValid() ) {
+	
+	try {
+		$sr = new SimpleSAML_XML_SAML20_AuthnRequest($config, $metadata);
+	
+		$req = $sr->generate($spentityid);
+		
+	
+		
+		$httpredirect = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+		
+		$relayState = SimpleSAML_Utilities::selfURL();
+		if (isset($_GET['RelayState'])) {
+			$relayState = $_GET['RelayState'];
+		}
+		
+		$httpredirect->sendMessage($req, $idpentityid, $relayState);
+
+	
+	} catch(Exception $exception) {
+		
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+
+		$et->data['message'] = 'Some error occured when trying to issue the authentication request to the IdP.';	
+		$et->data['e'] = $exception;
+		
+		$et->show();
+
+	}
+
+} else {
+
+	
+	
+	$relaystate = $session->getRelayState();
+	
+	if (isset($relaystate) && !empty($relaystate)) {
+		header('Location: ' . $relaystate );
+	} else {
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+
+		$et->data['message'] = 'Could not get relay state, do not know where to send the user.';	
+		$et->data['e'] = new Exception();
+		
+		$et->show();
+
+	
+	}
+
+}
+
+
+
+
+#print_r($metadata->getMetaData('sam.feide.no'));
+#print_r($req);
+
+//echo 'Location: ' . $relaystate;
+
+
+?>
diff --git a/www/shib13/sp/AssertionConsumerService.php b/www/shib13/sp/AssertionConsumerService.php
new file mode 100644
index 0000000000000000000000000000000000000000..20daca2af066e263e275d6cbb8315304466a0d9f
--- /dev/null
+++ b/www/shib13/sp/AssertionConsumerService.php
@@ -0,0 +1,69 @@
+<?php
+
+require_once('../../_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/Shib13/AuthnRequest.php');
+require_once('SimpleSAML/Bindings/Shib13/HTTPPost.php');
+require_once('SimpleSAML/XHTML/Template.php');
+
+session_start();
+
+try {
+	
+	/*
+	echo '<pre>';
+	print_r($_POST);
+	echo '</pre>';
+	*/
+	$config = SimpleSAML_Configuration::getInstance();
+	$metadata = new SimpleSAML_XML_MetaDataStore($config);
+	
+	#print_r($metadata->getMetaData('sam.feide.no'));
+#	$sr = new SimpleSAML_XML_Shib13_AuthnResponse($config, $metadata);
+	
+	$binding = new SimpleSAML_Bindings_Shib13_HTTPPost($config, $metadata);
+	$authnResponse = $binding->decodeResponse($_POST);
+
+	$xml = $authnResponse->getXML();
+	/*
+	echo '<pre>';
+	echo $xml;
+	echo '</pre>';
+*/
+
+	$authnResponse->validate();
+	$session = $authnResponse->createSession();
+	
+
+
+	if (isset($session)) {
+		$relayState = $authnResponse->getRelayState();
+		if (isset($relayState)) {
+			header("Location: " . $relayState);
+			exit(0);
+		} else {
+			echo 'Could not find RelayState parameter, you are stucked here.';
+		}
+	} else {
+		throw new Exception('Unkown error. Could not get session.');
+	}
+
+
+} catch(Exception $exception) {
+
+	$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+
+	$et->data['message'] = 'Some error occured when trying to issue the authentication request to the IdP.';	
+	$et->data['e'] = $exception;
+	
+	$et->show();
+
+
+}
+
+
+?>
\ No newline at end of file
diff --git a/www/shib13/sp/initSSO.php b/www/shib13/sp/initSSO.php
new file mode 100644
index 0000000000000000000000000000000000000000..ccb3a799df93fbfc9de2cc42994560a58b86e26b
--- /dev/null
+++ b/www/shib13/sp/initSSO.php
@@ -0,0 +1,99 @@
+<?php
+
+require_once('../../_include.php');
+
+
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/XHTML/Template.php');
+require_once('SimpleSAML/XML/MetaDataStore.php');
+require_once('SimpleSAML/XML/Shib13/AuthnRequest.php');
+//require_once('SimpleSAML/XML/SAML20/AuthnResponse.php');
+//require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+//require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+
+session_start();
+
+$config = SimpleSAML_Configuration::getInstance();
+$metadata = new SimpleSAML_XML_MetaDataStore($config);
+
+
+$session = SimpleSAML_Session::getInstance();
+		
+
+/*
+ * Incomming URL parameters
+ *
+ * idpentityid 		The entityid of the wanted IdP to authenticate with. If not provided will use default.
+ * spentityid		The entityid of the SP config to use. If not provided will use default to host.
+ * 
+ */
+
+try {
+
+	$idpentityid = isset($_GET['idpentityid']) ? $_GET['idpentityid'] : $config->getValue('default-shib13-idp') ;
+	$spentityid = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID('shib13-sp-hosted');
+
+} catch (Exception $exception) {
+
+	$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+	$et->data['message'] = 'Error loading SAML 2.0 metadata';	
+	$et->data['e'] = $exception;	
+	$et->show();
+	exit(0);
+}
+
+if (!isset($session) || !$session->isValid() ) {
+	
+	try {
+		$ar = new SimpleSAML_XML_Shib13_AuthnRequest($config, $metadata);
+		$ar->setIssuer($spentityid);	
+		if(isset($_GET['RelayState'])) 
+			$ar->setRelayState($_GET['RelayState']);
+
+		$url = $ar->createRedirect($idpentityid);
+		header('Location: ' . $url);
+//		echo 'IdP: '  . $idpentityid . ' SP: ' . $spentityid;
+		
+		exit(0);
+	
+	} catch(Exception $exception) {
+		
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+
+		$et->data['message'] = 'Some error occured when trying to issue the authentication request to the IdP.';	
+		$et->data['e'] = $exception;
+		
+		$et->show();
+
+	}
+
+} else {
+
+	
+	
+	$relaystate = $session->getRelayState();
+	
+	if (isset($relaystate) && !empty($relaystate)) {
+		header('Location: ' . $relaystate );
+	} else {
+		$et = new SimpleSAML_XHTML_Template($config, 'error.php');
+
+		$et->data['message'] = 'Could not get relay state, do not know where to send the user.';	
+		$et->data['e'] = new Exception();
+		
+		$et->show();
+
+	
+	}
+
+}
+
+
+#print_r($metadata->getMetaData('sam.feide.no'));
+#print_r($req);
+
+//echo 'Location: ' . $relaystate;
+
+
+?>