Add OpenID auth for editing pages
[busui.git] / lib / openid-php / Auth / Yadis / PlainHTTPFetcher.php
blob:a/lib/openid-php/Auth/Yadis/PlainHTTPFetcher.php -> blob:b/lib/openid-php/Auth/Yadis/PlainHTTPFetcher.php
  <?php
   
  /**
  * This module contains the plain non-curl HTTP fetcher
  * implementation.
  *
  * PHP versions 4 and 5
  *
  * LICENSE: See the COPYING file included in this distribution.
  *
  * @package OpenID
  * @author JanRain, Inc. <openid@janrain.com>
  * @copyright 2005-2008 Janrain, Inc.
  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
  */
   
  /**
  * Interface import
  */
  require_once "Auth/Yadis/HTTPFetcher.php";
   
  /**
  * This class implements a plain, hand-built socket-based fetcher
  * which will be used in the event that CURL is unavailable.
  *
  * @package OpenID
  */
  class Auth_Yadis_PlainHTTPFetcher extends Auth_Yadis_HTTPFetcher {
  /**
  * Does this fetcher support SSL URLs?
  */
  function supportsSSL()
  {
  return function_exists('openssl_open');
  }
   
  function get($url, $extra_headers = null)
  {
  if (!$this->canFetchURL($url)) {
  return null;
  }
   
  $redir = true;
   
  $stop = time() + $this->timeout;
  $off = $this->timeout;
   
  while ($redir && ($off > 0)) {
   
  $parts = parse_url($url);
   
  $specify_port = true;
   
  // Set a default port.
  if (!array_key_exists('port', $parts)) {
  $specify_port = false;
  if ($parts['scheme'] == 'http') {
  $parts['port'] = 80;
  } elseif ($parts['scheme'] == 'https') {
  $parts['port'] = 443;
  } else {
  return null;
  }
  }
   
  if (!array_key_exists('path', $parts)) {
  $parts['path'] = '/';
  }
   
  $host = $parts['host'];
   
  if ($parts['scheme'] == 'https') {
  $host = 'ssl://' . $host;
  }
   
  $user_agent = Auth_OpenID_USER_AGENT;
   
  $headers = array(
  "GET ".$parts['path'].
  (array_key_exists('query', $parts) ?
  "?".$parts['query'] : "").
  " HTTP/1.0",
  "User-Agent: $user_agent",
  "Host: ".$parts['host'].
  ($specify_port ? ":".$parts['port'] : ""),
  "Port: ".$parts['port']);
   
  $errno = 0;
  $errstr = '';
   
  if ($extra_headers) {
  foreach ($extra_headers as $h) {
  $headers[] = $h;
  }
  }
   
  @$sock = fsockopen($host, $parts['port'], $errno, $errstr,
  $this->timeout);
  if ($sock === false) {
  return false;
  }
   
  stream_set_timeout($sock, $this->timeout);
   
  fputs($sock, implode("\r\n", $headers) . "\r\n\r\n");
   
  $data = "";
  $kilobytes = 0;
  while (!feof($sock) &&
  $kilobytes < Auth_OpenID_FETCHER_MAX_RESPONSE_KB ) {
  $data .= fgets($sock, 1024);
  $kilobytes += 1;
  }
   
  fclose($sock);
   
  // Split response into header and body sections
  list($headers, $body) = explode("\r\n\r\n", $data, 2);
  $headers = explode("\r\n", $headers);
   
  $http_code = explode(" ", $headers[0]);
  $code = $http_code[1];
   
  if (in_array($code, array('301', '302'))) {
  $url = $this->_findRedirect($headers, $url);
  $redir = true;
  } else {
  $redir = false;
  }
   
  $off = $stop - time();
  }
   
  $new_headers = array();
   
  foreach ($headers as $header) {
  if (preg_match("/:/", $header)) {
  $parts = explode(": ", $header, 2);
   
  if (count($parts) == 2) {
  list($name, $value) = $parts;
  $new_headers[$name] = $value;
  }
  }
   
  }
   
  return new Auth_Yadis_HTTPResponse($url, $code, $new_headers, $body);
  }
   
  function post($url, $body, $extra_headers = null)
  {
  if (!$this->canFetchURL($url)) {
  return null;
  }
   
  $parts = parse_url($url);
   
  $headers = array();
   
  $post_path = $parts['path'];
  if (isset($parts['query'])) {
  $post_path .= '?' . $parts['query'];
  }
   
  $headers[] = "POST ".$post_path." HTTP/1.0";
  $headers[] = "Host: " . $parts['host'];
  $headers[] = "Content-type: application/x-www-form-urlencoded";
  $headers[] = "Content-length: " . strval(strlen($body));
   
  if ($extra_headers &&
  is_array($extra_headers)) {
  $headers = array_merge($headers, $extra_headers);
  }
   
  // Join all headers together.
  $all_headers = implode("\r\n", $headers);
   
  // Add headers, two newlines, and request body.
  $request = $all_headers . "\r\n\r\n" . $body;
   
  // Set a default port.
  if (!array_key_exists('port', $parts)) {
  if ($parts['scheme'] == 'http') {
  $parts['port'] = 80;
  } elseif ($parts['scheme'] == 'https') {
  $parts['port'] = 443;
  } else {
  return null;
  }
  }
   
  if ($parts['scheme'] == 'https') {
  $parts['host'] = sprintf("ssl://%s", $parts['host']);
  }
   
  // Connect to the remote server.
  $errno = 0;
  $errstr = '';
   
  $sock = fsockopen($parts['host'], $parts['port'], $errno, $errstr,
  $this->timeout);
   
  if ($sock === false) {
  return null;
  }
   
  stream_set_timeout($sock, $this->timeout);
   
  // Write the POST request.
  fputs($sock, $request);
   
  // Get the response from the server.
  $response = "";
  while (!feof($sock)) {
  if ($data = fgets($sock, 128)) {
  $response .= $data;
  } else {
  break;
  }
  }
   
  // Split the request into headers and body.
  list($headers, $response_body) = explode("\r\n\r\n", $response, 2);
   
  $headers = explode("\r\n", $headers);
   
  // Expect the first line of the headers data to be something
  // like HTTP/1.1 200 OK. Split the line on spaces and take
  // the second token, which should be the return code.
  $http_code = explode(" ", $headers[0]);
  $code = $http_code[1];
   
  $new_headers = array();
   
  foreach ($headers as $header) {
  if (preg_match("/:/", $header)) {
  list($name, $value) = explode(": ", $header, 2);
  $new_headers[$name] = $value;
  }
   
  }
   
  return new Auth_Yadis_HTTPResponse($url, $code,
  $new_headers, $response_body);
  }
  }