|
TYPO3 API
SVNRelease
|
00001 <?php 00002 00003 /** 00004 * The core PHP Yadis implementation. 00005 * 00006 * PHP versions 4 and 5 00007 * 00008 * LICENSE: See the COPYING file included in this distribution. 00009 * 00010 * @package OpenID 00011 * @author JanRain, Inc. <openid@janrain.com> 00012 * @copyright 2005-2008 Janrain, Inc. 00013 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache 00014 */ 00015 00016 /** 00017 * Need both fetcher types so we can use the right one based on the 00018 * presence or absence of CURL. 00019 */ 00020 require_once "Auth/Yadis/PlainHTTPFetcher.php"; 00021 require_once "Auth/Yadis/ParanoidHTTPFetcher.php"; 00022 00023 /** 00024 * Need this for parsing HTML (looking for META tags). 00025 */ 00026 require_once "Auth/Yadis/ParseHTML.php"; 00027 00028 /** 00029 * Need this to parse the XRDS document during Yadis discovery. 00030 */ 00031 require_once "Auth/Yadis/XRDS.php"; 00032 00033 /** 00034 * XRDS (yadis) content type 00035 */ 00036 define('Auth_Yadis_CONTENT_TYPE', 'application/xrds+xml'); 00037 00038 /** 00039 * Yadis header 00040 */ 00041 define('Auth_Yadis_HEADER_NAME', 'X-XRDS-Location'); 00042 00043 /** 00044 * Contains the result of performing Yadis discovery on a URI. 00045 * 00046 * @package OpenID 00047 */ 00048 class Auth_Yadis_DiscoveryResult { 00049 00050 // The URI that was passed to the fetcher 00051 var $request_uri = null; 00052 00053 // The result of following redirects from the request_uri 00054 var $normalized_uri = null; 00055 00056 // The URI from which the response text was returned (set to 00057 // None if there was no XRDS document found) 00058 var $xrds_uri = null; 00059 00060 var $xrds = null; 00061 00062 // The content-type returned with the response_text 00063 var $content_type = null; 00064 00065 // The document returned from the xrds_uri 00066 var $response_text = null; 00067 00068 // Did the discovery fail miserably? 00069 var $failed = false; 00070 00071 function Auth_Yadis_DiscoveryResult($request_uri) 00072 { 00073 // Initialize the state of the object 00074 // sets all attributes to None except the request_uri 00075 $this->request_uri = $request_uri; 00076 } 00077 00078 function fail() 00079 { 00080 $this->failed = true; 00081 } 00082 00083 function isFailure() 00084 { 00085 return $this->failed; 00086 } 00087 00088 /** 00089 * Returns the list of service objects as described by the XRDS 00090 * document, if this yadis object represents a successful Yadis 00091 * discovery. 00092 * 00093 * @return array $services An array of {@link Auth_Yadis_Service} 00094 * objects 00095 */ 00096 function services() 00097 { 00098 if ($this->xrds) { 00099 return $this->xrds->services(); 00100 } 00101 00102 return null; 00103 } 00104 00105 function usedYadisLocation() 00106 { 00107 // Was the Yadis protocol's indirection used? 00108 return $this->normalized_uri != $this->xrds_uri; 00109 } 00110 00111 function isXRDS() 00112 { 00113 // Is the response text supposed to be an XRDS document? 00114 return ($this->usedYadisLocation() || 00115 $this->content_type == Auth_Yadis_CONTENT_TYPE); 00116 } 00117 } 00118 00119 /** 00120 * 00121 * Perform the Yadis protocol on the input URL and return an iterable 00122 * of resulting endpoint objects. 00123 * 00124 * input_url: The URL on which to perform the Yadis protocol 00125 * 00126 * @return: The normalized identity URL and an iterable of endpoint 00127 * objects generated by the filter function. 00128 * 00129 * xrds_parse_func: a callback which will take (uri, xrds_text) and 00130 * return an array of service endpoint objects or null. Usually 00131 * array('Auth_OpenID_ServiceEndpoint', 'fromXRDS'). 00132 * 00133 * discover_func: if not null, a callback which should take (uri) and 00134 * return an Auth_Yadis_Yadis object or null. 00135 */ 00136 function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func, 00137 $discover_func=null, $fetcher=null) 00138 { 00139 if ($discover_func === null) { 00140 $discover_function = array('Auth_Yadis_Yadis', 'discover'); 00141 } 00142 00143 $yadis_result = call_user_func_array($discover_func, 00144 array($input_url, $fetcher)); 00145 00146 if ($yadis_result === null) { 00147 return array($input_url, array()); 00148 } 00149 00150 $endpoints = call_user_func_array($xrds_parse_func, 00151 array($yadis_result->normalized_uri, 00152 $yadis_result->response_text)); 00153 00154 if ($endpoints === null) { 00155 $endpoints = array(); 00156 } 00157 00158 return array($yadis_result->normalized_uri, $endpoints); 00159 } 00160 00161 /** 00162 * This is the core of the PHP Yadis library. This is the only class 00163 * a user needs to use to perform Yadis discovery. This class 00164 * performs the discovery AND stores the result of the discovery. 00165 * 00166 * First, require this library into your program source: 00167 * 00168 * <pre> require_once "Auth/Yadis/Yadis.php";</pre> 00169 * 00170 * To perform Yadis discovery, first call the "discover" method 00171 * statically with a URI parameter: 00172 * 00173 * <pre> $http_response = array(); 00174 * $fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); 00175 * $yadis_object = Auth_Yadis_Yadis::discover($uri, 00176 * $http_response, $fetcher);</pre> 00177 * 00178 * If the discovery succeeds, $yadis_object will be an instance of 00179 * {@link Auth_Yadis_Yadis}. If not, it will be null. The XRDS 00180 * document found during discovery should have service descriptions, 00181 * which can be accessed by calling 00182 * 00183 * <pre> $service_list = $yadis_object->services();</pre> 00184 * 00185 * which returns an array of objects which describe each service. 00186 * These objects are instances of Auth_Yadis_Service. Each object 00187 * describes exactly one whole Service element, complete with all of 00188 * its Types and URIs (no expansion is performed). The common use 00189 * case for using the service objects returned by services() is to 00190 * write one or more filter functions and pass those to services(): 00191 * 00192 * <pre> $service_list = $yadis_object->services( 00193 * array("filterByURI", 00194 * "filterByExtension"));</pre> 00195 * 00196 * The filter functions (whose names appear in the array passed to 00197 * services()) take the following form: 00198 * 00199 * <pre> function myFilter(&$service) { 00200 * // Query $service object here. Return true if the service 00201 * // matches your query; false if not. 00202 * }</pre> 00203 * 00204 * This is an example of a filter which uses a regular expression to 00205 * match the content of URI tags (note that the Auth_Yadis_Service 00206 * class provides a getURIs() method which you should use instead of 00207 * this contrived example): 00208 * 00209 * <pre> 00210 * function URIMatcher(&$service) { 00211 * foreach ($service->getElements('xrd:URI') as $uri) { 00212 * if (preg_match("/some_pattern/", 00213 * $service->parser->content($uri))) { 00214 * return true; 00215 * } 00216 * } 00217 * return false; 00218 * }</pre> 00219 * 00220 * The filter functions you pass will be called for each service 00221 * object to determine which ones match the criteria your filters 00222 * specify. The default behavior is that if a given service object 00223 * matches ANY of the filters specified in the services() call, it 00224 * will be returned. You can specify that a given service object will 00225 * be returned ONLY if it matches ALL specified filters by changing 00226 * the match mode of services(): 00227 * 00228 * <pre> $yadis_object->services(array("filter1", "filter2"), 00229 * SERVICES_YADIS_MATCH_ALL);</pre> 00230 * 00231 * See {@link SERVICES_YADIS_MATCH_ALL} and {@link 00232 * SERVICES_YADIS_MATCH_ANY}. 00233 * 00234 * Services described in an XRDS should have a library which you'll 00235 * probably be using. Those libraries are responsible for defining 00236 * filters that can be used with the "services()" call. If you need 00237 * to write your own filter, see the documentation for {@link 00238 * Auth_Yadis_Service}. 00239 * 00240 * @package OpenID 00241 */ 00242 class Auth_Yadis_Yadis { 00243 00244 /** 00245 * Returns an HTTP fetcher object. If the CURL extension is 00246 * present, an instance of {@link Auth_Yadis_ParanoidHTTPFetcher} 00247 * is returned. If not, an instance of 00248 * {@link Auth_Yadis_PlainHTTPFetcher} is returned. 00249 * 00250 * If Auth_Yadis_CURL_OVERRIDE is defined, this method will always 00251 * return a {@link Auth_Yadis_PlainHTTPFetcher}. 00252 */ 00253 function getHTTPFetcher($timeout = 20) 00254 { 00255 if (Auth_Yadis_Yadis::curlPresent() && 00256 (!defined('Auth_Yadis_CURL_OVERRIDE'))) { 00257 $fetcher = new Auth_Yadis_ParanoidHTTPFetcher($timeout); 00258 } else { 00259 $fetcher = new Auth_Yadis_PlainHTTPFetcher($timeout); 00260 } 00261 return $fetcher; 00262 } 00263 00264 function curlPresent() 00265 { 00266 return function_exists('curl_init'); 00267 } 00268 00269 /** 00270 * @access private 00271 */ 00272 function _getHeader($header_list, $names) 00273 { 00274 foreach ($header_list as $name => $value) { 00275 foreach ($names as $n) { 00276 if (strtolower($name) == strtolower($n)) { 00277 return $value; 00278 } 00279 } 00280 } 00281 00282 return null; 00283 } 00284 00285 /** 00286 * @access private 00287 */ 00288 function _getContentType($content_type_header) 00289 { 00290 if ($content_type_header) { 00291 $parts = explode(";", $content_type_header); 00292 return strtolower($parts[0]); 00293 } 00294 } 00295 00296 /** 00297 * This should be called statically and will build a Yadis 00298 * instance if the discovery process succeeds. This implements 00299 * Yadis discovery as specified in the Yadis specification. 00300 * 00301 * @param string $uri The URI on which to perform Yadis discovery. 00302 * 00303 * @param array $http_response An array reference where the HTTP 00304 * response object will be stored (see {@link 00305 * Auth_Yadis_HTTPResponse}. 00306 * 00307 * @param Auth_Yadis_HTTPFetcher $fetcher An instance of a 00308 * Auth_Yadis_HTTPFetcher subclass. 00309 * 00310 * @param array $extra_ns_map An array which maps namespace names 00311 * to namespace URIs to be used when parsing the Yadis XRDS 00312 * document. 00313 * 00314 * @param integer $timeout An optional fetcher timeout, in seconds. 00315 * 00316 * @return mixed $obj Either null or an instance of 00317 * Auth_Yadis_Yadis, depending on whether the discovery 00318 * succeeded. 00319 */ 00320 function discover($uri, $fetcher, 00321 $extra_ns_map = null, $timeout = 20) 00322 { 00323 $result = new Auth_Yadis_DiscoveryResult($uri); 00324 00325 $request_uri = $uri; 00326 $headers = array("Accept: " . Auth_Yadis_CONTENT_TYPE . 00327 ', text/html; q=0.3, application/xhtml+xml; q=0.5'); 00328 00329 if ($fetcher === null) { 00330 $fetcher = Auth_Yadis_Yadis::getHTTPFetcher($timeout); 00331 } 00332 00333 $response = $fetcher->get($uri, $headers); 00334 00335 if (!$response || ($response->status != 200 and 00336 $response->status != 206)) { 00337 $result->fail(); 00338 return $result; 00339 } 00340 00341 $result->normalized_uri = $response->final_url; 00342 $result->content_type = Auth_Yadis_Yadis::_getHeader( 00343 $response->headers, 00344 array('content-type')); 00345 00346 if ($result->content_type && 00347 (Auth_Yadis_Yadis::_getContentType($result->content_type) == 00348 Auth_Yadis_CONTENT_TYPE)) { 00349 $result->xrds_uri = $result->normalized_uri; 00350 } else { 00351 $yadis_location = Auth_Yadis_Yadis::_getHeader( 00352 $response->headers, 00353 array(Auth_Yadis_HEADER_NAME)); 00354 00355 if (!$yadis_location) { 00356 $parser = new Auth_Yadis_ParseHTML(); 00357 $yadis_location = $parser->getHTTPEquiv($response->body); 00358 } 00359 00360 if ($yadis_location) { 00361 $result->xrds_uri = $yadis_location; 00362 00363 $response = $fetcher->get($yadis_location); 00364 00365 if ((!$response) || ($response->status != 200 and 00366 $response->status != 206)) { 00367 $result->fail(); 00368 return $result; 00369 } 00370 00371 $result->content_type = Auth_Yadis_Yadis::_getHeader( 00372 $response->headers, 00373 array('content-type')); 00374 } 00375 } 00376 00377 $result->response_text = $response->body; 00378 return $result; 00379 } 00380 } 00381 00382 ?>
1.8.0