Add simpleid-1.0.5
diff --git a/simpleid/www/extensions/pape/pape.extension.php b/simpleid/www/extensions/pape/pape.extension.php
new file mode 100644
index 0000000..e189f2e
--- /dev/null
+++ b/simpleid/www/extensions/pape/pape.extension.php
@@ -0,0 +1,200 @@
+<?php
+/*
+ * SimpleID
+ *
+ * Copyright (C) Kelvin Mo 2009
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * $Id$
+ */
+
+/**
+ * Implements the Provider Authentication Policy Extension extension.
+ * 
+ *
+ * @package simpleid
+ * @subpackage extensions
+ * @filesource
+ */
+
+/** Namespace for the PAPE extension */
+define('OPENID_NS_PAPE', 'http://specs.openid.net/extensions/pape/1.0');
+
+/** Namespaces for PAPE policies */
+define('PAPE_POLICY_NONE', 'http://schemas.openid.net/pape/policies/2007/06/none');
+define('PAPE_POLICY_PPID', 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier');
+
+/** Namespaces for PAPE levels */
+define('PAPE_LEVEL_NIST800_63', 'http://csrc.nist.gov/publications/nistpubs/800-63/SP800-63V1_0_2.pdf');
+
+/**
+ * Returns the support for PAPE in SimpleID XRDS document
+ *
+ * @return array
+ * @see hook_xrds_types()
+ */
+function pape_xrds_types() {
+    return array(
+        OPENID_NS_PAPE,
+        PAPE_POLICY_PPID,
+        PAPE_LEVEL_NIST800_63
+    );
+}
+
+/**
+ * @see hook_checkid_identity()
+ */
+function pape_checkid_identity($request, $identity, $immediate) {
+    global $user;
+    
+    // We only respond if the extension is requested
+    if (!openid_extension_requested(OPENID_NS_PAPE, $request)) return null;
+    
+    // See if we are choosing an identity and save for later
+    // This may be used by pape_response() to produce a private identifier
+    if ($request['openid.identity'] == OPENID_IDENTIFIER_SELECT) _pape_identifier_select(true);
+    
+    $pape_request = openid_extension_filter_request(OPENID_NS_PAPE, $request);
+    
+    // If the relying party provides a max_auth_age
+    if (isset($pape_request['max_auth_age'])) {
+        // If we are not logged in then we don't need to do anything
+        if ($user == NULL) return NULL;
+        
+        // If the last time we logged on actively (i.e. using a password) is greater than
+        // max_auth_age, we then require the user to log in again
+        if ((!isset($user['auth_active']) || !$user['auth_active']) 
+            && ((time() - $user['auth_time']) > $pape_request['max_auth_age'])) {
+            set_message(t('This web site\'s policy requires you to log in again to confirm your identity.'));
+            
+            _user_logout();
+            return CHECKID_LOGIN_REQUIRED;
+        }
+    }
+}
+
+/**
+ * @see hook_response()
+ */
+function pape_response($assertion, $request) {
+    global $user, $version;
+    
+    // We only deal with positive assertions
+    if (!$assertion) return array();
+    
+    // We only respond if we are using OpenID 2 or later
+    if ($version < OPENID_VERSION_2) return array();
+    
+    // Get what is requested
+    $pape_request = openid_extension_filter_request(OPENID_NS_PAPE, $request);
+        
+    // If the extension is requested, we use the same alias, otherwise, we
+    // make one up
+    $alias = openid_extension_alias(OPENID_NS_PAPE, 'pape');
+    $response = array();
+    
+    // The PAPE specification recommends us to respond even when the extension
+    // is not present in the request.
+    $response['openid.ns.' . $alias] = OPENID_NS_PAPE;
+    
+    // We return the last time the user logged in using the login form
+    $response['openid.' . $alias . '.auth_time'] = gmstrftime('%Y-%m-%dT%H:%M:%SZ', $user['auth_time']);
+    
+    // We don't comply with NIST_SP800-63
+    $response['openid.' . $alias . '.auth_level.ns.nist'] = PAPE_LEVEL_NIST800_63;
+    $response['openid.' . $alias . '.auth_level.nist'] = 0;
+    
+    // The default is that we don't apply any authentication policies. This can be changed later in the
+    // function
+    $response['openid.' . $alias . '.auth_policies'] = PAPE_POLICY_NONE;
+
+    // Now we go through the authentication policies
+    if (isset($pape_request['preferred_auth_policies'])) {
+        $policies = preg_split('/\s+/', $pape_request['preferred_auth_policies']);
+        
+        if (in_array(PAPE_POLICY_PPID, $policies)) {
+            // We want a ppid.  Check that the authentication request is correct
+            if (_pape_identifier_select()) {
+                $realm = openid_get_realm($request, $version);
+                $identity = $request['openid.identity'];
+                
+                $ppid = _pape_ppid($identity, $realm);                
+                $response['openid.claimed_id'] = $ppid;
+                $response['openid.identity'] = $ppid;
+            }
+        }
+    }
+    
+    return $response;
+}
+
+/**
+ * Returns an array of fields that need signing.
+ *
+ * @see hook_signed_fields()
+ */
+function pape_signed_fields($response) {
+    $fields = array_keys(openid_extension_filter_request(OPENID_NS_PAPE, $response));
+    $alias = openid_extension_alias(OPENID_NS_PAPE);
+    $signed_fields = array();
+
+    if (isset($response['openid.ns.' . $alias])) $signed_fields[] = 'ns.' . $alias;
+    foreach ($fields as $field) {
+        if (isset($response['openid.' . $alias . '.' . $field])) $signed_fields[] = $alias . '.' . $field;
+    }
+    
+    return $signed_fields;
+}
+
+/**
+ * Sets and returns whether the current OpenID request is requesting an identity.
+ *
+ * @param bool $identifier_select
+ * @return bool whether the current OpenID request is requesting an identity
+ */
+function _pape_identifier_select($identifier_select = NULL) {
+    static $static_identifier_select = false;
+    
+    if (!is_null($identifier_select)) $static_identifier_select = $identifier_select;
+    
+    return $static_identifier_select;
+}
+
+/**
+ * Generates a private personal identifier (PPID).  The PPID is an opaque identifier
+ * for a particular user-RP pair
+ *
+ * @param string $identity the identity of the user
+ * @param string $realm the URL of the relying party
+ * @return string the PPID
+ */
+function _pape_ppid($identity, $realm) {
+    // We are reusing the site-token from get_form_token() in common.inc
+    if (store_get('site-token') == NULL) {
+        $site_token = mt_rand();
+        store_set('site-token', $site_token);
+    } else {
+        $site_token = store_get('site-token');
+    }
+    
+    $parts = parse_url($realm);
+    $host = $parts['host'];
+    if (strstr($host, 'www.') === 0) $host = substr($host, 4);
+    
+    return simpleid_url('ppid/' . md5($site_token . $identity . $host));
+}
+
+?>