view Http.inc.php @ 134:b6b4a58c7625

Using .inc.php rather than just .inc for include files.
author Tom Fredrik Blenning <bfg@bfgconsult.no>
date Sun, 22 Jan 2023 19:22:00 +0100
parents Http.inc@51b53cd01080
children
line wrap: on
line source

<?php
include_once 'ScriptIncludeCache.inc.php';

/// @cond
$baseDir = dirname(__FILE__);
$cache = ScriptIncludeCache::instance(__FILE__);
/// @endcond

/**
 * Thrown if a request has gone bad
 */
class RequestException extends RuntimeException
{
  private $_info;

  /**
   * Constructs a RequestException
   *
   * @param $info an info array as defined in http_get, if a key with
   * name error exist, this will be the error text for the
   * RuntimeException
   */
  function __construct($info)
  {
    $this->_info = $info;
    if (array_key_exists('error', $info)) {
      parent::__construct($info['error']);
    }
  }

  /**
   * Get the info object associated with this RequestException
   *
   * @return $info an info array as defined in http_get
   */
  function info()
  {
    return $this->_info;
  }
}

/**
 * Http contains a set of functions for retrieving http information
 */
class Http
{
  /**
   * Gets the content of a page
   *
   * This mimics the file_content with a uri parameter which is often
   * disabled due to security reasons
   *
   * @param $uri The uri to fetch
   */
  static function get_uri_contents($uri)
  {
    $crl = curl_init();
    $timeout = 5;

    curl_setopt ($crl, CURLOPT_URL, $uri);
    curl_setopt ($crl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($crl, CURLOPT_CONNECTTIMEOUT, $timeout);
    $ret = curl_exec($crl);
    curl_close($crl);
    return $ret;
  }

  /**
   * Splits an http header response into an associative array
   *
   * @param $response The headers to parse
   * @return an Associative array, the key '' refers to the HTTP status header
   */
  static function headersToArray($response)
  {
    $headers = array();
    $response = trim($response);
    $str = explode("\n", $response);
    $headers[''] = trim($str[0]);
    foreach($str as $kv) {
      $p = strpos($kv, ":");
      if ($p) {
	$key = substr($kv, 0, $p);
	$value = trim(substr($kv, $p + 1));
	$headers[$key] = $value;
      }
    }
    return $headers;
  }

  /**
   * Queries a URL for headers
   *
   * @param $url the url to query
   * @param $timeout float number of seconds to wait before timeout
   * @return an associative array of all headers returned
   */
  static function getHeaders($url, $timeout = 1)
  {
    //Workaround when getHeaders doesn't work
    if (false) {
      $response = http_head($url, array("timeout" => $timeout), $info);
      if (array_key_exists('error', $info) && $info['error']) {
	throw new RequestException($info);
      }
      return self::headersToArray($response);
    }
    elseif (true) {
      $rp = get_headers($url);
      $response=array('' =>  array_shift ($rp));
      foreach($rp as $kv) {
	if (!str_contains($kv, ':')) {
	  if (!preg_match("/^HTTP\/\S+\s(\d+)/", $response[''], $re)) {
	    throw new Exception('Uninteligble header');
	  }
	  //FIXME: We should do something with this,
	  //but now we just assume we have a redirect
	  $retCode=intval($re[1]);
	  $response=array('' =>  $kv);
	}
	else {
	  $tmp=array_map('trim', explode(':', $kv, 2));
	  $response[$tmp[0]]=$tmp[1];
	}
      }
      return $response;
    }
    else {
      return array('' => 'HTTP/1.1 200 OK');
    }

  }

  /**
   * Performs a post to an URI for headers
   *
   * @param $uri the uri to query
   * @param $params an associative array of params to post
   * @param $timeout float number of seconds to wait before timeout
   * @return an associative array of all headers returned
   */
  static function postHeaders($uri, $params, $timeout = 1)
  {
    $crl = curl_init();

    $descriptorspec = array(
			    0 => array("pipe", "r"),
			    1 => array("pipe", "w"),
			    //2 => array("file", "/tmp/error-output.txt", "a")
			    );

    //We use tac, since it buffers, and we don't care about the output
    //being reordered.
    $process = proc_open('tac | tac', $descriptorspec, $pipes);

    curl_setopt ($crl, CURLOPT_URL, $uri);
    curl_setopt ($crl, CURLOPT_WRITEHEADER, $pipes[0]);
    curl_setopt ($crl, CURLOPT_NOBODY, true);
    curl_setopt ($crl, CURLOPT_POST, true);
    curl_setopt ($crl, CURLOPT_POSTFIELDS, $params);

    curl_setopt ($crl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($crl, CURLOPT_CONNECTTIMEOUT, $timeout);
    $ret = curl_exec($crl);
    curl_close($crl);

    fclose($pipes[0]);
    $buf = fread($pipes[1], 8192);

    return self::headersToArray($buf);
  }
}
?>