Add simpleid-1.0.5
diff --git a/simpleid/www/extensions/ui/ui.extension.php b/simpleid/www/extensions/ui/ui.extension.php
new file mode 100644
index 0000000..3982be0
--- /dev/null
+++ b/simpleid/www/extensions/ui/ui.extension.php
@@ -0,0 +1,260 @@
+<?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 popup and icon modes from the User Interface extension
+ *
+ * @package simpleid
+ * @subpackage extensions
+ * @filesource
+ */
+
+/** Namespace for the User Interface extension */
+define('OPENID_NS_UI', 'http://specs.openid.net/extensions/ui/1.0');
+
+/**
+ * Returns the popup mode in SimpleID XRDS document
+ *
+ * @return array
+ * @see hook_xrds_types()
+ */
+function ui_xrds_types() {
+    return array(
+        'http://specs.openid.net/extensions/ui/1.0/mode/popup',
+        'http://specs.openid.net/extensions/ui/1.0/icon'
+    );
+}
+
+/**
+ * Detects the openid.ui.x-has-session parameter and processes it accordingly.
+ *
+ * @return array
+ * @see hook_response()
+ */
+function ui_response($assertion, $request) {
+    global $user;
+    global $version;
+    
+    // We only deal with negative assertions
+    if ($assertion) return array();
+    
+    // We only respond if the extension is requested
+    if (!openid_extension_requested(OPENID_NS_UI, $request)) return array();
+    
+    // We only deal with openid.ui.x-has-session requests
+    $filtered_request = openid_extension_filter_request(OPENID_NS_UI, $request);
+    if (!isset($filtered_request['mode']) || ($filtered_request['mode'] != 'x-has-session')) return array();
+    
+    // If user is null, there is no active session
+    if ($user == NULL) return array();
+    
+    // There is an active session
+    $alias = openid_extension_alias(OPENID_NS_UI);
+    $response = array();
+    
+    $response['openid.ns.' . $alias] = OPENID_NS_UI;
+    $response['openid.' . $alias . '.mode'] = 'x-has-session';
+    
+    return $response;
+}
+
+/**
+ * Returns an array of fields that need signing.
+ *
+ * @see hook_signed_fields()
+ */
+function ui_signed_fields($response) {
+    // We only respond if the extension is requested
+    if (!openid_extension_requested(OPENID_NS_UI, $response)) return array();
+    
+    $fields = array_keys(openid_extension_filter_request(OPENID_NS_UI, $response));
+    $alias = openid_extension_alias(OPENID_NS_UI);
+    $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;
+}
+
+/**
+ * Detects the presence of the UI extension and modifies the login form
+ * accordingly.
+ *
+ * @param string $destination
+ * @param string $state
+ * @see hook_user_login_form()
+ */
+function ui_user_login_form($destination, $state) {
+    if (($destination != 'continue') || (!$state)) return;
+    
+    $request = unpickle($state);
+    openid_parse_request($request);
+    
+    // Skip if popup does not exist
+    if (!openid_extension_requested(OPENID_NS_UI, $request)) return;
+    
+    $filtered_request = openid_extension_filter_request(OPENID_NS_UI, $request);
+    
+    if (isset($filtered_request['mode']) && ($filtered_request['mode'] == 'popup')) _ui_insert_css_js();
+    
+    return;
+}
+
+/**
+ * Detects the presence of the UI extension and modifies the relying party
+ * verification form accordingly.
+ *
+ * @param array $request
+ * @param array $response
+ * @param array $rp
+ * @return string
+ * @see hook_consent_form()
+ */
+function ui_consent_form($request, $response, $rp) {
+    // Skip if popup does not exist
+    if (!openid_extension_requested(OPENID_NS_UI, $request)) return '';
+    
+    $filtered_request = openid_extension_filter_request(OPENID_NS_UI, $request);
+    
+    if (isset($filtered_request['mode']) && ($filtered_request['mode'] == 'popup')) _ui_insert_css_js();
+    
+    if (isset($filtered_request['icon']) && ($filtered_request['icon'] == 'true')) {
+        global $xtpl;
+        
+        $realm = $request['openid.realm'];
+        $icon_url = simpleid_url('ui/icon', 'realm=' . rawurlencode($realm) . '&tk=' . _ui_icon_token($realm));
+        
+        $xtpl->assign('icon_url', htmlspecialchars($icon_url, ENT_QUOTES, 'UTF-8'));
+        $xtpl->parse('main.openid_consent.icon');
+    }
+    
+    return '';
+}
+
+/**
+ * Specifies that the OpenID response should be sent via the fragment
+ *
+ */
+function ui_indirect_response($url, $response) {
+    global $openid_ns_to_alias;
+    if (!array_key_exists(OPENID_NS_UI, $openid_ns_to_alias)) return NULL;
+    
+    // Cheat - if we run this, then the redirect page will also be themed!
+    _ui_insert_css_js();
+    
+    if (strstr($url, '#')) {
+        return OPENID_RESPONSE_FRAGMENT;
+    } else {
+        return NULL;
+    }
+}
+
+/**
+ * Adds an extra route to the SimpleWeb framework.
+ */
+function ui_routes() {
+    return array('ui/icon' => 'ui_icon');
+}
+
+/**
+ * Returns an icon.
+ */
+function ui_icon() {
+    if (!isset($_GET['realm']) || !isset($_GET['tk']) || ($_GET['tk'] != _ui_icon_token($_GET['realm']))) {
+        header_response_code('404 Not Found');
+        indirect_fatal_error(t('Invalid UI icon parameters.'));
+    }
+    
+    $realm = $_GET['realm'];
+    $icon_res = _ui_get_icon($realm);
+    
+    if ($icon_res === NULL) {
+        header_response_code('404 Not Found');
+        indirect_fatal_error(t('Unable to get icon.'));
+    }
+    
+    header('Via: ' . $icon_res['protocol'] . ' simpleid-ui-icon-' . md5($realm));
+    header('Cache-Control: max-age=86400');
+    header('Content-Type: ' . $icon_res['headers']['content-type']);
+    if (isset($icon_res['headers']['content-encoding'])) header('Content-Encoding: ' . $icon_res['headers']['content-encoding']);
+    print $icon_res['data'];
+}
+
+/**
+ * Inserts the necessary CSS and JavaScript code to implement the popup mode
+ * from the User Interface extension.
+ */
+function _ui_insert_css_js() {
+    global $xtpl;
+    
+    $css = (isset($xtpl->vars['css'])) ? $xtpl->vars['css'] : '';
+    $js = (isset($xtpl->vars['javascript'])) ? $xtpl->vars['javascript'] : '';
+    
+    $xtpl->assign('css', $css . '@import url(' . get_base_path() . 'extensions/ui/ui.css);');
+    $xtpl->assign('javascript', $js . '<script src="' . get_base_path() . 'extensions/ui/ui.js" type="text/javascript"></script>');
+}
+
+/**
+ * Attempts to obtain an icon from a RP
+ *
+ * @param string $realm the openid.realm parameter
+ * @return array the response from {@link http_make_request()} with the discovered URL of the
+ * RP's icon
+ */
+function _ui_get_icon($realm) {
+    $rp_info = simpleid_get_rp_info($realm);
+    
+    if (isset($rp_info['ui_icon'])) return $rp_info['ui_icon'];
+    
+    $services = discovery_xrds_services_by_type($rp_info['services'], 'http://specs.openid.net/extensions/ui/icon');
+        
+    if ($services) {
+        $icon_url = $services[0]['uri'];
+        
+        $icon_res = http_make_request($icon_url);
+        if (isset($icon_res['http-error'])) {
+            return NULL;
+        }
+        
+        $rp_info['ui_icon'] = $icon_res;
+        simpleid_set_rp_info($realm, $rp_info);
+    } else {
+        return NULL;
+    }
+}
+
+/**
+ * Returns a token to be used when requesting the icon.
+ *
+ * The token is used to prevent flooding SimpleID with external requests.
+ *
+ * @param string $realm the openid.realm parameter
+ * @return string the token
+ */
+function _ui_icon_token($realm) {
+    return get_form_token('q=ui/icon&realm=' . rawurlencode($realm));
+}
+?>