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/ParseHTML.php

Documentation is available at ParseHTML.php

  1. <?php
  2.  
  3. /**
  4.  * This is the HTML pseudo-parser for the Yadis library.
  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.  * This class is responsible for scanning an HTML string to find META
  18.  * tags and their attributes.  This is used by the Yadis discovery
  19.  * process.  This class must be instantiated to be used.
  20.  *
  21.  * @package Yadis
  22.  */
  23.  
  24.     /**
  25.      * @access private
  26.      */
  27.     var $_re_flags "si";
  28.  
  29.     /**
  30.      * @access private
  31.      */
  32.     var $_tag_expr "<%s\b(?!:)([^>]*?)(?:\/>|>(.*?)(?:<\/?%s\s*>|\Z))";
  33.  
  34.     /**
  35.      * @access private
  36.      */
  37.     var $_close_tag_expr "<\/?%s\s*>";
  38.  
  39.     /**
  40.      * @access private
  41.      */
  42.     var $_removed_re =
  43.            "<!--.*?-->|<!\[CDATA\[.*?\]\]>|<script\b(?!:)[^>]*>.*?<\/script>";
  44.  
  45.     /**
  46.      * @access private
  47.      */
  48.     var $_attr_find '\b([-\w]+)=("[^"]*"|\'[^\']*\'|[^\'"\s\/<>]+)';
  49.  
  50.     function Services_Yadis_ParseHTML()
  51.     {
  52.         $this->_meta_find sprintf("/<meta\b(?!:)([^>]*)(?!<)>/%s",
  53.                                     $this->_re_flags);
  54.  
  55.         $this->_removed_re sprintf("/%s/%s",
  56.                                      $this->_removed_re,
  57.                                      $this->_re_flags);
  58.  
  59.         $this->_attr_find sprintf("/%s/%s",
  60.                                     $this->_attr_find,
  61.                                     $this->_re_flags);
  62.  
  63.         $this->_entity_replacements array(
  64.                                             'amp' => '&',
  65.                                             'lt' => '<',
  66.                                             'gt' => '>',
  67.                                             'quot' => '"'
  68.                                             );
  69.  
  70.         $this->_ent_replace =
  71.             sprintf("&(%s);"implode("|",
  72.                                       $this->_entity_replacements));
  73.     }
  74.  
  75.     /**
  76.      * Replace HTML entities (amp, lt, gt, and quot) as well as
  77.      * numeric entities (e.g. #x9f;) with their actual values and
  78.      * return the new string.
  79.      *
  80.      * @access private
  81.      * @param string $str The string in which to look for entities
  82.      * @return string $new_str The new string entities decoded
  83.      */
  84.     function replaceEntities($str)
  85.     {
  86.         foreach ($this->_entity_replacements as $old => $new{
  87.             $str preg_replace(sprintf("/&%s;/"$old)$new$str);
  88.         }
  89.  
  90.         // Replace numeric entities because html_entity_decode doesn't
  91.         // do it for us.
  92.         $str preg_replace('~&#x([0-9a-f]+);~ei''chr(hexdec("\\1"))'$str);
  93.         $str preg_replace('~&#([0-9]+);~e''chr(\\1)'$str);
  94.  
  95.         return $str;
  96.     }
  97.  
  98.     /**
  99.      * Strip single and double quotes off of a string, if they are
  100.      * present.
  101.      *
  102.      * @access private
  103.      * @param string $str The original string
  104.      * @return string $new_str The new string with leading and
  105.      *  trailing quotes removed
  106.      */
  107.     function removeQuotes($str)
  108.     {
  109.         $matches array();
  110.         $double '/^"(.*)"$/';
  111.         $single "/^\'(.*)\'$/";
  112.  
  113.         if (preg_match($double$str$matches)) {
  114.             return $matches[1];
  115.         else if (preg_match($single$str$matches)) {
  116.             return $matches[1];
  117.         else {
  118.             return $str;
  119.         }
  120.     }
  121.  
  122.     /**
  123.      * Create a regular expression that will match an opening (and
  124.      * optional) closing tag of a given name.
  125.      *
  126.      * @access private
  127.      * @param string $tag_name The tag name to match
  128.      * @param array $close_tags An array of tag names which also
  129.      *  constitute closing of the original tag
  130.      * @return string $regex A regular expression string to be used
  131.      *  in, say, preg_match.
  132.      */
  133.     function tagMatcher($tag_name$close_tags null)
  134.     {
  135.         if ($close_tags{
  136.             $options implode("|"array_merge(array($tag_name)$close_tags));
  137.             $closer sprintf("(?:%s)"$options);
  138.         else {
  139.             $closer $tag_name;
  140.         }
  141.  
  142.         $expr sprintf($this->_tag_expr$tag_name$closer);
  143.         return sprintf("/%s/%s"$expr$this->_re_flags);
  144.     }
  145.  
  146.     /**
  147.      * @access private
  148.      */
  149.     function htmlFind($str)
  150.     {
  151.         return $this->tagMatcher('html'array('body'));
  152.     }
  153.  
  154.     /**
  155.      * @access private
  156.      */
  157.     function headFind()
  158.     {
  159.         return $this->tagMatcher('head'array('body'));
  160.     }
  161.  
  162.     /**
  163.      * Given an HTML document string, this finds all the META tags in
  164.      * the document, provided they are found in the
  165.      * <HTML><HEAD>...</HEAD> section of the document.  The <HTML> tag
  166.      * may be missing.
  167.      *
  168.      * @access private
  169.      * @param string $html_string An HTMl document string
  170.      * @return array $tag_list Array of tags; each tag is an array of
  171.      *  attribute -> value.
  172.      */
  173.     function getMetaTags($html_string)
  174.     {
  175.         $stripped preg_replace($this->_removed_re,
  176.                                  "",
  177.                                  $html_string);
  178.  
  179.         // Look for the closing body tag.
  180.         $body_closer sprintf($this->_close_tag_expr'body');
  181.         $body_matches array();
  182.         preg_match($body_closer$html_string$body_matches,
  183.                    PREG_OFFSET_CAPTURE);
  184.         if ($body_matches{
  185.             $html_string substr($html_string0$body_matches[0][1]);
  186.         }
  187.  
  188.         // Look for the opening body tag, and discard everything after
  189.         // that tag.
  190.         $body_re $this->tagMatcher('body');
  191.         $body_matches array();
  192.         preg_match($body_re$html_string$body_matchesPREG_OFFSET_CAPTURE);
  193.         if ($body_matches{
  194.             $html_string substr($html_string0$body_matches[0][1]);
  195.         }
  196.  
  197.         // If an HTML tag is found at all, it must be in the right
  198.         // order; else, it may be missing (which is a case we allow
  199.         // for).
  200.         $html_re $this->tagMatcher('html'array('body'));
  201.         preg_match($html_re$html_string$html_matches);
  202.         if ($html_matches{
  203.             $html $html_matches[0];
  204.         else {
  205.             $html $html_string;
  206.         }
  207.  
  208.         // Try to find the <HEAD> tag.
  209.         $head_re $this->headFind();
  210.         $head_matches array();
  211.         if (!preg_match($head_re$html$head_matches)) {
  212.             return array();
  213.         }
  214.  
  215.         $link_data array();
  216.         $link_matches array();
  217.  
  218.         if (!preg_match_all($this->_meta_find$head_matches[0],
  219.                             $link_matches)) {
  220.             return array();
  221.         }
  222.  
  223.         foreach ($link_matches[0as $link{
  224.             $attr_matches array();
  225.             preg_match_all($this->_attr_find$link$attr_matches);
  226.             $link_attrs array();
  227.             foreach ($attr_matches[0as $index => $full_match{
  228.                 $name $attr_matches[1][$index];
  229.                 $value $this->replaceEntities(
  230.                               $this->removeQuotes($attr_matches[2][$index]));
  231.  
  232.                 $link_attrs[strtolower($name)$value;
  233.             }
  234.             $link_data[$link_attrs;
  235.         }
  236.  
  237.         return $link_data;
  238.     }
  239.  
  240.     /**
  241.      * Looks for a META tag with an "http-equiv" attribute whose value
  242.      * is one of ("x-xrds-location", "x-yadis-location"), ignoring
  243.      * case.  If such a META tag is found, its "content" attribute
  244.      * value is returned.
  245.      *
  246.      * @param string $html_string An HTML document in string format
  247.      * @return mixed $content The "content" attribute value of the
  248.      *  META tag, if found, or null if no such tag was found.
  249.      */
  250.     function getHTTPEquiv($html_string)
  251.     {
  252.         $meta_tags $this->getMetaTags($html_string);
  253.  
  254.         if ($meta_tags{
  255.             foreach ($meta_tags as $tag{
  256.                 if (array_key_exists('http-equiv'$tag&&
  257.                     (in_array(strtolower($tag['http-equiv']),
  258.                               array('x-xrds-location''x-yadis-location'))) &&
  259.                     array_key_exists('content'$tag)) {
  260.                     return $tag['content'];
  261.                 }
  262.             }
  263.         }
  264.  
  265.         return null;
  266.     }
  267. }
  268.  
  269. ?>

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