|
TYPO3 API
SVNRelease
|
00001 <?php 00002 00003 /** 00004 * Simple registration request and response parsing and object 00005 * representation. 00006 * 00007 * This module contains objects representing simple registration 00008 * requests and responses that can be used with both OpenID relying 00009 * parties and OpenID providers. 00010 * 00011 * 1. The relying party creates a request object and adds it to the 00012 * {@link Auth_OpenID_AuthRequest} object before making the 00013 * checkid request to the OpenID provider: 00014 * 00015 * $sreg_req = Auth_OpenID_SRegRequest::build(array('email')); 00016 * $auth_request->addExtension($sreg_req); 00017 * 00018 * 2. The OpenID provider extracts the simple registration request 00019 * from the OpenID request using {@link 00020 * Auth_OpenID_SRegRequest::fromOpenIDRequest}, gets the user's 00021 * approval and data, creates an {@link Auth_OpenID_SRegResponse} 00022 * object and adds it to the id_res response: 00023 * 00024 * $sreg_req = Auth_OpenID_SRegRequest::fromOpenIDRequest( 00025 * $checkid_request); 00026 * // [ get the user's approval and data, informing the user that 00027 * // the fields in sreg_response were requested ] 00028 * $sreg_resp = Auth_OpenID_SRegResponse::extractResponse( 00029 * $sreg_req, $user_data); 00030 * $sreg_resp->toMessage($openid_response->fields); 00031 * 00032 * 3. The relying party uses {@link 00033 * Auth_OpenID_SRegResponse::fromSuccessResponse} to extract the data 00034 * from the OpenID response: 00035 * 00036 * $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse( 00037 * $success_response); 00038 * 00039 * @package OpenID 00040 */ 00041 00042 /** 00043 * Import message and extension internals. 00044 */ 00045 require_once 'Auth/OpenID/Message.php'; 00046 require_once 'Auth/OpenID/Extension.php'; 00047 00048 // The data fields that are listed in the sreg spec 00049 global $Auth_OpenID_sreg_data_fields; 00050 $Auth_OpenID_sreg_data_fields = array( 00051 'fullname' => 'Full Name', 00052 'nickname' => 'Nickname', 00053 'dob' => 'Date of Birth', 00054 'email' => 'E-mail Address', 00055 'gender' => 'Gender', 00056 'postcode' => 'Postal Code', 00057 'country' => 'Country', 00058 'language' => 'Language', 00059 'timezone' => 'Time Zone'); 00060 00061 /** 00062 * Check to see that the given value is a valid simple registration 00063 * data field name. Return true if so, false if not. 00064 */ 00065 function Auth_OpenID_checkFieldName($field_name) 00066 { 00067 global $Auth_OpenID_sreg_data_fields; 00068 00069 if (!in_array($field_name, array_keys($Auth_OpenID_sreg_data_fields))) { 00070 return false; 00071 } 00072 return true; 00073 } 00074 00075 // URI used in the wild for Yadis documents advertising simple 00076 // registration support 00077 define('Auth_OpenID_SREG_NS_URI_1_0', 'http://openid.net/sreg/1.0'); 00078 00079 // URI in the draft specification for simple registration 1.1 00080 // <http://openid.net/specs/openid-simple-registration-extension-1_1-01.html> 00081 define('Auth_OpenID_SREG_NS_URI_1_1', 'http://openid.net/extensions/sreg/1.1'); 00082 00083 // This attribute will always hold the preferred URI to use when 00084 // adding sreg support to an XRDS file or in an OpenID namespace 00085 // declaration. 00086 define('Auth_OpenID_SREG_NS_URI', Auth_OpenID_SREG_NS_URI_1_1); 00087 00088 Auth_OpenID_registerNamespaceAlias(Auth_OpenID_SREG_NS_URI_1_1, 'sreg'); 00089 00090 /** 00091 * Does the given endpoint advertise support for simple 00092 * registration? 00093 * 00094 * $endpoint: The endpoint object as returned by OpenID discovery. 00095 * returns whether an sreg type was advertised by the endpoint 00096 */ 00097 function Auth_OpenID_supportsSReg(&$endpoint) 00098 { 00099 return ($endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_1) || 00100 $endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_0)); 00101 } 00102 00103 /** 00104 * A base class for classes dealing with Simple Registration protocol 00105 * messages. 00106 * 00107 * @package OpenID 00108 */ 00109 class Auth_OpenID_SRegBase extends Auth_OpenID_Extension { 00110 /** 00111 * Extract the simple registration namespace URI from the given 00112 * OpenID message. Handles OpenID 1 and 2, as well as both sreg 00113 * namespace URIs found in the wild, as well as missing namespace 00114 * definitions (for OpenID 1) 00115 * 00116 * $message: The OpenID message from which to parse simple 00117 * registration fields. This may be a request or response message. 00118 * 00119 * Returns the sreg namespace URI for the supplied message. The 00120 * message may be modified to define a simple registration 00121 * namespace. 00122 * 00123 * @access private 00124 */ 00125 function _getSRegNS(&$message) 00126 { 00127 $alias = null; 00128 $found_ns_uri = null; 00129 00130 // See if there exists an alias for one of the two defined 00131 // simple registration types. 00132 foreach (array(Auth_OpenID_SREG_NS_URI_1_1, 00133 Auth_OpenID_SREG_NS_URI_1_0) as $sreg_ns_uri) { 00134 $alias = $message->namespaces->getAlias($sreg_ns_uri); 00135 if ($alias !== null) { 00136 $found_ns_uri = $sreg_ns_uri; 00137 break; 00138 } 00139 } 00140 00141 if ($alias === null) { 00142 // There is no alias for either of the types, so try to 00143 // add one. We default to using the modern value (1.1) 00144 $found_ns_uri = Auth_OpenID_SREG_NS_URI_1_1; 00145 if ($message->namespaces->addAlias(Auth_OpenID_SREG_NS_URI_1_1, 00146 'sreg') === null) { 00147 // An alias for the string 'sreg' already exists, but 00148 // it's defined for something other than simple 00149 // registration 00150 return null; 00151 } 00152 } 00153 00154 return $found_ns_uri; 00155 } 00156 } 00157 00158 /** 00159 * An object to hold the state of a simple registration request. 00160 * 00161 * required: A list of the required fields in this simple registration 00162 * request 00163 * 00164 * optional: A list of the optional fields in this simple registration 00165 * request 00166 * 00167 * @package OpenID 00168 */ 00169 class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase { 00170 00171 var $ns_alias = 'sreg'; 00172 00173 /** 00174 * Initialize an empty simple registration request. 00175 */ 00176 function build($required=null, $optional=null, 00177 $policy_url=null, 00178 $sreg_ns_uri=Auth_OpenID_SREG_NS_URI, 00179 $cls='Auth_OpenID_SRegRequest') 00180 { 00181 $obj = new $cls(); 00182 00183 $obj->required = array(); 00184 $obj->optional = array(); 00185 $obj->policy_url = $policy_url; 00186 $obj->ns_uri = $sreg_ns_uri; 00187 00188 if ($required) { 00189 if (!$obj->requestFields($required, true, true)) { 00190 return null; 00191 } 00192 } 00193 00194 if ($optional) { 00195 if (!$obj->requestFields($optional, false, true)) { 00196 return null; 00197 } 00198 } 00199 00200 return $obj; 00201 } 00202 00203 /** 00204 * Create a simple registration request that contains the fields 00205 * that were requested in the OpenID request with the given 00206 * arguments 00207 * 00208 * $request: The OpenID authentication request from which to 00209 * extract an sreg request. 00210 * 00211 * $cls: name of class to use when creating sreg request object. 00212 * Used for testing. 00213 * 00214 * Returns the newly created simple registration request 00215 */ 00216 function fromOpenIDRequest($request, $cls='Auth_OpenID_SRegRequest') 00217 { 00218 00219 $obj = call_user_func_array(array($cls, 'build'), 00220 array(null, null, null, Auth_OpenID_SREG_NS_URI, $cls)); 00221 00222 // Since we're going to mess with namespace URI mapping, don't 00223 // mutate the object that was passed in. 00224 $m = $request->message; 00225 00226 $obj->ns_uri = $obj->_getSRegNS($m); 00227 $args = $m->getArgs($obj->ns_uri); 00228 00229 if ($args === null || Auth_OpenID::isFailure($args)) { 00230 return null; 00231 } 00232 00233 $obj->parseExtensionArgs($args); 00234 00235 return $obj; 00236 } 00237 00238 /** 00239 * Parse the unqualified simple registration request parameters 00240 * and add them to this object. 00241 * 00242 * This method is essentially the inverse of 00243 * getExtensionArgs. This method restores the serialized simple 00244 * registration request fields. 00245 * 00246 * If you are extracting arguments from a standard OpenID 00247 * checkid_* request, you probably want to use fromOpenIDRequest, 00248 * which will extract the sreg namespace and arguments from the 00249 * OpenID request. This method is intended for cases where the 00250 * OpenID server needs more control over how the arguments are 00251 * parsed than that method provides. 00252 * 00253 * $args == $message->getArgs($ns_uri); 00254 * $request->parseExtensionArgs($args); 00255 * 00256 * $args: The unqualified simple registration arguments 00257 * 00258 * strict: Whether requests with fields that are not defined in 00259 * the simple registration specification should be tolerated (and 00260 * ignored) 00261 */ 00262 function parseExtensionArgs($args, $strict=false) 00263 { 00264 foreach (array('required', 'optional') as $list_name) { 00265 $required = ($list_name == 'required'); 00266 $items = Auth_OpenID::arrayGet($args, $list_name); 00267 if ($items) { 00268 foreach (explode(',', $items) as $field_name) { 00269 if (!$this->requestField($field_name, $required, $strict)) { 00270 if ($strict) { 00271 return false; 00272 } 00273 } 00274 } 00275 } 00276 } 00277 00278 $this->policy_url = Auth_OpenID::arrayGet($args, 'policy_url'); 00279 00280 return true; 00281 } 00282 00283 /** 00284 * A list of all of the simple registration fields that were 00285 * requested, whether they were required or optional. 00286 */ 00287 function allRequestedFields() 00288 { 00289 return array_merge($this->required, $this->optional); 00290 } 00291 00292 /** 00293 * Have any simple registration fields been requested? 00294 */ 00295 function wereFieldsRequested() 00296 { 00297 return count($this->allRequestedFields()); 00298 } 00299 00300 /** 00301 * Was this field in the request? 00302 */ 00303 function contains($field_name) 00304 { 00305 return (in_array($field_name, $this->required) || 00306 in_array($field_name, $this->optional)); 00307 } 00308 00309 /** 00310 * Request the specified field from the OpenID user 00311 * 00312 * $field_name: the unqualified simple registration field name 00313 * 00314 * required: whether the given field should be presented to the 00315 * user as being a required to successfully complete the request 00316 * 00317 * strict: whether to raise an exception when a field is added to 00318 * a request more than once 00319 */ 00320 function requestField($field_name, 00321 $required=false, $strict=false) 00322 { 00323 if (!Auth_OpenID_checkFieldName($field_name)) { 00324 return false; 00325 } 00326 00327 if ($strict) { 00328 if ($this->contains($field_name)) { 00329 return false; 00330 } 00331 } else { 00332 if (in_array($field_name, $this->required)) { 00333 return true; 00334 } 00335 00336 if (in_array($field_name, $this->optional)) { 00337 if ($required) { 00338 unset($this->optional[array_search($field_name, 00339 $this->optional)]); 00340 } else { 00341 return true; 00342 } 00343 } 00344 } 00345 00346 if ($required) { 00347 $this->required[] = $field_name; 00348 } else { 00349 $this->optional[] = $field_name; 00350 } 00351 00352 return true; 00353 } 00354 00355 /** 00356 * Add the given list of fields to the request 00357 * 00358 * field_names: The simple registration data fields to request 00359 * 00360 * required: Whether these values should be presented to the user 00361 * as required 00362 * 00363 * strict: whether to raise an exception when a field is added to 00364 * a request more than once 00365 */ 00366 function requestFields($field_names, $required=false, $strict=false) 00367 { 00368 if (!is_array($field_names)) { 00369 return false; 00370 } 00371 00372 foreach ($field_names as $field_name) { 00373 if (!$this->requestField($field_name, $required, $strict=$strict)) { 00374 return false; 00375 } 00376 } 00377 00378 return true; 00379 } 00380 00381 /** 00382 * Get a dictionary of unqualified simple registration arguments 00383 * representing this request. 00384 * 00385 * This method is essentially the inverse of 00386 * C{L{parseExtensionArgs}}. This method serializes the simple 00387 * registration request fields. 00388 */ 00389 function getExtensionArgs() 00390 { 00391 $args = array(); 00392 00393 if ($this->required) { 00394 $args['required'] = implode(',', $this->required); 00395 } 00396 00397 if ($this->optional) { 00398 $args['optional'] = implode(',', $this->optional); 00399 } 00400 00401 if ($this->policy_url) { 00402 $args['policy_url'] = $this->policy_url; 00403 } 00404 00405 return $args; 00406 } 00407 } 00408 00409 /** 00410 * Represents the data returned in a simple registration response 00411 * inside of an OpenID C{id_res} response. This object will be created 00412 * by the OpenID server, added to the C{id_res} response object, and 00413 * then extracted from the C{id_res} message by the Consumer. 00414 * 00415 * @package OpenID 00416 */ 00417 class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase { 00418 00419 var $ns_alias = 'sreg'; 00420 00421 function Auth_OpenID_SRegResponse($data=null, 00422 $sreg_ns_uri=Auth_OpenID_SREG_NS_URI) 00423 { 00424 if ($data === null) { 00425 $this->data = array(); 00426 } else { 00427 $this->data = $data; 00428 } 00429 00430 $this->ns_uri = $sreg_ns_uri; 00431 } 00432 00433 /** 00434 * Take a C{L{SRegRequest}} and a dictionary of simple 00435 * registration values and create a C{L{SRegResponse}} object 00436 * containing that data. 00437 * 00438 * request: The simple registration request object 00439 * 00440 * data: The simple registration data for this response, as a 00441 * dictionary from unqualified simple registration field name to 00442 * string (unicode) value. For instance, the nickname should be 00443 * stored under the key 'nickname'. 00444 */ 00445 function extractResponse($request, $data) 00446 { 00447 $obj = new Auth_OpenID_SRegResponse(); 00448 $obj->ns_uri = $request->ns_uri; 00449 00450 foreach ($request->allRequestedFields() as $field) { 00451 $value = Auth_OpenID::arrayGet($data, $field); 00452 if ($value !== null) { 00453 $obj->data[$field] = $value; 00454 } 00455 } 00456 00457 return $obj; 00458 } 00459 00460 /** 00461 * Create a C{L{SRegResponse}} object from a successful OpenID 00462 * library response 00463 * (C{L{openid.consumer.consumer.SuccessResponse}}) response 00464 * message 00465 * 00466 * success_response: A SuccessResponse from consumer.complete() 00467 * 00468 * signed_only: Whether to process only data that was 00469 * signed in the id_res message from the server. 00470 * 00471 * Returns a simple registration response containing the data that 00472 * was supplied with the C{id_res} response. 00473 */ 00474 function fromSuccessResponse(&$success_response, $signed_only=true) 00475 { 00476 global $Auth_OpenID_sreg_data_fields; 00477 00478 $obj = new Auth_OpenID_SRegResponse(); 00479 $obj->ns_uri = $obj->_getSRegNS($success_response->message); 00480 00481 if ($signed_only) { 00482 $args = $success_response->getSignedNS($obj->ns_uri); 00483 } else { 00484 $args = $success_response->message->getArgs($obj->ns_uri); 00485 } 00486 00487 if ($args === null || Auth_OpenID::isFailure($args)) { 00488 return null; 00489 } 00490 00491 foreach ($Auth_OpenID_sreg_data_fields as $field_name => $desc) { 00492 if (in_array($field_name, array_keys($args))) { 00493 $obj->data[$field_name] = $args[$field_name]; 00494 } 00495 } 00496 00497 return $obj; 00498 } 00499 00500 function getExtensionArgs() 00501 { 00502 return $this->data; 00503 } 00504 00505 // Read-only dictionary interface 00506 function get($field_name, $default=null) 00507 { 00508 if (!Auth_OpenID_checkFieldName($field_name)) { 00509 return null; 00510 } 00511 00512 return Auth_OpenID::arrayGet($this->data, $field_name, $default); 00513 } 00514 00515 function contents() 00516 { 00517 return $this->data; 00518 } 00519 } 00520 00521 ?>
1.8.0