<?php
/**
* Browser.class Manipula requisições de uma maneira mais simples e fácil.
* @author Elieder Damasceno Sousa
* @version 0.7
* facebook.com/eliedersousa
* eliederdamasceno@gmail.com
* @eliedersousa
* ********************************
* UPDATES:
v0.7:
- Método parsePage(), para parsear formulários e scripts na página.
- Método preparePostData() reformulado para usar a função http_build_query()
- Método getProxyList(), que retorna uma lista com proxys
- Adicionado novos USERAGENTS (Firefox12, Chrome19, IE6/7, TESTE)
- Adicionado controle de erros em cada método, para impedir o uso incorreto dos mesmos.
- Default headers do Firefox para serem enviados em cada requisição
- Adicionado controles if(isset($data[""])) para cada CURLOPT que necessite, afim de impedir que as requisições enviem parâmetros default.
- Adicionado suporte inicial a proxys na função cURL.
- Corrigido o bug de redirecionamento, na função parseHeaders.
v0.5:
- Adicionado os métodos
v0.4:
- Adicionado o método printAll(), para printar todas as variáveis.
v0.3:
- Método openMultiplePages() para multiplas requisições; além das constantes de requisição.
*/
class Browser {
/**
* Guarda a history de páginas requisitadas, com [url, time, post]
* @var array $history
*/
public $history;
/**
* Guarda todos os headers setados pelas requisições. Se $followLocationManual estiver habilitado,
* os redirecionamentos são tratados em índices separados; caso contrário os headers de cada página redirecionada
* ficam em um mesmo índice.
* @var array $headers
*/
public $headers;
/**
* Guarda os cookies setados pelas requisições.
* @var array $cookies
*/
public $cookies;
// Variável auxiliar, para setar qual foi o último domínio que pegamos um cookie.
// Isso é extremamente importante para que eu possa passar de maneira inteligente o cookie para
// O domínio correto; embora esteja errado, pois o domínio tem que ser determinado com base
// Na URL passada, e não no último cookie capturado (pois eu posso requisitar 2 páginas de domínios
// Diferentes em sequência
// TODO: Manipular o domínio com base na URL, e não no cookie.
/**
* Guarda o domínio atual que estamos trabalhando (da requisição anterior).
* @var string $domain
*/
private $domain = "";
/**
* O USERAGENT que será usado em todas as requisições.
* @var string $useragent
*/
private $useragent = self::USERAGENT_FIREFOX12;
/**
* Controle de headers, e history
* @var int $historyCount
*/
private $historyCount = 0;
/**
* Manipula a forma como os redirecionamentos são feitos nas requisições. Se a variável estiver como 0, os
* redirecionamentos serão feitos com CURLOPT_FOLLOWLOCATION; caso esteja com o valor 1, serão feitos manualmente.
* @var int $followLocationManual
*/
private $followLocationManual = 0;
private $disableFollow = 0;
/**
* Valor máximo de segundos que uma requisição pode esperar antes de ser abortada.
* @var int $curl_timeout
*/
private $curl_timeout = 80;
/**
* Valor em microsegundos que o loop de requisições múltiplas deve esperar para verificar se todas acabaram.
* @var int $curl_multi_timeout
*/
private $curl_multi_timeout = 100;
/**
* Quantidade máxima de redirecionamentos automaticos que a classe seguirá.
* Evita cair em loop caso o redirect venha em uma mensagem codificada por GZIP.
*/
private $curl_maxredirects = 4;
// Constantes de manipulação de múltiplas requisições
const CURLMULTI_URLS = 1;
const CURLMULTI_POST = 2;
const CURLMULTI_AUTH = 3;
// TODO: Fazer as constantes de USERAGENT!
// Aqui, todos useragents estão para o Windows.
const USERAGENT_IE6 = "Mozilla/4.0 (compatible; MSIE 6.1; Windows XP)";
const USERAGENT_IE7 = "Mozilla/4.0(compatible; MSIE 7.0b; Windows NT 6.0)";
const USERAGENT_FIREFOX8 = "Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0!";
const USERAGENT_FIREFOX12 = "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20100101 Firefox/12.0";
const USERAGENT_CHROME190 = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5";
const USERAGENT_TESTE = "# USERAGENT PARA TESTES DA BROWSER CLASS #";
/**
* Instancia a classe Browser.
* @return void
*/
public function __construct() {
$this->history = array();
$this->headers = array();
$this->cookies = array();
// Se o host não der suporte a FOLLOWLOCATION
if(ini_get("safe_mode")) {
$this->followLocationManual = 1;
} else {
$this->followLocationManual = 0;
}
}
/**
* Constrói os headers na variável $headers; separando por índices.
* Útil para manter CURLOPT_HEADER sempre desligado!
* Retorna o tamanho dos headers em bytes (strlen($headers))
* @return int
*/
private function HeaderListener($req, $header) {
$arrayheader = array();
preg_match('/.*/', $header, $arrayheader);
if(strlen(trim($arrayheader[0])) > 0) array_push($this->headers[$this->historyCount], $arrayheader[0]);
return strlen($header);
}
/**
* Abre a página requisitada, guardando os dados na array $history, e separando informações.
* Lembre-se sempre: $data tem que ser uma array!
* array("post"=>post....);
* @param string $url
* @param array $data
* @return string | requisição_curl
*/
public function open($url, $data=null) {
if(!isset($url) || !is_string($url)) {
throw new Exception("Browser::open - O primeiro parâmetro requer uma string.");
die();
}
if(isset($data) && !is_array($data)) {
throw new Exception("Browser::open - O segundo parâmetro, quando passado, requer uma string.");
die();
}
// TODO: filtrar a URL, para que ela não aceite & e etcs...
// $url = html_entity_decode($url);
if(isset($data["post"]) && is_array($data["post"])) $data["post"] = $this->preparePostData($data["post"]);
// TODO: open() -> Validação da $url passada.
return $this->cURL($url, $data);
}
// TODO: cURL() -> Arrumar a descrição dos parâmetros dessa função; especialmente o parâmetro $data que não pede só string, mas também uma array.
/**
* Faz as requisições, grava elas na array history, e inicia a análise dos headers.
* @param string $url A URL que será requisitada.
* @param string $data Uma string com dados em formato nome=valor&nome2=valor2&....,
* para ser passada em requisições POST.
* @return string | requisição_curl
*/
private function cURL($url, $data=null, &$multiplerequest=null) {
if(!isset($url) || !is_string($url)) {
throw new Exception("Browser::cURL - O primeiro parâmetro requer uma string.");
die();
}
if(isset($data) && !is_array($data)) {
throw new Exception("Browser::cURL - O segundo parâmetro, quando passado, requer uma array.");
die();
}
// Possiveis valores para $data:
// auth, post, referer
// post DEVE ser uma string de nome=valor&nome2=
// auth deve ser user:pass
array_push($this->history, array("url" => $url, "time" => time(), "data" => $data));
$this->headers[$this->historyCount] = array();
// TODO: cURL() -> Preparar headers aqui.
// TODO: cURL() -> Preparar referer aqui.
$rq = @curl_init($url);
// PREPARANDO OS COOKIES
// TODO: Está errado: o certo seria pegar o domínio com base na url passada
$domainCookie = isset($this->cookies[$this->domain]) ? implode(";", $this->cookies[$this->domain]) : null;
if(!$this->followLocationManual) {
try {
curl_setopt($rq, CURLOPT_FOLLOWLOCATION, 1);
} catch(Exception $e) {};
}
// Referer da página sempre será a página anterior, OU a própria página, se followLocationManual for 1
// Isso por que alguns logins pedem que o redirecionamento tenha como referer a página anterior.
// TODO: Criar um parâmetro na função openPage() para que essa função cURL trate o referer da forma que
// o usuário quiser, por exemplo: $isLoginURL (um parâmetro lá na openPage() que diz se a URL chamada é uma
// página de login, e caso seja, o referer usado seja da página anterior)...
if($this->followLocationManual) {
$referer = isset($this->history[$this->historyCount-1]) ? $this->history[$this->historyCount-1]["url"] : $url;
} else {
$referer = $url;
}
// Firefox 12 default headers.
$default_header = array(
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language: pt-br,pt;q=0.8,en-us;q=0.5,en;q=0.3",
"Accept-Encoding: gzip, deflate",
"Connection: keep-alive");
// GENERAL AREA
// #CURLOPT_ENCODING com o valor 'NULL' envia "Accept-Encoding: deflate, gzip", o inverso de "gzip, deflate" kkk
if(isset($data["auth"])) curl_setopt($rq, CURLOPT_USERPWD, $data["auth"]);
if(isset($data["encoder"])) curl_setopt($rq, CURLOPT_ENCODING, $data["encoder"]);
if(isset($domainCookie)) curl_setopt($rq, CURLOPT_COOKIE, $domainCookie);
if(!isset($data["ignore_referer"])) curl_setopt($rq, CURLOPT_REFERER, $referer);
curl_setopt_array($rq, array(
CURLOPT_HTTPHEADER => isset($data["header"]) ? $default_header.$data["header"] : $default_header,
CURLOPT_HEADER => 0, //(isset($multiplerequest) ? 1 : 0), (com essa linha comentada, multiplas requisições não terão header.
CURLOPT_TIMEOUT => $this->curl_timeout,
CURLOPT_MAXREDIRS => (isset($data["encoder"])) ? 1 : $this->curl_maxredirects, // Um valor seguro para impedir cair em loop.
CURLOPT_USERAGENT => $this->useragent,
// TODO: cURL() -> CURLOPT_SSL: Future Features.
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADERFUNCTION => array(&$this, 'HeaderListener'),
));
// USING PROXY?
if(isset($data["proxy"])) {
// proxyauth = 'user:password';
// curl_setopt($rq, CURLOPT_PROXYUSERPWD, $data["proxyauth"]);
// curl_setopt($rq, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($rq, CURLOPT_PROXY, $data["proxy"]);
}
// POST AREA
if(isset($data["post"])) {
curl_setopt($rq, CURLOPT_POST, 1);
curl_setopt($rq, CURLOPT_POSTFIELDS, $data["post"]);
}
// MULTIPLE_REQUESTS E RETURN AREA
if(isset($multiplerequest)) {
curl_multi_add_handle($multiplerequest, $rq);
return $rq;
} else {
// RETURN AREA
// TODO: cURL() -> Fazer um parser para o resultado da requisição, para filtrar tags na página a fim de criar robôs.
// Por isso que aqui, não faço diretamente: return curl_exec($rq);
$result = curl_exec($rq);
// Após a requisição vamos extrair todas as informações dos headers
$followURL = $this->parseHeaders($url);
// Retorna a requisição, ou chama a função recursivamente caso tenha que dar followLocation.
if($this->followLocationManual) {
if($followURL != null) return $this->cURL($followURL);
}
return $result;
}
}
public function getProxyList() {
$list = $this->open("http://www.ip-adress.com/proxy_list/");
preg_match_all("/\>(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{2,5})/", $list, $list);
return $list[1];
}
public function openMultipleRequest($data, $tipo=Browser::CURLMULTI_URLS, $url=null) {
// Cria um handler múltiplo.
$mh = curl_multi_init();
$container = array();
$conteudo = array();
$active = array();
if($tipo == Browser::CURLMULTI_URLS) {
// Manipula múltiplas requisições de urls diferentes.
// Isso aqui é só preparação; estamos apenas preparando as requisições (curl_init e curl_setopt's)
foreach($data["url"] as $url) {
// Chama a função que faz a requisição, mandando como parâmetro o manipulador curl_multi.
$container[] = $this->cURL($url, null, $mh);
}
// Aaaand... heeere we gooo!
do {
$n = curl_multi_exec($mh, $active);
usleep($this->curl_multi_timeout);
} while($active);
foreach ($container as $w) {
$conteudo[] = curl_multi_getcontent($w);
curl_multi_remove_handle($mh, $w);
curl_close($w);
}
} else if($tipo == Browser::CURLMULTI_POST) {
// $data é uma array de: {"auth"=>"autenticação", "post" => "post"}
// Ou seja, são vários índices de "posts";
// Manipula múltiplas requisições a uma mesma URL, mas com POSTS diferentes
foreach ($data as $pieceofdata) {
if(isset($pieceofdata["post"]) && is_array($pieceofdata["post"])) $pieceofdata["post"] = $this->preparePostData($pieceofdata["post"]);
// Chama a função que faz a requisição, mandando como parâmetro o manipulador curl_multi.
$container[] = $this->cURL($url, $pieceofdata, $mh);
}
// Aaaand... heeere we gooo! (again)
do {
curl_multi_exec($mh, $active);
usleep($this->curl_multi_timeout);
} while($active > 0);
foreach ($container as $w) {
$conteudo[] = curl_multi_getcontent($w);
curl_multi_remove_handle($mh, $w);
curl_close($w);
}
} else {
throw new Exception("Browser::openMultiplePage() -> something goes wrong!");
die();
}
return $conteudo;
}
/**
* Prepara a array passada como parâmetro para ser enviada como uma string
* @param array $data Array de dados de uma requisição POST em forma de array("nome" => valor)
* @return string
*/
private function preparePostData($data) {
if(!isset($data) || !is_array($data)) {
throw new Exception("Browser::preparePostData() - O parâmetro requer uma array.");
die();
}
// TODO: deprecated - usar http_build_query(), com aquele parâmetro que impede bug no Windows.
/*$str = "";
foreach ($data as $nome => $valor) $str .= "$nome=$valor&";
$str = substr($str, 0, strlen($str) - 1);
return $str;*/
return http_build_query($data);
}
// Analisa os headers da página, setando cookies para o domínio, etc.
// TODO: Esta função está errada. Para que o followLocationManual funcione, eu preciso setar os cookie para um
// domínio DEPOIS do redirect ter sido feito.
// OU seja, PRIMEIRO verificar se tem redirect, depois os cookies; e se tiver redirect, fazê-lo, e ai sim, na
// próxima chamada, pegar os cookies da requisição anterior (que vieram junto com o header do redirect anterior
// e setar.
private function parseHeaders($url) {
// Guarda possíveis cookies deste domínio
$cookies = array();
$domain = "";
// Nos headers, cada cookie está em uma linha Set-Cookie: logo precisamos desse loop.
foreach($this->headers[$this->historyCount] as $header) {
// Procura por Set-Cookie no header que está analisando, e guarda em $temp
preg_match("/Set-Cookie: (.+)/", $header, $temp);
// Se algum cookie foi encontrado, é separado
if(isset($temp[1]) && strlen(trim($temp[1])) > 0) {
// Separa o cookie em [nome,valor]
// Primeiro, vamos filtrar o cookie até o primeiro ';'
preg_match("/([^\;]*)/", $temp[1], $preCookie);
// Agora sim, separamos em [nome,valor]
$cookieReady = $this->splitCookie($preCookie[1]);
// Seta o cookie
// Lembre-se: para enviar um cookie, precisamos do nome=valor!
// Por isso, uso $cookieReady["name"]."=".$cookieReady["value"]
// Separei o cookie por [nome,valor] apenas para usar o nome dele como índice na array
$cookies[$cookieReady["name"]] = $cookieReady["name"]."=".$cookieReady["value"];
// Tenta pegar o nome de domínio através do $cookie
// Usando $temp[1], pois $splittedCookie[2] só tem o valor, e não as informações de domínio.
$this->domain = $this->returnDomainFromCookieHeader($temp[1]);
}
// Faz um followLocation 'manualmente' (sem usar CURL), caso a flag esteja ligada
if($this->followLocationManual) {
// Procura por Location: no header que está analisando, e guarda em $temp
preg_match("/Location: (.+)/", $header, $temp);
// Se achar uma linha com Location:, segue a url encontrada!
if(isset($temp[1])) {
$followUrl = $temp[1];
// TEMP: Usando essa linha, só fará redirecionamentos para o mesmo domínio.
// $followUrl = $url.$followUrl;
preg_match("/(^\/.+)/", $temp[1], $samedomain);
if(isset($samedomain[1])) {
preg_match("/(.+)\//", $url, $findslash);
if(isset($findslash[1])) {
$url = $findslash[1];
}
$followUrl = $url.$samedomain[1];
}
}
}
}
// Pega o domínio pela $url caso ele não esteja no cookie.
if(!$this->domain) $this->domain = $this->returnDomainFromURL($url);
// Se houve cookies, insere para a array $cookies[$domain] os cookies capturados.
// TODO: Isso está errado; ele sobrescreve todo o índice; e não, ele só pode adicionar cookies, e reenscrever os que já existem; sem deletar os que não serão modificados.
if(count($cookies) > 0) {
// Para cada cookie, vamos adicionar os que não existem, e subsituir os que já existem
foreach($cookies as $cookieName=>$cookieValue) {
$this->cookies[$this->domain][$cookieName] = $cookieValue;
}
}
// Aqui é um local seguro para incrementarmos o $historyCount.
$this->historyCount++;
// E depois de analisar todos os headers, faz um followLocation caso $followURL esteja setado.
if($this->followLocationManual && isset($followUrl)) {
return $followUrl;
} else return null;
}
/* FAIL on Ajax */
public function parsePage($page) {
// Primeiramente, vamos transformar $page em um DOMdocument válido, para usar XPath.
$document = new DOMDocument();
@$document->loadHTML($page);
$xpath = new DOMXPath($document);
// E vamos pegar todos os forms na página.
$domforms = $document->getElementsByTagName("form");
$formslength = $domforms->length;
$container = array();
// Para cada form encontrado na página
for($w=0;$w<$formslength;$w++) {
// Vamos pegar os inputs dentro dele.
$xpathinputs = $xpath->query(".//input", $domforms->item($w));
$inputslength = $xpathinputs->length;
// E para cada input encontrado...
for($z=0;$z<$inputslength;$z++) {
$inputs[$z] = array();
// Vamos pegar seus atributos, e jogá-los em uma array.
foreach($xpathinputs->item($z)->attributes as $name => $value) {
$inputs[$z][$name] = $value->value;
}
// Por fim, vamos pegar o nodeValue do input (se houver).
// TODO: Verificar se usar trim() aqui é seguro.
$inputs[$z]["nodeValue"] = trim($xpathinputs->item($z)->nodeValue);
}
// Após parsear os inputs do form, vamos pegar os atributos do form em si, e colocar tudo na array 'container'.
$attforms = array();
foreach($domforms->item($w)->attributes as $name => $value) {
$attforms[$name] = $value->value;
}
$attforms["nodeValue"] = trim($domforms->item($w)->nodeValue);
$attforms["inputs"] = $inputs;
array_push($container, $attforms);
}
// Tags 'script'
$domscripts = $document->getElementsByTagName("script");
$scriptslength = $domscripts->length;
$scriptscontainer = array();
for($t=0;$t<$scriptslength;$t++) {
if($domscripts->item($t)->hasAttribute("src")) {
$scriptscontainer["src{$t}"] = $domscripts->item($t)->getAttribute("src");
} else {
$scriptscontainer[$t] = $domscripts->item($t)->nodeValue;
}
}
array_push($container, $scriptscontainer);
return $container;
}
/**
* Separa um cookie em [nome,valor]
* @param string
* @return array
*/
private function splitCookie($cookie) {
if(!isset($cookie) || !is_string($cookie)) {
throw new Exception("Browser::splitCookie - O parâmetro requer uma string.");
die();
}
// Tira os espacinhos que tem entre os cookies
$cookie = trim($cookie);
// Para separar: nome vai até o primeiro ' = '
// 'valor' vai até o primeiro ' ; ' , o resto do cookie são informações de validade...
// Essas informações de validade são úteis apenas para por exemplo
// Pegar o domínio de onde o cookie é válido
// Pega o primeiro sinal de igual (o que separa nome/valor no cookie)
$position = stripos($cookie, "=");
// Separa por [nome,valor]
$name = substr($cookie, 0, $position);
$value = substr($cookie, $position+1);
return array("name" => $name, "value" => $value);
}
/**
* Grava o cookie atual (e do domínio atual) em um arquivo.
* Lembre-se: o cookie gravado será o da última requisição feita.
* O cookie gravado sempre será gravado em formato .txt
* @param string $filename O caminho onde o arquivo de texto será criado. Tenha certeza de que o local tem permissões de escrita (chmod 0777)
* @return int
*/
public function writeCookieOnFile($filename) {
if(!isset($filename) || !is_string($filename)) {
throw new Exception("Browser::writeCookieOnFile - O parâmetro requer uma string.");
die();
}
$cookie = implode(";", $this->cookies[$this->domain]);
if(!preg_match("/\.txt/", $filename)) $filename .= ".txt";
return file_put_contents("{$filename}", $cookie);
}
/**
* Retorna o nome de domínio passado a url.
* @param string $url
* @return string
*/
private function returnDomainFromURL($url) {
preg_match("/^(?:.?.tp.?\:\/\/)?([^\/]+)/", $url, $domain);
$domain = $domain[1];
if(isset($domain)) return $domain; else return null;
}
/**
* Pega o nome de domínio atráves do header de um Set-Cookie
* @param string $header
* @return string
*/
private function returnDomainFromCookieHeader($header) {
// Pega o nome do domínio que está no cookie
// TODO: Revisar esta regexp para pegar o nome do domínio no cookie (talvez mude de domínio para domínio)
preg_match("/domain=\.?([^;]+)/i", $header, $domain);
if(isset($domain[1])) {
$domain = trim($domain[1]);
return $domain;
} else {
return null;
}
}
//------------------------------------------------------------------------------------------------
// GETTERS/SETTERS
//------------------------------------------------------------------------------------------------
/**
* Seta um user-agent para nosso navegador.
* Use Browser::USERAGENT para facilitar.
* @param string $useragent Use uma das constantes em: Browser::USERAGENT
* return void
*/
public function setUserAgent($useragent) {
if(!isset($useragent) || !is_string($useragent)) {
throw new Exception("Browser::setUserAgent - O parâmetro requer uma string.");
die();
}
$this->useragent = $useragent;
}
/**
* Retorna a string representando o user-agent atual.
* @return string
*/
public function getUserAgent() {
return $this->useragent;
}
/**
* Retorna o domínio atual (o domínio da última requisição).
* @return string
*/
public function getDomainName() {
return $this->domain;
}
/**
* Retorna um cookie específico para um domínio. Se o cookie não existir, o método retorna null.
* @param string $cookie
* @param string $domain
* @return string
*/
public function getCookie($cookie, $domain=null) {
if(!is_string($cookie)) {
throw new Exception("Browser::getCookie - Parâmetro 1 requer uma string.");
die();
}
if(!isset($domain)) {
$domain = $this->domain;
} else if(!is_string($domain)) {
throw new Exception("Browser::getCookie - Parâmetro 2 requer uma string, ou valor nulo.");
die();
}
if(isset($this->cookies[$domain][$cookie])) {
return $this->cookies[$domain][$cookie];
} else {
return null;
}
}
/**
* Seta cookies para um domínio. O método apaga todos os cookies antigos daquele domínio!
* Esta função é útil quando se tem os cookies em uma string.
* Por exemplo, como os que são salvos com a função writeCookieOnFile().
* @param string $cookie Uma string contendo todos os cookies.
* @param string $dominio (OPCIONAL) Domínio onde serão usados os cookies.
*/
public function setCookie($cookie, $domain=null) {
if(!is_string($cookie)) {
throw new Exception("Browser::setCookie - Parâmetro 1 requer uma string.");
die();
}
// Se o domínio não foi passado, vamos usar o atual.
if(!isset($domain)) {
$domain = $this->domain;
} else if(!is_string($domain)) {
throw new Exception("Browser::setCookie - Parâmetro 2 requer uma string, ou valor nulo.");
die();
}
// Apagando os cookies antigos
$this->cookies[$domain] = array();
// Depois, vamos separar os cookies um por um, por [nome,valor]
$cookies = explode(";", $cookie);
foreach($cookies as $entirecookie) {
// Separa o cookie em [nome,valor]
$cookieready = $this->splitCookie($entirecookie);
// Seta o cookie
$this->cookies[$domain][$cookieready["name"]] = $cookieready["name"]."=".$cookieready["value"];
}
}
/**
* Configura para que as requisições não sejam feitas com CURLOPT_FOLLOWLOCATION, caso o host esteja
* em safe_mode, ou open_basedir. Use o parâmetro 1 para usar fazer redirecionamentos 'manualmente',
* 0 para usar CURLOPT_FOLLOWLOCATION. O valor default é 0.
* OBS: Ao ser instanciada, a classe já identifica se a função está habilitada no host, configurando automaticamente esse método.
* @param int $isRedirecting FALSE|0 -> Usa CURLOPT_FOLLOWLOCATION, TRUE|1 -> faz a requisição manualmente.
* @return void
*/
public function setManualRedirect($isRedirecting) {
$this->followLocationManual = (bool)$isRedirecting;
}
//------------------------------------------------------------------------------------------------
// DEBUG!
//------------------------------------------------------------------------------------------------
/**
* Dá um print_r em todas as variáveis importantes de uma só vez.
* @return void
*/
public function printAll() {
print_r(array(
"domain" => $this->domain,
"useragent" => $this->useragent,
"historyCount" => $this->historyCount,
"history" => $this->history,
"cookies" => $this->cookies,
"headers" => $this->headers,
));
}
}
?>