PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/www/extensions/ui/ui.extension.php

https://gitlab.com/pirati.cz/simpleid
PHP | 260 lines | 112 code | 46 blank | 102 comment | 37 complexity | 4bdbf89334f549071bf827beac12a69d MD5 | raw file
  1. <?php
  2. /*
  3. * SimpleID
  4. *
  5. * Copyright (C) Kelvin Mo 2009
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2 of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public
  18. * License along with this program; if not, write to the Free
  19. * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. *
  21. * $Id$
  22. */
  23. /**
  24. * Implements the popup and icon modes from the User Interface extension
  25. *
  26. * @package simpleid
  27. * @subpackage extensions
  28. * @filesource
  29. */
  30. /** Namespace for the User Interface extension */
  31. define('OPENID_NS_UI', 'http://specs.openid.net/extensions/ui/1.0');
  32. /**
  33. * Returns the popup mode in SimpleID XRDS document
  34. *
  35. * @return array
  36. * @see hook_xrds_types()
  37. */
  38. function ui_xrds_types() {
  39. return array(
  40. 'http://specs.openid.net/extensions/ui/1.0/mode/popup',
  41. 'http://specs.openid.net/extensions/ui/1.0/icon'
  42. );
  43. }
  44. /**
  45. * Detects the openid.ui.x-has-session parameter and processes it accordingly.
  46. *
  47. * @return array
  48. * @see hook_response()
  49. */
  50. function ui_response($assertion, $request) {
  51. global $user;
  52. global $version;
  53. // We only deal with negative assertions
  54. if ($assertion) return array();
  55. // We only respond if the extension is requested
  56. if (!openid_extension_requested(OPENID_NS_UI, $request)) return array();
  57. // We only deal with openid.ui.x-has-session requests
  58. $filtered_request = openid_extension_filter_request(OPENID_NS_UI, $request);
  59. if (!isset($filtered_request['mode']) || ($filtered_request['mode'] != 'x-has-session')) return array();
  60. // If user is null, there is no active session
  61. if ($user == NULL) return array();
  62. // There is an active session
  63. $alias = openid_extension_alias(OPENID_NS_UI);
  64. $response = array();
  65. $response['openid.ns.' . $alias] = OPENID_NS_UI;
  66. $response['openid.' . $alias . '.mode'] = 'x-has-session';
  67. return $response;
  68. }
  69. /**
  70. * Returns an array of fields that need signing.
  71. *
  72. * @see hook_signed_fields()
  73. */
  74. function ui_signed_fields($response) {
  75. // We only respond if the extension is requested
  76. if (!openid_extension_requested(OPENID_NS_UI, $response)) return array();
  77. $fields = array_keys(openid_extension_filter_request(OPENID_NS_UI, $response));
  78. $alias = openid_extension_alias(OPENID_NS_UI);
  79. $signed_fields = array();
  80. if (isset($response['openid.ns.' . $alias])) $signed_fields[] = 'ns.' . $alias;
  81. foreach ($fields as $field) {
  82. if (isset($response['openid.' . $alias . '.' . $field])) $signed_fields[] = $alias . '.' . $field;
  83. }
  84. return $signed_fields;
  85. }
  86. /**
  87. * Detects the presence of the UI extension and modifies the login form
  88. * accordingly.
  89. *
  90. * @param string $destination
  91. * @param string $state
  92. * @see hook_user_login_form()
  93. */
  94. function ui_user_login_form($destination, $state) {
  95. if (($destination != 'continue') || (!$state)) return;
  96. $request = unpickle($state);
  97. openid_parse_request($request);
  98. // Skip if popup does not exist
  99. if (!openid_extension_requested(OPENID_NS_UI, $request)) return;
  100. $filtered_request = openid_extension_filter_request(OPENID_NS_UI, $request);
  101. if (isset($filtered_request['mode']) && ($filtered_request['mode'] == 'popup')) _ui_insert_css_js();
  102. return;
  103. }
  104. /**
  105. * Detects the presence of the UI extension and modifies the relying party
  106. * verification form accordingly.
  107. *
  108. * @param array $request
  109. * @param array $response
  110. * @param array $rp
  111. * @return string
  112. * @see hook_consent_form()
  113. */
  114. function ui_consent_form($request, $response, $rp) {
  115. // Skip if popup does not exist
  116. if (!openid_extension_requested(OPENID_NS_UI, $request)) return '';
  117. $filtered_request = openid_extension_filter_request(OPENID_NS_UI, $request);
  118. if (isset($filtered_request['mode']) && ($filtered_request['mode'] == 'popup')) _ui_insert_css_js();
  119. if (isset($filtered_request['icon']) && ($filtered_request['icon'] == 'true')) {
  120. global $xtpl;
  121. $realm = $request['openid.realm'];
  122. $icon_url = simpleid_url('ui/icon', 'realm=' . rawurlencode($realm) . '&tk=' . _ui_icon_token($realm));
  123. $xtpl->assign('icon_url', htmlspecialchars($icon_url, ENT_QUOTES, 'UTF-8'));
  124. $xtpl->parse('main.openid_consent.icon');
  125. }
  126. return '';
  127. }
  128. /**
  129. * Specifies that the OpenID response should be sent via the fragment
  130. *
  131. */
  132. function ui_indirect_response($url, $response) {
  133. global $openid_ns_to_alias;
  134. if (!array_key_exists(OPENID_NS_UI, $openid_ns_to_alias)) return NULL;
  135. // Cheat - if we run this, then the redirect page will also be themed!
  136. _ui_insert_css_js();
  137. if (strstr($url, '#')) {
  138. return OPENID_RESPONSE_FRAGMENT;
  139. } else {
  140. return NULL;
  141. }
  142. }
  143. /**
  144. * Adds an extra route to the SimpleWeb framework.
  145. */
  146. function ui_routes() {
  147. return array('ui/icon' => 'ui_icon');
  148. }
  149. /**
  150. * Returns an icon.
  151. */
  152. function ui_icon() {
  153. if (!isset($_GET['realm']) || !isset($_GET['tk']) || ($_GET['tk'] != _ui_icon_token($_GET['realm']))) {
  154. header_response_code('404 Not Found');
  155. indirect_fatal_error(t('Invalid UI icon parameters.'));
  156. }
  157. $realm = $_GET['realm'];
  158. $icon_res = _ui_get_icon($realm);
  159. if ($icon_res === NULL) {
  160. header_response_code('404 Not Found');
  161. indirect_fatal_error(t('Unable to get icon.'));
  162. }
  163. header('Via: ' . $icon_res['protocol'] . ' simpleid-ui-icon-' . md5($realm));
  164. header('Cache-Control: max-age=86400');
  165. header('Content-Type: ' . $icon_res['headers']['content-type']);
  166. if (isset($icon_res['headers']['content-encoding'])) header('Content-Encoding: ' . $icon_res['headers']['content-encoding']);
  167. print $icon_res['data'];
  168. }
  169. /**
  170. * Inserts the necessary CSS and JavaScript code to implement the popup mode
  171. * from the User Interface extension.
  172. */
  173. function _ui_insert_css_js() {
  174. global $xtpl;
  175. $css = (isset($xtpl->vars['css'])) ? $xtpl->vars['css'] : '';
  176. $js = (isset($xtpl->vars['javascript'])) ? $xtpl->vars['javascript'] : '';
  177. $xtpl->assign('css', $css . '@import url(' . get_base_path() . 'extensions/ui/ui.css);');
  178. $xtpl->assign('javascript', $js . '<script src="' . get_base_path() . 'extensions/ui/ui.js" type="text/javascript"></script>');
  179. }
  180. /**
  181. * Attempts to obtain an icon from a RP
  182. *
  183. * @param string $realm the openid.realm parameter
  184. * @return array the response from {@link http_make_request()} with the discovered URL of the
  185. * RP's icon
  186. */
  187. function _ui_get_icon($realm) {
  188. $rp_info = simpleid_get_rp_info($realm);
  189. if (isset($rp_info['ui_icon'])) return $rp_info['ui_icon'];
  190. $services = discovery_xrds_services_by_type($rp_info['services'], 'http://specs.openid.net/extensions/ui/icon');
  191. if ($services) {
  192. $icon_url = $services[0]['uri'];
  193. $icon_res = http_make_request($icon_url);
  194. if (isset($icon_res['http-error'])) {
  195. return NULL;
  196. }
  197. $rp_info['ui_icon'] = $icon_res;
  198. simpleid_set_rp_info($realm, $rp_info);
  199. } else {
  200. return NULL;
  201. }
  202. }
  203. /**
  204. * Returns a token to be used when requesting the icon.
  205. *
  206. * The token is used to prevent flooding SimpleID with external requests.
  207. *
  208. * @param string $realm the openid.realm parameter
  209. * @return string the token
  210. */
  211. function _ui_icon_token($realm) {
  212. return get_form_token('q=ui/icon&realm=' . rawurlencode($realm));
  213. }
  214. ?>