<?php

/*****************************************************************
Пример использования:

RemoteFile::setHeaders(array(
	'X-Requested-With: XMLHttpRequest',
	'Origin: http://vkontakte.ru',
	'Content-Type: application/x-www-form-urlencoded'
));
$headers = RemoteFile::getHeaders('http://cs4603.vkontakte.ru/u50132690/audio/432e2b109b94.mp3');
$html = RemoteFile::getData('http://vkontakte.ru/audio', array(
	'act'	=>'search',
	'q'		=> urlencode($this->_query)
))
*****************************************************************/

/**
 * Класс для работы с удаленными файлами
 * Реализован через библиотеку cURL
 *
 * @package classes
 * @author chez
 **/
class RemoteFile {

	private static $_timeout = 5;		// Таймаут ответа от сервера
	private static $_headers = array();	// Заголовки для отправки на сервер

	/**
	 * Отправка запроса и получение ответа от сервера
	 * Умеет возвращать текст ответа или заголовки
	 *
	 * @param string $url			URL запроса
	 * @param bool $headers			Флаг: возвращать заголовки, а не текст
	 * @param array $post_params	Массив POST-параметров, если установлен, то метод меняется на POST
	 * @return string				Ответ от сервера
	 * @author chez
	 **/
	private static function _exec($url, $headers = false, $post_params = array()) {
		if (count($post_params) > 0) {
			$p = '';
			foreach ($post_params as $key => $val) {
				$p .= '&'. $key .'='. $val;
			}
			$post_params = substr($p, 1);
		}
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HTTPHEADER, self::$_headers);
		if ($headers) {
			curl_setopt($ch, CURLOPT_HEADER, 1);
			curl_setopt($ch, CURLOPT_NOBODY, 1);
		}
		if (is_string($post_params)) {
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $post_params);
		}
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, self::$_timeout);
		$result = curl_exec($ch);
		if (curl_errno($ch) !== 0) {
			curl_close($ch);
			return false;
		}
		curl_close($ch);
		return $result;
	}

	/**
	 * Получение HTTP-заголовков ответа от сервера
	 *
	 * @param string $url			URL запроса
	 * @param array $post_params	Массив POST-параметров, если установлен, то метод меняется на POST
	 * @return array				Распарсеный массив заголовков
	 * @author chez
	 **/
	public static function getHeaders($url, $post_params = array()) {
		$headers = self::_exec($url, true);
		if ($headers === false) {
			return false;
		}
		$headers = explode("\r\n", $headers);
		$headers_array = array();

		while(list($i, $header) = each($headers)) {
			if (substr($header, 0, 5) == 'HTTP/') {
				$header = explode(' ', $header);
				$headers_array['http'] = $header[1];
			} elseif ($header != '') {
				preg_match('/^([a-z0-9\-]*):\s(.*)$/Ui', $header, $m);
				$headers_array[strtolower(str_replace('-', '_', $m[1]))] = $m[2];
			}
		}

		return $headers_array;
	}

	/**
	 * Получение ответа от сервера
	 *
	 * @param string $url			URL запроса
	 * @param array $post_params	Массив POST-параметров, если установлен, то метод меняется на POST
	 * @return string				Тело ответа от сервера
	 * @author chez
	 **/
	public static function getData($url, $post_params = array()) {
		return self::_exec($url, false, $post_params);
	}

	/**
	 * Запись заголовков, которые будет отправлены вместе с запросом
	 *
	 * @param array $headers	Индексный массив заголовков
	 * @return void
	 * @author chez
	 **/
	public static function setHeaders($headers) {
		self::$_headers = $headers;
	}
	
	/**
	 * Массововое получение заголовков по списку файлов
	 *
	 * @param array $fules	Ассоциативный массив id => url
	 * @return array		Ассоциативный массив id => headers
	 * @author chez
	 **/
	public static function getHeadersMT($files) {
		$mh = curl_multi_init();
		$headers_all = array();
		$handlers = array();
		foreach($files as $i => $url) {
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
    		curl_setopt($ch, CURLOPT_HEADER, 1);
    		curl_setopt($ch, CURLOPT_NOBODY, 1);
    		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    		curl_multi_add_handle($mh, $ch);
    		$handlers[$i] = $ch;
		}
		$running=null;
		do 
		{
			curl_multi_exec($mh, $running);
			usleep (500000);
		} while ($running > 0);
		foreach($handlers as $i => $ch) {
			$content = curl_multi_getcontent($handlers[$i]);
			curl_multi_remove_handle($mh, $handlers[$i]);
			$content = explode("\r\n", $content);
			$headers = array();
			foreach($content as $header) {
				if (substr($header, 0, 5) == 'HTTP/') {
					$header = explode(' ', $header);
					$headers['http'] = $header[1];
				} elseif ($header != '') {
					preg_match('/^([a-z0-9\-]*):\s(.*)$/Ui', $header, $m);
					$headers[strtolower(str_replace('-', '_', $m[1]))] = $m[2];
				}
			}
			$headers_all[$i] = $headers;
		}
		curl_multi_close($mh);
		return $headers_all;
	}
}