00001 <?php
00002
00019 require_once 'Auth/Yadis/XML.php';
00020
00025 define('SERVICES_YADIS_MATCH_ALL', 101);
00026
00031 define('SERVICES_YADIS_MATCH_ANY', 102);
00032
00037 define('SERVICES_YADIS_MAX_PRIORITY', pow(2, 30));
00038
00042 define('Auth_Yadis_XMLNS_XRD_2_0', 'xri://$xrd*($v*2.0)');
00043
00047 define('Auth_Yadis_XMLNS_XRDS', 'xri://$xrds');
00048
00049 function Auth_Yadis_getNSMap()
00050 {
00051 return array('xrds' => Auth_Yadis_XMLNS_XRDS,
00052 'xrd' => Auth_Yadis_XMLNS_XRD_2_0);
00053 }
00054
00058 function Auth_Yadis_array_scramble($arr)
00059 {
00060 $result = array();
00061
00062 while (count($arr)) {
00063 $index = array_rand($arr, 1);
00064 $result[] = $arr[$index];
00065 unset($arr[$index]);
00066 }
00067
00068 return $result;
00069 }
00070
00083 class Auth_Yadis_Service {
00084
00088 function Auth_Yadis_Service()
00089 {
00090 $this->element = null;
00091 $this->parser = null;
00092 }
00093
00100 function getTypes()
00101 {
00102 $t = array();
00103 foreach ($this->getElements('xrd:Type') as $elem) {
00104 $c = $this->parser->content($elem);
00105 if ($c) {
00106 $t[] = $c;
00107 }
00108 }
00109 return $t;
00110 }
00111
00112 function matchTypes($type_uris)
00113 {
00114 $result = array();
00115
00116 foreach ($this->getTypes() as $typ) {
00117 if (in_array($typ, $type_uris)) {
00118 $result[] = $typ;
00119 }
00120 }
00121
00122 return $result;
00123 }
00124
00131 function getURIs()
00132 {
00133 $uris = array();
00134 $last = array();
00135
00136 foreach ($this->getElements('xrd:URI') as $elem) {
00137 $uri_string = $this->parser->content($elem);
00138 $attrs = $this->parser->attributes($elem);
00139 if ($attrs &&
00140 array_key_exists('priority', $attrs)) {
00141 $priority = intval($attrs['priority']);
00142 if (!array_key_exists($priority, $uris)) {
00143 $uris[$priority] = array();
00144 }
00145
00146 $uris[$priority][] = $uri_string;
00147 } else {
00148 $last[] = $uri_string;
00149 }
00150 }
00151
00152 $keys = array_keys($uris);
00153 sort($keys);
00154
00155
00156 $result = array();
00157 foreach ($keys as $k) {
00158 $new_uris = Auth_Yadis_array_scramble($uris[$k]);
00159 $result = array_merge($result, $new_uris);
00160 }
00161
00162 $result = array_merge($result,
00163 Auth_Yadis_array_scramble($last));
00164
00165 return $result;
00166 }
00167
00175 function getPriority()
00176 {
00177 $attributes = $this->parser->attributes($this->element);
00178
00179 if (array_key_exists('priority', $attributes)) {
00180 return intval($attributes['priority']);
00181 }
00182
00183 return null;
00184 }
00185
00201 function getElements($name)
00202 {
00203 return $this->parser->evalXPath($name, $this->element);
00204 }
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214 function Auth_Yadis_getXRDExpiration($xrd_element, $default=null)
00215 {
00216 $expires_element = $xrd_element->$parser->evalXPath('/xrd:Expires');
00217 if ($expires_element === null) {
00218 return $default;
00219 } else {
00220 $expires_string = $expires_element->text;
00221
00222
00223
00224 $t = strptime($expires_string, "%Y-%m-%dT%H:%M:%SZ");
00225
00226 if ($t === false) {
00227 return false;
00228 }
00229
00230
00231
00232 return mktime($t['tm_hour'], $t['tm_min'], $t['tm_sec'],
00233 $t['tm_mon'], $t['tm_day'], $t['tm_year']);
00234 }
00235 }
00236
00252 class Auth_Yadis_XRDS {
00253
00258 function Auth_Yadis_XRDS(&$xmlParser, &$xrdNodes)
00259 {
00260 $this->parser =& $xmlParser;
00261 $this->xrdNode = $xrdNodes[count($xrdNodes) - 1];
00262 $this->allXrdNodes =& $xrdNodes;
00263 $this->serviceList = array();
00264 $this->_parse();
00265 }
00266
00276 function &parseXRDS($xml_string, $extra_ns_map = null)
00277 {
00278 $_null = null;
00279
00280 if (!$xml_string) {
00281 return $_null;
00282 }
00283
00284 $parser = Auth_Yadis_getXMLParser();
00285
00286 $ns_map = Auth_Yadis_getNSMap();
00287
00288 if ($extra_ns_map && is_array($extra_ns_map)) {
00289 $ns_map = array_merge($ns_map, $extra_ns_map);
00290 }
00291
00292 if (!($parser && $parser->init($xml_string, $ns_map))) {
00293 return $_null;
00294 }
00295
00296
00297 $root = $parser->evalXPath('/xrds:XRDS[1]');
00298 if (!$root) {
00299 return $_null;
00300 }
00301
00302 if (is_array($root)) {
00303 $root = $root[0];
00304 }
00305
00306 $attrs = $parser->attributes($root);
00307
00308 if (array_key_exists('xmlns:xrd', $attrs) &&
00309 $attrs['xmlns:xrd'] != Auth_Yadis_XMLNS_XRDS) {
00310 return $_null;
00311 } else if (array_key_exists('xmlns', $attrs) &&
00312 preg_match('/xri/', $attrs['xmlns']) &&
00313 $attrs['xmlns'] != Auth_Yadis_XMLNS_XRD_2_0) {
00314 return $_null;
00315 }
00316
00317
00318 $xrd_nodes = $parser->evalXPath('/xrds:XRDS[1]/xrd:XRD');
00319
00320 if (!$xrd_nodes) {
00321 return $_null;
00322 }
00323
00324 $xrds = new Auth_Yadis_XRDS($parser, $xrd_nodes);
00325 return $xrds;
00326 }
00327
00331 function _addService($priority, $service)
00332 {
00333 $priority = intval($priority);
00334
00335 if (!array_key_exists($priority, $this->serviceList)) {
00336 $this->serviceList[$priority] = array();
00337 }
00338
00339 $this->serviceList[$priority][] = $service;
00340 }
00341
00348 function _parse()
00349 {
00350 $this->serviceList = array();
00351
00352 $services = $this->parser->evalXPath('xrd:Service', $this->xrdNode);
00353
00354 foreach ($services as $node) {
00355 $s =& new Auth_Yadis_Service();
00356 $s->element = $node;
00357 $s->parser =& $this->parser;
00358
00359 $priority = $s->getPriority();
00360
00361 if ($priority === null) {
00362 $priority = SERVICES_YADIS_MAX_PRIORITY;
00363 }
00364
00365 $this->_addService($priority, $s);
00366 }
00367 }
00368
00393 function services($filters = null,
00394 $filter_mode = SERVICES_YADIS_MATCH_ANY)
00395 {
00396
00397 $pri_keys = array_keys($this->serviceList);
00398 sort($pri_keys, SORT_NUMERIC);
00399
00400
00401
00402 if (!$filters ||
00403 (!is_array($filters))) {
00404
00405 $result = array();
00406 foreach ($pri_keys as $pri) {
00407 $result = array_merge($result, $this->serviceList[$pri]);
00408 }
00409
00410 return $result;
00411 }
00412
00413
00414 if (!in_array($filter_mode, array(SERVICES_YADIS_MATCH_ANY,
00415 SERVICES_YADIS_MATCH_ALL))) {
00416 return null;
00417 }
00418
00419
00420
00421 $filtered = array();
00422
00423 foreach ($pri_keys as $priority_value) {
00424 $service_obj_list = $this->serviceList[$priority_value];
00425
00426 foreach ($service_obj_list as $service) {
00427
00428 $matches = 0;
00429
00430 foreach ($filters as $filter) {
00431 if (call_user_func_array($filter, array($service))) {
00432 $matches++;
00433
00434 if ($filter_mode == SERVICES_YADIS_MATCH_ANY) {
00435 $pri = $service->getPriority();
00436 if ($pri === null) {
00437 $pri = SERVICES_YADIS_MAX_PRIORITY;
00438 }
00439
00440 if (!array_key_exists($pri, $filtered)) {
00441 $filtered[$pri] = array();
00442 }
00443
00444 $filtered[$pri][] = $service;
00445 break;
00446 }
00447 }
00448 }
00449
00450 if (($filter_mode == SERVICES_YADIS_MATCH_ALL) &&
00451 ($matches == count($filters))) {
00452
00453 $pri = $service->getPriority();
00454 if ($pri === null) {
00455 $pri = SERVICES_YADIS_MAX_PRIORITY;
00456 }
00457
00458 if (!array_key_exists($pri, $filtered)) {
00459 $filtered[$pri] = array();
00460 }
00461 $filtered[$pri][] = $service;
00462 }
00463 }
00464 }
00465
00466 $pri_keys = array_keys($filtered);
00467 sort($pri_keys, SORT_NUMERIC);
00468
00469 $result = array();
00470 foreach ($pri_keys as $pri) {
00471 $result = array_merge($result, $filtered[$pri]);
00472 }
00473
00474 return $result;
00475 }
00476 }
00477
00478 ?>