| [ Index ] |
PHP Cross Reference of Joomla 1.5.26 DE |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * This module contains the XRDS parsing code. 5 * 6 * PHP versions 4 and 5 7 * 8 * LICENSE: See the COPYING file included in this distribution. 9 * 10 * @package OpenID 11 * @author JanRain, Inc. <openid@janrain.com> 12 * @copyright 2005-2008 Janrain, Inc. 13 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache 14 */ 15 16 // Do not allow direct access 17 defined( '_JEXEC' ) or die( 'Restricted access' ); 18 19 /** 20 * Require the XPath implementation. 21 */ 22 require_once 'Auth/Yadis/XML.php'; 23 24 /** 25 * This match mode means a given service must match ALL filters passed 26 * to the Auth_Yadis_XRDS::services() call. 27 */ 28 define('SERVICES_YADIS_MATCH_ALL', 101); 29 30 /** 31 * This match mode means a given service must match ANY filters (at 32 * least one) passed to the Auth_Yadis_XRDS::services() call. 33 */ 34 define('SERVICES_YADIS_MATCH_ANY', 102); 35 36 /** 37 * The priority value used for service elements with no priority 38 * specified. 39 */ 40 define('SERVICES_YADIS_MAX_PRIORITY', pow(2, 30)); 41 42 /** 43 * XRD XML namespace 44 */ 45 define('Auth_Yadis_XMLNS_XRD_2_0', 'xri://$xrd*($v*2.0)'); 46 47 /** 48 * XRDS XML namespace 49 */ 50 define('Auth_Yadis_XMLNS_XRDS', 'xri://$xrds'); 51 52 function Auth_Yadis_getNSMap() 53 { 54 return array('xrds' => Auth_Yadis_XMLNS_XRDS, 55 'xrd' => Auth_Yadis_XMLNS_XRD_2_0); 56 } 57 58 /** 59 * @access private 60 */ 61 function Auth_Yadis_array_scramble($arr) 62 { 63 $result = array(); 64 65 while (count($arr)) { 66 $index = array_rand($arr, 1); 67 $result[] = $arr[$index]; 68 unset($arr[$index]); 69 } 70 71 return $result; 72 } 73 74 /** 75 * This class represents a <Service> element in an XRDS document. 76 * Objects of this type are returned by 77 * Auth_Yadis_XRDS::services() and 78 * Auth_Yadis_Yadis::services(). Each object corresponds directly 79 * to a <Service> element in the XRDS and supplies a 80 * getElements($name) method which you should use to inspect the 81 * element's contents. See {@link Auth_Yadis_Yadis} for more 82 * information on the role this class plays in Yadis discovery. 83 * 84 * @package OpenID 85 */ 86 class Auth_Yadis_Service { 87 88 /** 89 * Creates an empty service object. 90 */ 91 function Auth_Yadis_Service() 92 { 93 $this->element = null; 94 $this->parser = null; 95 } 96 97 /** 98 * Return the URIs in the "Type" elements, if any, of this Service 99 * element. 100 * 101 * @return array $type_uris An array of Type URI strings. 102 */ 103 function getTypes() 104 { 105 $t = array(); 106 foreach ($this->getElements('xrd:Type') as $elem) { 107 $c = $this->parser->content($elem); 108 if ($c) { 109 $t[] = $c; 110 } 111 } 112 return $t; 113 } 114 115 function matchTypes($type_uris) 116 { 117 $result = array(); 118 119 foreach ($this->getTypes() as $typ) { 120 if (in_array($typ, $type_uris)) { 121 $result[] = $typ; 122 } 123 } 124 125 return $result; 126 } 127 128 /** 129 * Return the URIs in the "URI" elements, if any, of this Service 130 * element. The URIs are returned sorted in priority order. 131 * 132 * @return array $uris An array of URI strings. 133 */ 134 function getURIs() 135 { 136 $uris = array(); 137 $last = array(); 138 139 foreach ($this->getElements('xrd:URI') as $elem) { 140 $uri_string = $this->parser->content($elem); 141 $attrs = $this->parser->attributes($elem); 142 if ($attrs && 143 array_key_exists('priority', $attrs)) { 144 $priority = intval($attrs['priority']); 145 if (!array_key_exists($priority, $uris)) { 146 $uris[$priority] = array(); 147 } 148 149 $uris[$priority][] = $uri_string; 150 } else { 151 $last[] = $uri_string; 152 } 153 } 154 155 $keys = array_keys($uris); 156 sort($keys); 157 158 // Rebuild array of URIs. 159 $result = array(); 160 foreach ($keys as $k) { 161 $new_uris = Auth_Yadis_array_scramble($uris[$k]); 162 $result = array_merge($result, $new_uris); 163 } 164 165 $result = array_merge($result, 166 Auth_Yadis_array_scramble($last)); 167 168 return $result; 169 } 170 171 /** 172 * Returns the "priority" attribute value of this <Service> 173 * element, if the attribute is present. Returns null if not. 174 * 175 * @return mixed $result Null or integer, depending on whether 176 * this Service element has a 'priority' attribute. 177 */ 178 function getPriority() 179 { 180 $attributes = $this->parser->attributes($this->element); 181 182 if (array_key_exists('priority', $attributes)) { 183 return intval($attributes['priority']); 184 } 185 186 return null; 187 } 188 189 /** 190 * Used to get XML elements from this object's <Service> element. 191 * 192 * This is what you should use to get all custom information out 193 * of this element. This is used by service filter functions to 194 * determine whether a service element contains specific tags, 195 * etc. NOTE: this only considers elements which are direct 196 * children of the <Service> element for this object. 197 * 198 * @param string $name The name of the element to look for 199 * @return array $list An array of elements with the specified 200 * name which are direct children of the <Service> element. The 201 * nodes returned by this function can be passed to $this->parser 202 * methods (see {@link Auth_Yadis_XMLParser}). 203 */ 204 function getElements($name) 205 { 206 return $this->parser->evalXPath($name, $this->element); 207 } 208 } 209 210 /* 211 * Return the expiration date of this XRD element, or None if no 212 * expiration was specified. 213 * 214 * @param $default The value to use as the expiration if no expiration 215 * was specified in the XRD. 216 */ 217 function Auth_Yadis_getXRDExpiration($xrd_element, $default=null) 218 { 219 $expires_element = $xrd_element->$parser->evalXPath('/xrd:Expires'); 220 if ($expires_element === null) { 221 return $default; 222 } else { 223 $expires_string = $expires_element->text; 224 225 // Will raise ValueError if the string is not the expected 226 // format 227 $t = strptime($expires_string, "%Y-%m-%dT%H:%M:%SZ"); 228 229 if ($t === false) { 230 return false; 231 } 232 233 // [int $hour [, int $minute [, int $second [, 234 // int $month [, int $day [, int $year ]]]]]] 235 return mktime($t['tm_hour'], $t['tm_min'], $t['tm_sec'], 236 $t['tm_mon'], $t['tm_day'], $t['tm_year']); 237 } 238 } 239 240 /** 241 * This class performs parsing of XRDS documents. 242 * 243 * You should not instantiate this class directly; rather, call 244 * parseXRDS statically: 245 * 246 * <pre> $xrds = Auth_Yadis_XRDS::parseXRDS($xml_string);</pre> 247 * 248 * If the XRDS can be parsed and is valid, an instance of 249 * Auth_Yadis_XRDS will be returned. Otherwise, null will be 250 * returned. This class is used by the Auth_Yadis_Yadis::discover 251 * method. 252 * 253 * @package OpenID 254 */ 255 class Auth_Yadis_XRDS { 256 257 /** 258 * Instantiate a Auth_Yadis_XRDS object. Requires an XPath 259 * instance which has been used to parse a valid XRDS document. 260 */ 261 function Auth_Yadis_XRDS(&$xmlParser, &$xrdNodes) 262 { 263 $this->parser =& $xmlParser; 264 $this->xrdNode = $xrdNodes[count($xrdNodes) - 1]; 265 $this->allXrdNodes =& $xrdNodes; 266 $this->serviceList = array(); 267 $this->_parse(); 268 } 269 270 /** 271 * Parse an XML string (XRDS document) and return either a 272 * Auth_Yadis_XRDS object or null, depending on whether the 273 * XRDS XML is valid. 274 * 275 * @param string $xml_string An XRDS XML string. 276 * @return mixed $xrds An instance of Auth_Yadis_XRDS or null, 277 * depending on the validity of $xml_string 278 */ 279 function &parseXRDS($xml_string, $extra_ns_map = null) 280 { 281 $_null = null; 282 283 if (!$xml_string) { 284 return $_null; 285 } 286 287 $parser = Auth_Yadis_getXMLParser(); 288 289 $ns_map = Auth_Yadis_getNSMap(); 290 291 if ($extra_ns_map && is_array($extra_ns_map)) { 292 $ns_map = array_merge($ns_map, $extra_ns_map); 293 } 294 295 if (!($parser && $parser->init($xml_string, $ns_map))) { 296 return $_null; 297 } 298 299 // Try to get root element. 300 $root = $parser->evalXPath('/xrds:XRDS[1]'); 301 if (!$root) { 302 return $_null; 303 } 304 305 if (is_array($root)) { 306 $root = $root[0]; 307 } 308 309 $attrs = $parser->attributes($root); 310 311 if (array_key_exists('xmlns:xrd', $attrs) && 312 $attrs['xmlns:xrd'] != Auth_Yadis_XMLNS_XRDS) { 313 return $_null; 314 } else if (array_key_exists('xmlns', $attrs) && 315 preg_match('/xri/', $attrs['xmlns']) && 316 $attrs['xmlns'] != Auth_Yadis_XMLNS_XRD_2_0) { 317 return $_null; 318 } 319 320 // Get the last XRD node. 321 $xrd_nodes = $parser->evalXPath('/xrds:XRDS[1]/xrd:XRD'); 322 323 if (!$xrd_nodes) { 324 return $_null; 325 } 326 327 $xrds = new Auth_Yadis_XRDS($parser, $xrd_nodes); 328 return $xrds; 329 } 330 331 /** 332 * @access private 333 */ 334 function _addService($priority, $service) 335 { 336 $priority = intval($priority); 337 338 if (!array_key_exists($priority, $this->serviceList)) { 339 $this->serviceList[$priority] = array(); 340 } 341 342 $this->serviceList[$priority][] = $service; 343 } 344 345 /** 346 * Creates the service list using nodes from the XRDS XML 347 * document. 348 * 349 * @access private 350 */ 351 function _parse() 352 { 353 $this->serviceList = array(); 354 355 $services = $this->parser->evalXPath('xrd:Service', $this->xrdNode); 356 357 foreach ($services as $node) { 358 $s =& new Auth_Yadis_Service(); 359 $s->element = $node; 360 $s->parser =& $this->parser; 361 362 $priority = $s->getPriority(); 363 364 if ($priority === null) { 365 $priority = SERVICES_YADIS_MAX_PRIORITY; 366 } 367 368 $this->_addService($priority, $s); 369 } 370 } 371 372 /** 373 * Returns a list of service objects which correspond to <Service> 374 * elements in the XRDS XML document for this object. 375 * 376 * Optionally, an array of filter callbacks may be given to limit 377 * the list of returned service objects. Furthermore, the default 378 * mode is to return all service objects which match ANY of the 379 * specified filters, but $filter_mode may be 380 * SERVICES_YADIS_MATCH_ALL if you want to be sure that the 381 * returned services match all the given filters. See {@link 382 * Auth_Yadis_Yadis} for detailed usage information on filter 383 * functions. 384 * 385 * @param mixed $filters An array of callbacks to filter the 386 * returned services, or null if all services are to be returned. 387 * @param integer $filter_mode SERVICES_YADIS_MATCH_ALL or 388 * SERVICES_YADIS_MATCH_ANY, depending on whether the returned 389 * services should match ALL or ANY of the specified filters, 390 * respectively. 391 * @return mixed $services An array of {@link 392 * Auth_Yadis_Service} objects if $filter_mode is a valid 393 * mode; null if $filter_mode is an invalid mode (i.e., not 394 * SERVICES_YADIS_MATCH_ANY or SERVICES_YADIS_MATCH_ALL). 395 */ 396 function services($filters = null, 397 $filter_mode = SERVICES_YADIS_MATCH_ANY) 398 { 399 400 $pri_keys = array_keys($this->serviceList); 401 sort($pri_keys, SORT_NUMERIC); 402 403 // If no filters are specified, return the entire service 404 // list, ordered by priority. 405 if (!$filters || 406 (!is_array($filters))) { 407 408 $result = array(); 409 foreach ($pri_keys as $pri) { 410 $result = array_merge($result, $this->serviceList[$pri]); 411 } 412 413 return $result; 414 } 415 416 // If a bad filter mode is specified, return null. 417 if (!in_array($filter_mode, array(SERVICES_YADIS_MATCH_ANY, 418 SERVICES_YADIS_MATCH_ALL))) { 419 return null; 420 } 421 422 // Otherwise, use the callbacks in the filter list to 423 // determine which services are returned. 424 $filtered = array(); 425 426 foreach ($pri_keys as $priority_value) { 427 $service_obj_list = $this->serviceList[$priority_value]; 428 429 foreach ($service_obj_list as $service) { 430 431 $matches = 0; 432 433 foreach ($filters as $filter) { 434 if (call_user_func_array($filter, array($service))) { 435 $matches++; 436 437 if ($filter_mode == SERVICES_YADIS_MATCH_ANY) { 438 $pri = $service->getPriority(); 439 if ($pri === null) { 440 $pri = SERVICES_YADIS_MAX_PRIORITY; 441 } 442 443 if (!array_key_exists($pri, $filtered)) { 444 $filtered[$pri] = array(); 445 } 446 447 $filtered[$pri][] = $service; 448 break; 449 } 450 } 451 } 452 453 if (($filter_mode == SERVICES_YADIS_MATCH_ALL) && 454 ($matches == count($filters))) { 455 456 $pri = $service->getPriority(); 457 if ($pri === null) { 458 $pri = SERVICES_YADIS_MAX_PRIORITY; 459 } 460 461 if (!array_key_exists($pri, $filtered)) { 462 $filtered[$pri] = array(); 463 } 464 $filtered[$pri][] = $service; 465 } 466 } 467 } 468 469 $pri_keys = array_keys($filtered); 470 sort($pri_keys, SORT_NUMERIC); 471 472 $result = array(); 473 foreach ($pri_keys as $pri) { 474 $result = array_merge($result, $filtered[$pri]); 475 } 476 477 return $result; 478 } 479 } 480 481 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Mar 28 15:54:07 2012 | Cross-referenced by PHPXref 0.7.1 |