?
Path : /home/admin/domains/happytokorea.com/public_html_bk/test3/libraries/openid/Auth/OpenID/ |
Current File : /home/admin/domains/happytokorea.com/public_html_bk/test3/libraries/openid/Auth/OpenID/Parse.php |
<?php /** * This module implements a VERY limited parser that finds <link> tags * in the head of HTML or XHTML documents and parses out their * attributes according to the OpenID spec. It is a liberal parser, * but it requires these things from the data in order to work: * * - There must be an open <html> tag * * - There must be an open <head> tag inside of the <html> tag * * - Only <link>s that are found inside of the <head> tag are parsed * (this is by design) * * - The parser follows the OpenID specification in resolving the * attributes of the link tags. This means that the attributes DO * NOT get resolved as they would by an XML or HTML parser. In * particular, only certain entities get replaced, and href * attributes do not get resolved relative to a base URL. * * From http://openid.net/specs.bml: * * - The openid.server URL MUST be an absolute URL. OpenID consumers * MUST NOT attempt to resolve relative URLs. * * - The openid.server URL MUST NOT include entities other than &, * <, >, and ". * * The parser ignores SGML comments and <![CDATA[blocks]]>. Both kinds * of quoting are allowed for attributes. * * The parser deals with invalid markup in these ways: * * - Tag names are not case-sensitive * * - The <html> tag is accepted even when it is not at the top level * * - The <head> tag is accepted even when it is not a direct child of * the <html> tag, but a <html> tag must be an ancestor of the * <head> tag * * - <link> tags are accepted even when they are not direct children * of the <head> tag, but a <head> tag must be an ancestor of the * <link> tag * * - If there is no closing tag for an open <html> or <head> tag, the * remainder of the document is viewed as being inside of the * tag. If there is no closing tag for a <link> tag, the link tag is * treated as a short tag. Exceptions to this rule are that <html> * closes <html> and <body> or <head> closes <head> * * - Attributes of the <link> tag are not required to be quoted. * * - In the case of duplicated attribute names, the attribute coming * last in the tag will be the value returned. * * - Any text that does not parse as an attribute within a link tag * will be ignored. (e.g. <link pumpkin rel='openid.server' /> will * ignore pumpkin) * * - If there are more than one <html> or <head> tag, the parser only * looks inside of the first one. * * - The contents of <script> tags are ignored entirely, except * unclosed <script> tags. Unclosed <script> tags are ignored. * * - Any other invalid markup is ignored, including unclosed SGML * comments and unclosed <![CDATA[blocks. * * PHP versions 4 and 5 * * LICENSE: See the COPYING file included in this distribution. * * @access private * @package OpenID * @author JanRain, Inc. <openid@janrain.com> * @copyright 2005-2008 Janrain, Inc. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache */ // Do not allow direct access defined( '_JEXEC' ) or die( 'Restricted access' ); /** * Require Auth_OpenID::arrayGet(). */ require_once "Auth/OpenID.php"; class Auth_OpenID_Parse { /** * Specify some flags for use with regex matching. */ var $_re_flags = "si"; /** * Stuff to remove before we start looking for tags */ var $_removed_re = "<!--.*?-->|<!\[CDATA\[.*?\]\]>|<script\b(?!:)[^>]*>.*?<\/script>"; /** * Starts with the tag name at a word boundary, where the tag name * is not a namespace */ var $_tag_expr = "<%s\b(?!:)([^>]*?)(?:\/>|>(.*?)(?:<\/?%s\s*>|\Z))"; var $_attr_find = '\b(\w+)=("[^"]*"|\'[^\']*\'|[^\'"\s\/<>]+)'; var $_open_tag_expr = "<%s\b"; var $_close_tag_expr = "<((\/%s\b)|(%s[^>\/]*\/))>"; function Auth_OpenID_Parse() { $this->_link_find = sprintf("/<link\b(?!:)([^>]*)(?!<)>/%s", $this->_re_flags); $this->_entity_replacements = array( 'amp' => '&', 'lt' => '<', 'gt' => '>', 'quot' => '"' ); $this->_attr_find = sprintf("/%s/%s", $this->_attr_find, $this->_re_flags); $this->_removed_re = sprintf("/%s/%s", $this->_removed_re, $this->_re_flags); $this->_ent_replace = sprintf("&(%s);", implode("|", $this->_entity_replacements)); } /** * Returns a regular expression that will match a given tag in an * SGML string. */ function tagMatcher($tag_name, $close_tags = null) { $expr = $this->_tag_expr; if ($close_tags) { $options = implode("|", array_merge(array($tag_name), $close_tags)); $closer = sprintf("(?:%s)", $options); } else { $closer = $tag_name; } $expr = sprintf($expr, $tag_name, $closer); return sprintf("/%s/%s", $expr, $this->_re_flags); } function openTag($tag_name) { $expr = sprintf($this->_open_tag_expr, $tag_name); return sprintf("/%s/%s", $expr, $this->_re_flags); } function closeTag($tag_name) { $expr = sprintf($this->_close_tag_expr, $tag_name, $tag_name); return sprintf("/%s/%s", $expr, $this->_re_flags); } function htmlBegin($s) { $matches = array(); $result = preg_match($this->openTag('html'), $s, $matches, PREG_OFFSET_CAPTURE); if ($result === false || !$matches) { return false; } // Return the offset of the first match. return $matches[0][1]; } function htmlEnd($s) { $matches = array(); $result = preg_match($this->closeTag('html'), $s, $matches, PREG_OFFSET_CAPTURE); if ($result === false || !$matches) { return false; } // Return the offset of the first match. return $matches[count($matches) - 1][1]; } function headFind() { return $this->tagMatcher('head', array('body', 'html')); } function replaceEntities($str) { foreach ($this->_entity_replacements as $old => $new) { $str = preg_replace(sprintf("/&%s;/", $old), $new, $str); } return $str; } function removeQuotes($str) { $matches = array(); $double = '/^"(.*)"$/'; $single = "/^\'(.*)\'$/"; if (preg_match($double, $str, $matches)) { return $matches[1]; } else if (preg_match($single, $str, $matches)) { return $matches[1]; } else { return $str; } } /** * Find all link tags in a string representing a HTML document and * return a list of their attributes. * * @param string $html The text to parse * @return array $list An array of arrays of attributes, one for each * link tag */ function parseLinkAttrs($html) { $stripped = preg_replace($this->_removed_re, "", $html); $html_begin = $this->htmlBegin($stripped); $html_end = $this->htmlEnd($stripped); if ($html_begin === false) { return array(); } if ($html_end === false) { $html_end = strlen($stripped); } $stripped = substr($stripped, $html_begin, $html_end - $html_begin); // Try to find the <HEAD> tag. $head_re = $this->headFind(); $head_matches = array(); if (!preg_match($head_re, $stripped, $head_matches)) { return array(); } $link_data = array(); $link_matches = array(); if (!preg_match_all($this->_link_find, $head_matches[0], $link_matches)) { return array(); } foreach ($link_matches[0] as $link) { $attr_matches = array(); preg_match_all($this->_attr_find, $link, $attr_matches); $link_attrs = array(); foreach ($attr_matches[0] as $index => $full_match) { $name = $attr_matches[1][$index]; $value = $this->replaceEntities( $this->removeQuotes($attr_matches[2][$index])); $link_attrs[strtolower($name)] = $value; } $link_data[] = $link_attrs; } return $link_data; } function relMatches($rel_attr, $target_rel) { // Does this target_rel appear in the rel_str? // XXX: TESTME $rels = preg_split("/\s+/", trim($rel_attr)); foreach ($rels as $rel) { $rel = strtolower($rel); if ($rel == $target_rel) { return 1; } } return 0; } function linkHasRel($link_attrs, $target_rel) { // Does this link have target_rel as a relationship? // XXX: TESTME $rel_attr = Auth_OpeniD::arrayGet($link_attrs, 'rel', null); return ($rel_attr && $this->relMatches($rel_attr, $target_rel)); } function findLinksRel($link_attrs_list, $target_rel) { // Filter the list of link attributes on whether it has // target_rel as a relationship. // XXX: TESTME $result = array(); foreach ($link_attrs_list as $attr) { if ($this->linkHasRel($attr, $target_rel)) { $result[] = $attr; } } return $result; } function findFirstHref($link_attrs_list, $target_rel) { // Return the value of the href attribute for the first link // tag in the list that has target_rel as a relationship. // XXX: TESTME $matches = $this->findLinksRel($link_attrs_list, $target_rel); if (!$matches) { return null; } $first = $matches[0]; return Auth_OpenID::arrayGet($first, 'href', null); } } function Auth_OpenID_legacy_discover($html_text, $server_rel, $delegate_rel) { $p = new Auth_OpenID_Parse(); $link_attrs = $p->parseLinkAttrs($html_text); $server_url = $p->findFirstHref($link_attrs, $server_rel); if ($server_url === null) { return false; } else { $delegate_url = $p->findFirstHref($link_attrs, $delegate_rel); return array($delegate_url, $server_url); } } ?>