<?php
/**
* Своя реализация curl
*/
class http_client {
public $ua = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.83 Safari/535.11';
public $timeout = 20; // таймаут запроса (сек)
public $referer = '';
public $accept = '*/*';
public $accept_encoding = 'identity';
public $accept_charset = 'windows-1251,utf-8;q=0.7,*;q=0.3';
public $accept_language = 'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4';
protected $_url;
protected $_post = array(); // массив с POST
protected $_cookie = array(); // массив с COOKIE
protected $_files = array(); //
protected $_sock = false;
protected $_http_proxy = false; // HTTP прокси
protected $_socks_proxy = false; // SOCKS прокси
protected $_boundary = false; // разделитель для отправляемых данных
public $errn;
public $errs;
/**
* @param string $url
*/
function __construct($url) {
$this->_url = $url;
$this->dataReset();
}
/**
* Сброс всех данных для запроса
*/
public function dataReset() {
$this->_boundary = passgen();
$this->_post = array();
$this->_cookie = array();
$this->_sock = false;
$this->errn = '';
$this->errs = '';
}
/**
* Подключение к сокету хоста или прокси сервера
* @return boolean
*/
protected function _connect() {
if ($this->_http_proxy) {
$purl = @parse_url($this->_http_proxy);
} else {
$purl = @parse_url($this->_url);
}
if (!empty($purl['host'])) {
$port = empty($purl['port']) ? 80 : $purl['port'];
if (empty($purl['scheme'])) {
$scheme = '';
} elseif ($purl['scheme'] == 'https') {
$scheme = 'ssl://';
$port = '443';
} else {
$scheme = '';
}
if ($this->_socks_proxy) {
$spurl = @parse_url($this->_socks_proxy);
$sport = empty($spurl['port']) ? 9050 : $spurl['port'];
if (!$this->_sock = @fsockopen('tcp://' . $spurl['host'], $sport, $this->errn, $this->errs, $this->timeout)) {
misc::log($spurl['host'] . ' (Прокси-сервер) - Не удалось подключиться', 'http_client');
} else {
$packet = "\x05\x01\x00";
fwrite($this->_sock, $packet, strlen($packet));
$response = fread($this->_sock, 3);
fwrite($this->_sock, "\x05\x01\x00\x03" . chr(strlen($purl['host'])) . $purl['host'] . pack("n", $port));
$response = fread($this->_sock, 2048);
if (ord($response[0]) == 5) {
$status = ord($response[1]);
if ($status != 0) {
misc::log($spurl['host'] . ' (Прокси-сервер) - Не удалось подключиться', 'http_client');
return false;
} else {
misc::log($spurl['host'] . ' (Прокси-сервер) - Успешно подключились', 'http_client');
return true;
}
} else {
misc::log($spurl['host'] . ' (Прокси-сервер) - Не удалось подключиться', 'http_client');
return false;
}
}
}
if (!$this->_sock = @fsockopen($scheme . $purl['host'], $port, $this->errn, $this->errs, $this->timeout)) {
misc::log($scheme . $purl['host'] . ($this->_http_proxy ? ' (Прокси-сервер)' : '') . ' - Не удалось подключиться', 'http_client');
return false;
} else {
stream_set_timeout($this->_sock, $this->timeout);
misc::log($scheme . $purl['host'] . ($this->_http_proxy ? ' (Прокси-сервер)' : '') . ' - Успешно подлючились', 'http_client');
return true;
}
}
}
/**
* Закрытие подключения
*/
protected function _disconnect() {
fclose($this->_sock);
misc::log('Сокет закрыт', 'http_client');
}
/**
* Установка прокси-сервера
* @param string $proxy Адрес прокси
* @param boolean $socks используется socks
*/
public function set_proxy($proxy, $socks = true) {
if ($proxy === false) {
$this->_http_proxy = false;
$this->_socks_proxy = false;
}
if ($socks) {
$this->_socks_proxy = $proxy;
} else {
$this->_http_proxy = $proxy;
}
}
/**
* Установка POST переменной
* @param string $name Имя
* @param string $value Значение
*/
public function set_post($name, $value = '') {
$this->_post[$name] = $value;
}
/**
* Установка COOKIE
* @param string $name Имя
* @param string $value Значение
*/
public function set_cookie($name, $value = null) {
$this->_cookie[] = urlencode($name) . '=' . urlencode($value);
}
/**
* Прикрепление файла для отправки
* @param string $name Имя поля, в котором будет передаваться файл
* @param string $path Путь к файлу на сервере
* @param string $filename Имя файла
* @return boolean
*/
public function set_file($name, $path, $filename = false) {
if (!$content = @file_get_contents($path)) {
return false;
}
if ($filename === false) {
$filename = basename($path);
}
$this->_files[$name] = array('name' => $filename, 'content' => $content);
return true;
}
/**
* Сохранение полученных данных в файл
* @param string $file_path путь к файлу на сервере
* @param int $max_size максимальный размер принимаемых данных
* @return boolean
*/
public function save_content($file_path, $max_size = 0) {
misc::log('Запрос на сохранение файла (' . $this->_url . ')', 'http_client');
if (!$fo = @fopen($file_path, 'wb')) {
@unlink($file_path);
misc::log('Не удалось открыть указатель ресурса', 'http_client');
return false;
}
if (!$this->_connect()) {
@unlink($file_path);
misc::log('Соединение разорвано', 'http_client');
return false;
}
fputs($this->_sock, $this->getOutputHeaders());
$headers = '';
while (!feof($this->_sock)) {
$data = fgets($this->_sock, 2048);
if ($data == "\r\n") {
break;
}
$headers .= $data;
}
$saved = 0;
while (!feof($this->_sock)) {
if ($data = fgets($this->_sock, 4096)) {
$saved += strlen($data);
if ($max_size && $saved > $max_size) {
@unlink($file_path);
misc::log('Превышено ограничение на длину скачиваемого файла', 'http_client');
return false;
}
if (!@fwrite($fo, $data)) {
@unlink($file_path);
misc::log('Не удалось сохранить файл', 'http_client');
return false;
}
}
}
$size = filesize($file_path);
if ($size) {
misc::log('Файл успешно получен и сохранен ' . misc::size_data($size), 'http_client');
} else {
misc::log('Получен файл с нулевым размером', 'http_client');
}
fclose($fo);
$this->_disconnect();
return (bool) $size;
}
/**
* Получение имени файла из ответа
* @return string
*/
public function getFileName() {
$headers = $this->get_headers();
if ($headers) {
if (preg_match('/filename=(.+?);/', $headers, $m)) {
return $m[1];
}
}
$path = @parse_url($this->_url);
return basename($path['path']);
}
/**
* Получение заголовков ответа
* @return string
*/
public function getHeaders() {
return $this->get_headers();
}
/**
* Получение содержимого ответа
* @param boolean $with_headers включать заголовки
* @return string
*/
public function getContent($with_headers = false) {
return $this->get_content($with_headers);
}
/**
* Получение содержимого ответа
* @param boolean $with_headers включать заголовки
* @return string
*/
public function get_content($with_headers = false) {
misc::log('Запрос на получение контента (' . $this->_url . ')', 'http_client');
if (!$this->_connect()) {
misc::log('Соединение разорвано', 'http_client');
return false;
}
$output_headers = $this->getOutputHeaders();
fputs($this->_sock, $output_headers, strlen($output_headers));
$headers = '';
while (!feof($this->_sock)) {
$data = fgets($this->_sock, 2048);
if ($data == "\r\n") {
break;
}
$headers .= $data;
}
if ($with_headers) {
$content = $headers . "\r\n";
} else {
$content = '';
}
while (!feof($this->_sock)) {
if ($data = fgets($this->_sock, 4096)) {
$content .= $data;
}
}
misc::log('Контент успешно получен (' . misc::size_data(strlen($content)) . ')', 'http_client');
$this->_disconnect();
return $content;
}
/**
* Получение заголовков ответа
* @return string
*/
public function get_headers() {
misc::log('Запрос на получение заголовков (' . $this->_url . ')', 'http_client');
if (!$this->_connect()) {
misc::log('Соединение разорвано', 'http_client');
return false;
}
$output_headers = $this->getOutputHeaders();
fputs($this->_sock, $output_headers, strlen($output_headers));
$headers = '';
while (!feof($this->_sock)) {
$data = fgets($this->_sock, 2048);
if ($data == "\r\n") {
break;
}
$headers .= $data;
}
misc::log('Заголовки успешно получены', 'http_client');
$this->_disconnect();
return $headers;
}
/**
* формирование данных для multipart/form-data
* @return string
*/
protected function _multipart() {
$data = array();
if ($this->_post) {
foreach ($this->_post as $key => $value) {
$data[] = "--{$this->_boundary}\r\nContent-Disposition: form-data; name='" . urlencode($key) . "'\r\n\r\n$value";
}
}
if ($this->_files) {
foreach ($this->_files as $name => $value) {
$data[] = "--{$this->_boundary}\r\nContent-Disposition: form-data; name=\"" . urlencode($name) . "\"; filename=\"" . urlencode($value['name']) . "\"\r\nContent-Type: " . files_types::get_mime($value['name']) . "\r\nContent-Transfer-Encoding: binary\r\n\r\n{$value['content']}";
}
}
return implode("\r\n", $data) . "\r\n--{$this->_boundary}--\r\n";
}
/**
* Получение заголовков запроса
* @return string
*/
function getOutputHeaders() {
$headers = array();
$purl = @parse_url($this->_url);
$scheme = empty($purl['scheme']) ? 'http' : $purl['scheme'];
$host = empty($purl['host']) ? '' : $purl['host'];
if ($this->_http_proxy) {
$path = $scheme . '://' . $host . (empty($purl['path']) ? '/' : $purl['path']);
} else {
$path = empty($purl['path']) ? '/' : $purl['path'];
}
$query = empty($purl['query']) ? '' : '?' . $purl['query'];
$headers[] = ($this->_post ? 'POST' : 'GET') . ' ' . $path . $query . ' HTTP/1.0';
$headers[] = 'Host: ' . $host;
if ($this->accept) {
$headers[] = 'Accept: ' . $this->accept;
}
if ($this->accept_charset) {
$headers[] = 'Accept-Charset: ' . $this->accept_charset;
}
if ($this->accept_encoding) {
$headers[] = 'Accept-Encoding: ' . $this->accept_encoding;
}
if ($this->accept_language) {
$headers[] = 'Accept-Language: ' . $this->accept_language;
}
if ($this->referer) {
$headers[] = 'Referer: ' . $this->referer;
}
if ($this->_cookie) {
$headers[] = 'Cookie: ' . implode(';', $this->_cookie);
}
if ($this->ua) {
$headers[] = 'User-Agent: ' . $this->ua;
}
if ($this->_files || $this->_post) {
$post_data = $this->_multipart();
$headers[] = 'Content-Type: multipart/form-data; boundary=' . $this->_boundary;
$headers[] = 'Content-Length: ' . strlen($post_data);
}
if (isset($purl['user']) && isset($purl['pass'])) {
$headers[] = 'Authorization: Basic ' . base64_encode($purl['user'] . ':' . $purl['pass']);
}
$headers[] = 'Connection: Close';
$header = implode("\r\n", $headers) . "\r\n\r\n";
if (!empty($post_data)) {
$header .= $post_data;
}
return $header;
}
}
?>