[BUGFIX] Fix T3editor after PSR-7 change
[Packages/TYPO3.CMS.git] / typo3 / sysext / openid / lib / php-openid / Auth / OpenID / SReg.php
1 <?php
2
3 /**
4 * Simple registration request and response parsing and object
5 * representation.
6 *
7 * This module contains objects representing simple registration
8 * requests and responses that can be used with both OpenID relying
9 * parties and OpenID providers.
10 *
11 * 1. The relying party creates a request object and adds it to the
12 * {@link Auth_OpenID_AuthRequest} object before making the
13 * checkid request to the OpenID provider:
14 *
15 * $sreg_req = Auth_OpenID_SRegRequest::build(array('email'));
16 * $auth_request->addExtension($sreg_req);
17 *
18 * 2. The OpenID provider extracts the simple registration request
19 * from the OpenID request using {@link
20 * Auth_OpenID_SRegRequest::fromOpenIDRequest}, gets the user's
21 * approval and data, creates an {@link Auth_OpenID_SRegResponse}
22 * object and adds it to the id_res response:
23 *
24 * $sreg_req = Auth_OpenID_SRegRequest::fromOpenIDRequest(
25 * $checkid_request);
26 * // [ get the user's approval and data, informing the user that
27 * // the fields in sreg_response were requested ]
28 * $sreg_resp = Auth_OpenID_SRegResponse::extractResponse(
29 * $sreg_req, $user_data);
30 * $sreg_resp->toMessage($openid_response->fields);
31 *
32 * 3. The relying party uses {@link
33 * Auth_OpenID_SRegResponse::fromSuccessResponse} to extract the data
34 * from the OpenID response:
35 *
36 * $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse(
37 * $success_response);
38 *
39 * @package OpenID
40 */
41
42 /**
43 * Import message and extension internals.
44 */
45 require_once 'Auth/OpenID/Message.php';
46 require_once 'Auth/OpenID/Extension.php';
47
48 // The data fields that are listed in the sreg spec
49 global $Auth_OpenID_sreg_data_fields;
50 $Auth_OpenID_sreg_data_fields = array(
51 'fullname' => 'Full Name',
52 'nickname' => 'Nickname',
53 'dob' => 'Date of Birth',
54 'email' => 'E-mail Address',
55 'gender' => 'Gender',
56 'postcode' => 'Postal Code',
57 'country' => 'Country',
58 'language' => 'Language',
59 'timezone' => 'Time Zone');
60
61 /**
62 * Check to see that the given value is a valid simple registration
63 * data field name. Return true if so, false if not.
64 */
65 function Auth_OpenID_checkFieldName($field_name)
66 {
67 global $Auth_OpenID_sreg_data_fields;
68
69 if (!in_array($field_name, array_keys($Auth_OpenID_sreg_data_fields))) {
70 return false;
71 }
72 return true;
73 }
74
75 // URI used in the wild for Yadis documents advertising simple
76 // registration support
77 define('Auth_OpenID_SREG_NS_URI_1_0', 'http://openid.net/sreg/1.0');
78
79 // URI in the draft specification for simple registration 1.1
80 // <http://openid.net/specs/openid-simple-registration-extension-1_1-01.html>
81 define('Auth_OpenID_SREG_NS_URI_1_1', 'http://openid.net/extensions/sreg/1.1');
82
83 // This attribute will always hold the preferred URI to use when
84 // adding sreg support to an XRDS file or in an OpenID namespace
85 // declaration.
86 define('Auth_OpenID_SREG_NS_URI', Auth_OpenID_SREG_NS_URI_1_1);
87
88 Auth_OpenID_registerNamespaceAlias(Auth_OpenID_SREG_NS_URI_1_1, 'sreg');
89
90 /**
91 * Does the given endpoint advertise support for simple
92 * registration?
93 *
94 * $endpoint: The endpoint object as returned by OpenID discovery.
95 * returns whether an sreg type was advertised by the endpoint
96 */
97 function Auth_OpenID_supportsSReg($endpoint)
98 {
99 return ($endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_1) ||
100 $endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_0));
101 }
102
103 /**
104 * A base class for classes dealing with Simple Registration protocol
105 * messages.
106 *
107 * @package OpenID
108 */
109 class Auth_OpenID_SRegBase extends Auth_OpenID_Extension {
110 /**
111 * Extract the simple registration namespace URI from the given
112 * OpenID message. Handles OpenID 1 and 2, as well as both sreg
113 * namespace URIs found in the wild, as well as missing namespace
114 * definitions (for OpenID 1)
115 *
116 * $message: The OpenID message from which to parse simple
117 * registration fields. This may be a request or response message.
118 *
119 * Returns the sreg namespace URI for the supplied message. The
120 * message may be modified to define a simple registration
121 * namespace.
122 *
123 * @access private
124 */
125 static function _getSRegNS($message)
126 {
127 $alias = null;
128 $found_ns_uri = null;
129
130 // See if there exists an alias for one of the two defined
131 // simple registration types.
132 foreach (array(Auth_OpenID_SREG_NS_URI_1_1,
133 Auth_OpenID_SREG_NS_URI_1_0) as $sreg_ns_uri) {
134 $alias = $message->namespaces->getAlias($sreg_ns_uri);
135 if ($alias !== null) {
136 $found_ns_uri = $sreg_ns_uri;
137 break;
138 }
139 }
140
141 if ($alias === null) {
142 // There is no alias for either of the types, so try to
143 // add one. We default to using the modern value (1.1)
144 $found_ns_uri = Auth_OpenID_SREG_NS_URI_1_1;
145 if ($message->namespaces->addAlias(Auth_OpenID_SREG_NS_URI_1_1,
146 'sreg') === null) {
147 // An alias for the string 'sreg' already exists, but
148 // it's defined for something other than simple
149 // registration
150 return null;
151 }
152 }
153
154 return $found_ns_uri;
155 }
156 }
157
158 /**
159 * An object to hold the state of a simple registration request.
160 *
161 * required: A list of the required fields in this simple registration
162 * request
163 *
164 * optional: A list of the optional fields in this simple registration
165 * request
166 *
167 * @package OpenID
168 */
169 class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase {
170
171 var $ns_alias = 'sreg';
172
173 /**
174 * Initialize an empty simple registration request.
175 */
176 static function build($required=null, $optional=null,
177 $policy_url=null,
178 $sreg_ns_uri=Auth_OpenID_SREG_NS_URI,
179 $cls='Auth_OpenID_SRegRequest')
180 {
181 $obj = new $cls();
182
183 $obj->required = array();
184 $obj->optional = array();
185 $obj->policy_url = $policy_url;
186 $obj->ns_uri = $sreg_ns_uri;
187
188 if ($required) {
189 if (!$obj->requestFields($required, true, true)) {
190 return null;
191 }
192 }
193
194 if ($optional) {
195 if (!$obj->requestFields($optional, false, true)) {
196 return null;
197 }
198 }
199
200 return $obj;
201 }
202
203 /**
204 * Create a simple registration request that contains the fields
205 * that were requested in the OpenID request with the given
206 * arguments
207 *
208 * $request: The OpenID authentication request from which to
209 * extract an sreg request.
210 *
211 * $cls: name of class to use when creating sreg request object.
212 * Used for testing.
213 *
214 * Returns the newly created simple registration request
215 */
216 static function fromOpenIDRequest($request, $cls='Auth_OpenID_SRegRequest')
217 {
218
219 $obj = call_user_func_array(array($cls, 'build'),
220 array(null, null, null, Auth_OpenID_SREG_NS_URI, $cls));
221
222 // Since we're going to mess with namespace URI mapping, don't
223 // mutate the object that was passed in.
224 $m = $request->message;
225
226 $obj->ns_uri = $obj->_getSRegNS($m);
227 $args = $m->getArgs($obj->ns_uri);
228
229 if ($args === null || Auth_OpenID::isFailure($args)) {
230 return null;
231 }
232
233 $obj->parseExtensionArgs($args);
234
235 return $obj;
236 }
237
238 /**
239 * Parse the unqualified simple registration request parameters
240 * and add them to this object.
241 *
242 * This method is essentially the inverse of
243 * getExtensionArgs. This method restores the serialized simple
244 * registration request fields.
245 *
246 * If you are extracting arguments from a standard OpenID
247 * checkid_* request, you probably want to use fromOpenIDRequest,
248 * which will extract the sreg namespace and arguments from the
249 * OpenID request. This method is intended for cases where the
250 * OpenID server needs more control over how the arguments are
251 * parsed than that method provides.
252 *
253 * $args == $message->getArgs($ns_uri);
254 * $request->parseExtensionArgs($args);
255 *
256 * $args: The unqualified simple registration arguments
257 *
258 * strict: Whether requests with fields that are not defined in
259 * the simple registration specification should be tolerated (and
260 * ignored)
261 */
262 function parseExtensionArgs($args, $strict=false)
263 {
264 foreach (array('required', 'optional') as $list_name) {
265 $required = ($list_name == 'required');
266 $items = Auth_OpenID::arrayGet($args, $list_name);
267 if ($items) {
268 foreach (explode(',', $items) as $field_name) {
269 if (!$this->requestField($field_name, $required, $strict)) {
270 if ($strict) {
271 return false;
272 }
273 }
274 }
275 }
276 }
277
278 $this->policy_url = Auth_OpenID::arrayGet($args, 'policy_url');
279
280 return true;
281 }
282
283 /**
284 * A list of all of the simple registration fields that were
285 * requested, whether they were required or optional.
286 */
287 function allRequestedFields()
288 {
289 return array_merge($this->required, $this->optional);
290 }
291
292 /**
293 * Have any simple registration fields been requested?
294 */
295 function wereFieldsRequested()
296 {
297 return count($this->allRequestedFields());
298 }
299
300 /**
301 * Was this field in the request?
302 */
303 function contains($field_name)
304 {
305 return (in_array($field_name, $this->required) ||
306 in_array($field_name, $this->optional));
307 }
308
309 /**
310 * Request the specified field from the OpenID user
311 *
312 * $field_name: the unqualified simple registration field name
313 *
314 * required: whether the given field should be presented to the
315 * user as being a required to successfully complete the request
316 *
317 * strict: whether to raise an exception when a field is added to
318 * a request more than once
319 */
320 function requestField($field_name,
321 $required=false, $strict=false)
322 {
323 if (!Auth_OpenID_checkFieldName($field_name)) {
324 return false;
325 }
326
327 if ($strict) {
328 if ($this->contains($field_name)) {
329 return false;
330 }
331 } else {
332 if (in_array($field_name, $this->required)) {
333 return true;
334 }
335
336 if (in_array($field_name, $this->optional)) {
337 if ($required) {
338 unset($this->optional[array_search($field_name,
339 $this->optional)]);
340 } else {
341 return true;
342 }
343 }
344 }
345
346 if ($required) {
347 $this->required[] = $field_name;
348 } else {
349 $this->optional[] = $field_name;
350 }
351
352 return true;
353 }
354
355 /**
356 * Add the given list of fields to the request
357 *
358 * field_names: The simple registration data fields to request
359 *
360 * required: Whether these values should be presented to the user
361 * as required
362 *
363 * strict: whether to raise an exception when a field is added to
364 * a request more than once
365 */
366 function requestFields($field_names, $required=false, $strict=false)
367 {
368 if (!is_array($field_names)) {
369 return false;
370 }
371
372 foreach ($field_names as $field_name) {
373 if (!$this->requestField($field_name, $required, $strict=$strict)) {
374 return false;
375 }
376 }
377
378 return true;
379 }
380
381 /**
382 * Get a dictionary of unqualified simple registration arguments
383 * representing this request.
384 *
385 * This method is essentially the inverse of
386 * C{L{parseExtensionArgs}}. This method serializes the simple
387 * registration request fields.
388 */
389 function getExtensionArgs()
390 {
391 $args = array();
392
393 if ($this->required) {
394 $args['required'] = implode(',', $this->required);
395 }
396
397 if ($this->optional) {
398 $args['optional'] = implode(',', $this->optional);
399 }
400
401 if ($this->policy_url) {
402 $args['policy_url'] = $this->policy_url;
403 }
404
405 return $args;
406 }
407 }
408
409 /**
410 * Represents the data returned in a simple registration response
411 * inside of an OpenID C{id_res} response. This object will be created
412 * by the OpenID server, added to the C{id_res} response object, and
413 * then extracted from the C{id_res} message by the Consumer.
414 *
415 * @package OpenID
416 */
417 class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase {
418
419 var $ns_alias = 'sreg';
420
421 function Auth_OpenID_SRegResponse($data=null,
422 $sreg_ns_uri=Auth_OpenID_SREG_NS_URI)
423 {
424 if ($data === null) {
425 $this->data = array();
426 } else {
427 $this->data = $data;
428 }
429
430 $this->ns_uri = $sreg_ns_uri;
431 }
432
433 /**
434 * Take a C{L{SRegRequest}} and a dictionary of simple
435 * registration values and create a C{L{SRegResponse}} object
436 * containing that data.
437 *
438 * request: The simple registration request object
439 *
440 * data: The simple registration data for this response, as a
441 * dictionary from unqualified simple registration field name to
442 * string (unicode) value. For instance, the nickname should be
443 * stored under the key 'nickname'.
444 */
445 static function extractResponse($request, $data)
446 {
447 $obj = new Auth_OpenID_SRegResponse();
448 $obj->ns_uri = $request->ns_uri;
449
450 foreach ($request->allRequestedFields() as $field) {
451 $value = Auth_OpenID::arrayGet($data, $field);
452 if ($value !== null) {
453 $obj->data[$field] = $value;
454 }
455 }
456
457 return $obj;
458 }
459
460 /**
461 * Create a C{L{SRegResponse}} object from a successful OpenID
462 * library response
463 * (C{L{openid.consumer.consumer.SuccessResponse}}) response
464 * message
465 *
466 * success_response: A SuccessResponse from consumer.complete()
467 *
468 * signed_only: Whether to process only data that was
469 * signed in the id_res message from the server.
470 *
471 * Returns a simple registration response containing the data that
472 * was supplied with the C{id_res} response.
473 */
474 static function fromSuccessResponse($success_response, $signed_only=true)
475 {
476 global $Auth_OpenID_sreg_data_fields;
477
478 $obj = new Auth_OpenID_SRegResponse();
479 $obj->ns_uri = $obj->_getSRegNS($success_response->message);
480
481 if ($signed_only) {
482 $args = $success_response->getSignedNS($obj->ns_uri);
483 } else {
484 $args = $success_response->message->getArgs($obj->ns_uri);
485 }
486
487 if ($args === null || Auth_OpenID::isFailure($args)) {
488 return null;
489 }
490
491 foreach ($Auth_OpenID_sreg_data_fields as $field_name => $desc) {
492 if (in_array($field_name, array_keys($args))) {
493 $obj->data[$field_name] = $args[$field_name];
494 }
495 }
496
497 return $obj;
498 }
499
500 function getExtensionArgs()
501 {
502 return $this->data;
503 }
504
505 // Read-only dictionary interface
506 function get($field_name, $default=null)
507 {
508 if (!Auth_OpenID_checkFieldName($field_name)) {
509 return null;
510 }
511
512 return Auth_OpenID::arrayGet($this->data, $field_name, $default);
513 }
514
515 function contents()
516 {
517 return $this->data;
518 }
519 }
520
521