Support Joomla!

Joomla! 1.5 Documentation

Packages

Package: Yadis

Developer Network License

The Joomla! Developer Network content is © copyright 2006 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution- NonCommercial- ShareAlike 2.5
Source code for file /openid/Services/Yadis/XRDS.php

Documentation is available at XRDS.php

  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 Yadis
  11.  * @author JanRain, Inc. <[email protected]>
  12.  * @copyright 2005 Janrain, Inc.
  13.  * @license http://www.gnu.org/copyleft/lesser.html LGPL
  14.  */
  15.  
  16. /**
  17.  * Require the XPath implementation.
  18.  */
  19. require_once 'Services/Yadis/XML.php';
  20.  
  21. /**
  22.  * This match mode means a given service must match ALL filters passed
  23.  * to the Services_Yadis_XRDS::services() call.
  24.  */
  25. define('SERVICES_YADIS_MATCH_ALL'101);
  26.  
  27. /**
  28.  * This match mode means a given service must match ANY filters (at
  29.  * least one) passed to the Services_Yadis_XRDS::services() call.
  30.  */
  31. define('SERVICES_YADIS_MATCH_ANY'102);
  32.  
  33. global $_Services_Yadis_ns_map;
  34. $_Services_Yadis_ns_map array('xrds' => 'xri://$xrds',
  35.                                 'xrd' => 'xri://$xrd*($v*2.0)');
  36.  
  37. define('SERVICES_YADIS_MAX_PRIORITY'pow(230));
  38.  
  39. /**
  40.  * @access private
  41.  */
  42. function Services_Yadis_array_scramble($arr)
  43. {
  44.     $result array();
  45.  
  46.     while (count($arr)) {
  47.         $index array_rand($arr1);
  48.         $result[$arr[$index];
  49.         unset($arr[$index]);
  50.     }
  51.  
  52.     return $result;
  53. }
  54.  
  55. /**
  56.  * This class represents a <Service> element in an XRDS document.
  57.  * Objects of this type are returned by
  58.  * Services_Yadis_XRDS::services() and
  59.  * Services_Yadis_Yadis::services().  Each object corresponds directly
  60.  * to a <Service> element in the XRDS and supplies a
  61.  * getElements($name) method which you should use to inspect the
  62.  * element's contents.  See {@link Services_Yadis_Yadis} for more
  63.  * information on the role this class plays in Yadis discovery.
  64.  *
  65.  * @package Yadis
  66.  */
  67.  
  68.     /**
  69.      * Creates an empty service object.
  70.      */
  71.     function Services_Yadis_Service()
  72.     {
  73.         $this->element null;
  74.         $this->parser null;
  75.     }
  76.  
  77.     /**
  78.      * Return the URIs in the "Type" elements, if any, of this Service
  79.      * element.
  80.      *
  81.      * @return array $type_uris An array of Type URI strings.
  82.      */
  83.     function getTypes()
  84.     {
  85.         $t array();
  86.         foreach ($this->getElements('xrd:Type'as $elem{
  87.             $c $this->parser->content($elem);
  88.             if ($c{
  89.                 $t[$c;
  90.             }
  91.         }
  92.         return $t;
  93.     }
  94.  
  95.     /**
  96.      * Return the URIs in the "URI" elements, if any, of this Service
  97.      * element.  The URIs are returned sorted in priority order.
  98.      *
  99.      * @return array $uris An array of URI strings.
  100.      */
  101.     function getURIs()
  102.     {
  103.         $uris array();
  104.         $last array();
  105.  
  106.         foreach ($this->getElements('xrd:URI'as $elem{
  107.             $uri_string $this->parser->content($elem);
  108.             $attrs $this->parser->attributes($elem);
  109.             if ($attrs &&
  110.                 array_key_exists('priority'$attrs)) {
  111.                 $priority intval($attrs['priority']);
  112.                 if (!array_key_exists($priority$uris)) {
  113.                     $uris[$priorityarray();
  114.                 }
  115.  
  116.                 $uris[$priority][$uri_string;
  117.             else {
  118.                 $last[$uri_string;
  119.             }
  120.         }
  121.  
  122.         $keys array_keys($uris);
  123.         sort($keys);
  124.  
  125.         // Rebuild array of URIs.
  126.         $result array();
  127.         foreach ($keys as $k{
  128.             $new_uris Services_Yadis_array_scramble($uris[$k]);
  129.             $result array_merge($result$new_uris);
  130.         }
  131.  
  132.         $result array_merge($result,
  133.                               Services_Yadis_array_scramble($last));
  134.  
  135.         return $result;
  136.     }
  137.  
  138.     /**
  139.      * Returns the "priority" attribute value of this <Service>
  140.      * element, if the attribute is present.  Returns null if not.
  141.      *
  142.      * @return mixed $result Null or integer, depending on whether
  143.      *  this Service element has a 'priority' attribute.
  144.      */
  145.     function getPriority()
  146.     {
  147.         $attributes $this->parser->attributes($this->element);
  148.  
  149.         if (array_key_exists('priority'$attributes)) {
  150.             return intval($attributes['priority']);
  151.         }
  152.  
  153.         return null;
  154.     }
  155.  
  156.     /**
  157.      * Used to get XML elements from this object's <Service> element.
  158.      *
  159.      * This is what you should use to get all custom information out
  160.      * of this element. This is used by service filter functions to
  161.      * determine whether a service element contains specific tags,
  162.      * etc.  NOTE: this only considers elements which are direct
  163.      * children of the <Service> element for this object.
  164.      *
  165.      * @param string $name The name of the element to look for
  166.      * @return array $list An array of elements with the specified
  167.      *  name which are direct children of the <Service> element.  The
  168.      *  nodes returned by this function can be passed to $this->parser
  169.      *  methods (see {@link Services_Yadis_XMLParser}).
  170.      */
  171.     function getElements($name)
  172.     {
  173.         return $this->parser->evalXPath($name$this->element);
  174.     }
  175. }
  176.  
  177. /**
  178.  * This class performs parsing of XRDS documents.
  179.  *
  180.  * You should not instantiate this class directly; rather, call
  181.  * parseXRDS statically:
  182.  *
  183.  * <pre>  $xrds = Services_Yadis_XRDS::parseXRDS($xml_string);</pre>
  184.  *
  185.  * If the XRDS can be parsed and is valid, an instance of
  186.  * Services_Yadis_XRDS will be returned.  Otherwise, null will be
  187.  * returned.  This class is used by the Services_Yadis_Yadis::discover
  188.  * method.
  189.  *
  190.  * @package Yadis
  191.  */
  192.  
  193.     /**
  194.      * Instantiate a Services_Yadis_XRDS object.  Requires an XPath
  195.      * instance which has been used to parse a valid XRDS document.
  196.      */
  197.     function Services_Yadis_XRDS(&$xmlParser&$xrdNodes)
  198.     {
  199.         $this->parser =$xmlParser;
  200.         $this->xrdNode $xrdNodes[count($xrdNodes1];
  201.         $this->allXrdNodes =$xrdNodes;
  202.         $this->serviceList array();
  203.         $this->_parse();
  204.     }
  205.  
  206.     /**
  207.      * Parse an XML string (XRDS document) and return either a
  208.      * Services_Yadis_XRDS object or null, depending on whether the
  209.      * XRDS XML is valid.
  210.      *
  211.      * @param string $xml_string An XRDS XML string.
  212.      * @return mixed $xrds An instance of Services_Yadis_XRDS or null,
  213.      *  depending on the validity of $xml_string
  214.      */
  215.     function parseXRDS($xml_string$extra_ns_map null)
  216.     {
  217.         global $_Services_Yadis_ns_map;
  218.  
  219.         if (!$xml_string{
  220.             return null;
  221.         }
  222.  
  223.         $parser Services_Yadis_getXMLParser();
  224.  
  225.         $ns_map $_Services_Yadis_ns_map;
  226.  
  227.         if ($extra_ns_map && is_array($extra_ns_map)) {
  228.             $ns_map array_merge($ns_map$extra_ns_map);
  229.         }
  230.  
  231.         if (!($parser && $parser->init($xml_string$ns_map))) {
  232.             return null;
  233.         }
  234.  
  235.         // Try to get root element.
  236.         $root $parser->evalXPath('/xrds:XRDS[1]');
  237.         if (!$root{
  238.             return null;
  239.         }
  240.  
  241.         if (is_array($root)) {
  242.             $root $root[0];
  243.         }
  244.  
  245.         $attrs $parser->attributes($root);
  246.  
  247.         if (array_key_exists('xmlns:xrd'$attrs&&
  248.             $attrs['xmlns:xrd'!= 'xri://$xrd*($v*2.0)'{
  249.             return null;
  250.         else if (array_key_exists('xmlns'$attrs&&
  251.                    preg_match('/xri/'$attrs['xmlns']&&
  252.                    $attrs['xmlns'!= 'xri://$xrd*($v*2.0)'{
  253.             return null;
  254.         }
  255.  
  256.         // Get the last XRD node.
  257.         $xrd_nodes $parser->evalXPath('/xrds:XRDS[1]/xrd:XRD');
  258.  
  259.         if (!$xrd_nodes{
  260.             return null;
  261.         }
  262.  
  263.         $xrds new Services_Yadis_XRDS($parser$xrd_nodes);
  264.         return $xrds;
  265.     }
  266.  
  267.     /**
  268.      * @access private
  269.      */
  270.     function _addService($priority$service)
  271.     {
  272.         $priority intval($priority);
  273.  
  274.         if (!array_key_exists($priority$this->serviceList)) {
  275.             $this->serviceList[$priorityarray();
  276.         }
  277.  
  278.         $this->serviceList[$priority][$service;
  279.     }
  280.  
  281.     /**
  282.      * Creates the service list using nodes from the XRDS XML
  283.      * document.
  284.      *
  285.      * @access private
  286.      */
  287.     function _parse()
  288.     {
  289.         $this->serviceList array();
  290.  
  291.         $services $this->parser->evalXPath('xrd:Service'$this->xrdNode);
  292.  
  293.         foreach ($services as $node{
  294.             $s =new Services_Yadis_Service();
  295.             $s->element $node;
  296.             $s->parser =$this->parser;
  297.  
  298.             $priority $s->getPriority();
  299.  
  300.             if ($priority === null{
  301.                 $priority SERVICES_YADIS_MAX_PRIORITY;
  302.             }
  303.  
  304.             $this->_addService($priority$s);
  305.         }
  306.     }
  307.  
  308.     /**
  309.      * Returns a list of service objects which correspond to <Service>
  310.      * elements in the XRDS XML document for this object.
  311.      *
  312.      * Optionally, an array of filter callbacks may be given to limit
  313.      * the list of returned service objects.  Furthermore, the default
  314.      * mode is to return all service objects which match ANY of the
  315.      * specified filters, but $filter_mode may be
  316.      * SERVICES_YADIS_MATCH_ALL if you want to be sure that the
  317.      * returned services match all the given filters.  See {@link }
  318.      * Services_Yadis_Yadis} for detailed usage information on filter
  319.      * functions.
  320.      *
  321.      * @param mixed $filters An array of callbacks to filter the
  322.      *  returned services, or null if all services are to be returned.
  323.      * @param integer $filter_mode SERVICES_YADIS_MATCH_ALL or
  324.      *  SERVICES_YADIS_MATCH_ANY, depending on whether the returned
  325.      *  services should match ALL or ANY of the specified filters,
  326.      *  respectively.
  327.      * @return mixed $services An array of {@link }
  328.      *  Services_Yadis_Service} objects if $filter_mode is a valid
  329.      *  mode; null if $filter_mode is an invalid mode (i.e., not
  330.      *  SERVICES_YADIS_MATCH_ANY or SERVICES_YADIS_MATCH_ALL).
  331.      */
  332.     function services($filters null,
  333.                       $filter_mode SERVICES_YADIS_MATCH_ANY)
  334.     {
  335.  
  336.         $pri_keys array_keys($this->serviceList);
  337.         sort($pri_keysSORT_NUMERIC);
  338.  
  339.         // If no filters are specified, return the entire service
  340.         // list, ordered by priority.
  341.         if (!$filters ||
  342.             (!is_array($filters))) {
  343.  
  344.             $result array();
  345.             foreach ($pri_keys as $pri{
  346.                 $result array_merge($result$this->serviceList[$pri]);
  347.             }
  348.  
  349.             return $result;
  350.         }
  351.  
  352.         // If a bad filter mode is specified, return null.
  353.         if (!in_array($filter_modearray(SERVICES_YADIS_MATCH_ANY,
  354.                                           SERVICES_YADIS_MATCH_ALL))) {
  355.             return null;
  356.         }
  357.  
  358.         // Otherwise, use the callbacks in the filter list to
  359.         // determine which services are returned.
  360.         $filtered array();
  361.  
  362.         foreach ($pri_keys as $priority_value{
  363.             $service_obj_list $this->serviceList[$priority_value];
  364.  
  365.             foreach ($service_obj_list as $service{
  366.  
  367.                 $matches 0;
  368.  
  369.                 foreach ($filters as $filter{
  370.                     if (call_user_func_array($filterarray($service))) {
  371.                         $matches++;
  372.  
  373.                         if ($filter_mode == SERVICES_YADIS_MATCH_ANY{
  374.                             $pri $service->getPriority();
  375.                             if ($pri === null{
  376.                                 $pri SERVICES_YADIS_MAX_PRIORITY;
  377.                             }
  378.  
  379.                             if (!array_key_exists($pri$filtered)) {
  380.                                 $filtered[$priarray();
  381.                             }
  382.  
  383.                             $filtered[$pri][$service;
  384.                             break;
  385.                         }
  386.                     }
  387.                 }
  388.  
  389.                 if (($filter_mode == SERVICES_YADIS_MATCH_ALL&&
  390.                     ($matches == count($filters))) {
  391.  
  392.                     $pri $service->getPriority();
  393.                     if ($pri === null{
  394.                         $pri SERVICES_YADIS_MAX_PRIORITY;
  395.                     }
  396.  
  397.                     if (!array_key_exists($pri$filtered)) {
  398.                         $filtered[$priarray();
  399.                     }
  400.                     $filtered[$pri][$service;
  401.                 }
  402.             }
  403.         }
  404.  
  405.         $pri_keys array_keys($filtered);
  406.         sort($pri_keysSORT_NUMERIC);
  407.  
  408.         $result array();
  409.         foreach ($pri_keys as $pri{
  410.             $result array_merge($result$filtered[$pri]);
  411.         }
  412.  
  413.         return $result;
  414.     }
  415. }
  416.  
  417. ?>

Documentation generated on Mon, 05 Mar 2007 21:33:05 +0000 by phpDocumentor 1.3.1