forked from GNUsocial/gnu-social
		
	
		
			
				
	
	
		
			284 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			284 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Phergie
 | |
|  *
 | |
|  * PHP version 5
 | |
|  *
 | |
|  * LICENSE
 | |
|  *
 | |
|  * This source file is subject to the new BSD license that is bundled
 | |
|  * with this package in the file LICENSE.
 | |
|  * It is also available through the world-wide-web at this URL:
 | |
|  * http://phergie.org/license
 | |
|  *
 | |
|  * @category  Phergie
 | |
|  * @package   Phergie_Plugin_Http
 | |
|  * @author    Phergie Development Team <team@phergie.org>
 | |
|  * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
 | |
|  * @license   http://phergie.org/license New BSD License
 | |
|  * @link      http://pear.phergie.org/package/Phergie_Plugin_Http
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Provides an HTTP client for plugins to use in contacting web services or
 | |
|  * retrieving feeds or web pages.
 | |
|  *
 | |
|  * @category Phergie
 | |
|  * @package  Phergie_Plugin_Http
 | |
|  * @author   Phergie Development Team <team@phergie.org>
 | |
|  * @license  http://phergie.org/license New BSD License
 | |
|  * @link     http://pear.phergie.org/package/Phergie_Plugin_Http
 | |
|  * @uses     extension simplexml optional
 | |
|  * @uses     extension json optional
 | |
|  */
 | |
| class Phergie_Plugin_Http extends Phergie_Plugin_Abstract
 | |
| {
 | |
|     /**
 | |
|      * Response to the last executed HTTP request
 | |
|      *
 | |
|      * @var Phergie_Plugin_Http_Response
 | |
|      */
 | |
|     protected $response;
 | |
| 
 | |
|     /**
 | |
|      * Mapping of content types to handlers for them
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $handlers;
 | |
| 
 | |
|     /**
 | |
|      * Initializes the handler lookup table.
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function onLoad()
 | |
|     {
 | |
|         $this->handlers = array(
 | |
|             '(?:application|text)/xml(?:;.*)?'
 | |
|                 => 'simplexml_load_string',
 | |
|             '(?:(?:application|text)/(?:x-)?json)|text/javascript.*'
 | |
|                 => 'json_decode',
 | |
|         );
 | |
| 
 | |
|         if (is_array($this->config['http.handlers'])) {
 | |
|             $this->handlers = array_merge(
 | |
|                 $this->handlers,
 | |
|                 $this->config['http.handlers']
 | |
|             );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets a handler callback for a content type, which is called when a
 | |
|      * response of that content type is received to perform any needed
 | |
|      * transformations on the response body content before storing it in the
 | |
|      * response object. Note that the calling plugin is responsible for
 | |
|      * indicating any dependencies related to specified handler callbacks.
 | |
|      *
 | |
|      * @param string   $type     PCRE regular expression (without delimiters) that
 | |
|      *        matches one or more MIME types
 | |
|      * @param callback $callback Callback to execute when a response of a content
 | |
|      *        type matched by $type is encountered
 | |
|      *
 | |
|      * @return Phergie_Plugin_Http Provides a fluent interface
 | |
|      */
 | |
|     public function setHandler($type, $callback)
 | |
|     {
 | |
|         if (!is_callable($callback)) {
 | |
|             throw new Phergie_Plugin_Exception(
 | |
|                 'Invalid callback specified',
 | |
|                 Phergie_Plugin_Exception::ERR_FATAL_ERROR
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         $this->handlers[$type] = $callback;
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Supporting method that parses the status line of an HTTP response
 | |
|      * message.
 | |
|      *
 | |
|      * @param string $status Status line
 | |
|      *
 | |
|      * @return array Associative array containing the HTTP version, response
 | |
|      *         code, and response description
 | |
|      */
 | |
|     protected function parseStatusLine($status)
 | |
|     {
 | |
|         $parts = explode(' ', $status, 3);
 | |
|         $parsed = array(
 | |
|             'version' => str_replace('HTTP/', '', $parts[0]),
 | |
|             'code' => $parts[1],
 | |
|             'message' => rtrim($parts[2])
 | |
|         );
 | |
|         return $parsed;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Supporting method that acts as an error handler to intercept HTTP
 | |
|      * responses resulting in PHP-level errors.
 | |
|      *
 | |
|      * @param int    $errno   Level of the error raised
 | |
|      * @param string $errstr  Error message
 | |
|      * @param string $errfile Name of the file in which the error was raised
 | |
|      * @param string $errline Line number on which the error was raised
 | |
|      *
 | |
|      * @return bool Always returns TRUE to allow normal execution to
 | |
|      *         continue once this method terminates
 | |
|      */
 | |
|     public function handleError($errno, $errstr, $errfile, $errline)
 | |
|     {
 | |
|         if ($httperr = strstr($errstr, 'HTTP/')) {
 | |
|             $parts = $this->parseStatusLine($httperr);
 | |
|             $this->response
 | |
|                 ->setCode($parts['code'])
 | |
|                 ->setMessage($parts['message']);
 | |
|         }
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Supporting method that executes a request and handles the response.
 | |
|      *
 | |
|      * @param string $url     URL to request
 | |
|      * @param array  $context Associative array of stream context parameters
 | |
|      *
 | |
|      * @return Phergie_Plugin_Http_Response Object representing the response
 | |
|      *         resulting from the request
 | |
|      */
 | |
|     public function request($url, array $context)
 | |
|     {
 | |
|         $this->response = new Phergie_Plugin_Http_Response;
 | |
| 
 | |
|         $url = (string) $url;
 | |
|         $context = stream_context_create(array('http' => $context));
 | |
| 
 | |
|         set_error_handler(array($this, 'handleError'), E_WARNING);
 | |
|         $stream = fopen($url, 'r', false, $context);
 | |
|         if ($stream) {
 | |
|             $meta = stream_get_meta_data($stream);
 | |
|             $status = $this->parseStatusLine($meta['wrapper_data'][0]);
 | |
|             $code = $status['code'];
 | |
|             $message = $status['message'];
 | |
|             $headers = array();
 | |
|             foreach (array_slice($meta['wrapper_data'], 1) as $header) {
 | |
|                 if (!strpos($header, ':')) {
 | |
|                     continue;
 | |
|                 }
 | |
|                 list($name, $value) = explode(': ', $header, 2);
 | |
|                 $headers[$name] = $value;
 | |
|             }
 | |
|             unset($meta['wrapper_data']);
 | |
| 
 | |
|             $this->response
 | |
|                 ->setCode($code)
 | |
|                 ->setMessage($message)
 | |
|                 ->setHeaders($headers)
 | |
|                 ->setMeta($meta);
 | |
| 
 | |
|             $body = stream_get_contents($stream);
 | |
|             $type = $this->response->getHeaders('content-type');
 | |
|             foreach ($this->handlers as $expr => $handler) {
 | |
|                 if (preg_match('#^' . $expr . '$#i', $type)) {
 | |
|                     $handled = call_user_func($handler, $body);
 | |
|                     if (!empty($handled)) {
 | |
|                         $body = $handled;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             $this->response->setContent($body);
 | |
|         }
 | |
|         restore_error_handler();
 | |
| 
 | |
|         return $this->response;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Performs a GET request.
 | |
|      *
 | |
|      * @param string $url     URL for the request
 | |
|      * @param array  $query   Optional associative array of parameters
 | |
|      *        constituting the URL query string if $url has none
 | |
|      * @param array  $context Optional associative array of additional stream
 | |
|      *        context parameters
 | |
|      *
 | |
|      * @return Phergie_Plugin_Http_Response Received response data
 | |
|      */
 | |
|     public function get($url, array $query = array(), array $context = array())
 | |
|     {
 | |
|         if (!empty($query)) {
 | |
|             $url .= '?' . http_build_query($query);
 | |
|         }
 | |
| 
 | |
|         $context['method'] = 'GET';
 | |
| 
 | |
|         return $this->request($url, $context);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Performs a HEAD request.
 | |
|      *
 | |
|      * @param string $url     URL for the request
 | |
|      * @param array  $query   Optional associative array of parameters
 | |
|      *        constituting the URL query string if $url has none
 | |
|      * @param array  $context Optional associative array of additional stream
 | |
|      *        context parameters
 | |
|      *
 | |
|      * @return Phergie_Plugin_Http_Response Received response data
 | |
|      */
 | |
|     public function head($url, array $query = array(), array $context = array())
 | |
|     {
 | |
|         if (!empty($query)) {
 | |
|             $url .= '?' . http_build_query($query);
 | |
|         }
 | |
| 
 | |
|         $context['method'] = 'HEAD';
 | |
| 
 | |
|         return $this->request($url, $context);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Performs a POST request.
 | |
|      *
 | |
|      * @param string $url     URL for the request
 | |
|      * @param array  $query   Optional associative array of parameters
 | |
|      *        constituting the URL query string if $url has none
 | |
|      * @param array  $post    Optional associative array of parameters
 | |
|      *        constituting the POST request body if it is using the
 | |
|      *        traditional URL-encoded format
 | |
|      * @param array  $context Optional associative array of additional stream
 | |
|      *        context parameters
 | |
|      *
 | |
|      * @return Phergie_Plugin_Http_Response Received response data
 | |
|      */
 | |
|     public function post($url, array $query = array(),
 | |
|         array $post = array(), array $context = array()
 | |
|     ) {
 | |
|         if (!empty($query)) {
 | |
|             $url .= '?' . http_build_query($query);
 | |
|         }
 | |
| 
 | |
|         $context['method'] = 'POST';
 | |
| 
 | |
|         if (!empty($post)
 | |
|             && (!empty($context['header'])
 | |
|             xor stripos($context['header'], 'Content-Type'))
 | |
|         ) {
 | |
|             if (!empty($context['header'])) {
 | |
|                 $context['header'] .= "\r\n";
 | |
|             } else {
 | |
|                 $context['header'] = '';
 | |
|             }
 | |
|             $context['header'] .=
 | |
|                 'Content-Type: application/x-www-form-urlencoded';
 | |
|             $context['content'] = http_build_query($post);
 | |
|         }
 | |
| 
 | |
|         return $this->request($url, $context);
 | |
|     }
 | |
| } |