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 */ 12require_once 'Auth/OpenID.php'; 13require_once 'Auth/OpenID/KVForm.php'; 14require_once 'Auth/Yadis/XML.php'; 15require_once 'Auth/OpenID/Consumer.php'; // For Auth_OpenID_FailureResponse 16 17// This doesn't REALLY belong here, but where is better? 18define('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 23define('Auth_OpenID_SREG_URI', 'http://openid.net/sreg/1.0'); 24 25// The OpenID 1.X namespace URI 26define('Auth_OpenID_OPENID1_NS', 'http://openid.net/signon/1.0'); 27define('Auth_OpenID_THE_OTHER_OPENID1_NS', 'http://openid.net/signon/1.1'); 28 29function 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 36define('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. 40define('Auth_OpenID_NULL_NAMESPACE', 'Null namespace'); 41 42// The null namespace, when it is an allowed OpenID namespace 43define('Auth_OpenID_OPENID_NS', 'OpenID namespace'); 44 45// The top-level namespace, excluding all pairs with keys that start 46// with "openid." 47define('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. 51define('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. 55define('Auth_OpenID_OPENID1_URL_LIMIT', 2047); 56 57// All OpenID protocol fields. Used to check namespace aliases. 58global $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. 68global $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 */ 78function 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 */ 105function 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 */ 125class 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 */ 276class 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 */ 415class 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, $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 $name, urldecode($value)); 688 } 689 690 $form .= sprintf("<input type=\"submit\" value=\"%s\" />\n", 691 $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 921