ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
AX.php
Go to the documentation of this file.
1<?php
2
13require_once "Auth/OpenID/Extension.php";
14require_once "Auth/OpenID/Message.php";
15require_once "Auth/OpenID/TrustRoot.php";
16
17define('Auth_OpenID_AX_NS_URI',
18 'http://openid.net/srv/ax/1.0');
19
20// Use this as the 'count' value for an attribute in a FetchRequest to
21// ask for as many values as the OP can provide.
22define('Auth_OpenID_AX_UNLIMITED_VALUES', 'unlimited');
23
24// Minimum supported alias length in characters. Here for
25// completeness.
26define('Auth_OpenID_AX_MINIMUM_SUPPORTED_ALIAS_LENGTH', 32);
27
33class Auth_OpenID_AX {
41 static function isError($thing)
42 {
43 return is_a($thing, 'Auth_OpenID_AX_Error');
44 }
45}
46
51function Auth_OpenID_AX_checkAlias($alias)
52{
53 if (strpos($alias, ',') !== false) {
54 return new Auth_OpenID_AX_Error(sprintf(
55 "Alias %s must not contain comma", $alias));
56 }
57 if (strpos($alias, '.') !== false) {
58 return new Auth_OpenID_AX_Error(sprintf(
59 "Alias %s must not contain period", $alias));
60 }
61
62 return true;
63}
64
72 function Auth_OpenID_AX_Error($message=null)
73 {
74 $this->message = $message;
75 }
76}
77
89 var $ns_alias = 'ax';
90
95 var $mode = null;
98
106 function _checkMode($ax_args)
107 {
108 $mode = Auth_OpenID::arrayGet($ax_args, 'mode');
109 if ($mode != $this->mode) {
110 return new Auth_OpenID_AX_Error(
111 sprintf(
112 "Expected mode '%s'; got '%s'",
113 $this->mode, $mode));
114 }
115
116 return true;
117 }
118
126 function _newArgs()
127 {
128 return array('mode' => $this->mode);
129 }
130}
131
154 function Auth_OpenID_AX_AttrInfo($type_uri, $count, $required,
155 $alias)
156 {
162 $this->required = $required;
163
168 $this->count = $count;
169
177 $this->type_uri = $type_uri;
178
187 $this->alias = $alias;
188 }
189
194 static function make($type_uri, $count=1, $required=false,
195 $alias=null)
196 {
197 if ($alias !== null) {
199
201 return $result;
202 }
203 }
204
205 return new Auth_OpenID_AX_AttrInfo($type_uri, $count, $required,
206 $alias);
207 }
208
216 function wantsUnlimitedValues()
217 {
218 return $this->count === Auth_OpenID_AX_UNLIMITED_VALUES;
219 }
220}
221
238function Auth_OpenID_AX_toTypeURIs($namespace_map, $alias_list_s)
239{
240 $uris = array();
241
242 if ($alias_list_s) {
243 foreach (explode(',', $alias_list_s) as $alias) {
244 $type_uri = $namespace_map->getNamespaceURI($alias);
245 if ($type_uri === null) {
246 // raise KeyError(
247 // 'No type is defined for attribute name %r' % (alias,))
248 return new Auth_OpenID_AX_Error(
249 sprintf('No type is defined for attribute name %s',
250 $alias)
251 );
252 } else {
253 $uris[] = $type_uri;
254 }
255 }
256 }
257
258 return $uris;
259}
260
270 var $mode = 'fetch_request';
272 function Auth_OpenID_AX_FetchRequest($update_url=null)
273 {
278 $this->requested_attributes = array();
279
285 $this->update_url = $update_url;
286 }
287
295 function add($attribute)
296 {
297 if ($this->contains($attribute->type_uri)) {
298 return new Auth_OpenID_AX_Error(
299 sprintf("The attribute %s has already been requested",
300 $attribute->type_uri));
301 }
302
303 $this->requested_attributes[$attribute->type_uri] = $attribute;
304
305 return true;
306 }
307
313 function getExtensionArgs()
314 {
315 $aliases = new Auth_OpenID_NamespaceMap();
316
317 $required = array();
318 $if_available = array();
319
320 $ax_args = $this->_newArgs();
321
322 foreach ($this->requested_attributes as $type_uri => $attribute) {
323 if ($attribute->alias === null) {
324 $alias = $aliases->add($type_uri);
325 } else {
326 $alias = $aliases->addAlias($type_uri, $attribute->alias);
327
328 if ($alias === null) {
329 return new Auth_OpenID_AX_Error(
330 sprintf("Could not add alias %s for URI %s",
331 $attribute->alias, $type_uri
332 ));
333 }
334 }
335
336 if ($attribute->required) {
337 $required[] = $alias;
338 } else {
339 $if_available[] = $alias;
340 }
341
342 if ($attribute->count != 1) {
343 $ax_args['count.' . $alias] = strval($attribute->count);
344 }
345
346 $ax_args['type.' . $alias] = $type_uri;
347 }
348
349 if ($required) {
350 $ax_args['required'] = implode(',', $required);
351 }
352
353 if ($if_available) {
354 $ax_args['if_available'] = implode(',', $if_available);
355 }
356
357 return $ax_args;
358 }
359
367 function getRequiredAttrs()
368 {
369 $required = array();
370 foreach ($this->requested_attributes as $type_uri => $attribute) {
371 if ($attribute->required) {
372 $required[] = $type_uri;
373 }
374 }
375
376 return $required;
377 }
378
389 static function fromOpenIDRequest($request)
390 {
391 $m = $request->message;
392 $obj = new Auth_OpenID_AX_FetchRequest();
393 $ax_args = $m->getArgs($obj->ns_uri);
394
395 $result = $obj->parseExtensionArgs($ax_args);
396
398 return $result;
399 }
400
401 if ($obj->update_url) {
402 // Update URL must match the openid.realm of the
403 // underlying OpenID 2 message.
404 $realm = $m->getArg(Auth_OpenID_OPENID_NS, 'realm',
405 $m->getArg(
407 'return_to'));
408
409 if (!$realm) {
410 $obj = new Auth_OpenID_AX_Error(
411 sprintf("Cannot validate update_url %s " .
412 "against absent realm", $obj->update_url));
413 } else if (!Auth_OpenID_TrustRoot::match($realm,
414 $obj->update_url)) {
415 $obj = new Auth_OpenID_AX_Error(
416 sprintf("Update URL %s failed validation against realm %s",
417 $obj->update_url, $realm));
418 }
419 }
420
421 return $obj;
422 }
423
432 function parseExtensionArgs($ax_args)
433 {
434 $result = $this->_checkMode($ax_args);
436 return $result;
437 }
438
439 $aliases = new Auth_OpenID_NamespaceMap();
440
441 foreach ($ax_args as $key => $value) {
442 if (strpos($key, 'type.') === 0) {
443 $alias = substr($key, 5);
444 $type_uri = $value;
445
446 $alias = $aliases->addAlias($type_uri, $alias);
447
448 if ($alias === null) {
449 return new Auth_OpenID_AX_Error(
450 sprintf("Could not add alias %s for URI %s",
451 $alias, $type_uri)
452 );
453 }
454
455 $count_s = Auth_OpenID::arrayGet($ax_args, 'count.' . $alias);
456 if ($count_s) {
457 $count = Auth_OpenID::intval($count_s);
458 if (($count === false) &&
459 ($count_s === Auth_OpenID_AX_UNLIMITED_VALUES)) {
460 $count = $count_s;
461 }
462 } else {
463 $count = 1;
464 }
465
466 if ($count === false) {
467 return new Auth_OpenID_AX_Error(
468 sprintf("Integer value expected for %s, got %s",
469 'count.' . $alias, $count_s));
470 }
471
472 $attrinfo = Auth_OpenID_AX_AttrInfo::make($type_uri, $count,
473 false, $alias);
474
475 if (Auth_OpenID_AX::isError($attrinfo)) {
476 return $attrinfo;
477 }
478
479 $this->add($attrinfo);
480 }
481 }
482
483 $required = Auth_OpenID_AX_toTypeURIs($aliases,
484 Auth_OpenID::arrayGet($ax_args, 'required'));
485
486 foreach ($required as $type_uri) {
487 $attrib = $this->requested_attributes[$type_uri];
488 $attrib->required = true;
489 }
490
491 $if_available = Auth_OpenID_AX_toTypeURIs($aliases,
492 Auth_OpenID::arrayGet($ax_args, 'if_available'));
493
494 $all_type_uris = array_merge($required, $if_available);
495
496 foreach ($aliases->iterNamespaceURIs() as $type_uri) {
497 if (!in_array($type_uri, $all_type_uris)) {
498 return new Auth_OpenID_AX_Error(
499 sprintf('Type URI %s was in the request but not ' .
500 'present in "required" or "if_available"',
501 $type_uri));
502
503 }
504 }
505
506 $this->update_url = Auth_OpenID::arrayGet($ax_args, 'update_url');
507
508 return true;
509 }
510
515 function iterAttrs()
516 {
517 return array_values($this->requested_attributes);
518 }
520 function iterTypes()
521 {
522 return array_keys($this->requested_attributes);
523 }
524
528 function contains($type_uri)
529 {
530 return in_array($type_uri, $this->iterTypes());
531 }
532}
533
544 {
545 $this->data = array();
546 }
547
559 function addValue($type_uri, $value)
560 {
561 if (!array_key_exists($type_uri, $this->data)) {
562 $this->data[$type_uri] = array();
563 }
564
565 $values =& $this->data[$type_uri];
566 $values[] = $value;
567 }
568
576 function setValues($type_uri, &$values)
577 {
578 $this->data[$type_uri] =& $values;
579 }
580
590 function _getExtensionKVArgs($aliases)
591 {
592 if ($aliases === null) {
593 $aliases = new Auth_OpenID_NamespaceMap();
594 }
595
596 $ax_args = array();
597
598 foreach ($this->data as $type_uri => $values) {
599 $alias = $aliases->add($type_uri);
600
601 $ax_args['type.' . $alias] = $type_uri;
602 $ax_args['count.' . $alias] = strval(count($values));
603
604 foreach ($values as $i => $value) {
605 $key = sprintf('value.%s.%d', $alias, $i + 1);
606 $ax_args[$key] = $value;
607 }
608 }
609
610 return $ax_args;
611 }
612
621 function parseExtensionArgs($ax_args)
622 {
623 $result = $this->_checkMode($ax_args);
625 return $result;
626 }
627
628 $aliases = new Auth_OpenID_NamespaceMap();
629
630 foreach ($ax_args as $key => $value) {
631 if (strpos($key, 'type.') === 0) {
632 $type_uri = $value;
633 $alias = substr($key, 5);
634
636
638 return $result;
639 }
640
641 $alias = $aliases->addAlias($type_uri, $alias);
642
643 if ($alias === null) {
644 return new Auth_OpenID_AX_Error(
645 sprintf("Could not add alias %s for URI %s",
646 $alias, $type_uri)
647 );
648 }
649 }
650 }
651
652 foreach ($aliases->iteritems() as $pair) {
653 list($type_uri, $alias) = $pair;
654
655 if (array_key_exists('count.' . $alias, $ax_args) && ($ax_args['count.' . $alias] !== Auth_OpenID_AX_UNLIMITED_VALUES)) {
656
657 $count_key = 'count.' . $alias;
658 $count_s = $ax_args[$count_key];
659
660 $count = Auth_OpenID::intval($count_s);
661
662 if ($count === false) {
663 return new Auth_OpenID_AX_Error(
664 sprintf("Integer value expected for %s, got %s",
665 'count. %s' . $alias, $count_s,
667 );
668 }
669
670 $values = array();
671 for ($i = 1; $i < $count + 1; $i++) {
672 $value_key = sprintf('value.%s.%d', $alias, $i);
673
674 if (!array_key_exists($value_key, $ax_args)) {
675 return new Auth_OpenID_AX_Error(
676 sprintf(
677 "No value found for key %s",
678 $value_key));
679 }
680
681 $value = $ax_args[$value_key];
682 $values[] = $value;
683 }
684 } else {
685 $key = 'value.' . $alias;
686
687 if (!array_key_exists($key, $ax_args)) {
688 return new Auth_OpenID_AX_Error(
689 sprintf(
690 "No value found for key %s",
691 $key));
692 }
693
694 $value = $ax_args['value.' . $alias];
695
696 if ($value == '') {
697 $values = array();
698 } else {
699 $values = array($value);
700 }
701 }
702
703 $this->data[$type_uri] = $values;
704 }
705
706 return true;
707 }
708
722 function getSingle($type_uri, $default=null)
723 {
724 $values = Auth_OpenID::arrayGet($this->data, $type_uri);
725 if (!$values) {
726 return $default;
727 } else if (count($values) == 1) {
728 return $values[0];
729 } else {
730 return new Auth_OpenID_AX_Error(
731 sprintf('More than one value present for %s',
732 $type_uri)
733 );
734 }
735 }
736
753 function get($type_uri)
754 {
755 if (array_key_exists($type_uri, $this->data)) {
756 return $this->data[$type_uri];
757 } else {
758 return new Auth_OpenID_AX_Error(
759 sprintf("Type URI %s not found in response",
760 $type_uri)
761 );
762 }
763 }
764
775 function count($type_uri)
776 {
777 if (array_key_exists($type_uri, $this->data)) {
778 return count($this->get($type_uri));
779 } else {
780 return new Auth_OpenID_AX_Error(
781 sprintf("Type URI %s not found in response",
782 $type_uri)
783 );
784 }
785 }
786}
787
794 var $mode = 'fetch_response';
796 function Auth_OpenID_AX_FetchResponse($update_url=null)
797 {
799 $this->update_url = $update_url;
800 }
801
810 function getExtensionArgs($request=null)
811 {
812 $aliases = new Auth_OpenID_NamespaceMap();
813
814 $zero_value_types = array();
815
816 if ($request !== null) {
817 // Validate the data in the context of the request (the
818 // same attributes should be present in each, and the
819 // counts in the response must be no more than the counts
820 // in the request)
821
822 foreach ($this->data as $type_uri => $unused) {
823 if (!$request->contains($type_uri)) {
824 return new Auth_OpenID_AX_Error(
825 sprintf("Response attribute not present in request: %s",
826 $type_uri)
827 );
828 }
829 }
830
831 foreach ($request->iterAttrs() as $attr_info) {
832 // Copy the aliases from the request so that reading
833 // the response in light of the request is easier
834 if ($attr_info->alias === null) {
835 $aliases->add($attr_info->type_uri);
836 } else {
837 $alias = $aliases->addAlias($attr_info->type_uri,
838 $attr_info->alias);
839
840 if ($alias === null) {
841 return new Auth_OpenID_AX_Error(
842 sprintf("Could not add alias %s for URI %s",
843 $attr_info->alias, $attr_info->type_uri)
844 );
845 }
846 }
847
848 if (array_key_exists($attr_info->type_uri, $this->data)) {
849 $values = $this->data[$attr_info->type_uri];
850 } else {
851 $values = array();
852 $zero_value_types[] = $attr_info;
853 }
854
855 if (($attr_info->count != Auth_OpenID_AX_UNLIMITED_VALUES) &&
856 ($attr_info->count < count($values))) {
857 return new Auth_OpenID_AX_Error(
858 sprintf("More than the number of requested values " .
859 "were specified for %s",
860 $attr_info->type_uri)
861 );
862 }
863 }
864 }
865
866 $kv_args = $this->_getExtensionKVArgs($aliases);
867
868 // Add the KV args into the response with the args that are
869 // unique to the fetch_response
870 $ax_args = $this->_newArgs();
871
872 // For each requested attribute, put its type/alias and count
873 // into the response even if no data were returned.
874 foreach ($zero_value_types as $attr_info) {
875 $alias = $aliases->getAlias($attr_info->type_uri);
876 $kv_args['type.' . $alias] = $attr_info->type_uri;
877 $kv_args['count.' . $alias] = '0';
878 }
879
880 $update_url = null;
881 if ($request) {
882 $update_url = $request->update_url;
883 } else {
884 $update_url = $this->update_url;
885 }
886
887 if ($update_url) {
888 $ax_args['update_url'] = $update_url;
889 }
890
891 Auth_OpenID::update($ax_args, $kv_args);
892
893 return $ax_args;
894 }
895
900 function parseExtensionArgs($ax_args)
901 {
902 $result = parent::parseExtensionArgs($ax_args);
903
905 return $result;
906 }
907
908 $this->update_url = Auth_OpenID::arrayGet($ax_args, 'update_url');
909
910 return true;
911 }
912
925 static function fromSuccessResponse($success_response, $signed=true)
926 {
927 $obj = new Auth_OpenID_AX_FetchResponse();
928 if ($signed) {
929 $ax_args = $success_response->getSignedNS($obj->ns_uri);
930 } else {
931 $ax_args = $success_response->message->getArgs($obj->ns_uri);
932 }
933 if ($ax_args === null || Auth_OpenID::isFailure($ax_args) ||
934 sizeof($ax_args) == 0) {
935 return null;
936 }
937
938 $result = $obj->parseExtensionArgs($ax_args);
940 #XXX log me
941 return null;
942 }
943 return $obj;
944 }
945}
946
953 var $mode = 'store_request';
954
959 function getExtensionArgs($aliases=null)
960 {
961 $ax_args = $this->_newArgs();
962 $kv_args = $this->_getExtensionKVArgs($aliases);
963 Auth_OpenID::update($ax_args, $kv_args);
964 return $ax_args;
965 }
966}
967
976 var $SUCCESS_MODE = 'store_response_success';
977 var $FAILURE_MODE = 'store_response_failure';
978
983 function make($succeeded=true, $error_message=null)
984 {
985 if (($succeeded) && ($error_message !== null)) {
986 return new Auth_OpenID_AX_Error('An error message may only be '.
987 'included in a failing fetch response');
988 }
989
990 return new Auth_OpenID_AX_StoreResponse($succeeded, $error_message);
991 }
993 function Auth_OpenID_AX_StoreResponse($succeeded=true, $error_message=null)
994 {
995 if ($succeeded) {
996 $this->mode = $this->SUCCESS_MODE;
997 } else {
998 $this->mode = $this->FAILURE_MODE;
999 }
1000
1001 $this->error_message = $error_message;
1002 }
1003
1007 function succeeded()
1008 {
1009 return $this->mode == $this->SUCCESS_MODE;
1010 }
1012 function getExtensionArgs()
1013 {
1014 $ax_args = $this->_newArgs();
1015 if ((!$this->succeeded()) && $this->error_message) {
1016 $ax_args['error'] = $this->error_message;
1017 }
1018
1019 return $ax_args;
1020 }
1021}
1022
const Auth_OpenID_AX_NS_URI
Require utility classes and functions for the consumer.
Definition: AX.php:17
const Auth_OpenID_AX_UNLIMITED_VALUES
Definition: AX.php:21
Auth_OpenID_AX_toTypeURIs($namespace_map, $alias_list_s)
Given a namespace mapping and a string containing a comma-separated list of namespace aliases,...
Definition: AX.php:237
Auth_OpenID_AX_checkAlias($alias)
Check an alias for invalid characters; raise AXError if any are found.
Definition: AX.php:50
$result
const Auth_OpenID_OPENID_NS
Definition: Message.php:42
$attrib
Regular expression to match HTML/XML attribute pairs within a tag.
Definition: Sanitizer.php:41
wantsUnlimitedValues()
When processing a request for this attribute, the OP should call this method to determine whether all...
Definition: AX.php:215
static make($type_uri, $count=1, $required=false, $alias=null)
Construct an attribute information object.
Definition: AX.php:193
Auth_OpenID_AX_AttrInfo($type_uri, $count, $required, $alias)
Construct an attribute information object.
Definition: AX.php:153
Auth_OpenID_AX_Error($message=null)
Definition: AX.php:71
parseExtensionArgs($ax_args)
Given attribute exchange arguments, populate this FetchRequest.
Definition: AX.php:431
iterAttrs()
Iterate over the AttrInfo objects that are contained in this fetch_request.
Definition: AX.php:514
Auth_OpenID_AX_FetchRequest($update_url=null)
Definition: AX.php:271
contains($type_uri)
Is the given type URI present in this fetch_request?
Definition: AX.php:527
getRequiredAttrs()
Get the type URIs for all attributes that have been marked as required.
Definition: AX.php:366
getExtensionArgs()
Get the serialized form of this attribute fetch request.
Definition: AX.php:312
add($attribute)
Add an attribute to this attribute exchange request.
Definition: AX.php:294
static fromOpenIDRequest($request)
Extract a FetchRequest from an OpenID message.
Definition: AX.php:388
Auth_OpenID_AX_FetchResponse($update_url=null)
Definition: AX.php:795
static fromSuccessResponse($success_response, $signed=true)
Construct a FetchResponse object from an OpenID library SuccessResponse object.
Definition: AX.php:924
parseExtensionArgs($ax_args)
Definition: AX.php:899
_getExtensionKVArgs($aliases)
Get the extension arguments for the key/value pairs contained in this message.
Definition: AX.php:589
parseExtensionArgs($ax_args)
Parse attribute exchange key/value arguments into this object.
Definition: AX.php:620
addValue($type_uri, $value)
Add a single value for the given attribute type to the message.
Definition: AX.php:558
count($type_uri)
Get the number of responses for a particular attribute in this fetch_response message.
Definition: AX.php:774
getSingle($type_uri, $default=null)
Get a single value for an attribute.
Definition: AX.php:721
setValues($type_uri, &$values)
Set the values for the given attribute type.
Definition: AX.php:575
_newArgs()
Return a set of attribute exchange arguments containing the basic information that must be in every a...
Definition: AX.php:125
_checkMode($ax_args)
Return Auth_OpenID_AX_Error if the mode in the attribute exchange arguments does not match what is ex...
Definition: AX.php:105
$mode
mode: The type of this attribute exchange message.
Definition: AX.php:94
$ns_alias
ns_alias: The preferred namespace alias for attribute exchange messages
Definition: AX.php:88
make($succeeded=true, $error_message=null)
Returns Auth_OpenID_AX_Error on error or an Auth_OpenID_AX_StoreResponse object on success.
Definition: AX.php:982
succeeded()
Was this response a success response?
Definition: AX.php:1006
getExtensionArgs()
Get the string arguments that should be added to an OpenID message for this extension.
Definition: AX.php:1011
Auth_OpenID_AX_StoreResponse($succeeded=true, $error_message=null)
Definition: AX.php:992
static isError($thing)
Definition: AX.php:40
getExtensionArgs()
Get the string arguments that should be added to an OpenID message for this extension.
Definition: Extension.php:32
static match($trust_root, $url)
Does this URL match the given trust root?
Definition: TrustRoot.php:270
static arrayGet($arr, $key, $fallback=null)
Convenience function for getting array values.
Definition: OpenID.php:242
static isFailure($thing)
Return true if $thing is an Auth_OpenID_FailureResponse object; false if not.
Definition: OpenID.php:118
static intval($value)
Replacement (wrapper) for PHP's intval() because it's broken.
Definition: OpenID.php:444
static update(&$dest, &$src)
Definition: OpenID.php:511