/**
  * This should be called statically and will build a Yadis
  * instance if the discovery process succeeds.  This implements
  * Yadis discovery as specified in the Yadis specification.
  *
  * @param string $uri The URI on which to perform Yadis discovery.
  *
  * @param array $http_response An array reference where the HTTP
  * response object will be stored (see {@link
  * Services_Yadis_HTTPResponse}.
  *
  * @param Services_Yadis_HTTPFetcher $fetcher An instance of a
  * Services_Yadis_HTTPFetcher subclass.
  *
  * @param array $extra_ns_map An array which maps namespace names
  * to namespace URIs to be used when parsing the Yadis XRDS
  * document.
  *
  * @param integer $timeout An optional fetcher timeout, in seconds.
  *
  * @return mixed $obj Either null or an instance of
  * Services_Yadis_Yadis, depending on whether the discovery
  * succeeded.
  */
 function discover($uri, &$http_response, &$fetcher, $extra_ns_map = null, $timeout = 20)
 {
     if (!$uri) {
         return null;
     }
     $request_uri = $uri;
     $headers = array("Accept: application/xrds+xml");
     if (!$fetcher) {
         $fetcher = Services_Yadis_Yadis::getHTTPFetcher($timeout);
     }
     $response = $fetcher->get($uri, $headers);
     $http_response = $response;
     if (!$response) {
         return null;
     }
     if ($response->status != 200) {
         return null;
     }
     $xrds_uri = $response->final_url;
     $uri = $response->final_url;
     $body = $response->body;
     $xrds_header_uri = Services_Yadis_Yadis::_getHeader($response->headers, array('x-xrds-location', 'x-yadis-location'));
     $content_type = Services_Yadis_Yadis::_getHeader($response->headers, array('content-type'));
     if ($xrds_header_uri) {
         $xrds_uri = $xrds_header_uri;
         $response = $fetcher->get($xrds_uri);
         $http_response = $response;
         if (!$response) {
             return null;
         } else {
             $body = $response->body;
             $headers = $response->headers;
             $content_type = Services_Yadis_Yadis::_getHeader($headers, array('content-type'));
         }
     }
     if (Services_Yadis_Yadis::_getContentType($content_type) != 'application/xrds+xml') {
         // Treat the body as HTML and look for a META tag.
         $parser = new Services_Yadis_ParseHTML();
         $new_uri = $parser->getHTTPEquiv($body);
         $xrds_uri = null;
         if ($new_uri) {
             $response = $fetcher->get($new_uri);
             if ($response->status != 200) {
                 return null;
             }
             $http_response = $response;
             $body = $response->body;
             $xrds_uri = $new_uri;
             $content_type = Services_Yadis_Yadis::_getHeader($response->headers, array('content-type'));
         }
     }
     $xrds = Services_Yadis_XRDS::parseXRDS($body, $extra_ns_map);
     if ($xrds !== null) {
         $y = new Services_Yadis_Yadis();
         $y->request_uri = $request_uri;
         $y->xrds = $xrds;
         $y->uri = $uri;
         $y->xrds_uri = $xrds_uri;
         $y->body = $body;
         $y->content_type = $content_type;
         return $y;
     } else {
         return null;
     }
 }