|
TYPO3 API
SVNRelease
|
00001 <?php 00002 00003 /** 00004 * Implements the OpenID attribute exchange specification, version 1.0 00005 * as of svn revision 370 from openid.net svn. 00006 * 00007 * @package OpenID 00008 */ 00009 00010 /** 00011 * Require utility classes and functions for the consumer. 00012 */ 00013 require_once "Auth/OpenID/Extension.php"; 00014 require_once "Auth/OpenID/Message.php"; 00015 require_once "Auth/OpenID/TrustRoot.php"; 00016 00017 define('Auth_OpenID_AX_NS_URI', 00018 'http://openid.net/srv/ax/1.0'); 00019 00020 // Use this as the 'count' value for an attribute in a FetchRequest to 00021 // ask for as many values as the OP can provide. 00022 define('Auth_OpenID_AX_UNLIMITED_VALUES', 'unlimited'); 00023 00024 // Minimum supported alias length in characters. Here for 00025 // completeness. 00026 define('Auth_OpenID_AX_MINIMUM_SUPPORTED_ALIAS_LENGTH', 32); 00027 00028 /** 00029 * AX utility class. 00030 * 00031 * @package OpenID 00032 */ 00033 class Auth_OpenID_AX { 00034 /** 00035 * @param mixed $thing Any object which may be an 00036 * Auth_OpenID_AX_Error object. 00037 * 00038 * @return bool true if $thing is an Auth_OpenID_AX_Error; false 00039 * if not. 00040 */ 00041 function isError($thing) 00042 { 00043 return is_a($thing, 'Auth_OpenID_AX_Error'); 00044 } 00045 } 00046 00047 /** 00048 * Check an alias for invalid characters; raise AXError if any are 00049 * found. Return None if the alias is valid. 00050 */ 00051 function Auth_OpenID_AX_checkAlias($alias) 00052 { 00053 if (strpos($alias, ',') !== false) { 00054 return new Auth_OpenID_AX_Error(sprintf( 00055 "Alias %s must not contain comma", $alias)); 00056 } 00057 if (strpos($alias, '.') !== false) { 00058 return new Auth_OpenID_AX_Error(sprintf( 00059 "Alias %s must not contain period", $alias)); 00060 } 00061 00062 return true; 00063 } 00064 00065 /** 00066 * Results from data that does not meet the attribute exchange 1.0 00067 * specification 00068 * 00069 * @package OpenID 00070 */ 00071 class Auth_OpenID_AX_Error { 00072 function Auth_OpenID_AX_Error($message=null) 00073 { 00074 $this->message = $message; 00075 } 00076 } 00077 00078 /** 00079 * Abstract class containing common code for attribute exchange 00080 * messages. 00081 * 00082 * @package OpenID 00083 */ 00084 class Auth_OpenID_AX_Message extends Auth_OpenID_Extension { 00085 /** 00086 * ns_alias: The preferred namespace alias for attribute exchange 00087 * messages 00088 */ 00089 var $ns_alias = 'ax'; 00090 00091 /** 00092 * mode: The type of this attribute exchange message. This must be 00093 * overridden in subclasses. 00094 */ 00095 var $mode = null; 00096 00097 var $ns_uri = Auth_OpenID_AX_NS_URI; 00098 00099 /** 00100 * Return Auth_OpenID_AX_Error if the mode in the attribute 00101 * exchange arguments does not match what is expected for this 00102 * class; true otherwise. 00103 * 00104 * @access private 00105 */ 00106 function _checkMode($ax_args) 00107 { 00108 $mode = Auth_OpenID::arrayGet($ax_args, 'mode'); 00109 if ($mode != $this->mode) { 00110 return new Auth_OpenID_AX_Error( 00111 sprintf( 00112 "Expected mode '%s'; got '%s'", 00113 $this->mode, $mode)); 00114 } 00115 00116 return true; 00117 } 00118 00119 /** 00120 * Return a set of attribute exchange arguments containing the 00121 * basic information that must be in every attribute exchange 00122 * message. 00123 * 00124 * @access private 00125 */ 00126 function _newArgs() 00127 { 00128 return array('mode' => $this->mode); 00129 } 00130 } 00131 00132 /** 00133 * Represents a single attribute in an attribute exchange 00134 * request. This should be added to an AXRequest object in order to 00135 * request the attribute. 00136 * 00137 * @package OpenID 00138 */ 00139 class Auth_OpenID_AX_AttrInfo { 00140 /** 00141 * Construct an attribute information object. Do not call this 00142 * directly; call make(...) instead. 00143 * 00144 * @param string $type_uri The type URI for this attribute. 00145 * 00146 * @param int $count The number of values of this type to request. 00147 * 00148 * @param bool $required Whether the attribute will be marked as 00149 * required in the request. 00150 * 00151 * @param string $alias The name that should be given to this 00152 * attribute in the request. 00153 */ 00154 function Auth_OpenID_AX_AttrInfo($type_uri, $count, $required, 00155 $alias) 00156 { 00157 /** 00158 * required: Whether the attribute will be marked as required 00159 * when presented to the subject of the attribute exchange 00160 * request. 00161 */ 00162 $this->required = $required; 00163 00164 /** 00165 * count: How many values of this type to request from the 00166 * subject. Defaults to one. 00167 */ 00168 $this->count = $count; 00169 00170 /** 00171 * type_uri: The identifier that determines what the attribute 00172 * represents and how it is serialized. For example, one type 00173 * URI representing dates could represent a Unix timestamp in 00174 * base 10 and another could represent a human-readable 00175 * string. 00176 */ 00177 $this->type_uri = $type_uri; 00178 00179 /** 00180 * alias: The name that should be given to this attribute in 00181 * the request. If it is not supplied, a generic name will be 00182 * assigned. For example, if you want to call a Unix timestamp 00183 * value 'tstamp', set its alias to that value. If two 00184 * attributes in the same message request to use the same 00185 * alias, the request will fail to be generated. 00186 */ 00187 $this->alias = $alias; 00188 } 00189 00190 /** 00191 * Construct an attribute information object. For parameter 00192 * details, see the constructor. 00193 */ 00194 function make($type_uri, $count=1, $required=false, 00195 $alias=null) 00196 { 00197 if ($alias !== null) { 00198 $result = Auth_OpenID_AX_checkAlias($alias); 00199 00200 if (Auth_OpenID_AX::isError($result)) { 00201 return $result; 00202 } 00203 } 00204 00205 return new Auth_OpenID_AX_AttrInfo($type_uri, $count, $required, 00206 $alias); 00207 } 00208 00209 /** 00210 * When processing a request for this attribute, the OP should 00211 * call this method to determine whether all available attribute 00212 * values were requested. If self.count == UNLIMITED_VALUES, this 00213 * returns True. Otherwise this returns False, in which case 00214 * self.count is an integer. 00215 */ 00216 function wantsUnlimitedValues() 00217 { 00218 return $this->count === Auth_OpenID_AX_UNLIMITED_VALUES; 00219 } 00220 } 00221 00222 /** 00223 * Given a namespace mapping and a string containing a comma-separated 00224 * list of namespace aliases, return a list of type URIs that 00225 * correspond to those aliases. 00226 * 00227 * @param $namespace_map The mapping from namespace URI to alias 00228 * @param $alias_list_s The string containing the comma-separated 00229 * list of aliases. May also be None for convenience. 00230 * 00231 * @return $seq The list of namespace URIs that corresponds to the 00232 * supplied list of aliases. If the string was zero-length or None, an 00233 * empty list will be returned. 00234 * 00235 * return null If an alias is present in the list of aliases but 00236 * is not present in the namespace map. 00237 */ 00238 function Auth_OpenID_AX_toTypeURIs($namespace_map, $alias_list_s) 00239 { 00240 $uris = array(); 00241 00242 if ($alias_list_s) { 00243 foreach (explode(',', $alias_list_s) as $alias) { 00244 $type_uri = $namespace_map->getNamespaceURI($alias); 00245 if ($type_uri === null) { 00246 // raise KeyError( 00247 // 'No type is defined for attribute name %r' % (alias,)) 00248 return new Auth_OpenID_AX_Error( 00249 sprintf('No type is defined for attribute name %s', 00250 $alias) 00251 ); 00252 } else { 00253 $uris[] = $type_uri; 00254 } 00255 } 00256 } 00257 00258 return $uris; 00259 } 00260 00261 /** 00262 * An attribute exchange 'fetch_request' message. This message is sent 00263 * by a relying party when it wishes to obtain attributes about the 00264 * subject of an OpenID authentication request. 00265 * 00266 * @package OpenID 00267 */ 00268 class Auth_OpenID_AX_FetchRequest extends Auth_OpenID_AX_Message { 00269 00270 var $mode = 'fetch_request'; 00271 00272 function Auth_OpenID_AX_FetchRequest($update_url=null) 00273 { 00274 /** 00275 * requested_attributes: The attributes that have been 00276 * requested thus far, indexed by the type URI. 00277 */ 00278 $this->requested_attributes = array(); 00279 00280 /** 00281 * update_url: A URL that will accept responses for this 00282 * attribute exchange request, even in the absence of the user 00283 * who made this request. 00284 */ 00285 $this->update_url = $update_url; 00286 } 00287 00288 /** 00289 * Add an attribute to this attribute exchange request. 00290 * 00291 * @param attribute: The attribute that is being requested 00292 * @return true on success, false when the requested attribute is 00293 * already present in this fetch request. 00294 */ 00295 function add($attribute) 00296 { 00297 if ($this->contains($attribute->type_uri)) { 00298 return new Auth_OpenID_AX_Error( 00299 sprintf("The attribute %s has already been requested", 00300 $attribute->type_uri)); 00301 } 00302 00303 $this->requested_attributes[$attribute->type_uri] = $attribute; 00304 00305 return true; 00306 } 00307 00308 /** 00309 * Get the serialized form of this attribute fetch request. 00310 * 00311 * @returns Auth_OpenID_AX_FetchRequest The fetch request message parameters 00312 */ 00313 function getExtensionArgs() 00314 { 00315 $aliases = new Auth_OpenID_NamespaceMap(); 00316 00317 $required = array(); 00318 $if_available = array(); 00319 00320 $ax_args = $this->_newArgs(); 00321 00322 foreach ($this->requested_attributes as $type_uri => $attribute) { 00323 if ($attribute->alias === null) { 00324 $alias = $aliases->add($type_uri); 00325 } else { 00326 $alias = $aliases->addAlias($type_uri, $attribute->alias); 00327 00328 if ($alias === null) { 00329 return new Auth_OpenID_AX_Error( 00330 sprintf("Could not add alias %s for URI %s", 00331 $attribute->alias, $type_uri 00332 )); 00333 } 00334 } 00335 00336 if ($attribute->required) { 00337 $required[] = $alias; 00338 } else { 00339 $if_available[] = $alias; 00340 } 00341 00342 if ($attribute->count != 1) { 00343 $ax_args['count.' . $alias] = strval($attribute->count); 00344 } 00345 00346 $ax_args['type.' . $alias] = $type_uri; 00347 } 00348 00349 if ($required) { 00350 $ax_args['required'] = implode(',', $required); 00351 } 00352 00353 if ($if_available) { 00354 $ax_args['if_available'] = implode(',', $if_available); 00355 } 00356 00357 return $ax_args; 00358 } 00359 00360 /** 00361 * Get the type URIs for all attributes that have been marked as 00362 * required. 00363 * 00364 * @return A list of the type URIs for attributes that have been 00365 * marked as required. 00366 */ 00367 function getRequiredAttrs() 00368 { 00369 $required = array(); 00370 foreach ($this->requested_attributes as $type_uri => $attribute) { 00371 if ($attribute->required) { 00372 $required[] = $type_uri; 00373 } 00374 } 00375 00376 return $required; 00377 } 00378 00379 /** 00380 * Extract a FetchRequest from an OpenID message 00381 * 00382 * @param request: The OpenID request containing the attribute 00383 * fetch request 00384 * 00385 * @returns mixed An Auth_OpenID_AX_Error or the 00386 * Auth_OpenID_AX_FetchRequest extracted from the request message if 00387 * successful 00388 */ 00389 function &fromOpenIDRequest($request) 00390 { 00391 $m = $request->message; 00392 $obj = new Auth_OpenID_AX_FetchRequest(); 00393 $ax_args = $m->getArgs($obj->ns_uri); 00394 00395 $result = $obj->parseExtensionArgs($ax_args); 00396 00397 if (Auth_OpenID_AX::isError($result)) { 00398 return $result; 00399 } 00400 00401 if ($obj->update_url) { 00402 // Update URL must match the openid.realm of the 00403 // underlying OpenID 2 message. 00404 $realm = $m->getArg(Auth_OpenID_OPENID_NS, 'realm', 00405 $m->getArg( 00406 Auth_OpenID_OPENID_NS, 00407 'return_to')); 00408 00409 if (!$realm) { 00410 $obj = new Auth_OpenID_AX_Error( 00411 sprintf("Cannot validate update_url %s " . 00412 "against absent realm", $obj->update_url)); 00413 } else if (!Auth_OpenID_TrustRoot::match($realm, 00414 $obj->update_url)) { 00415 $obj = new Auth_OpenID_AX_Error( 00416 sprintf("Update URL %s failed validation against realm %s", 00417 $obj->update_url, $realm)); 00418 } 00419 } 00420 00421 return $obj; 00422 } 00423 00424 /** 00425 * Given attribute exchange arguments, populate this FetchRequest. 00426 * 00427 * @return $result Auth_OpenID_AX_Error if the data to be parsed 00428 * does not follow the attribute exchange specification. At least 00429 * when 'if_available' or 'required' is not specified for a 00430 * particular attribute type. Returns true otherwise. 00431 */ 00432 function parseExtensionArgs($ax_args) 00433 { 00434 $result = $this->_checkMode($ax_args); 00435 if (Auth_OpenID_AX::isError($result)) { 00436 return $result; 00437 } 00438 00439 $aliases = new Auth_OpenID_NamespaceMap(); 00440 00441 foreach ($ax_args as $key => $value) { 00442 if (strpos($key, 'type.') === 0) { 00443 $alias = substr($key, 5); 00444 $type_uri = $value; 00445 00446 $alias = $aliases->addAlias($type_uri, $alias); 00447 00448 if ($alias === null) { 00449 return new Auth_OpenID_AX_Error( 00450 sprintf("Could not add alias %s for URI %s", 00451 $alias, $type_uri) 00452 ); 00453 } 00454 00455 $count_s = Auth_OpenID::arrayGet($ax_args, 'count.' . $alias); 00456 if ($count_s) { 00457 $count = Auth_OpenID::intval($count_s); 00458 if (($count === false) && 00459 ($count_s === Auth_OpenID_AX_UNLIMITED_VALUES)) { 00460 $count = $count_s; 00461 } 00462 } else { 00463 $count = 1; 00464 } 00465 00466 if ($count === false) { 00467 return new Auth_OpenID_AX_Error( 00468 sprintf("Integer value expected for %s, got %s", 00469 'count.' . $alias, $count_s)); 00470 } 00471 00472 $attrinfo = Auth_OpenID_AX_AttrInfo::make($type_uri, $count, 00473 false, $alias); 00474 00475 if (Auth_OpenID_AX::isError($attrinfo)) { 00476 return $attrinfo; 00477 } 00478 00479 $this->add($attrinfo); 00480 } 00481 } 00482 00483 $required = Auth_OpenID_AX_toTypeURIs($aliases, 00484 Auth_OpenID::arrayGet($ax_args, 'required')); 00485 00486 foreach ($required as $type_uri) { 00487 $attrib =& $this->requested_attributes[$type_uri]; 00488 $attrib->required = true; 00489 } 00490 00491 $if_available = Auth_OpenID_AX_toTypeURIs($aliases, 00492 Auth_OpenID::arrayGet($ax_args, 'if_available')); 00493 00494 $all_type_uris = array_merge($required, $if_available); 00495 00496 foreach ($aliases->iterNamespaceURIs() as $type_uri) { 00497 if (!in_array($type_uri, $all_type_uris)) { 00498 return new Auth_OpenID_AX_Error( 00499 sprintf('Type URI %s was in the request but not ' . 00500 'present in "required" or "if_available"', 00501 $type_uri)); 00502 00503 } 00504 } 00505 00506 $this->update_url = Auth_OpenID::arrayGet($ax_args, 'update_url'); 00507 00508 return true; 00509 } 00510 00511 /** 00512 * Iterate over the AttrInfo objects that are contained in this 00513 * fetch_request. 00514 */ 00515 function iterAttrs() 00516 { 00517 return array_values($this->requested_attributes); 00518 } 00519 00520 function iterTypes() 00521 { 00522 return array_keys($this->requested_attributes); 00523 } 00524 00525 /** 00526 * Is the given type URI present in this fetch_request? 00527 */ 00528 function contains($type_uri) 00529 { 00530 return in_array($type_uri, $this->iterTypes()); 00531 } 00532 } 00533 00534 /** 00535 * An abstract class that implements a message that has attribute keys 00536 * and values. It contains the common code between fetch_response and 00537 * store_request. 00538 * 00539 * @package OpenID 00540 */ 00541 class Auth_OpenID_AX_KeyValueMessage extends Auth_OpenID_AX_Message { 00542 00543 function Auth_OpenID_AX_KeyValueMessage() 00544 { 00545 $this->data = array(); 00546 } 00547 00548 /** 00549 * Add a single value for the given attribute type to the 00550 * message. If there are already values specified for this type, 00551 * this value will be sent in addition to the values already 00552 * specified. 00553 * 00554 * @param type_uri: The URI for the attribute 00555 * @param value: The value to add to the response to the relying 00556 * party for this attribute 00557 * @return null 00558 */ 00559 function addValue($type_uri, $value) 00560 { 00561 if (!array_key_exists($type_uri, $this->data)) { 00562 $this->data[$type_uri] = array(); 00563 } 00564 00565 $values =& $this->data[$type_uri]; 00566 $values[] = $value; 00567 } 00568 00569 /** 00570 * Set the values for the given attribute type. This replaces any 00571 * values that have already been set for this attribute. 00572 * 00573 * @param type_uri: The URI for the attribute 00574 * @param values: A list of values to send for this attribute. 00575 */ 00576 function setValues($type_uri, $values) 00577 { 00578 $this->data[$type_uri] =& $values; 00579 } 00580 00581 /** 00582 * Get the extension arguments for the key/value pairs contained 00583 * in this message. 00584 * 00585 * @param aliases: An alias mapping. Set to None if you don't care 00586 * about the aliases for this request. 00587 * 00588 * @access private 00589 */ 00590 function _getExtensionKVArgs($aliases) 00591 { 00592 if ($aliases === null) { 00593 $aliases = new Auth_OpenID_NamespaceMap(); 00594 } 00595 00596 $ax_args = array(); 00597 00598 foreach ($this->data as $type_uri => $values) { 00599 $alias = $aliases->add($type_uri); 00600 00601 $ax_args['type.' . $alias] = $type_uri; 00602 $ax_args['count.' . $alias] = strval(count($values)); 00603 00604 foreach ($values as $i => $value) { 00605 $key = sprintf('value.%s.%d', $alias, $i + 1); 00606 $ax_args[$key] = $value; 00607 } 00608 } 00609 00610 return $ax_args; 00611 } 00612 00613 /** 00614 * Parse attribute exchange key/value arguments into this object. 00615 * 00616 * @param ax_args: The attribute exchange fetch_response 00617 * arguments, with namespacing removed. 00618 * 00619 * @return Auth_OpenID_AX_Error or true 00620 */ 00621 function parseExtensionArgs($ax_args) 00622 { 00623 $result = $this->_checkMode($ax_args); 00624 if (Auth_OpenID_AX::isError($result)) { 00625 return $result; 00626 } 00627 00628 $aliases = new Auth_OpenID_NamespaceMap(); 00629 00630 foreach ($ax_args as $key => $value) { 00631 if (strpos($key, 'type.') === 0) { 00632 $type_uri = $value; 00633 $alias = substr($key, 5); 00634 00635 $result = Auth_OpenID_AX_checkAlias($alias); 00636 00637 if (Auth_OpenID_AX::isError($result)) { 00638 return $result; 00639 } 00640 00641 $alias = $aliases->addAlias($type_uri, $alias); 00642 00643 if ($alias === null) { 00644 return new Auth_OpenID_AX_Error( 00645 sprintf("Could not add alias %s for URI %s", 00646 $alias, $type_uri) 00647 ); 00648 } 00649 } 00650 } 00651 00652 foreach ($aliases->iteritems() as $pair) { 00653 list($type_uri, $alias) = $pair; 00654 00655 if (array_key_exists('count.' . $alias, $ax_args)) { 00656 00657 $count_key = 'count.' . $alias; 00658 $count_s = $ax_args[$count_key]; 00659 00660 $count = Auth_OpenID::intval($count_s); 00661 00662 if ($count === false) { 00663 return new Auth_OpenID_AX_Error( 00664 sprintf("Integer value expected for %s, got %s", 00665 'count. %s' . $alias, $count_s, 00666 Auth_OpenID_AX_UNLIMITED_VALUES) 00667 ); 00668 } 00669 00670 $values = array(); 00671 for ($i = 1; $i < $count + 1; $i++) { 00672 $value_key = sprintf('value.%s.%d', $alias, $i); 00673 00674 if (!array_key_exists($value_key, $ax_args)) { 00675 return new Auth_OpenID_AX_Error( 00676 sprintf( 00677 "No value found for key %s", 00678 $value_key)); 00679 } 00680 00681 $value = $ax_args[$value_key]; 00682 $values[] = $value; 00683 } 00684 } else { 00685 $key = 'value.' . $alias; 00686 00687 if (!array_key_exists($key, $ax_args)) { 00688 return new Auth_OpenID_AX_Error( 00689 sprintf( 00690 "No value found for key %s", 00691 $key)); 00692 } 00693 00694 $value = $ax_args['value.' . $alias]; 00695 00696 if ($value == '') { 00697 $values = array(); 00698 } else { 00699 $values = array($value); 00700 } 00701 } 00702 00703 $this->data[$type_uri] = $values; 00704 } 00705 00706 return true; 00707 } 00708 00709 /** 00710 * Get a single value for an attribute. If no value was sent for 00711 * this attribute, use the supplied default. If there is more than 00712 * one value for this attribute, this method will fail. 00713 * 00714 * @param type_uri: The URI for the attribute 00715 * @param default: The value to return if the attribute was not 00716 * sent in the fetch_response. 00717 * 00718 * @return $value Auth_OpenID_AX_Error on failure or the value of 00719 * the attribute in the fetch_response message, or the default 00720 * supplied 00721 */ 00722 function getSingle($type_uri, $default=null) 00723 { 00724 $values = Auth_OpenID::arrayGet($this->data, $type_uri); 00725 if (!$values) { 00726 return $default; 00727 } else if (count($values) == 1) { 00728 return $values[0]; 00729 } else { 00730 return new Auth_OpenID_AX_Error( 00731 sprintf('More than one value present for %s', 00732 $type_uri) 00733 ); 00734 } 00735 } 00736 00737 /** 00738 * Get the list of values for this attribute in the 00739 * fetch_response. 00740 * 00741 * XXX: what to do if the values are not present? default 00742 * parameter? this is funny because it's always supposed to return 00743 * a list, so the default may break that, though it's provided by 00744 * the user's code, so it might be okay. If no default is 00745 * supplied, should the return be None or []? 00746 * 00747 * @param type_uri: The URI of the attribute 00748 * 00749 * @return $values The list of values for this attribute in the 00750 * response. May be an empty list. If the attribute was not sent 00751 * in the response, returns Auth_OpenID_AX_Error. 00752 */ 00753 function get($type_uri) 00754 { 00755 if (array_key_exists($type_uri, $this->data)) { 00756 return $this->data[$type_uri]; 00757 } else { 00758 return new Auth_OpenID_AX_Error( 00759 sprintf("Type URI %s not found in response", 00760 $type_uri) 00761 ); 00762 } 00763 } 00764 00765 /** 00766 * Get the number of responses for a particular attribute in this 00767 * fetch_response message. 00768 * 00769 * @param type_uri: The URI of the attribute 00770 * 00771 * @returns int The number of values sent for this attribute. If 00772 * the attribute was not sent in the response, returns 00773 * Auth_OpenID_AX_Error. 00774 */ 00775 function count($type_uri) 00776 { 00777 if (array_key_exists($type_uri, $this->data)) { 00778 return count($this->get($type_uri)); 00779 } else { 00780 return new Auth_OpenID_AX_Error( 00781 sprintf("Type URI %s not found in response", 00782 $type_uri) 00783 ); 00784 } 00785 } 00786 } 00787 00788 /** 00789 * A fetch_response attribute exchange message. 00790 * 00791 * @package OpenID 00792 */ 00793 class Auth_OpenID_AX_FetchResponse extends Auth_OpenID_AX_KeyValueMessage { 00794 var $mode = 'fetch_response'; 00795 00796 function Auth_OpenID_AX_FetchResponse($update_url=null) 00797 { 00798 $this->Auth_OpenID_AX_KeyValueMessage(); 00799 $this->update_url = $update_url; 00800 } 00801 00802 /** 00803 * Serialize this object into arguments in the attribute exchange 00804 * namespace 00805 * 00806 * @return $args The dictionary of unqualified attribute exchange 00807 * arguments that represent this fetch_response, or 00808 * Auth_OpenID_AX_Error on error. 00809 */ 00810 function getExtensionArgs($request=null) 00811 { 00812 $aliases = new Auth_OpenID_NamespaceMap(); 00813 00814 $zero_value_types = array(); 00815 00816 if ($request !== null) { 00817 // Validate the data in the context of the request (the 00818 // same attributes should be present in each, and the 00819 // counts in the response must be no more than the counts 00820 // in the request) 00821 00822 foreach ($this->data as $type_uri => $unused) { 00823 if (!$request->contains($type_uri)) { 00824 return new Auth_OpenID_AX_Error( 00825 sprintf("Response attribute not present in request: %s", 00826 $type_uri) 00827 ); 00828 } 00829 } 00830 00831 foreach ($request->iterAttrs() as $attr_info) { 00832 // Copy the aliases from the request so that reading 00833 // the response in light of the request is easier 00834 if ($attr_info->alias === null) { 00835 $aliases->add($attr_info->type_uri); 00836 } else { 00837 $alias = $aliases->addAlias($attr_info->type_uri, 00838 $attr_info->alias); 00839 00840 if ($alias === null) { 00841 return new Auth_OpenID_AX_Error( 00842 sprintf("Could not add alias %s for URI %s", 00843 $attr_info->alias, $attr_info->type_uri) 00844 ); 00845 } 00846 } 00847 00848 if (array_key_exists($attr_info->type_uri, $this->data)) { 00849 $values = $this->data[$attr_info->type_uri]; 00850 } else { 00851 $values = array(); 00852 $zero_value_types[] = $attr_info; 00853 } 00854 00855 if (($attr_info->count != Auth_OpenID_AX_UNLIMITED_VALUES) && 00856 ($attr_info->count < count($values))) { 00857 return new Auth_OpenID_AX_Error( 00858 sprintf("More than the number of requested values " . 00859 "were specified for %s", 00860 $attr_info->type_uri) 00861 ); 00862 } 00863 } 00864 } 00865 00866 $kv_args = $this->_getExtensionKVArgs($aliases); 00867 00868 // Add the KV args into the response with the args that are 00869 // unique to the fetch_response 00870 $ax_args = $this->_newArgs(); 00871 00872 // For each requested attribute, put its type/alias and count 00873 // into the response even if no data were returned. 00874 foreach ($zero_value_types as $attr_info) { 00875 $alias = $aliases->getAlias($attr_info->type_uri); 00876 $kv_args['type.' . $alias] = $attr_info->type_uri; 00877 $kv_args['count.' . $alias] = '0'; 00878 } 00879 00880 $update_url = null; 00881 if ($request) { 00882 $update_url = $request->update_url; 00883 } else { 00884 $update_url = $this->update_url; 00885 } 00886 00887 if ($update_url) { 00888 $ax_args['update_url'] = $update_url; 00889 } 00890 00891 Auth_OpenID::update($ax_args, $kv_args); 00892 00893 return $ax_args; 00894 } 00895 00896 /** 00897 * @return $result Auth_OpenID_AX_Error on failure or true on 00898 * success. 00899 */ 00900 function parseExtensionArgs($ax_args) 00901 { 00902 $result = parent::parseExtensionArgs($ax_args); 00903 00904 if (Auth_OpenID_AX::isError($result)) { 00905 return $result; 00906 } 00907 00908 $this->update_url = Auth_OpenID::arrayGet($ax_args, 'update_url'); 00909 00910 return true; 00911 } 00912 00913 /** 00914 * Construct a FetchResponse object from an OpenID library 00915 * SuccessResponse object. 00916 * 00917 * @param success_response: A successful id_res response object 00918 * 00919 * @param signed: Whether non-signed args should be processsed. If 00920 * True (the default), only signed arguments will be processsed. 00921 * 00922 * @return $response A FetchResponse containing the data from the 00923 * OpenID message 00924 */ 00925 function fromSuccessResponse($success_response, $signed=true) 00926 { 00927 $obj = new Auth_OpenID_AX_FetchResponse(); 00928 if ($signed) { 00929 $ax_args = $success_response->getSignedNS($obj->ns_uri); 00930 } else { 00931 $ax_args = $success_response->message->getArgs($obj->ns_uri); 00932 } 00933 if ($ax_args === null || Auth_OpenID::isFailure($ax_args) || 00934 sizeof($ax_args) == 0) { 00935 return null; 00936 } 00937 00938 $result = $obj->parseExtensionArgs($ax_args); 00939 if (Auth_OpenID_AX::isError($result)) { 00940 #XXX log me 00941 return null; 00942 } 00943 return $obj; 00944 } 00945 } 00946 00947 /** 00948 * A store request attribute exchange message representation. 00949 * 00950 * @package OpenID 00951 */ 00952 class Auth_OpenID_AX_StoreRequest extends Auth_OpenID_AX_KeyValueMessage { 00953 var $mode = 'store_request'; 00954 00955 /** 00956 * @param array $aliases The namespace aliases to use when making 00957 * this store response. Leave as None to use defaults. 00958 */ 00959 function getExtensionArgs($aliases=null) 00960 { 00961 $ax_args = $this->_newArgs(); 00962 $kv_args = $this->_getExtensionKVArgs($aliases); 00963 Auth_OpenID::update($ax_args, $kv_args); 00964 return $ax_args; 00965 } 00966 } 00967 00968 /** 00969 * An indication that the store request was processed along with this 00970 * OpenID transaction. Use make(), NOT the constructor, to create 00971 * response objects. 00972 * 00973 * @package OpenID 00974 */ 00975 class Auth_OpenID_AX_StoreResponse extends Auth_OpenID_AX_Message { 00976 var $SUCCESS_MODE = 'store_response_success'; 00977 var $FAILURE_MODE = 'store_response_failure'; 00978 00979 /** 00980 * Returns Auth_OpenID_AX_Error on error or an 00981 * Auth_OpenID_AX_StoreResponse object on success. 00982 */ 00983 function &make($succeeded=true, $error_message=null) 00984 { 00985 if (($succeeded) && ($error_message !== null)) { 00986 return new Auth_OpenID_AX_Error('An error message may only be '. 00987 'included in a failing fetch response'); 00988 } 00989 00990 return new Auth_OpenID_AX_StoreResponse($succeeded, $error_message); 00991 } 00992 00993 function Auth_OpenID_AX_StoreResponse($succeeded=true, $error_message=null) 00994 { 00995 if ($succeeded) { 00996 $this->mode = $this->SUCCESS_MODE; 00997 } else { 00998 $this->mode = $this->FAILURE_MODE; 00999 } 01000 01001 $this->error_message = $error_message; 01002 } 01003 01004 /** 01005 * Was this response a success response? 01006 */ 01007 function succeeded() 01008 { 01009 return $this->mode == $this->SUCCESS_MODE; 01010 } 01011 01012 function getExtensionArgs() 01013 { 01014 $ax_args = $this->_newArgs(); 01015 if ((!$this->succeeded()) && $this->error_message) { 01016 $ax_args['error'] = $this->error_message; 01017 } 01018 01019 return $ax_args; 01020 } 01021 } 01022 01023 ?>
1.8.0