[BUGFIX] Fix T3editor after PSR-7 change
[Packages/TYPO3.CMS.git] / typo3 / sysext / openid / lib / php-openid / Auth / OpenID / Message.php
1 <?php
2
3 /**
4 * Extension argument processing code
5 *
6 * @package OpenID
7 */
8
9 /**
10 * Import tools needed to deal with messages.
11 */
12 require_once 'Auth/OpenID.php';
13 require_once 'Auth/OpenID/KVForm.php';
14 require_once 'Auth/Yadis/XML.php';
15 require_once 'Auth/OpenID/Consumer.php'; // For Auth_OpenID_FailureResponse
16
17 // This doesn't REALLY belong here, but where is better?
18 define('Auth_OpenID_IDENTIFIER_SELECT',
19 "http://specs.openid.net/auth/2.0/identifier_select");
20
21 // URI for Simple Registration extension, the only commonly deployed
22 // OpenID 1.x extension, and so a special case
23 define('Auth_OpenID_SREG_URI', 'http://openid.net/sreg/1.0');
24
25 // The OpenID 1.X namespace URI
26 define('Auth_OpenID_OPENID1_NS', 'http://openid.net/signon/1.0');
27 define('Auth_OpenID_THE_OTHER_OPENID1_NS', 'http://openid.net/signon/1.1');
28
29 function Auth_OpenID_isOpenID1($ns)
30 {
31 return ($ns == Auth_OpenID_THE_OTHER_OPENID1_NS) ||
32 ($ns == Auth_OpenID_OPENID1_NS);
33 }
34
35 // The OpenID 2.0 namespace URI
36 define('Auth_OpenID_OPENID2_NS', 'http://specs.openid.net/auth/2.0');
37
38 // The namespace consisting of pairs with keys that are prefixed with
39 // "openid." but not in another namespace.
40 define('Auth_OpenID_NULL_NAMESPACE', 'Null namespace');
41
42 // The null namespace, when it is an allowed OpenID namespace
43 define('Auth_OpenID_OPENID_NS', 'OpenID namespace');
44
45 // The top-level namespace, excluding all pairs with keys that start
46 // with "openid."
47 define('Auth_OpenID_BARE_NS', 'Bare namespace');
48
49 // Sentinel for Message implementation to indicate that getArg should
50 // return null instead of returning a default.
51 define('Auth_OpenID_NO_DEFAULT', 'NO DEFAULT ALLOWED');
52
53 // Limit, in bytes, of identity provider and return_to URLs, including
54 // response payload. See OpenID 1.1 specification, Appendix D.
55 define('Auth_OpenID_OPENID1_URL_LIMIT', 2047);
56
57 // All OpenID protocol fields. Used to check namespace aliases.
58 global $Auth_OpenID_OPENID_PROTOCOL_FIELDS;
59 $Auth_OpenID_OPENID_PROTOCOL_FIELDS = array(
60 'ns', 'mode', 'error', 'return_to', 'contact', 'reference',
61 'signed', 'assoc_type', 'session_type', 'dh_modulus', 'dh_gen',
62 'dh_consumer_public', 'claimed_id', 'identity', 'realm',
63 'invalidate_handle', 'op_endpoint', 'response_nonce', 'sig',
64 'assoc_handle', 'trust_root', 'openid');
65
66 // Global namespace / alias registration map. See
67 // Auth_OpenID_registerNamespaceAlias.
68 global $Auth_OpenID_registered_aliases;
69 $Auth_OpenID_registered_aliases = array();
70
71 /**
72 * Registers a (namespace URI, alias) mapping in a global namespace
73 * alias map. Raises NamespaceAliasRegistrationError if either the
74 * namespace URI or alias has already been registered with a different
75 * value. This function is required if you want to use a namespace
76 * with an OpenID 1 message.
77 */
78 function Auth_OpenID_registerNamespaceAlias($namespace_uri, $alias)
79 {
80 global $Auth_OpenID_registered_aliases;
81
82 if (Auth_OpenID::arrayGet($Auth_OpenID_registered_aliases,
83 $alias) == $namespace_uri) {
84 return true;
85 }
86
87 if (in_array($namespace_uri,
88 array_values($Auth_OpenID_registered_aliases))) {
89 return false;
90 }
91
92 if (in_array($alias, array_keys($Auth_OpenID_registered_aliases))) {
93 return false;
94 }
95
96 $Auth_OpenID_registered_aliases[$alias] = $namespace_uri;
97 return true;
98 }
99
100 /**
101 * Removes a (namespace_uri, alias) registration from the global
102 * namespace alias map. Returns true if the removal succeeded; false
103 * if not (if the mapping did not exist).
104 */
105 function Auth_OpenID_removeNamespaceAlias($namespace_uri, $alias)
106 {
107 global $Auth_OpenID_registered_aliases;
108
109 if (Auth_OpenID::arrayGet($Auth_OpenID_registered_aliases,
110 $alias) === $namespace_uri) {
111 unset($Auth_OpenID_registered_aliases[$alias]);
112 return true;
113 }
114
115 return false;
116 }
117
118 /**
119 * An Auth_OpenID_Mapping maintains a mapping from arbitrary keys to
120 * arbitrary values. (This is unlike an ordinary PHP array, whose
121 * keys may be only simple scalars.)
122 *
123 * @package OpenID
124 */
125 class Auth_OpenID_Mapping {
126 /**
127 * Initialize a mapping. If $classic_array is specified, its keys
128 * and values are used to populate the mapping.
129 */
130 function Auth_OpenID_Mapping($classic_array = null)
131 {
132 $this->keys = array();
133 $this->values = array();
134
135 if (is_array($classic_array)) {
136 foreach ($classic_array as $key => $value) {
137 $this->set($key, $value);
138 }
139 }
140 }
141
142 /**
143 * Returns true if $thing is an Auth_OpenID_Mapping object; false
144 * if not.
145 */
146 static function isA($thing)
147 {
148 return (is_object($thing) &&
149 strtolower(get_class($thing)) == 'auth_openid_mapping');
150 }
151
152 /**
153 * Returns an array of the keys in the mapping.
154 */
155 function keys()
156 {
157 return $this->keys;
158 }
159
160 /**
161 * Returns an array of values in the mapping.
162 */
163 function values()
164 {
165 return $this->values;
166 }
167
168 /**
169 * Returns an array of (key, value) pairs in the mapping.
170 */
171 function items()
172 {
173 $temp = array();
174
175 for ($i = 0; $i < count($this->keys); $i++) {
176 $temp[] = array($this->keys[$i],
177 $this->values[$i]);
178 }
179 return $temp;
180 }
181
182 /**
183 * Returns the "length" of the mapping, or the number of keys.
184 */
185 function len()
186 {
187 return count($this->keys);
188 }
189
190 /**
191 * Sets a key-value pair in the mapping. If the key already
192 * exists, its value is replaced with the new value.
193 */
194 function set($key, $value)
195 {
196 $index = array_search($key, $this->keys);
197
198 if ($index !== false) {
199 $this->values[$index] = $value;
200 } else {
201 $this->keys[] = $key;
202 $this->values[] = $value;
203 }
204 }
205
206 /**
207 * Gets a specified value from the mapping, associated with the
208 * specified key. If the key does not exist in the mapping,
209 * $default is returned instead.
210 */
211 function get($key, $default = null)
212 {
213 $index = array_search($key, $this->keys);
214
215 if ($index !== false) {
216 return $this->values[$index];
217 } else {
218 return $default;
219 }
220 }
221
222 /**
223 * @access private
224 */
225 function _reflow()
226 {
227 // PHP is broken yet again. Sort the arrays to remove the
228 // hole in the numeric indexes that make up the array.
229 $old_keys = $this->keys;
230 $old_values = $this->values;
231
232 $this->keys = array();
233 $this->values = array();
234
235 foreach ($old_keys as $k) {
236 $this->keys[] = $k;
237 }
238
239 foreach ($old_values as $v) {
240 $this->values[] = $v;
241 }
242 }
243
244 /**
245 * Deletes a key-value pair from the mapping with the specified
246 * key.
247 */
248 function del($key)
249 {
250 $index = array_search($key, $this->keys);
251
252 if ($index !== false) {
253 unset($this->keys[$index]);
254 unset($this->values[$index]);
255 $this->_reflow();
256 return true;
257 }
258 return false;
259 }
260
261 /**
262 * Returns true if the specified value has a key in the mapping;
263 * false if not.
264 */
265 function contains($value)
266 {
267 return (array_search($value, $this->keys) !== false);
268 }
269 }
270
271 /**
272 * Maintains a bijective map between namespace uris and aliases.
273 *
274 * @package OpenID
275 */
276 class Auth_OpenID_NamespaceMap {
277 function Auth_OpenID_NamespaceMap()
278 {
279 $this->alias_to_namespace = new Auth_OpenID_Mapping();
280 $this->namespace_to_alias = new Auth_OpenID_Mapping();
281 $this->implicit_namespaces = array();
282 }
283
284 function getAlias($namespace_uri)
285 {
286 return $this->namespace_to_alias->get($namespace_uri);
287 }
288
289 function getNamespaceURI($alias)
290 {
291 return $this->alias_to_namespace->get($alias);
292 }
293
294 function iterNamespaceURIs()
295 {
296 // Return an iterator over the namespace URIs
297 return $this->namespace_to_alias->keys();
298 }
299
300 function iterAliases()
301 {
302 // Return an iterator over the aliases"""
303 return $this->alias_to_namespace->keys();
304 }
305
306 function iteritems()
307 {
308 return $this->namespace_to_alias->items();
309 }
310
311 function isImplicit($namespace_uri)
312 {
313 return in_array($namespace_uri, $this->implicit_namespaces);
314 }
315
316 function addAlias($namespace_uri, $desired_alias, $implicit=false)
317 {
318 // Add an alias from this namespace URI to the desired alias
319 global $Auth_OpenID_OPENID_PROTOCOL_FIELDS;
320
321 // Check that desired_alias is not an openid protocol field as
322 // per the spec.
323 if (in_array($desired_alias, $Auth_OpenID_OPENID_PROTOCOL_FIELDS)) {
324 Auth_OpenID::log("\"%s\" is not an allowed namespace alias",
325 $desired_alias);
326 return null;
327 }
328
329 // Check that desired_alias does not contain a period as per
330 // the spec.
331 if (strpos($desired_alias, '.') !== false) {
332 Auth_OpenID::log('"%s" must not contain a dot', $desired_alias);
333 return null;
334 }
335
336 // Check that there is not a namespace already defined for the
337 // desired alias
338 $current_namespace_uri =
339 $this->alias_to_namespace->get($desired_alias);
340
341 if (($current_namespace_uri !== null) &&
342 ($current_namespace_uri != $namespace_uri)) {
343 Auth_OpenID::log('Cannot map "%s" because previous mapping exists',
344 $namespace_uri);
345 return null;
346 }
347
348 // Check that there is not already a (different) alias for
349 // this namespace URI
350 $alias = $this->namespace_to_alias->get($namespace_uri);
351
352 if (($alias !== null) && ($alias != $desired_alias)) {
353 Auth_OpenID::log('Cannot map %s to alias %s. ' .
354 'It is already mapped to alias %s',
355 $namespace_uri, $desired_alias, $alias);
356 return null;
357 }
358
359 assert((Auth_OpenID_NULL_NAMESPACE === $desired_alias) ||
360 is_string($desired_alias));
361
362 $this->alias_to_namespace->set($desired_alias, $namespace_uri);
363 $this->namespace_to_alias->set($namespace_uri, $desired_alias);
364 if ($implicit) {
365 array_push($this->implicit_namespaces, $namespace_uri);
366 }
367
368 return $desired_alias;
369 }
370
371 function add($namespace_uri)
372 {
373 // Add this namespace URI to the mapping, without caring what
374 // alias it ends up with
375
376 // See if this namespace is already mapped to an alias
377 $alias = $this->namespace_to_alias->get($namespace_uri);
378
379 if ($alias !== null) {
380 return $alias;
381 }
382
383 // Fall back to generating a numerical alias
384 $i = 0;
385 while (1) {
386 $alias = 'ext' . strval($i);
387 if ($this->addAlias($namespace_uri, $alias) === null) {
388 $i += 1;
389 } else {
390 return $alias;
391 }
392 }
393
394 // Should NEVER be reached!
395 return null;
396 }
397
398 function contains($namespace_uri)
399 {
400 return $this->isDefined($namespace_uri);
401 }
402
403 function isDefined($namespace_uri)
404 {
405 return $this->namespace_to_alias->contains($namespace_uri);
406 }
407 }
408
409 /**
410 * In the implementation of this object, null represents the global
411 * namespace as well as a namespace with no key.
412 *
413 * @package OpenID
414 */
415 class Auth_OpenID_Message {
416
417 function Auth_OpenID_Message($openid_namespace = null)
418 {
419 // Create an empty Message
420 $this->allowed_openid_namespaces = array(
421 Auth_OpenID_OPENID1_NS,
422 Auth_OpenID_THE_OTHER_OPENID1_NS,
423 Auth_OpenID_OPENID2_NS);
424
425 $this->args = new Auth_OpenID_Mapping();
426 $this->namespaces = new Auth_OpenID_NamespaceMap();
427 if ($openid_namespace === null) {
428 $this->_openid_ns_uri = null;
429 } else {
430 $implicit = Auth_OpenID_isOpenID1($openid_namespace);
431 $this->setOpenIDNamespace($openid_namespace, $implicit);
432 }
433 }
434
435 function isOpenID1()
436 {
437 return Auth_OpenID_isOpenID1($this->getOpenIDNamespace());
438 }
439
440 function isOpenID2()
441 {
442 return $this->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS;
443 }
444
445 static function fromPostArgs($args)
446 {
447 // Construct a Message containing a set of POST arguments
448 $obj = new Auth_OpenID_Message();
449
450 // Partition into "openid." args and bare args
451 $openid_args = array();
452 foreach ($args as $key => $value) {
453
454 if (is_array($value)) {
455 return null;
456 }
457
458 $parts = explode('.', $key, 2);
459
460 if (count($parts) == 2) {
461 list($prefix, $rest) = $parts;
462 } else {
463 $prefix = null;
464 }
465
466 if ($prefix != 'openid') {
467 $obj->args->set(array(Auth_OpenID_BARE_NS, $key), $value);
468 } else {
469 $openid_args[$rest] = $value;
470 }
471 }
472
473 if ($obj->_fromOpenIDArgs($openid_args)) {
474 return $obj;
475 } else {
476 return null;
477 }
478 }
479
480 static function fromOpenIDArgs($openid_args)
481 {
482 // Takes an array.
483
484 // Construct a Message from a parsed KVForm message
485 $obj = new Auth_OpenID_Message();
486 if ($obj->_fromOpenIDArgs($openid_args)) {
487 return $obj;
488 } else {
489 return null;
490 }
491 }
492
493 /**
494 * @access private
495 */
496 function _fromOpenIDArgs($openid_args)
497 {
498 global $Auth_OpenID_registered_aliases;
499
500 // Takes an Auth_OpenID_Mapping instance OR an array.
501
502 if (!Auth_OpenID_Mapping::isA($openid_args)) {
503 $openid_args = new Auth_OpenID_Mapping($openid_args);
504 }
505
506 $ns_args = array();
507
508 // Resolve namespaces
509 foreach ($openid_args->items() as $pair) {
510 list($rest, $value) = $pair;
511
512 $parts = explode('.', $rest, 2);
513
514 if (count($parts) == 2) {
515 list($ns_alias, $ns_key) = $parts;
516 } else {
517 $ns_alias = Auth_OpenID_NULL_NAMESPACE;
518 $ns_key = $rest;
519 }
520
521 if ($ns_alias == 'ns') {
522 if ($this->namespaces->addAlias($value, $ns_key) === null) {
523 return false;
524 }
525 } else if (($ns_alias == Auth_OpenID_NULL_NAMESPACE) &&
526 ($ns_key == 'ns')) {
527 // null namespace
528 if ($this->setOpenIDNamespace($value, false) === false) {
529 return false;
530 }
531 } else {
532 $ns_args[] = array($ns_alias, $ns_key, $value);
533 }
534 }
535
536 if (!$this->getOpenIDNamespace()) {
537 if ($this->setOpenIDNamespace(Auth_OpenID_OPENID1_NS, true) ===
538 false) {
539 return false;
540 }
541 }
542
543 // Actually put the pairs into the appropriate namespaces
544 foreach ($ns_args as $triple) {
545 list($ns_alias, $ns_key, $value) = $triple;
546 $ns_uri = $this->namespaces->getNamespaceURI($ns_alias);
547 if ($ns_uri === null) {
548 $ns_uri = $this->_getDefaultNamespace($ns_alias);
549 if ($ns_uri === null) {
550
551 $ns_uri = Auth_OpenID_OPENID_NS;
552 $ns_key = sprintf('%s.%s', $ns_alias, $ns_key);
553 } else {
554 $this->namespaces->addAlias($ns_uri, $ns_alias, true);
555 }
556 }
557
558 $this->setArg($ns_uri, $ns_key, $value);
559 }
560
561 return true;
562 }
563
564 function _getDefaultNamespace($mystery_alias)
565 {
566 global $Auth_OpenID_registered_aliases;
567 if ($this->isOpenID1()) {
568 return @$Auth_OpenID_registered_aliases[$mystery_alias];
569 }
570 return null;
571 }
572
573 function setOpenIDNamespace($openid_ns_uri, $implicit)
574 {
575 if (!in_array($openid_ns_uri, $this->allowed_openid_namespaces)) {
576 Auth_OpenID::log('Invalid null namespace: "%s"', $openid_ns_uri);
577 return false;
578 }
579
580 $succeeded = $this->namespaces->addAlias($openid_ns_uri,
581 Auth_OpenID_NULL_NAMESPACE,
582 $implicit);
583 if ($succeeded === false) {
584 return false;
585 }
586
587 $this->_openid_ns_uri = $openid_ns_uri;
588
589 return true;
590 }
591
592 function getOpenIDNamespace()
593 {
594 return $this->_openid_ns_uri;
595 }
596
597 static function fromKVForm($kvform_string)
598 {
599 // Create a Message from a KVForm string
600 return Auth_OpenID_Message::fromOpenIDArgs(
601 Auth_OpenID_KVForm::toArray($kvform_string));
602 }
603
604 function copy()
605 {
606 return $this;
607 }
608
609 function toPostArgs()
610 {
611 // Return all arguments with openid. in front of namespaced
612 // arguments.
613
614 $args = array();
615
616 // Add namespace definitions to the output
617 foreach ($this->namespaces->iteritems() as $pair) {
618 list($ns_uri, $alias) = $pair;
619 if ($this->namespaces->isImplicit($ns_uri)) {
620 continue;
621 }
622 if ($alias == Auth_OpenID_NULL_NAMESPACE) {
623 $ns_key = 'openid.ns';
624 } else {
625 $ns_key = 'openid.ns.' . $alias;
626 }
627 $args[$ns_key] = $ns_uri;
628 }
629
630 foreach ($this->args->items() as $pair) {
631 list($ns_parts, $value) = $pair;
632 list($ns_uri, $ns_key) = $ns_parts;
633 $key = $this->getKey($ns_uri, $ns_key);
634 $args[$key] = $value;
635 }
636
637 return $args;
638 }
639
640 function toArgs()
641 {
642 // Return all namespaced arguments, failing if any
643 // non-namespaced arguments exist.
644 $post_args = $this->toPostArgs();
645 $kvargs = array();
646 foreach ($post_args as $k => $v) {
647 if (strpos($k, 'openid.') !== 0) {
648 // raise ValueError(
649 // 'This message can only be encoded as a POST, because it '
650 // 'contains arguments that are not prefixed with "openid."')
651 return null;
652 } else {
653 $kvargs[substr($k, 7)] = $v;
654 }
655 }
656
657 return $kvargs;
658 }
659
660 function toFormMarkup($action_url, $form_tag_attrs = null,
661 $submit_text = "Continue")
662 {
663 $form = "<form accept-charset=\"UTF-8\" ".
664 "enctype=\"application/x-www-form-urlencoded\"";
665
666 if (!$form_tag_attrs) {
667 $form_tag_attrs = array();
668 }
669
670 $form_tag_attrs['action'] = $action_url;
671 $form_tag_attrs['method'] = 'post';
672
673 unset($form_tag_attrs['enctype']);
674 unset($form_tag_attrs['accept-charset']);
675
676 if ($form_tag_attrs) {
677 foreach ($form_tag_attrs as $name => $attr) {
678 $form .= sprintf(" %s=\"%s\"", $name, htmlspecialchars($attr));
679 }
680 }
681
682 $form .= ">\n";
683
684 foreach ($this->toPostArgs() as $name => $value) {
685 $form .= sprintf(
686 "<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
687 htmlspecialchars($name), htmlspecialchars($value));
688 }
689
690 $form .= sprintf("<input type=\"submit\" value=\"%s\" />\n",
691 htmlspecialchars($submit_text));
692
693 $form .= "</form>\n";
694
695 return $form;
696 }
697
698 function toURL($base_url)
699 {
700 // Generate a GET URL with the parameters in this message
701 // attached as query parameters.
702 return Auth_OpenID::appendArgs($base_url, $this->toPostArgs());
703 }
704
705 function toKVForm()
706 {
707 // Generate a KVForm string that contains the parameters in
708 // this message. This will fail if the message contains
709 // arguments outside of the 'openid.' prefix.
710 return Auth_OpenID_KVForm::fromArray($this->toArgs());
711 }
712
713 function toURLEncoded()
714 {
715 // Generate an x-www-urlencoded string
716 $args = array();
717
718 foreach ($this->toPostArgs() as $k => $v) {
719 $args[] = array($k, $v);
720 }
721
722 sort($args);
723 return Auth_OpenID::httpBuildQuery($args);
724 }
725
726 /**
727 * @access private
728 */
729 function _fixNS($namespace)
730 {
731 // Convert an input value into the internally used values of
732 // this object
733
734 if ($namespace == Auth_OpenID_OPENID_NS) {
735 if ($this->_openid_ns_uri === null) {
736 return new Auth_OpenID_FailureResponse(null,
737 'OpenID namespace not set');
738 } else {
739 $namespace = $this->_openid_ns_uri;
740 }
741 }
742
743 if (($namespace != Auth_OpenID_BARE_NS) &&
744 (!is_string($namespace))) {
745 //TypeError
746 $err_msg = sprintf("Namespace must be Auth_OpenID_BARE_NS, ".
747 "Auth_OpenID_OPENID_NS or a string. got %s",
748 print_r($namespace, true));
749 return new Auth_OpenID_FailureResponse(null, $err_msg);
750 }
751
752 if (($namespace != Auth_OpenID_BARE_NS) &&
753 (strpos($namespace, ':') === false)) {
754 // fmt = 'OpenID 2.0 namespace identifiers SHOULD be URIs. Got %r'
755 // warnings.warn(fmt % (namespace,), DeprecationWarning)
756
757 if ($namespace == 'sreg') {
758 // fmt = 'Using %r instead of "sreg" as namespace'
759 // warnings.warn(fmt % (SREG_URI,), DeprecationWarning,)
760 return Auth_OpenID_SREG_URI;
761 }
762 }
763
764 return $namespace;
765 }
766
767 function hasKey($namespace, $ns_key)
768 {
769 $namespace = $this->_fixNS($namespace);
770 if (Auth_OpenID::isFailure($namespace)) {
771 // XXX log me
772 return false;
773 } else {
774 return $this->args->contains(array($namespace, $ns_key));
775 }
776 }
777
778 function getKey($namespace, $ns_key)
779 {
780 // Get the key for a particular namespaced argument
781 $namespace = $this->_fixNS($namespace);
782 if (Auth_OpenID::isFailure($namespace)) {
783 return $namespace;
784 }
785 if ($namespace == Auth_OpenID_BARE_NS) {
786 return $ns_key;
787 }
788
789 $ns_alias = $this->namespaces->getAlias($namespace);
790
791 // No alias is defined, so no key can exist
792 if ($ns_alias === null) {
793 return null;
794 }
795
796 if ($ns_alias == Auth_OpenID_NULL_NAMESPACE) {
797 $tail = $ns_key;
798 } else {
799 $tail = sprintf('%s.%s', $ns_alias, $ns_key);
800 }
801
802 return 'openid.' . $tail;
803 }
804
805 function getArg($namespace, $key, $default = null)
806 {
807 // Get a value for a namespaced key.
808 $namespace = $this->_fixNS($namespace);
809
810 if (Auth_OpenID::isFailure($namespace)) {
811 return $namespace;
812 } else {
813 if ((!$this->args->contains(array($namespace, $key))) &&
814 ($default == Auth_OpenID_NO_DEFAULT)) {
815 $err_msg = sprintf("Namespace %s missing required field %s",
816 $namespace, $key);
817 return new Auth_OpenID_FailureResponse(null, $err_msg);
818 } else {
819 return $this->args->get(array($namespace, $key), $default);
820 }
821 }
822 }
823
824 function getArgs($namespace)
825 {
826 // Get the arguments that are defined for this namespace URI
827
828 $namespace = $this->_fixNS($namespace);
829 if (Auth_OpenID::isFailure($namespace)) {
830 return $namespace;
831 } else {
832 $stuff = array();
833 foreach ($this->args->items() as $pair) {
834 list($key, $value) = $pair;
835 list($pair_ns, $ns_key) = $key;
836 if ($pair_ns == $namespace) {
837 $stuff[$ns_key] = $value;
838 }
839 }
840
841 return $stuff;
842 }
843 }
844
845 function updateArgs($namespace, $updates)
846 {
847 // Set multiple key/value pairs in one call
848
849 $namespace = $this->_fixNS($namespace);
850
851 if (Auth_OpenID::isFailure($namespace)) {
852 return $namespace;
853 } else {
854 foreach ($updates as $k => $v) {
855 $this->setArg($namespace, $k, $v);
856 }
857 return true;
858 }
859 }
860
861 function setArg($namespace, $key, $value)
862 {
863 // Set a single argument in this namespace
864 $namespace = $this->_fixNS($namespace);
865
866 if (Auth_OpenID::isFailure($namespace)) {
867 return $namespace;
868 } else {
869 $this->args->set(array($namespace, $key), $value);
870 if ($namespace !== Auth_OpenID_BARE_NS) {
871 $this->namespaces->add($namespace);
872 }
873 return true;
874 }
875 }
876
877 function delArg($namespace, $key)
878 {
879 $namespace = $this->_fixNS($namespace);
880
881 if (Auth_OpenID::isFailure($namespace)) {
882 return $namespace;
883 } else {
884 return $this->args->del(array($namespace, $key));
885 }
886 }
887
888 function getAliasedArg($aliased_key, $default = null)
889 {
890 if ($aliased_key == 'ns') {
891 // Return the namespace URI for the OpenID namespace
892 return $this->getOpenIDNamespace();
893 }
894
895 $parts = explode('.', $aliased_key, 2);
896
897 if (count($parts) != 2) {
898 $ns = null;
899 } else {
900 list($alias, $key) = $parts;
901
902 if ($alias == 'ns') {
903 // Return the namespace URI for a namespace alias
904 // parameter.
905 return $this->namespaces->getNamespaceURI($key);
906 } else {
907 $ns = $this->namespaces->getNamespaceURI($alias);
908 }
909 }
910
911 if ($ns === null) {
912 $key = $aliased_key;
913 $ns = $this->getOpenIDNamespace();
914 }
915
916 return $this->getArg($ns, $key, $default);
917 }
918 }
919
920