PageRenderTime 27ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/openid/Services/Yadis/Yadis.php

https://github.com/DanielTichy/i-krajvysocina.cz
PHP | 315 lines | 129 code | 29 blank | 157 comment | 20 complexity | 4a7419489ad941a10bc2661c0a8eae28 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1. <?php
  2. // Check to ensure this file is within the rest of the framework
  3. defined('JPATH_BASE') or die();
  4. /**
  5. * The core PHP Yadis implementation.
  6. *
  7. * PHP versions 4 and 5
  8. *
  9. * LICENSE: See the COPYING file included in this distribution.
  10. *
  11. * @package Yadis
  12. * @author JanRain, Inc. <openid@janrain.com>
  13. * @copyright 2005 Janrain, Inc.
  14. * @license http://www.gnu.org/copyleft/lesser.html LGPL
  15. */
  16. /**
  17. * Need both fetcher types so we can use the right one based on the
  18. * presence or absence of CURL.
  19. */
  20. require_once "Services/Yadis/PlainHTTPFetcher.php";
  21. require_once "Services/Yadis/ParanoidHTTPFetcher.php";
  22. /**
  23. * Need this for parsing HTML (looking for META tags).
  24. */
  25. require_once "Services/Yadis/ParseHTML.php";
  26. /**
  27. * Need this to parse the XRDS document during Yadis discovery.
  28. */
  29. require_once "Services/Yadis/XRDS.php";
  30. /**
  31. * This is the core of the PHP Yadis library. This is the only class
  32. * a user needs to use to perform Yadis discovery. This class
  33. * performs the discovery AND stores the result of the discovery.
  34. *
  35. * First, require this library into your program source:
  36. *
  37. * <pre> require_once "Services/Yadis/Yadis.php";</pre>
  38. *
  39. * To perform Yadis discovery, first call the "discover" method
  40. * statically with a URI parameter:
  41. *
  42. * <pre> $http_response = array();
  43. * $fetcher = Services_Yadis_Yadis::getHTTPFetcher();
  44. * $yadis_object = Services_Yadis_Yadis::discover($uri,
  45. * $http_response, $fetcher);</pre>
  46. *
  47. * If the discovery succeeds, $yadis_object will be an instance of
  48. * {@link Services_Yadis_Yadis}. If not, it will be null. The XRDS
  49. * document found during discovery should have service descriptions,
  50. * which can be accessed by calling
  51. *
  52. * <pre> $service_list = $yadis_object->services();</pre>
  53. *
  54. * which returns an array of objects which describe each service.
  55. * These objects are instances of Services_Yadis_Service. Each object
  56. * describes exactly one whole Service element, complete with all of
  57. * its Types and URIs (no expansion is performed). The common use
  58. * case for using the service objects returned by services() is to
  59. * write one or more filter functions and pass those to services():
  60. *
  61. * <pre> $service_list = $yadis_object->services(
  62. * array("filterByURI",
  63. * "filterByExtension"));</pre>
  64. *
  65. * The filter functions (whose names appear in the array passed to
  66. * services()) take the following form:
  67. *
  68. * <pre> function myFilter(&$service) {
  69. * // Query $service object here. Return true if the service
  70. * // matches your query; false if not.
  71. * }</pre>
  72. *
  73. * This is an example of a filter which uses a regular expression to
  74. * match the content of URI tags (note that the Services_Yadis_Service
  75. * class provides a getURIs() method which you should use instead of
  76. * this contrived example):
  77. *
  78. * <pre>
  79. * function URIMatcher(&$service) {
  80. * foreach ($service->getElements('xrd:URI') as $uri) {
  81. * if (preg_match("/some_pattern/",
  82. * $service->parser->content($uri))) {
  83. * return true;
  84. * }
  85. * }
  86. * return false;
  87. * }</pre>
  88. *
  89. * The filter functions you pass will be called for each service
  90. * object to determine which ones match the criteria your filters
  91. * specify. The default behavior is that if a given service object
  92. * matches ANY of the filters specified in the services() call, it
  93. * will be returned. You can specify that a given service object will
  94. * be returned ONLY if it matches ALL specified filters by changing
  95. * the match mode of services():
  96. *
  97. * <pre> $yadis_object->services(array("filter1", "filter2"),
  98. * SERVICES_YADIS_MATCH_ALL);</pre>
  99. *
  100. * See {@link SERVICES_YADIS_MATCH_ALL} and {@link
  101. * SERVICES_YADIS_MATCH_ANY}.
  102. *
  103. * Services described in an XRDS should have a library which you'll
  104. * probably be using. Those libraries are responsible for defining
  105. * filters that can be used with the "services()" call. If you need
  106. * to write your own filter, see the documentation for {@link
  107. * Services_Yadis_Service}.
  108. *
  109. * @package Yadis
  110. */
  111. class Services_Yadis_Yadis {
  112. /**
  113. * Returns an HTTP fetcher object. If the CURL extension is
  114. * present, an instance of {@link Services_Yadis_ParanoidHTTPFetcher}
  115. * is returned. If not, an instance of
  116. * {@link Services_Yadis_PlainHTTPFetcher} is returned.
  117. */
  118. function getHTTPFetcher($timeout = 20)
  119. {
  120. if (Services_Yadis_Yadis::curlPresent()) {
  121. $fetcher = new Services_Yadis_ParanoidHTTPFetcher($timeout);
  122. } else {
  123. $fetcher = new Services_Yadis_PlainHTTPFetcher($timeout);
  124. }
  125. return $fetcher;
  126. }
  127. function curlPresent()
  128. {
  129. return function_exists('curl_init');
  130. }
  131. /**
  132. * @access private
  133. */
  134. function _getHeader($header_list, $names)
  135. {
  136. foreach ($header_list as $name => $value) {
  137. foreach ($names as $n) {
  138. if (strtolower($name) == strtolower($n)) {
  139. return $value;
  140. }
  141. }
  142. }
  143. return null;
  144. }
  145. /**
  146. * @access private
  147. */
  148. function _getContentType($content_type_header)
  149. {
  150. if ($content_type_header) {
  151. $parts = explode(";", $content_type_header);
  152. return strtolower($parts[0]);
  153. }
  154. }
  155. /**
  156. * This should be called statically and will build a Yadis
  157. * instance if the discovery process succeeds. This implements
  158. * Yadis discovery as specified in the Yadis specification.
  159. *
  160. * @param string $uri The URI on which to perform Yadis discovery.
  161. *
  162. * @param array $http_response An array reference where the HTTP
  163. * response object will be stored (see {@link
  164. * Services_Yadis_HTTPResponse}.
  165. *
  166. * @param Services_Yadis_HTTPFetcher $fetcher An instance of a
  167. * Services_Yadis_HTTPFetcher subclass.
  168. *
  169. * @param array $extra_ns_map An array which maps namespace names
  170. * to namespace URIs to be used when parsing the Yadis XRDS
  171. * document.
  172. *
  173. * @param integer $timeout An optional fetcher timeout, in seconds.
  174. *
  175. * @return mixed $obj Either null or an instance of
  176. * Services_Yadis_Yadis, depending on whether the discovery
  177. * succeeded.
  178. */
  179. function discover($uri, &$http_response, &$fetcher,
  180. $extra_ns_map = null, $timeout = 20)
  181. {
  182. if (!$uri) {
  183. return null;
  184. }
  185. $request_uri = $uri;
  186. $headers = array("Accept: application/xrds+xml");
  187. if (!$fetcher) {
  188. $fetcher = Services_Yadis_Yadis::getHTTPFetcher($timeout);
  189. }
  190. $response = $fetcher->get($uri, $headers);
  191. $http_response = $response;
  192. if (!$response) {
  193. return null;
  194. }
  195. if ($response->status != 200) {
  196. return null;
  197. }
  198. $xrds_uri = $response->final_url;
  199. $uri = $response->final_url;
  200. $body = $response->body;
  201. $xrds_header_uri = Services_Yadis_Yadis::_getHeader(
  202. $response->headers,
  203. array('x-xrds-location',
  204. 'x-yadis-location'));
  205. $content_type = Services_Yadis_Yadis::_getHeader($response->headers,
  206. array('content-type'));
  207. if ($xrds_header_uri) {
  208. $xrds_uri = $xrds_header_uri;
  209. $response = $fetcher->get($xrds_uri);
  210. $http_response = $response;
  211. if (!$response) {
  212. return null;
  213. } else {
  214. $body = $response->body;
  215. $headers = $response->headers;
  216. $content_type = Services_Yadis_Yadis::_getHeader($headers,
  217. array('content-type'));
  218. }
  219. }
  220. if (Services_Yadis_Yadis::_getContentType($content_type) !=
  221. 'application/xrds+xml') {
  222. // Treat the body as HTML and look for a META tag.
  223. $parser = new Services_Yadis_ParseHTML();
  224. $new_uri = $parser->getHTTPEquiv($body);
  225. $xrds_uri = null;
  226. if ($new_uri) {
  227. $response = $fetcher->get($new_uri);
  228. if ($response->status != 200) {
  229. return null;
  230. }
  231. $http_response = $response;
  232. $body = $response->body;
  233. $xrds_uri = $new_uri;
  234. $content_type = Services_Yadis_Yadis::_getHeader(
  235. $response->headers,
  236. array('content-type'));
  237. }
  238. }
  239. $xrds = Services_Yadis_XRDS::parseXRDS($body, $extra_ns_map);
  240. if ($xrds !== null) {
  241. $y = new Services_Yadis_Yadis();
  242. $y->request_uri = $request_uri;
  243. $y->xrds = $xrds;
  244. $y->uri = $uri;
  245. $y->xrds_uri = $xrds_uri;
  246. $y->body = $body;
  247. $y->content_type = $content_type;
  248. return $y;
  249. } else {
  250. return null;
  251. }
  252. }
  253. /**
  254. * Instantiates an empty Services_Yadis_Yadis object. This
  255. * constructor should not be used by any user of the library.
  256. * This constructor results in a completely useless object which
  257. * must be populated with valid discovery information. Instead of
  258. * using this constructor, call
  259. * Services_Yadis_Yadis::discover($uri).
  260. */
  261. function Services_Yadis_Yadis()
  262. {
  263. $this->request_uri = null;
  264. $this->uri = null;
  265. $this->xrds = null;
  266. $this->xrds_uri = null;
  267. $this->body = null;
  268. $this->content_type = null;
  269. }
  270. /**
  271. * Returns the list of service objects as described by the XRDS
  272. * document, if this yadis object represents a successful Yadis
  273. * discovery.
  274. *
  275. * @return array $services An array of {@link Services_Yadis_Service}
  276. * objects
  277. */
  278. function services()
  279. {
  280. if ($this->xrds) {
  281. return $this->xrds->services();
  282. }
  283. return null;
  284. }
  285. }
  286. ?>