Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Cassiano José

Alterar dados de um site via PHP

Recommended Posts

Pessoal, eu terminei meu curso de PHP direitinho, mas sou iniciante.

Eu peguei um trabalho pra 'tentar' fazer o seguinte:

O Cara quer que eu 'modifique' o site de apostas pra ficar da forma dele, por exemplo, a cotação no site é de 1,29, então ele quer que essa cotação caia para 1,00 e os dados colocados não seja enviado para o site original, e sim para o sistema dele.

Até aí tudo bem, já tinha ideia de como ia fazer isso.

Mas demore demais e ele acabou contratando outro cara que fez isso em 1 mês e já vi funcionando, só não consigo entender como ele fez.

O site é https://br.sportingbet.com/esportes-futebol/brazil-carioca/1-102-190181.html

Vocês podem ver que a "casa" ta 1,30, eu poderia facilmente usar um preg_match e fazer a alteração desses 1,30 para 1,00 e exibir o site modificado em outra URL processada pelo PHP.

Mas quando verifico o código do site, vejo que essa função da cotação é em javascript, e é assim:

<div id="couponTemplate-params" style="display:none">
    <input id="displayCouponUrl"  value="/services/CouponTemplate.mvc/GetCoupon"/>
    <input id="action" value="EVENTCLASSCOUPON" />
    <input id="sportIds"  value="102" />
    <input id="marketTypeId"  value="" />
    <input id="eventId"  value="" />
    <input id="bookId" value=""/>
    <input id="eventClassId"  value="190181" />
    <input id="sportId"  value="102" />
    <input id="oddsFormat"  value="EU" />
</div>

Como os resultados da cotação aparecem no browse?

Já procurei em todos os .js e não consigo encontrar de onde parte os dados, fico nessa dúvida pra sempre!

Alguém sabe como o cara modificou a cotação pra ele e exibiu o site com cotação diferente no servidor dele?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Poxa, foi mal!

esqueci que os links expiram! rs

O link do site é esse: https://br.sportingbet.com/

Eu até o "clonei" usando o file_get_contents, mas como você pode visualizar no ip do meu servidor:

http://23.89.198.169/webalizer/pega-site.php

(não liguem pra desorganização do template, estou apenas testando)

... eu não consigo fazer os cliques da aposta funcionar ou modificar os números que estão na cotação.

Já hospedei todos os js e tal!

Não consigo mesmo entender, é um enigma pra mim este site!

Mas se alguém ajudasse a desvendar comigo eu ficaria realmente agradecido!

Não viria até aqui pedir ajuda se não já tivesse tentado todos os métodos que conheço rsrs

Vlw galera!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Enfim achei que eles estão em uma div:


     <div id="isOffered">

 
        
            <a class="price addBetButton footballBetButton" id="bk_84311315_mk_sel1" href="javascript:;">
            <span class="priceText wide UK">2/7</span>
            <span class="priceText wide EU">1.285</span>
            <span class="priceText wide US">-350</span>
            <span class="priceText wide CH">1.285</span>
            <span class="priceChangeArrow"></span>
            <input class="betCode" type="hidden" value="0]SK@84311315@321583997@NB*2~7*0*-1*0*0]CPN:0" />
            <input class="originalBetCode" type="hidden" value="0]SK@84311315@321583997@NB*2~7*0*-1*0*0]CPN:0" />            
</a>
    </div>

 <div id="isOffered">

 
        
            <a class="price addBetButton footballBetButton" id="bk_84312848_mk_sel1" href="javascript:;">
            <span class="priceText wide UK">2/7</span>
            <span class="priceText wide EU">1.285</span>
            <span class="priceText wide US">-350</span>
            <span class="priceText wide CH">1.285</span>
            <span class="priceChangeArrow"></span>
            <input class="betCode" type="hidden" value="0]SK@84312848@321589842@NB*2~7*0*-1*0*0]CPN:0" />
            <input class="originalBetCode" type="hidden" value="0]SK@84312848@321589842@NB*2~7*0*-1*0*0]CPN:0" />            
</a>
    </div>

Estão organizados por ID.

Qual seria a forma mais fácil pra mim alterar os valores de todos os campos "priceText wide UK" para -20% do número atual?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você pode utilizar uma regex para primeiro capturar os valores que você quer.

 

Depois faz o processamento diminuindo -20% e guarda os novos valores em um array na ordem correta. Com esse novo array você utiliza preg_replace para cada item do array até substituir todos os valores

 

Se você não quer mexer com expressões regulares, você pode utilizar uma biblioteca para webscrapping, como: https://github.com/FriendsOfPHP/Goutte

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você pode utilizar uma regex para primeiro capturar os valores que você quer.

 

Depois faz o processamento diminuindo -20% e guarda os novos valores em um array na ordem correta. Com esse novo array você utiliza preg_replace para cada item do array até substituir todos os valores

 

Se você não quer mexer com expressões regulares, você pode utilizar uma biblioteca para webscrapping, como: https://github.com/FriendsOfPHP/Goutte

Obrigado Lucas!

Vou tentar.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Lucas, como eu poderia fazer com que a página seja 100% 'clonada'?

Digo, porque usando o file_get_contents eu tenho site incompleto.

Tem alguma forma de eu utilizar classe html dom parser, para percorrer o html e obter os arquivos css, js, imagens, etc.?

se sim, me dá um exemplo por gentileza, porque não sei ainda trabalhar com dom parser corretamente.

pode ser um exemplo bem básico!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não, o dom parser serve apenas para parsear o dom, ou seja, te dar uma estrutura de objetos que você possa percorrer.

 

O que você quer é um proxy, é um pouco mais complexo, mas o conceito é simples: https://github.com/jenssegers/php-proxy

 

O que um proxy faz é pegar a requisição HTTP que o usuário envia pelo o seu site, faz outra requisição HTTP idêntica para o servidor de destino e mostra a resposta pro usuário. Dessa forma vai dar a impressão que o conteúdo veio do seu site, mas na realidade o seu servidor pegou o conteúdo de outro lugar.

 

Quando for executar o exemplo da biblioteca que eu te mandei, tenha certeza de rodar na raíz do documento, nao em subpastas. Pois veja o seguinte, se você tentar acessar no proxy:

http://localhost/meuproject/index.php

O seu proxy vai acessar no destino o exato mesmo caminho:

https://br.sportingbet.com/meuproject/index.php

Quando na realidade você só quer o /index.php e não /meuproject/index.php.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Para pegar o valor da porcentagem:

// 8000 - 100%
//    x -  20%
function percent($percent, $value) {
	// Porcentagem sob o valor total
	return ($value * $percent) / 100;
}

echo "Resultado (20% sob 8.000): " . percent(20, 8000);

Próximo passo é pegar o valor e colocar na função.

 

OBSERVAÇÃO:

Como havias dito que o valor é gerado por js, dei uma olhada nas requisições.

Uma delas foi a seguinte url:

https://br.sportingbet.com/services/Multiples.mvc/GetCoupon?couponAction=AMACMARKET&sportIds=0&marketTypeId=&eventId=&bookId=&eventClassId=1239&sportId=0&eventTimeGroup=

 

Que me retorna valores referentes aos que acho que querias.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Para pegar o valor da porcentagem:

// 8000 - 100%
//    x -  20%
function percent($percent, $value) {
	// Porcentagem sob o valor total
	return ($value * $percent) / 100;
}

echo "Resultado (20% sob 8.000): " . percent(20, 8000);

Próximo passo é pegar o valor e colocar na função.

 

OBSERVAÇÃO:

Como havias dito que o valor é gerado por js, dei uma olhada nas requisições.

Uma delas foi a seguinte url:

https://br.sportingbet.com/services/Multiples.mvc/GetCoupon?couponAction=AMACMARKET&sportIds=0&marketTypeId=&eventId=&bookId=&eventClassId=1239&sportId=0&eventTimeGroup=

 

Que me retorna valores referentes aos que acho que querias.

Cara, muito bom!

Eu me odeio por ainda não ter terminado e aprendido muito sobre programação rs

No caso no meu proxy: http://cassiano.streamrocha.com/sport/browse.php?u=https%3A%2F%2Fbr.sportingbet.com%2F&b=0&f=norefer

Como eu diminuiria em 20% o valor desses campos fazendo o parseamento fazendo uso do próprio parser do projeto do Glype?

o arquivo de parseamento é este:

<?php
/*******************************************************************
* Glype is copyright and trademark 2007-2015 UpsideOut, Inc. d/b/a Glype
* and/or its licensors, successors and assigners. All rights reserved.
*
* Use of Glype is subject to the terms of the Software License Agreement.
* http://www.glype.com/license.php
*******************************************************************
* This is the parser for the proxy - changes the original 'raw'
* document so that everything (images, links, etc.) is rerouted to
* be downloaded via the proxy script instead of directly.
******************************************************************/

class parser {

	# State of javascript parser - null for parse everything, false
	# for parse all non-standard overrides, or (array) with specifics
	private $jsFlagState;

	# Browsing options (Remove Scripts, etc.)
	private $htmlOptions;

	# Constructor accepts options and saves them in the object
	function __construct($htmlOptions, $jsFlags) {
		$this->jsFlagState = $jsFlags;
		$this->htmlOptions = $htmlOptions;
	}


	/*****************************************************************
	* HTML parsers - main parsing function splits up document into
	* component parts ('normal' HTML, scripts and styles)
	******************************************************************/

	function HTMLDocument($input, $insert='', $inject=false, $footer='') {
		if (strlen($input)>65536) {
			if (version_compare(PHP_VERSION, '5.3.7')<=0) {
				ini_set('pcre.backtrack_limit', 1000000);
			}
		}

		#
		# Apply parsing that only needs to be done once..
		#

		# Record the charset
		global $charset;
		if (!isset($charset)) {
			$meta_equiv = preg_match('#(<meta[^>]*http\-equiv\s*=[^>]*>)#is', $input, $tmp, PREG_OFFSET_CAPTURE) ? $tmp[0][0] : null;
			if (isset($meta_equiv)) {
				$charset = preg_match('#charset\s*=\s*["\']+([^"\'\s>]*)#is', $meta_equiv, $tmp, PREG_OFFSET_CAPTURE) ? $tmp[1][0] : null;
			}
		}
		if (!isset($charset)) {
			$meta_charset = preg_match('#<meta[^>]*charset\s*=\s*["\']+([^"\'\s>]*)#is', $input, $tmp, PREG_OFFSET_CAPTURE) ? $tmp[1][0] : null;
			if (isset($meta_charset)) {
				$charset = $meta_charset;
			}
		}

		# Remove empty script comments
		$input = preg_replace('#/\*\s*\*/#s', '', $input);

		# Remove conditional comments
		$input = preg_replace('#<\!\-\-\[if \!IE\]>\s*\-\->(.*?)<\!\[endif\]\-\->#s','$1',$input);
		$input = preg_replace('#<\!\-\-\[if.*?<\!\[endif\]\-\->#s','',$input);

		# Prevent websites from calling disableOverride()
		$input = preg_replace('#disableOverride#s', 'disabled___disableOverride', $input);

		# Remove titles if option is enabled
		if ( $this->htmlOptions['stripTitle'] || $this->htmlOptions['encodePage'] ) {
			$input = preg_replace('#<title.*?</title>#is', '', $input, 1);
			$input = preg_replace('#<meta[^>]*name=["\'](title|description|keywords)["\'][^>]*>#is', '', $input, 3);
            $input = preg_replace('#<link[^>]*rel=["\'](icon|shortcut icon)["\'][^>]*>#is', '', $input, 2);
		}

		# Remove and record a <base> href
		$input = preg_replace_callback('#<base href\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^\s"\\\'>]{1,2048}))(?(1)\\1|)[^>]*>#i', 'html_stripBase', $input, 1);

		# Proxy url= values in meta redirects
		$input = preg_replace_callback('#content\s*=\s*(["\\\'])?[0-9]+\s*;\s*url=([\\\'"]|&\#39;)?((?(?<=")[^"]+|(?(?<=\\\')[^\\\']+|[^\\\'" >]+)))(?(2)\\2|)(?(1)\\1|)#i', 'html_metaRefresh', $input, 1);

		# Process forms
		$input = preg_replace_callback('#<form([^>]*)>(.*?)</form>#is', 'html_form', $input);

		# Remove scripts blocks (avoids individual processing below)
		if ( $this->htmlOptions['stripJS'] ) {
			$input = preg_replace('#<script[^>]*>.*?</script>#is', '', $input);
		}


		#
		# Split up the document into its different types and parse them
		#

		# Build up new document into this var
		$new	  = '';
		$offset = 0;

		# Find instances of script or style blocks
		while ( preg_match('#<(s(?:cript|tyle))[^>]*>#i', $input, $match, PREG_OFFSET_CAPTURE, $offset) ) {

			# What type of block is this?
			$block = strtolower($match[1][0]);

			# Start position of content
			$outerStart = $match[0][1];
			$innerStart = $outerStart + strlen($match[0][0]);

			# Determine type of end tag and find it's position
			$endTag	 = "</$block>";
			$innerEnd = stripos($input, $endTag, $innerStart);
			if ($innerEnd===false) {
				$endTag	 = "</";
				$innerEnd = stripos($input, $endTag, $innerStart);
				if ($innerEnd===false) {
					$input = preg_replace('#<script[^>]*>.*?$#is', '', $input);
					break;
				}
			}
			$outerEnd = $innerEnd + strlen($endTag);

			# Parse everything up till here and add to the new document
			$new .= $this->HTML(substr($input, $offset, $innerStart - $offset));

			# Find parsing function
			$parseFunction = $block == 'style' ? 'CSS' : 'JS' ;

			# Add the parsed block
			$new .= $this->$parseFunction(substr($input, $innerStart, $innerEnd - $innerStart));

			# Move offset to new position
			$offset = $innerEnd;

		}

		# And add the final chunk (between last script/style block and end of doc)
		$new .= $this->HTML(substr($input, $offset));

		# Replace input with the updated document
		$input = $new;

		global $foundPlugin;
		if ( $foundPlugin && function_exists('postParse') ) {
			$input = postParse($input, 'html');
			$foundPlugin=false;
		}

		# Make URLs relative
		$input = preg_replace('#=\s*(["\'])?\s*https?://[^"\'>/]*/#i', '=$1/', $input);

		# Encode the page
		if ( $this->htmlOptions['encodePage'] ) {
			$input = encodePage($input);
		}

		#
		# Now add our own code bits
		#

		# Insert our mini form after the <body>
		if ( $insert !== false ) {

			# Check for a frameset
			if ( ( $useFrames = stripos($input, '<frameset') ) !== false ) {

				# Flag the frames so only first displays mini-form
				$input = preg_replace_callback('#<frame[^>]+src\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^\s"\\\'>]{1,2048}))(?(1)\\1|)#i', 'html_flagFrames', $input);

			}

			# Attempt to add after body
			$input = preg_replace('#(<body[^>]*>)#i', '$1' . $insert, $input, 1, $tmp);

			# Check it inserted and append (if not a frameset)
			if ( ! $tmp && ! $useFrames ) {
				$input = $insert . $input;
			}

		}

		# Insert our javascript library
		if ( $inject ) {

			# Generate javascript to insert
			$inject = injectionJS();

			# Add our proxy javascript after <head>
			$input = preg_replace('#(<head[^>]*>)#i', '$1' . $inject, $input, 1, $tmp);

			# If no <head>, just prepend
			if ( ! $tmp ) {
				$input = $inject . $input;
			}

		}

		# Add anything to the footer?
		if ( $footer ) {

			$input = preg_replace('#(</body[^>]*>)#i', $footer . '$1', $input, 1, $tmp);

			# If no </body>, just append the footer
			if ( ! $tmp ){
				$input .= $footer;
			}

		}

		# Return new document
		return $input;

	}

	# Parse HTML sections
	function HTML($input) {

		# Removing objects? Follow spec and display inner content of object tags instead.
		if ( $this->htmlOptions['stripObjects'] ) {

			# Remove all object tags (including those deprecated but still common)
			$input = preg_replace('#<(?>object|applet|param|embed)[^>]*>#i', '', $input, -1, $tmp);

			# Found any? Remove the corresponding end tags
			if ( $tmp ) {
				$input = preg_replace('#</(?>object|applet|param|embed)>#i', '', $input, $tmp);
			}

		} else {

			# Parse <param name="movie" value="URL"> tags
			$input = preg_replace_callback('#<param[^>]+value\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^\s"\\\'>]{1,2048}))(?(1)\\1|)[^>]*>#i', 'html_paramValue', $input);

			# To do: proxy object related URLs

		}

		# Show content within <noscript> tags
		# (preg_ seems to be faster than 2 str_ireplace() calls)
		if ( $this->htmlOptions['stripJS'] ) {
			$input = preg_replace('#</?noscript>#i', '', $input);
		}

		# remove srcset attribute for now
		$input = preg_replace('#srcset\s*=\s*[\\\'"][^"]*[\\\'"]#i', '', $input);

		# Parse onX events
		$input = preg_replace_callback('#\b(on(?<!\.on)[a-z]{2,20})\s*=\s*([\\\'"])?((?(2)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^\s"\\\'>]{1,2048}))(?(2)\\2|)#i', array(&$this, 'html_eventJS'), $input);

		# Parse style attributes
		$input = preg_replace_callback('#style\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^\s"\\\'>]{1,2048}))(?(1)\\1|)#i', array(&$this, 'html_elementCSS'), $input);

		# Proxy URL attributes - this is the bottleneck but optimized as much as possible
		$input = preg_replace_callback('#(?><[A-Z0-9]{1,15})(?>\s+[^>\s]+)*?\s*(?>(href|src|background|poster)\s*=(?!\\\\)\s*)(?>([\\\'"])?)((?(2)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^ >]{1,2048}))(?(2)\\2|)#i', 'html_attribute', $input);

		# Return changed input
		return $input;

	}

	# Proxy an onX javascript event
	function html_eventJS($input) {
		return $this->htmlOptions['stripJS'] ? '' : $input[1] . '=' . $input[2] . $this->JS($input[3]) . $input[2];
	}

	# Proxy a style="CSS" attribute
	function html_elementCSS($input) {
		return 'style=' . $input[1] . $this->CSS($input[2]) . $input[1];
	}


	/*****************************************************************
	* CSS parser - main parsing function
	* CSS parsing is a complicated by the caching of CSS files. We need
	* to consider (A) cross-domain caching and (B) the unique URLs option.
	*	 A) If possible, use a relative URL so the saved URLs do not explictly
	*		 point to a single domain.
	*	 B) There is a second set of callback functions with "_unique" suffixed
	*		 and these return the original URL to be reparesed.
	******************************************************************/

	# The URLs depend on the unique and path info settings. The type parameter allows
	# us to specify the unique callbacks.
	function CSS($input, $storeUnique=false) {

		# What type of parsing is this? Normally we parse any URLs to redirect
		# back through the proxy but not when storing a cache with unique URLs.
		$type = $storeUnique ? '_unique' : '';

		# CSS needs proxying the calls to url(), @import and src=''
		$input = preg_replace_callback('#\burl\s*\(\s*[\\\'"]?([^\\\'"\)]+)[\\\'"]?\s*\)#i', 'css_URL' . $type, $input);
		$input = preg_replace_callback('#@import\s*[\\\'"]([^\\\'"\(\)]+)[\\\'"]#i', 'css_import' . $type, $input);
		$input = preg_replace_callback('#\bsrc\s*=\s*([\\\'"])?([^)\\\'"]+)(?(1)\\1|)#i', 'css_src' . $type, $input);

		# Make URLs relative
		$input = preg_replace('#https?://[^"\'>/]*/#i', '/', $input);

		# Return changed
		return $input;

	}


	/*****************************************************************
	* Javascript parser - main parsing function
	*
	* The specific parts that need proxying depends on which javascript
	* functions we've been able to override. On first page load, the browser
	* capabilities are tested to see what we can do client-side and the results
	* sent back to us. This allows us to parse only what we have to.
	* If $CONFIG['override_javascript'] is disabled, all commands are parsed
	* server-side. This will use much more CPU!
	*
	* Commands to proxy only if no override at all:
	*	 document.write()
	*	 document.writeln()
	*	 window.open()
	*	 eval()
	*
	* Commands to proxy, regardless of browser capabilities:
	*	 location.replace()
	*	 .innerHTML=
	*
	* Commands to proxy if the extra "watch" flag is set
	* (the browser doesn't support the .watch() method):
	*	 location=
	*	 x.location=
	*	 location.href=
	*
	* Commands to proxy if the extra "setters" flag is set
	* (the browser doesn't support the __defineSetter__() method):
	*	 .src=
	*	 .href=
	*	 .background=
	*	 .action=
	*
	* Commands to proxy if the extra "ajax" flag is set
	* (the browser failed to override the .open() method):
	*	 XMLHttpRequest.open()
	******************************************************************/

	function JS($input) {

		# Stripping?
		if ( $this->htmlOptions['stripJS'] ) {
			return '';
		}

		# Get our flags
		$flags = $this->jsFlagState;

		# Unless we know we don't need to, apply all the browser-specific flags
		if ( ! is_array($this->jsFlagState) ) {
			$flags = array('ajax', 'watch', 'setters');
		}

		# If override is disabled, add a "base" flag
		if ( $this->jsFlagState === null ) {
			$flags[] = 'base';
		}

		# Start parsing!
		$search = array();

		# Create shortcuts to various search patterns:
		#	  "before"	  - matches preceeding character (string of single char) [ignoring whitespace]
		#	  "after"	  - matches next character (string of single char) [ignoring whitespace]
		#	  "id"		  - key for identifying the original match (e.g. if we have >1 of the same key)
		$assignmentPattern	= array('before'	  => '.',				  'after' => '='); 
		$methodPattern			= array('before'	  => '.',				  'after' => '(');
		$functionPattern		= array('after' => '(');

		# Configure strings to search for, starting with always replaced commands
		$search['innerHTML'][] = $assignmentPattern;
		$search['location'][]  = array('after' => '.', 'id' => 'replace()');
			# ^ This is only for location.replace() - other forms are handled later

		# Look for attribute assignments
		if ( in_array('setters', $flags) ) {
			$search['src'][]		= $assignmentPattern;
			$search['href'][]		= $assignmentPattern;
			$search['action'][]		= $assignmentPattern;
			$search['background'][] = $assignmentPattern;
			$search['poster'][] 	= $assignmentPattern;
		}

		# Look for location changes
		# location.href will be handled above, location= is handled here
		if ( in_array('watch', $flags) ) {
			$search['location'][] = array('after' => '=', 'id' => 'assignment');
		}

		# Look for .open() if either AJAX (XMLHttpRequest.open) or
		# base (window.open) flags are present
		if ( in_array('ajax', $flags) || in_array('base', $flags) ) {
			$search['open'][] = $methodPattern;
		}

		# Add the basic code if no override
		if ( in_array('base', $flags) ) {
			$search['eval'][]		= $functionPattern;
			$search['writeln'][]	  = $methodPattern;
			$search['write'][]	= $methodPattern;
		}

		# Set up starting parameters
		$offset			= 0;
		$length			= strlen($input);
		$searchStrings = array_keys($search);

		while ( $offset < $length ) {

			# Start off by assuming no more items (i.e. the next position
			# of interest is the end of the document)
			$commandPos = $length;

			# Loop through the search subjects
			foreach ( $searchStrings as $item ) {

				# Any more instances of this?
				if ( ( $tmp = strpos($input, $item, $offset) ) === false ) {

					# Nope, skip to next item
					continue;

				}

				# If $item is whole word?
				if ( ( $input[$tmp-1] == '_' ) || ctype_alpha($input[$tmp-1]) ) {
				    
				    # No
					continue;

				}

				# Closer to the currently held 'next' position?
				if ( $tmp < $commandPos ) {

					$commandPos = $tmp;
					$command = $item;

				}

			}

			# No matches found? Finish parsing.
			if ( $commandPos == $length ) {
				break;
			}

			# We've found the main point of interest; now use the
			# search parameters to check the surrounding chars to validate
			# the match.
			$valid = false;

			foreach ( $search[$command] as $pattern ) {

				# Check the preceeding chars
				if ( isset($pattern['before']) && str_checkprev($input, $pattern['before'], $commandPos-1) === false ) {
					continue;
				}

				# Check next chars
				if ( isset($pattern['after']) && ( $charPos = str_checknext($input, $pattern['after'], $commandPos + strlen($command), false, false) ) === false ) {
					continue;
				}

				$postCharPos = ($charPos + 1) + strspn($input, " \t\r\n", $charPos + 1);

				# Still here? Match must be OK so generate a match ID
				if ( isset($pattern['id']) ) {
					$valid = $command . $pattern['id'];
				} else {
					$valid = $command;
				}

				break;
			}

			# What we do next depends on which match (if any) we've found...
			switch ( $valid ) {

				# Assigment
				case 'src':
				case 'href':
				case 'background':
				case 'poster':
				case 'action':
				case 'locationassignment':
				case 'innerHTML':

					# Check our post-char position for = as well (could be equality
					# test rather than assignment, i.e. == )
					if ( ! isset($input[$postCharPos]) || $input[$postCharPos] == '=' ) {
						break;
					}

					# Find the end of this statement
					$endPos = analyzeAssign_js($input, $charPos);
					$valueLength = $endPos - $postCharPos;

					# Produce replacement command
					$replacement = sprintf('parse%s(%s)', $command=='innerHTML' ? 'HTML' : 'URL', substr($input, $postCharPos, $valueLength));

					# Adjust total document length as appropriate
					$length += strlen($replacement);

					# Make the replacement
					$input = substr_replace($input, $replacement, $postCharPos, $valueLength);

					# Move offset up to new position
					$offset = $endPos + 10;

					# Go get next match
					continue 2;


				# Function calls - we don't know for certain if these are in fact members of the
				# appropriate objects (window/XMLHttpRequest for .open(), document for .write() and
				# .writeln) so we won't change anything. Main.js still overrides these functions but
				# does nothing with them by default. We add an extra parameter to tell our override
				# to kick in.
				case 'open':
				case 'write':
				case 'writeln':

					# Find the end position (the closing ")" for the function call)
					$endPos = analyze_js($input, $charPos);

					# Insert our additional argument just before that
					$glStr=',"gl"';
					if (strspn($input, ";\n\r\+{}()[]", $charPos) >= ($endPos - $charPos)) {
						$glStr='"gl"';
					}
					$input = substr_replace($input, $glStr, $endPos - 1, 0);

					# Adjust the document length
					$length += strlen($glStr);

					# And move the offset
					$offset = $endPos + strlen($glStr);

					# Get next match
					continue 2;


				# Eval() is a just as easy since we can just wrap the entire thing in parseJS().
				case 'eval':

					# Ensure this is a call to eval(), not anotherfunctionendingineval()
					if ( isset($input[$commandPos-1]) && strpos('abcdefghijklmnopqrstuvwxyz123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_', $input[$commandPos-1]) !== false ) {
						break;
					}

					# Find the end position (the closing ")" for the function call)
					$endPos = analyze_js($input, $charPos);
					$valueLength = $endPos - $postCharPos;

					# Generate our replacement
					$replacement = sprintf('parseJS(%s)', substr($input, $postCharPos, $valueLength));

					# Make the replacement
					$input = substr_replace($input, $replacement, $postCharPos, $valueLength);

					# Adjust the document length
					$length += 9;

					# And move the offset
					$offset = $endPos + 9;
					continue 2;


				# location.replace() is a tricky one. We have the position of the char
				# after . as $postCharPos and need to ensure we're calling replace(), 
				# then parse the entire URL
				case 'locationreplace()':

					# Validate the match
					if ( ! preg_match('#\Greplace\s*\(#', $input, $tmp, 0, $postCharPos) ) {
						break;
					}

					# Move $postCharPos to inside the brackets of .replace()
					$postCharPos += strlen($tmp[0]);

					# Find the end position (the closing ")" for the function call)
					$endPos = analyze_js($input, $postCharPos);
					$valueLength = $endPos - $postCharPos;

					# Generate our replacement
					$replacement = sprintf('parseURL(%s)', substr($input, $postCharPos, $valueLength));

					# Make the replacement
					$input = substr_replace($input, $replacement, $postCharPos, $valueLength);

					# Adjust the document length
					$length += 9;

					# And move the offset
					$offset = $endPos + 9;

					continue 2;
			}

			# Still here? A match didn't validate so adjust offset to just after
			# current position
			$offset = $commandPos + 1;

		}

		# Ignore document.domain
		$input = str_replace('document.domain', 'ignore', $input);

		# Return changed
		return $input;

	}

}


/*****************************************************************
* HTML callbacks
******************************************************************/

# Remove and record the <base> href
function html_stripBase($input) {
	global $base;
	$base = $input[2];
	return '';
}

# Proxy the location of a meta refresh
function html_metaRefresh($input) {
	return str_replace($input[3], proxyURL($input[3]), $input[0]);
}

# Proxy URL in <param name="movie" value="URL">
function html_paramValue($input) {

	# Check for a name="movie" tag
	if ( stripos($input[0], 'movie') === false ) {
		return $input[0];
	}

	return str_replace($input[2], proxyURL($input[2]), $input[0]);
}

# Process forms - the query string is used by the proxy script
# and GET data needs to be encoded anyway. We convert all GET
# forms to POST and then the proxy script will forward it properly.
function html_form($input) {

	# Check for a given method
	if ( preg_match('#\bmethod\s*=\s*["\\\']?(get|post)["\\\']?#i', $input[1], $tmp) ) {

		# Not POST?
		if ( strtolower($tmp[1]) != 'post' ) {

			# Convert to post and flag as a conversion
			$input[1] = str_replace($tmp[0], 'method="post"', $input[1]);
			$converted = true;

		}

	} else {

		# Append a POST method (no method given and GET is default)
		$input[1] .= ' method="post"';
		$converted = true;

	}

	# Prepare the extra input to insert
	$add = empty($converted) ? '' : '<input type="hidden" name="convertGET" value="1">';

	# To do: javascript onsubmit event to immediately redirect to the appropriate
	# location using GET data, without an intermediate POST to the proxy script.

	# Proxy the form action
	$input[1] = preg_replace_callback('#\baction\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^\s"\\\'>]{1,2048}))(?(1)\\1|)#i', 'html_formAction', $input[1]);

	# What type of form is this? Due to register_globals support, PHP converts
	# a number of characters to _ in incoming variable names. To get around this,
	# we can use the raw post data from php://input but this is not available
	# for multipart forms. Instead we must encode the input names in these forms.
	if ( stripos($input[1], 'multipart/form-data') ) {

		$input[2] = preg_replace_callback('#name\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^\s"\\\'>]{1,2048}))(?(1)\\1|)#i', 'html_inputName', $input[2]);

	}

	# Return updated form
	return '<form' . $input[1] . '>' . $add . $input[2] . '</form>';

}

# Proxy the action="URL" value in forms
function html_formAction($input) {
	return 'action=' . $input[1] . proxyURL($input[2]) . $input[1];
}

# Encode input names
function html_inputName($input) {
	return 'name=' . $input[1] . inputEncode($input[2]) . $input[1];
}

# Proxy URL values in attributes
function html_attribute($input) {

	# Is this an iframe?
	$flag = stripos($input[0], 'iframe') === 1 ? 'frame' : '';

	# URL occurred as value of an attribute and should have been htmlspecialchar()ed
	# We need to do the job of the browser and decode before proxying.
	return str_replace($input[3], htmlspecialchars(proxyURL(htmlspecialchars_decode($input[3]), $flag)), $input[0]);
}

# Flag frames in a frameset so only the first one shows the mini-form.
# This could be done in the above callback but adds extra processing
# when 99% of the time, it won't be needed.
function html_flagFrames($input) {

	static $addFlag;

	# If it's the first frame, leave it but set the flag var
	if ( ! isset($addFlag) ) {
		$addFlag = true;
		return $input[0];
	}

	# Add the frame flag
	$newURL = $input[2] . ( strpos($input[2], '?') ? '&f=frame' : 'fframe/');

	return str_replace($input[2], $newURL, $input[0]);

}


/*****************************************************************
* CSS callbacks
******************************************************************/

# Proxy CSS url(LOCATION)
function css_URL($input) {
	return 'url(' . proxyURL(trim($input[1])) . ')';
}

# Proxy CSS @import "URL"
function css_import($input) {
	return '@import "' . proxyURL($input[1]) . '"';
}

# Proxy CSS src=
function css_src($input) {
	return 'src=' . $input[1] . proxyURL($input[2]) . $input[1];
}

# Callbacks for use with unique URLs and cached CSS
# The <UNIQUE[]URL> acts as a marker for quick and easy processing later

# Unique CSS url(LOCATION)
function css_URL_unique($input) {
	return 'url(<UNIQUE[' . absoluteURL($input[1],'') . ']URL>)';
}

# Unique CSS @import "URL"
function css_import_unique($input) {
	return '@import "<UNIQUE[' . absoluteURL($input[1]) . ']URL>"';
}

# Unique CSS src=
function css_src_unique($input) {
	return 'src=' . $input[1] . '<UNIQUE[' . absoluteURL($input[2]) . ']URL>' . $input[1];
}


/*****************************************************************
* Helper functions
******************************************************************/

# Take a string, and check that the next non-whitespace char is the
# passed in char (X). Return false if non-whitespace and non-X char is
# found. Otherwise, return the position of X.
# If $inverse is true, the next non-whitespace char must NOT be in $char
# If $pastChar is true, ignore whitespace after finding X and return
# the position of the last post-X whitespace char.
function str_checknext($input, $char, $offset, $inverse = false, $pastChar = false) {

	for ( $i = $offset, $length = strlen($input); $i < $length; ++$i ) {

		# Examine char
		switch ( $input[$i] ) {

			# Ignore whitespace
			case ' ':
			case "\t":
			case "\r":
			case "\n":
				break;

			# Found the passed char
			case $char:

				# $inverse means we do NOT want this char
				if ( $inverse ) {
					return false;
				}

				# Move past this to the next non-whitespace?
				if ( $pastChar ) {
					++$i;
					return $i + strspn($input, " \t\r\n", $i);
				}

				# Found desired char, no $pastChar, just return  X offset
				return $i;

			# Found non-$char non-whitespace
			default:

				# This is the desired result if $inverse
				if ( $inverse ) {
					return $i;
				}

				# No $inverse, found a non-$char, return false
				return false;

		}

	}

	return false;

}


# Same as above but go backwards
function str_checkprev($input, $char, $offset, $inverse = false) {

	for ( $i = $offset; $i > 0; --$i ) {

		# Examine char
		switch ( $input[$i] ) {

			# Ignore whitespace
			case ' ':
			case "\t":
			case "\r":
			case "\n":
				break;

			# Found char
			case $char:
				return $inverse ? false : $i;

			# Found non-$char char
			default:
				return $inverse ? $i : false;

		}
	}

	return $inverse;

}


# Analyze javascript and return offset positions.
# Default is to find the end of the statement, indicated by:
#	 (1) ; while not in string
#	 (2) newline which, if not there, would create invalid syntax
#	 (3) a closing bracket (object, language construct or function call) for which
#		  no corresponding opening bracket was detected AFTER the passed offset
# If (int) $argPos is true, we return an array of the start and end position
# for the nth argument, where n = $argPos. The $start position must be just inside
# the parenthesis of the function call we're interested in.
function analyze_js($input, $start, $argPos = false) {

	# Add , if looking for an argument position
	if ( $argPos ) {
		$currentArg = 1;
	}

	# Loop through the input, stopping only at special chars
	for ( $i = $start, $length = strlen($input), $end = false, $openObjects = $openBrackets = $openArrays = 0;
			$end === false && $i < $length;
			++$i ) {
		$char = $input[$i];

		switch ( $char ) {

			# Starting string delimiters
			case '"':
			case "'":

				if ( $input[$i-1] == '\\' ) { 
					break;
				}

				# Skip straight to end of string
				# Find the corresponding end delimiter and ensure it's not escaped
				while ( ( $i = strpos($input, $char, $i+1) ) && $input[$i-1] == '\\' );

				# Check for false, in which case we assume the end is the end of the doc
				if ( $i === false ) {
					break 2;
				}

				break;

			# End of operation?
			case ';':
				$end = $i;
				break;

			# New lines
			case "\n":
			case "\r":
				# Newlines are OK if occuring within an open brackets, arrays or objects.
				if ( $openObjects || $openBrackets || $openArrays || $argPos ) {
					break;
				}

				# Newlines are also OK if followed by an opening function OR concatenation
				# e.g. someFunc\n(params) or someVar \n + anotherVar
				# Find next non-whitespace char position
				$tmp = $i + strspn($input, " \t\r\n", $i+1);

				# And compare to allowed chars
				if ( isset($input[$tmp+1]) && ( $input[$tmp+1] == '(' || $input[$tmp+1] == '+' ) ) {
					$i = $tmp;
					break;
				}

				# Newline not indicated as OK, set the end to here
				$end = $i;
				break;

			# Concatenation
			case '+':
				# Our interest in the + operator is it's use in allowing an expression
				# to span multiple lines. If we come across a +, move past all whitespace,
				# including newlines (which would otherwise indicate end of expression).
				$i += strspn($input, " \t\r\n", $i+1);
				break;

			# Opening chars (objects, parenthesis and arrays)
			case '{':
				++$openObjects;
				break;
			case '(':
				++$openBrackets;
				break;
			case '[':
				++$openArrays;
				break;

			# Closing chars - is there a corresponding open char?
			# Yes = reduce stored count. No = end of statement.
			case '}':
				$openObjects	? --$openObjects	 : $end = $i;
				break;
			case ')':
				$openBrackets	? --$openBrackets	 : $end = $i;
				break;
			case ']':
				$openArrays		? --$openArrays	 : $end = $i;
				break;

			# Commas - tell us which argument it is
			case ',':

				# Ignore commas inside other functions or whatnot
				if ( $openObjects || $openBrackets || $openArrays ) {
					break;
				}

				# End now
				if ( $currentArg == $argPos ) {
					$end = $i;
				}

				# Increase the current argument number
				++$currentArg;

				# If we're not after the first arg, start now?
				if ( $currentArg == $argPos ) {
					$start = $i+1;
				}

				break;

		}

	}

	# End not found? Use end of document
	if ( $end === false ) {
		$end = $length;
	}

	# Return array of start/end
	if ( $argPos ) {
		return array($start, $end);
	}

	# Return end
	return $end;

}
function analyzeAssign_js($input, $start) {

	# Loop through the input, stopping only at special chars
	for ( $i = $start, $length = strlen($input), $end = false, $openObjects = $openBrackets = $openArrays = 0;
			$end === false && $i < $length;
			++$i ) {
		$char = $input[$i];

		switch ( $char ) {

			# Starting string delimiters
			case '"':
			case "'":

				if ( $input[$i-1] == '\\' ) { 
					break;
				}

				# Skip straight to end of string
				# Find the corresponding end delimiter and ensure it's not escaped
				while ( ( $i = strpos($input, $char, $i+1) ) && $input[$i-1] == '\\' );

				# Check for false, in which case we assume the end is the end of the doc
				if ( $i === false ) {
					break 2;
				}

				break;

			# End of operation?
			case ';':
				$end = $i;
				break;

			# New lines
			case "\n":
			case "\r":
				# Newlines are OK if occuring within an open brackets, arrays or objects.
				if ( $openObjects || $openBrackets || $openArrays ) {
					break;
				}
				break;

			# Concatenation
			case '+':
				# Our interest in the + operator is it's use in allowing an expression
				# to span multiple lines. If we come across a +, move past all whitespace,
				# including newlines (which would otherwise indicate end of expression).
				$i += strspn($input, " \t\r\n", $i+1);
				break;

			# Opening chars (objects, parenthesis and arrays)
			case '{':
				++$openObjects;
				break;
			case '(':
				++$openBrackets;
				break;
			case '[':
				++$openArrays;
				break;

			# Closing chars - is there a corresponding open char?
			# Yes = reduce stored count. No = end of statement.
			case '}':
				$openObjects	? --$openObjects	 : $end = $i;
				break;
			case ')':
				$openBrackets	? --$openBrackets	 : $end = $i;
				break;
			case ']':
				$openArrays		? --$openArrays	 : $end = $i;
				break;

			# Commas - tell us which argument it is
			case ',':

				# Ignore commas inside other functions or whatnot
				if ( $openObjects || $openBrackets || $openArrays ) {
					break;
				}

				# End now
				$end = $i;
				break;

		}

	}

	# End not found? Use end of document
	if ( $end === false ) {
		$end = $length;
	}

	# Return end
	return $end;

}

/*****************************************************************
* Page encoding functions
******************************************************************/

# Encode page - splits into HTML/script sections and encodes HTML
function encodePage($input) {

	# Look for script blocks
#	if ( preg_match_all('#<(?:script|style).*?</(?:script|style)>#is', $input, $scripts, PREG_OFFSET_CAPTURE) ) { # not working
	if ( preg_match_all('#<script.*?</script>#is', $input, $scripts, PREG_OFFSET_CAPTURE) ) {

		# Create starting offset - only start encoding after the <head>
		# as this seems to help browsers cope!
		$offset = preg_match('#<body[^>]*>(.)#is', $input, $tmp, PREG_OFFSET_CAPTURE) ? $tmp[1][1] : 0;
		$new	  = $offset ? substr($input, 0, $offset) : '';

		# Go through all the matches
		foreach ( $scripts[0] as $id => $match ) {

			# Determine position of the preceeding non-script block
			$end	  = $match[1] ? $match[1]-1 : 0;
			$start  = $offset; 
			$length = $end - $start;

			# Add encoded block to page if there is one
			if ($length && $length>0) {
				$new .= "\n\n\n<!--start encode block-->\n";
				$new .= encodeBlock(substr($input, $start, $length));
				$new .= "\n<!--end encode block-->\n\n\n";
			}

			# Add unencoded script to page
			$new .= "\n\n\n<!--start unencoded block-->\n";
			$new .= $match[0];
			$new .= "\n<!--end unencoded block-->\n\n\n";

			# Move offset up
			$offset = $match[1] + strlen($match[0]);
		}

		# Add final block
		if ( $remainder = substr($input, $offset) ) {
			$new .= encodeBlock($remainder);
		}

		# Update input with new
		$input = $new;

	} else {
		# No scripts is easy - just encode the lot
		$input = encodeBlock($input);
	}

	# Return the encoded page
	return $input;
}

# Encode block - applies the actual encoding
# note - intended to obfustate URLs and HTML source code. Does not provide security. Use SSL for actual security.
function encodeBlock($input) {
	global $charset;
	$new='';

	if (isset($charset)) {
		$charset=strtolower($charset);
		if (function_exists('mb_convert_encoding')) {
			$input=mb_convert_encoding($input, 'HTML-ENTITIES', $charset);
		}
	}

	# Return javascript decoder
	return '<script type="text/javascript">document.write(arcfour(ginf.enc.u,base64_decode(\'' . arcfour('encrypt',$GLOBALS['unique_salt'],$input) . '\')));</script>';
}

E o arquivo de exibição é este:

<?php
/*******************************************************************
* Glype is copyright and trademark 2007-2015 UpsideOut, Inc. d/b/a Glype
* and/or its licensors, successors and assigners. All rights reserved.
*
* Use of Glype is subject to the terms of the Software License Agreement.
* http://www.glype.com/license.php
*******************************************************************
* This file is the main component of the glype proxy application.
* It decodes values contained within the current URI to determine a
* resource to download and pass onto the user.
******************************************************************/

/*****************************************************************
* Initialise
******************************************************************/

require 'includes/init.php';

if (count($adminDetails)===0) {
	header("HTTP/1.1 302 Found"); header("Location: admin.php"); exit;
}

# Debug mode - stores extra information in the cURL wrapper object and prints it
# out. It produces an ugly mess but still a quick tool for debugging.
define('DEBUG_MODE', 0);
define('CURL_LOG', 0);

# Log cURLs activity to file
# Change filename below if desired. Ensure file exists and is writable.
if ( CURL_LOG	&& ( $fh = @fopen('curl.txt', 'w')) ) {
	$toSet[CURLOPT_STDERR] = $fh;
	$toSet[CURLOPT_VERBOSE] = true;
}


/*****************************************************************
* PHP sends some headers by default. Stop them.
******************************************************************/

# Clear the default mime-type
header('Content-Type:');

# And remove the caching headers
header('Cache-Control:');
header('Last-Modified:');


/*****************************************************************
* Find URI of resource to load
* Flag and bitfield already extracted in /includes/init.php
******************************************************************/

switch ( true ) {

	# Try query string for URL
	case ! empty($_GET['u']) && ( $toLoad = deproxyURL($_GET['u'], true) ):
		break;

	# Try path info
	case ! empty($_SERVER['PATH_INFO'])	 && ( $toLoad = deproxyURL($_SERVER['PATH_INFO'], true) ):
		break;

	# Found no valid URL, return to index
	default:
		redirect();
}

# Validate the URL
if ( ! preg_match('#^((https?)://(?:([a-z0-9-.]+:[a-z0-9-.]+)@)?([a-z0-9-.]+)(?::([0-9]+))?)(?:/|$)((?:[^?/]*/)*)([^?]*)(?:\?([^\#]*))?(?:\#.*)?$#i', $toLoad, $tmp) ) {

	# Invalid, show error
	error('invalid_url', htmlentities($toLoad));

}

# Rename parts to more useful names
$URL = array(
	'scheme_host'	=> $tmp[1],
	'scheme'		=> $tmp[2],
	'auth'			=> $tmp[3],
	'host'			=> strtolower($tmp[4]),
	'domain'		=> strtolower(preg_match('#(?:^|\.)([a-z0-9-]+\.(?:[a-z.]{5,6}|[a-z]{2,}))$#', $tmp[4], $domain) ? $domain[1] : $tmp[4]), # Attempt to split off the subdomain (if any)
	'port'			=> $tmp[5],
	'path'			=> '/' . $tmp[6],
	'filename'		=> $tmp[7],
	'extension'		=> pathinfo($tmp[7], PATHINFO_EXTENSION),
	'query'			=> isset($tmp[8]) ? $tmp[8] : ''
);

# Apply encoding on full URL. In theory all parts of the URL need various special
# characters encoding but this needs to be done by the author of the webpage.
# We can make a guess at what needs encoding but some servers will complain when
# receiving the encoded character instead of unencoded and vice versa. We want
# to edit the URL as little as possible so we're only encoding spaces, as this
# seems to 'fix' the majority of cases.
$URL['href'] = str_replace(' ', '%20', $toLoad);


# Add any supplied authentication information to our auth array
if ($URL['auth']) {
	$_SESSION['authenticate'][$URL['scheme_host']] = $URL['auth'];
}



/*****************************************************************
* Protect LAN from access through proxy
* This does not stop all hostnames that resolve to LAN IPs
* unless the line containing "gethostbyname" is uncommented below
******************************************************************/
if (preg_match('#^localhost#i', $URL['host'])) {
	error('banned_site', $URL['host']);
}

$host = $URL['host'];

#$host = gethostbyname($host); # uncomment for more complete protection

if (preg_match('#^\d+$#', $host)) { # decimal IPs
	$host = implode('.', array($host>>24&255, $host>>16&255, $host>>8&255, $host&255));
}
if (preg_match('#^(0|10|127|169\.254|192\.168|172\.(?:1[6-9]|2[0-9]|3[01])|2[2-5][0-9])\.#', $host)) { # special use netblocks
	error('banned_site', $host);
}




/*****************************************************************
* Are we allowed to visit this site? Check whitelist/blacklist
******************************************************************/

# Whitelist - deny IF NOT on list
if ( ! empty($CONFIG['whitelist']) ) {

	$tmp = false;

	# Loop through
	foreach ( $CONFIG['whitelist'] as $domain ) {

		# Check for match
		if ( strpos($URL['host'], $domain) !== false ) {

			# Must be a permitted site
			$tmp = true;

		}

	}

	# Unless $tmp is flagged true, this is an illegal site
	if ( ! $tmp ) {
		error('banned_site', $URL['host']);
	}

}

# Blacklist
if ( ! empty($CONFIG['blacklist']) ) {

	# Loop through
	foreach ( $CONFIG['blacklist'] as $domain ) {

		# Check for match
		if ( strpos($URL['host'], $domain) !== false ) {

			# If matched, site is banned
			error('banned_site', $URL['host']);

		}

	}

}




/*****************************************************************
* Plugins
* Load any site-specific plugin.
******************************************************************/
global $foundPlugin;
$plugins = explode(',', $CONFIG['plugins']);
if ($foundPlugin = in_array($URL['domain'], $plugins)) {
	include(GLYPE_ROOT.'/plugins/'.$URL['domain'].'.php');
}



/*****************************************************************
* Close session to allow simultaneous transfers
* PHP automatically prevents multiple instances of the script running
* simultaneously to avoid concurrency issues with the session.
* This may be beneficial on high traffic servers but we have the option
* to close the session and thus allow simultaneous transfers.
******************************************************************/

if ( ! $CONFIG['queue_transfers'] ) {

	session_write_close();

}


/*****************************************************************
* Check load limit. This is done now rather than earlier so we
* don't stop serving the (relatively) cheap cached files.
******************************************************************/

if (
	# Option enabled (and possible? safe_mode prevents shell_exec)
	! SAFE_MODE && $CONFIG['load_limit']

	# Ignore inline elements - when borderline on the server load, if the HTML
	# page downloads fine but the inline images, css and js are blocked, the user
	# may get very frustrated very quickly without knowing about the load issues.
	&& ! in_array($URL['extension'], array('jpg','jpeg','png','gif','css','js','ico'))
	) {

	# Do we need to find the load and regenerate the temp cache file?
	# Try to fetch the load from the temp file (~30 times faster than
	# shell_exec()) and ensure the value is accurate and not outdated,
	if( ! file_exists($file = $CONFIG['tmp_dir'] . 'load.php') || ! (include $file) || ! isset($load, $lastChecked) || $lastChecked < $_SERVER['REQUEST_TIME']-60 ) {

		$load = (float) 0;

		# Attempt to fetch the load
		if ( ($uptime = @shell_exec('uptime')) && preg_match('#load average: ([0-9.]+),#', $uptime, $tmp) ) {
			$load = (float) $tmp[1];

			# And regenerate the file
			file_put_contents($file, '<?php $load = ' . $load . '; $lastChecked = ' . $_SERVER['REQUEST_TIME'] . ';');
		}

	}

	# Load found, (or at least, should be), check against max permitted
	if ( $load > $CONFIG['load_limit'] ) {
		error('server_busy'); # Show error
	}
}


/*****************************************************************
* * * * * * * * * * Prepare the REQUEST * * * * * * * * * * * *
******************************************************************/

/*****************************************************************
* Set cURL transfer options
* These options are merely passed to cURL and our script has no further
* impact or dependence of them. See the libcurl documentation and
* http://php.net/curl_setopt for more details.
*
* The following options are required for the proxy to function or
* inherit values from our config. In short: they shouldn't need changing.
******************************************************************/

# Time to wait for connection
$toSet[CURLOPT_CONNECTTIMEOUT] = $CONFIG['connection_timeout'];

# Time to allow for entire transfer
$toSet[CURLOPT_TIMEOUT] = $CONFIG['transfer_timeout'];

# Show SSL without verifying - we almost definitely don't have an up to date CA cert
# bundle so we can't verify the certificate. See http://curl.haxx.se/docs/sslcerts.html
$toSet[CURLOPT_SSL_VERIFYPEER] = false;
$toSet[CURLOPT_SSL_VERIFYHOST] = false;

# Send an empty Expect header (avoids 100 responses)
$toSet[CURLOPT_HTTPHEADER][] = 'Expect:';

# Can we use "If-Modified-Since" to save a transfer? Server can return 304 Not Modified
if ( isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ) {

	# How to treat the time condition : if un/modified since
	$toSet[CURLOPT_TIMECONDITION] = CURL_TIMECOND_IFMODSINCE;

	# The time value. Requires a timestamp so we can't just forward it raw
	$toSet[CURLOPT_TIMEVALUE] = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);

}

# Resume a transfer?
if ( $CONFIG['resume_transfers'] && isset($_SERVER['HTTP_RANGE']) ) {

	# And give cURL the right part
	$toSet[CURLOPT_RANGE] = substr($_SERVER['HTTP_RANGE'], 6);

}

# cURL has a max filesize option but it's not listed in the PHP manual so check it's available
if ( $CONFIG['max_filesize'] && defined('CURLOPT_MAXFILESIZE') ) {

	# Use the cURL option - should be faster than our implementation
	$toSet[CURLOPT_MAXFILESIZE] = $CONFIG['max_filesize'];

}


/*****************************************************************
* Performance options
* The values below are NOT the result of benchmarking tests. For
* optimum performance, you may want to try adjusting these values.
******************************************************************/

# DNS cache expiry time (seconds)
$toSet[CURLOPT_DNS_CACHE_TIMEOUT] = 600;

# Speed limits - aborts transfer if we're going too slowly
#$toSet[CURLOPT_LOW_SPEED_LIMIT] = 5; # speed limit in bytes per second
#$toSet[CURLOPT_LOW_SPEED_TIME] = 20; # seconds spent under the speed limit before aborting

# Number of max connections (no idea what this should be)
# $toSet[CURLOPT_MAXCONNECTS] = 100;

# Accept encoding in any format (allows compressed pages to be downloaded)
# Any bandwidth savings are likely to be minimal so better to save on load by
# downloading pages uncompressed. Use blank string for any compression or
# 'identity' to explicitly ask for uncompressed.
# $toSet[CURLOPT_ENCODING] = '';

# Undocumented in PHP manual (added 5.2.1) but allows uploads to some sites
# (e.g. imageshack) when without this option, an error occurs. Less efficient
# so probably best not to set this unless you need it.
#	 $toSet[CURLOPT_TCP_NODELAY] = true;


/*****************************************************************
* "Accept" headers
* No point sending back a file that the browser won't understand.
* Forward all the "Accept" headers. For each, check if it exists
* and if yes, add to the custom headers array.
* These may cause problems if the target server provides different
* content for the same URI based on these headers and we cache the response.
******************************************************************/

# Language (geotargeting will find the location of the server -
# forwarding this header can help avoid incorrect localisation)
if ( isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ) {
	$toSet[CURLOPT_HTTPHEADER][] = 'Accept-Language: ' . $_SERVER['HTTP_ACCEPT_LANGUAGE'];
}

# Accepted filetypes
if ( isset($_SERVER['HTTP_ACCEPT']) ) {
	$toSet[CURLOPT_HTTPHEADER][] = 'Accept: ' . $_SERVER['HTTP_ACCEPT'];
}

# Accepted charsets
if ( isset($_SERVER['HTTP_ACCEPT_CHARSET']) ) {
	$toSet[CURLOPT_HTTPHEADER][] = 'Accept-Charset: ' . $_SERVER['HTTP_ACCEPT_CHARSET'];
}


/*****************************************************************
* Browser options
* Allows customization of a "virtual" browser via /extras/edit-browser.php
******************************************************************/

# Send user agent
if ( $_SESSION['custom_browser']['user_agent'] ) {
	$toSet[CURLOPT_USERAGENT] = $_SESSION['custom_browser']['user_agent'];
}

# Set referrer
if ( $_SESSION['custom_browser']['referrer'] == 'real' ) {

	# Automatically determine referrer
	if ( isset($_SERVER['HTTP_REFERER']) && $flag != 'norefer' && strpos($tmp = deproxyURL($_SERVER['HTTP_REFERER']), GLYPE_URL) === false ) {
		$toSet[CURLOPT_REFERER] = $tmp;
	}

} else if ( $_SESSION['custom_browser']['referrer'] ) {

	# Send custom referrer
	$toSet[CURLOPT_REFERER] = $_SESSION['custom_browser']['referrer'];

}

# Clear the norefer flag
if ( $flag == 'norefer' ) {
	$flag = '';
}


/*****************************************************************
* Authentication
******************************************************************/

# Check for stored credentials for this site
if ( isset($_SESSION['authenticate'][$URL['scheme_host']]) ) {

	# Found credentials so use them!
	$toSet[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC;
	$toSet[CURLOPT_USERPWD] = $_SESSION['authenticate'][$URL['scheme_host']];

}


/*****************************************************************
* Cookies
* Find the relevant cookies for this request. All cookies get sent
* to the proxy, but we only want to forward the ones that were set
* for the current domain.
*
* Cookie storage methods:
* (1) Server-side - cookies stored server-side and handled
*		(mostly) internally by cURL
* (2) Encoded	- cookies forwarded to client but encoded
* (3) Normal - cookies forwarded without encoding
******************************************************************/

# Are cookies allowed?
if ( $options['allowCookies'] ) {

	# Option (1): cookies stored server-side
	if ( $CONFIG['cookies_on_server'] ) {

		# Check cookie folder exists or try to create it
		if ( $s = checkTmpDir($CONFIG['cookies_folder'], 'Deny from all') ) {

			# Set cURL to use this as the cookie jar
			$toSet[CURLOPT_COOKIEFILE] = $toSet[CURLOPT_COOKIEJAR] = $CONFIG['cookies_folder'] . glype_session_id();

		}

	} else if ( isset($_COOKIE[COOKIE_PREFIX]) ) {

		# Encoded or unencoded?
		if ( $CONFIG['encode_cookies'] ) {

			# Option (2): encoded cookies stored client-side
			foreach ( $_COOKIE[COOKIE_PREFIX] as $attributes => $value ) {

				# Decode cookie to [domain,path,name]
				$attributes = explode(' ', base64_decode($attributes));

				# Check successful decoding and skip if failed
				if ( ! isset($attributes[2]) ) {
					continue;
				}

				# Extract parts
				list($domain, $path, $name) = $attributes;

				# Check for a domain match and skip if no match
				if ( stripos($URL['host'], $domain) === false ) {
					continue;
				}

				# Check for match and skip to next path if fail
				if ( stripos($URL['path'], $path) !== 0 ) {
					continue;
				}

				# Multiple cookies of the same name are permitted if different paths
				# so use path AND name as the key in the temp array
				$key = $path . $name;

				# Check for existing cookie with same domain, same path and same name
				if ( isset($toSend[$key]) && $toSend[$key]['path'] == $path && $toSend[$key]['domain'] > strlen($domain) ) {

					# Conflicting cookies so ignore the one with the less complete tail match
					# (i.e. the current one)
					continue;

				}

				# Domain and path OK, decode cookie value
				$value = base64_decode($value);

				# Only send secure cookies on https connection - secure cookies marked by !SEC suffix
				# so remove the suffix
				$value = str_replace('!SEC', '', $value, $tmp);

				# And if secure cookie but not https site, do not send
				if ( $tmp && $URL['scheme'] != 'https' ) {
					continue;
				}


				# Everything checked and verified, add to $toSend for further processing later
				$toSend[$key] = array('path_size' => strlen($path), 'path' => $path, 'domain' => strlen($domain), 'send' => $name . '=' . $value);

			}

		} else {

			# Option (3): unencoded cookies stored client-side
			foreach ( $_COOKIE[COOKIE_PREFIX] as $domain => $paths ) {

				# $domain holds the domain (surprisingly) and $path is an array
				# of keys (paths) and more arrays (each child array of $path = one cookie)
				# e.g. Array('domain.com' => Array('/' => Array('cookie_name' => 'value')))

				# First check for domain match and skip to next domain if no match
				if ( stripos($URL['host'], $domain) === false ) {
					continue;
				}

				# If conflicting cookies with same name and same path,
				# send the one with the more complete tail match. To do this we
				# need to know how long each match is/was so record domain length.
				$domainSize = strlen($domain);

				# Now look at all the available paths
				foreach ( $paths as $path => $cookies ) {

					# Check for match and skip to next path if fail
					if ( stripos($URL['path'], $path) !== 0 ) {
						continue;
					}

					# In final header, cookies are ordered with most specific path
					# matches first so include the length of match in temp array
					$pathSize = strlen($path);

					# All cookies in $cookies array should be sent
					foreach ( $cookies as $name => $value ) {

						# Multiple cookies of the same name are permitted if different paths
						# so use path AND name as the key in the temp array
						$key = $path . $name;

						# Check for existing cookie with same domain, same path and same name
						if ( isset($toSend[$key]) && $toSend[$key]['path'] == $path && $toSend[$key]['domain'] > $domainSize ) {

							# Conflicting cookies so ignore the one with the less complete tail match
							# (i.e. the current one)
							continue;

						}

						# Only send secure cookies on https connection - secure cookies marked by !SEC suffix
						# so remove the suffix
						$value = str_replace('!SEC', '', $value, $tmp);

						# And if secure cookie but not https site, do not send
						if ( $tmp && $URL['scheme'] != 'https' ) {
							continue;
						}

						# Add to $toSend for further processing later
						$toSend[$key] = array('path_size' => $pathSize, 'path' => $path, 'domain' => $domainSize, 'send' => $name . '=' . $value);

					}

				}

			}

		}

		# Ensure we have found cookies
		if ( ! empty($toSend) ) {

			# Order by path specificity (as per Netscape spec)
			function compareArrays($a, $b) {
				return ( $a['path_size'] > $b['path_size'] ) ? -1 : 1;
			}

			# Apply the sort to order by path_size descending
			uasort($toSend, 'compareArrays');

			# Go through the ordered array and generate the Cookie: header
			$tmp = '';

			foreach ( $toSend as $cookie ) {
				$tmp .= $cookie['send'] . '; ';
			}

			# Give the string to cURL
			$toSet[CURLOPT_COOKIE] = $tmp;

		}

		# And clear the toSend array
		unset($toSend);

	}

}


/*****************************************************************
* Post
* Forward the post data. Usually very simple but complicated by
* multipart forms because in those cases, the raw post is not available.
******************************************************************/

if ( ! empty($_POST) ) {

	# enable backward compatibility with cURL's @ option for uploading files in PHP 5.5 and 5.6
	if (version_compare(PHP_VERSION, '5.5')>=0) {
		$toSet[CURLOPT_SAFE_UPLOAD] = false;
	}

	# Attempt to get raw POST from the input wrapper
	if ( ! ($tmp = file_get_contents('php://input')) ) {

		# Raw data not available (probably multipart/form-data).
		# cURL will do a multipart post if we pass an array as the
		# POSTFIELDS value but this array can only be one deep.

		# Recursively flatten array to one level deep and rename keys
		# as firstLayer[second][etc]. Also apply the input decode to all
		# array keys.
		function flattenArray($array, $prefix='') {

			# Start with empty array
			$stack = array();

			# Loop through the array to flatten
			foreach ( $array as $key => $value ) {

				# Decode the input name
				$key = inputDecode($key);

				# Determine what the new key should be - add the current key to
				# the prefix and surround in []
				$newKey = $prefix ? $prefix . '[' . $key . ']' : $key;

				if ( is_array($value) ) {

					# If it's an array, recurse and merge the returned array
					$stack = array_merge($stack, flattenArray($value, $newKey));

				} else {

					# Otherwise just add it to the current stack
					$stack[$newKey] = clean($value);

				}

			}

			# Return flattened
			return $stack;

		}

		$tmp = flattenArray($_POST);

		# Add any file uploads?
		if ( ! empty($_FILES) ) {

			# Loop through and add the files
			foreach ( $_FILES as $name => $file ) {

				# Is this an array?
				if ( is_array($file['tmp_name']) ) {

					# Flatten it - file arrays are in the slightly odd format of
					# $_FILES['layer1']['tmp_name']['layer2']['layer3,etc.'] so add
					# layer1 onto the start.
					$flattened = flattenArray(array($name => $file['tmp_name']));

					# And add all files to the post
					foreach ( $flattened as $key => $value ) {
						$tmp[$key] = '@' . $value;
					}

				} else {

					# Not another array. Check if the file uploaded successfully?
					if ( ! empty($file['error']) || empty($file['tmp_name']) ) {
						continue;
					}

					# Add to array with @ - tells cURL to upload this file
					$tmp[$name] = '@' . $file['tmp_name'];

				}

				# To do: rename the temp file to it's real name before
				# uploading it to the target? Otherwise, the target receives
				# the temp name instead of the original desired name
				# but doing this may be a security risk.

			}

		}

		}

	# Convert back to GET if required
	if ( isset($_POST['convertGET']) ) {

		# Remove convertGET from POST array and update our location
		$URL['href'] .= ( empty($URL['query']) ? '?' : '&' ) . str_replace('convertGET=1', '', $tmp);

	} else {

		# Genuine POST so set the cURL post value
		$toSet[CURLOPT_POST] = 1;
		$toSet[CURLOPT_POSTFIELDS] = $tmp;

	}

}


/*****************************************************************
* Apply pre-request code from plugins
******************************************************************/

if ( $foundPlugin && function_exists('preRequest') ) {
	preRequest();
}


/*****************************************************************
* Make the request
* This request object uses custom header/body reading functions
* so we can start processing responses on the fly - e.g. we don't
* need to wait till the whole file has downloaded before deciding
* if it needs parsing or can be sent out unchanged.
******************************************************************/

class Request {

	# Response status code
	public $status = 0;

	# Headers received and read by our callback
	public $headers = array();

	# Returned data (if saved)
	public $return;

	# Reason for aborting transfer (or empty to continue downloading)
	public $abort;

	# The error (if any) returned by curl_error()
	public $error;

	# Type of resource downloaded [html, js, css] or empty if no parsing needed
	public $parseType;

	# Automatically detect(ed) content type?
	public $sniff = false;

	# Forward cookies or not
	private $forwardCookies = false;

	# Limit filesize?
	private $limitFilesize = 0;

	# Speed limit (bytes per second)
	private $speedLimit = 0;

	# URL array split into pieces
	private $URL;

	# = $options from the global scope
	private $browsingOptions;

	# Options to pass to cURL
	private $curlOptions;


	# Constructor - takes the parameters and saves them
	public function __construct($curlOptions) {

		global $options, $CONFIG;

		# Set our reading callbacks
		$curlOptions[CURLOPT_HEADERFUNCTION] = array(&$this, 'readHeader');
		$curlOptions[CURLOPT_WRITEFUNCTION] = array(&$this, 'readBody');

		# Determine whether or not to forward cookies
		if ( $options['allowCookies'] && ! $CONFIG['cookies_on_server'] ) {
			$this->forwardCookies = $CONFIG['encode_cookies'] ? 'encode' : 'normal';
		}

		# Determine a filesize limit
		if ( $CONFIG['max_filesize'] ) {
			$this->limitFilesize = $CONFIG['max_filesize'];
		}

		# Determine speed limit
		if ( $CONFIG['download_speed_limit'] ) {
			$this->speedLimit = $CONFIG['download_speed_limit'];
		}

		# Set options
		$this->browsingOptions = $options;
		$this->curlOptions = $curlOptions;

		# Extend the PHP timeout
		if ( ! SAFE_MODE ) {
			set_time_limit($CONFIG['transfer_timeout']);
		}

		# Record debug information
		if ( DEBUG_MODE ) {
			$this->cookiesSent = isset($curlOptions[CURLOPT_COOKIE]) ? $curlOptions[CURLOPT_COOKIE] : ( isset($curlOptions[CURLOPT_COOKIEFILE]) ? 'using cookie jar' : 'none');
			$this->postSent = isset($curlOptions[CURLOPT_POSTFIELDS]) ? $curlOptions[CURLOPT_POSTFIELDS] : '';
		}

	}

	# Make the request and return the downloaded file if parsing is needed
	public function go($URL) {

		# Save options
		$this->URL = $URL;

		# Get a cURL handle
		$ch = curl_init($this->URL['href']);

		# Set the options
		curl_setopt_array($ch, $this->curlOptions);

		# Make the request
		curl_exec($ch);

		# Save any errors (but not if we caused the error by aborting!)
		if ( ! $this->abort ) {
			$this->error = curl_error($ch);
		}

		# And close the curl handle
		curl_close($ch);

		# And return the document (will be empty if no parsing needed,
		# because everything else is outputted immediately)
		return $this->return;

	}


	/*****************************************************************
	* * * * * * * * * * Manage the RESPONSE * * * * * * * * * * * *
	******************************************************************/


	/*****************************************************************
	* Read headers - receives headers line by line (cURL callback)
	******************************************************************/

	public function readHeader($handle, $header) {

		# Extract the status code (can occur more than once if 100 continue)
		if ( $this->status == 0 || ( $this->status == 100 && ! strpos($header, ':') ) ) {
			$this->status = substr($header, 9, 3);
		}

		# Attempt to extract header name and value
		$parts = explode(':', $header, 2);

		# Did it split successfully? (i.e. was there a ":" in the header?)
		if ( isset($parts[1]) ) {

			# Header names are case insensitive
			$headerType = strtolower($parts[0]);

			# And header values will have trailing newlines and prevailing spaces
			$headerValue = trim($parts[1]);

			# Set any cookies
			if ( $headerType == 'set-cookie' && $this->forwardCookies ) {

				$this->setCookie($headerValue);

			}

			# Everything else, store as associative array
			$this->headers[$headerType] = $headerValue;

			# Do we want to forward this header? First list the headers we want:
			$toForward = array('last-modified',
									 'content-disposition',
									 'content-type',
									 'content-range',
									 'content-language',
									 'expires',
									 'cache-control',
									 'pragma');

			# And check for a match before forwarding the header.
			if ( in_array($headerType, $toForward) ) {
				header($header);
			}

		} else {

			# Either first header or last 'header' (more precisely, the 2 newlines
			# that indicate end of headers)

			# No ":", so save whole header. Also check for end of headers.
			if ( ( $this->headers[] = trim($header) ) == false ) {

				# Must be end of headers so process them before reading body
				$this->processHeaders();

				# And has that processing given us any reason to abort?
				if ( $this->abort ) {
					return -1;
				}

			}

		}

		# cURL needs us to return length of data read
		return strlen($header);

	}


	/*****************************************************************
	* Process headers after all received and before body is read
	******************************************************************/

	private function processHeaders() {

		# Ensure we only run this function once
		static $runOnce;

		# Check for flag and if found, stop running function
		if ( isset($runOnce) ) {
			return;
		}

		# Set flag for next time
		$runOnce = true;

		# Send the appropriate status code
		header(' ', true, $this->status);

		# Find out if we want to abort the transfer
		switch ( true ) {

			# Redirection
			case isset($this->headers['location']):

				$this->abort = 'redirect';

				return;

			# 304 Not Modified
			case $this->status == 304:

				$this->abort = 'not_modified';

				return;

			# 401 Auth required
			case $this->status == 401:

				$this->abort = 'auth_required';

				return;

			# Error code (>=400)
			case $this->status >= 400:

				$this->abort = 'http_status_error';

				return;

			# Check for a content-length above the filesize limit
			case isset($this->headers['content-length']) && $this->limitFilesize && $this->headers['content-length'] > $this->limitFilesize:

				$this->abort = 'filesize_limit';

				return;

		}

		# Still here? No need to abort so next we determine parsing mechanism to use (if any)
		if ( isset($this->headers['content-type']) ) {

			# Define content-type to parser type relations
			$types = array(
				'text/javascript'			=> 'javascript',
				'text/ecmascript'			=> 'javascript',
				'application/javascript'	=> 'javascript',
				'application/x-javascript'	=> 'javascript',
				'application/ecmascript'	=> 'javascript',
				'application/x-ecmascript'	=> 'javascript',
				'text/livescript'			=> 'javascript',
				'text/jscript'				=> 'javascript',
				'application/xhtml+xml'		=> 'html',
				'text/html'					=> 'html',
				'text/css'					=> 'css',
			#	'text/xml'					=> 'rss',
			#	'application/rss+xml'		=> 'rss',
			#	'application/rdf+xml'		=> 'rss',
			#	'application/atom+xml'		=> 'rss',
			#	'application/xml'			=> 'rss',
			);

			# Extract mimetype from charset (if exists)
			global $charset;
			$content_type = explode(';', $this->headers['content-type'], 2);
			$mime = isset($content_type[0]) ? trim($content_type[0]) : '';
			if (isset($content_type[1])) {
				$charset = preg_match('#charset\s*=\s*([^"\'\s]*)#is', $content_type[1], $tmp, PREG_OFFSET_CAPTURE) ? $tmp[1][0] : null;
			}

			# Look for that mimetype in our array to find the parsing mechanism needed
			if ( isset($types[$mime]) ) {
				$this->parseType = $types[$mime];
			}

			# validate mimetypes
			if (!preg_match('#^(application|audio|image|text|video)/#i', $mime)) {
				header('Content-Type: text/plain');
			}

		} else {

			# Tell our read body function to 'sniff' the data to determine type
			$this->sniff = true;

		}

		# If no content-disposition sent, send one with the correct filename
		if ( ! isset($this->headers['content-disposition']) && $this->URL['filename'] ) {
			header('Content-Disposition: filename="' . $this->URL['filename'] . '"');
		}

		# If filesize limit exists, content-length received and we're still here, the
		# content-length is OK. If we assume the content-length is accurate (and since
		# clients [and possibly libcurl too] stop downloading after reaching the limit,
		# it's probably safe to assume that),we can save on load by not checking the
		# limit with each chunk received.
		if ( $this->limitFilesize && isset($this->headers['content-length']) ) {
			$this->limitFilesize = 0;
		}

	}


	/*****************************************************************
	* Read body - takes chunks of data (cURL callback)
	******************************************************************/

	public function readBody($handle, $data) {

		# Static var to tell us if this function has been run before
		static $first;

		# Check for set variable
		if ( ! isset($first) ) {

			# Run the pre-body code
			$this->firstBody($data);

			# Set the variable so we don't run this code again
			$first = false;

		}

		# Find length of data
		$length = strlen($data);

		# Limit speed to X bytes/second
		if ( $this->speedLimit ) {

			# Limit download speed
			# Speed		 = Amount of data / Time
			# [bytes/s] = [bytes]			/ [s]
			# We know the desired speed (defined earlier in bytes per second)
			# and we know the number of bytes we've received. Now we need to find
			# the time that it should take to receive those bytes.
			$time = $length / $this->speedLimit; # [s]

			# Convert time to microseconds and sleep for that value
			usleep(round($time * 1000000));
		}

		# Monitor length if desired
		if ( $this->limitFilesize ) {

			# Set up a static downloaded-bytes value
			static $downloadedBytes;

			if ( ! isset($downloadedBytes) ) {
				$downloadedBytes = 0;
			}

			# Add length to downloadedBytes
			$downloadedBytes += $length;

			# Is downloadedBytes over the limit?
			if ( $downloadedBytes > $this->limitFilesize ) {

				# Set the abort variable and return -1 (so cURL aborts)
				$this->abort = 'filesize_limit';
				return -1;

			}

		}

		# If parsing is required, save as $return
		if ( $this->parseType ) {

			$this->return .= $data;

		} else {
			echo $data; # No parsing so print immediately
		}

		# cURL needs us to return length of data read
		return $length;

	}




	/*****************************************************************
	* Process first chunk of data in body
	* Sniff the content if no content-type was sent and create the file
	* handle if caching this.
	******************************************************************/

	private function firstBody($data) {

		# Do we want to sniff the data to gues the mimetype?
		if ( $this->sniff ) {
			if (preg_match('#<html\b.*<head\b#i', $data)) {
				header('Content-Type: text/html');
				$this->parseType = 'html';
			} else {
				header('Content-Type: text/plain');
			}
		}

		# Now we know if parsing is required, we can forward content-length
		if ( ! $this->parseType && isset($this->headers['content-length']) ) {
			header('Content-Length: ' . $this->headers['content-length']);
		}

	}


	/*****************************************************************
	* Accept cookies - takes the value from Set-Cookie: [COOKIE STRING]
	* and forwards cookies to the client
	******************************************************************/

	private function setCookie($cookieString) {

		# The script can handle cookies following the Netscape specification
		# (or close enough!) and supports "Max-Age" from RFC2109

		# Split parts by ;
		$cookieParts = explode(';', $cookieString);

		# Process each line
		foreach ( $cookieParts as $part ) {

			# Split attribute/value pairs by =
			$pair = explode('=', $part, 2);

			# Ensure we have a second part
			$pair[1] = isset($pair[1]) ? $pair[1] : '';

			# First pair must be name/cookie value
			if ( ! isset($cookieName) ) {

				# Name is first pair item, value is second
				$cookieName = $pair[0];
				$cookieValue = $pair[1];

				# Skip rest of loop and start processing attributes
				continue;

			}

			# If still here, must be an attribute (case-insensitive so lower it)
			$pair[0] = strtolower($pair[0]);

			# And save in array
			if ( $pair[1] ) {

				# We have a attribute/value pair so save as associative
				$attr[ltrim($pair[0])] = $pair[1];

			} else {

				# Not a pair, just a value
				$attr[] = $pair[0];

			}

		}

		# All cookies need to be sent to this script (and then we choose
		# the correct cookies to forward to the client) so the extra attributes
		# (path, domain, etc.) must be stored in the cookie itself

		# Cookies stored as c[domain.com][path][cookie_name] with values of
		# cookie_value;secure;
		# If encoded, cookie name becomes c[base64_encode(domain.com path cookie_name)]

		# Find the EXPIRES date
		if ( isset($attr['expires']) ) {

			# From the "Expires" attribute (original Netscape spec)
			$expires = strtotime($attr['expires']);

		} else if ( isset($attr['max-age']) ) {

			# From the "Max-Age" attribute (RFC2109)
			$expires = $_SERVER['REQUEST_TIME']+$attr['max-age'];

		} else {

			# Default to temp cookies
			$expires = 0;

		}

		# If temp cookies, override expiry date to end of session unless time
		# is in the past since that means the cookie should be deleted
		if ( $this->browsingOptions['tempCookies'] && $expires > $_SERVER['REQUEST_TIME'] ) {
			$expires = 0;
		}

		# Find the PATH. The spec says if none found, default to the current path.
		# Certain browsers default to the the root path so we'll do the same.
		if ( ! isset($attr['path']) ) {
			$attr['path'] = '/';
		}

		# Were we sent a DOMAIN?
		if ( isset($attr['domain']) ) {

			# Ensure it's valid and we can accept this cookie
			if ( stripos($attr['domain'], $this->URL['domain']) === false ) {

				# Our current domain does not match the specified domain
				# so we reject the cookie
				return;

			}

			# Some cookies will be sent with the domain starting with . as per RFC2109
			# The . then has to be stripped off by us when doing the tail match to determine
			# which cookies to send since ".glype.com" should match "glype.com". It's more
			# efficient to do any manipulations while forwarding cookies than on every request
			if ( $attr['domain'][0] == '.' ) {
				$attr['domain'] = substr($attr['domain'], 1);
			}

		} else {

			# No domain sent so use current domain
			$attr['domain'] = $this->URL['domain'];

		}

		# Check for SECURE cookie
		$sentSecure = in_array('secure', $attr);

		# Append "[SEC]" to cookie value if we should only forward to secure connections
		if ( $sentSecure ) {
			$cookieValue .= '!SEC';
		}

		# If we're on HTTPS, we can also send this cookie back as secure
		$secure = HTTPS && $sentSecure;

		# If the PHP version is recent enough, we can also forward the httponly flag
		$httponly = in_array('httponly', $attr) && version_compare(PHP_VERSION,'5.2.0','>=') ? true : false;

		# Prepare cookie name/value to save as
		$name = COOKIE_PREFIX . '[' . $attr['domain'] . '][' . $attr['path'] . '][' . inputEncode($cookieName) . ']';
		$value = $cookieValue;

		# Add encodings
		if ( $this->forwardCookies == 'encode' ) {

			$name = COOKIE_PREFIX . '[' . urlencode(base64_encode($attr['domain'] . ' ' . $attr['path'] . ' ' . urlencode($cookieName))) . ']';
			$value = base64_encode($value);

		}

		# Send cookie ...
		if ( $httponly ) {

			# ... with httponly flag
			setcookie($name, $value, $expires, '/', '', $secure, true);

		} else {

			# ... without httponly flag
			setcookie($name, $value, $expires, '/', '', $secure);

		}

		# And log if in debug mode
		if ( DEBUG_MODE ) {

			$this->cookiesReceived[] = array('name'			=> $cookieName,
														'value'			=> $cookieValue,
														'attributes'	=> $attr);

		}

	}

}


/*****************************************************************
* Execute the request
******************************************************************/

# Initiate cURL wrapper request object with our cURL options
$fetch = new Request($toSet);

# And make the request
$document = $fetch->go($URL);


/*****************************************************************
* Handle aborted transfers
******************************************************************/

if ( $fetch->abort ) {

	switch ( $fetch->abort ) {

		# Do a redirection
		case 'redirect':

			# Proxy the location
			$location = proxyURL($fetch->headers['location'], $flag);

			# Do not redirect in debug mode
			if ( DEBUG_MODE ) {
				$fetch->redirected = '<a href="' . $location . '">' . $fetch->headers['location'] . '</a>';
				break;
			}

			# Go there
			header('Location: ' . $location, true, $fetch->status);
			exit;


		# Send back a 304 Not modified and stop running the script
		case 'not_modified':
			header("HTTP/1.1 304 Not Modified", true, 304);
			exit;


		# 401 Authentication (HTTP authentication hooks not available in all PHP versions
		# so we have to use our method)
		case 'auth_required':

			# Ensure we have some means of authenticating and extract details about the type of authentication
			if ( ! isset($fetch->headers['www-authenticate']) ) {
				break;
			}

			# Realm to display to the user
			$realm = preg_match('#\brealm="([^"]*)"#i', $fetch->headers['www-authenticate'], $tmp) ? $tmp[1] : '';

			# Prevent caching
			sendNoCache();

			# Prepare template variables (session may be closed at this point so send via form)
			$tmp = array('site'	 => $URL['scheme_host'],
							 'realm'	 => $realm,
							 'return' => currentURL());

			# Show our form and quit
			echo loadTemplate('authenticate.page', $tmp);
			exit;


		# File request above filesize limit
		case 'filesize_limit':

			# If already sent some of the file, we can't display an error
			# so just stop running
			if ( ! $fetch->parseType ) {
				exit;
			}

			# Send to error page with filesize limit expressed in MB
			error('file_too_large', round($CONFIG['max_filesize']/1024/1024, 3));
			exit;


		# >=400 response code (some sort of HTTP error)
		case 'http_status_error':

			# Provide a friendly message
			$explain = isset($httpErrors[$fetch->status]) ? $httpErrors[$fetch->status] : '';

			# Simply forward the error with details
			error('http_error', $fetch->status, trim(substr($fetch->headers[0], 12)), $explain);
			exit;


		# Unknown (shouldn't happen)
		default:
			error('cURL::$abort (' . $fetch->abort .')');
	}

}

# Any cURL errors?
if ( $fetch->error ) {

	error('curl_error', $fetch->error);

}


/*****************************************************************
* Transfer finished and errors handle. Process the file.
******************************************************************/

# Is this AJAX? If so, don't cache, log or parse.
# Also, assume ajax if return is VERY short.
if ( $flag == 'ajax' || ( $fetch->parseType && strlen($document) < 10 ) ) {

	# Print if not already printed
	if ( $fetch->parseType ) {
		echo $document;
	}

	# And exit
	exit;
}

# Do we want to parse the file?
if ( $fetch->parseType ) {

	/*****************************************************************
	* Apply the relevant parsing methods to the document
	******************************************************************/

	# Decode gzip compressed content
	if (isset($fetch->headers['content-encoding']) && $fetch->headers['content-encoding']=='gzip') {
		if (function_exists('gzinflate')) {
			unset($fetch->headers['content-encoding']);
			$document=gzinflate(substr($document,10,-8));
		}
	}

	# Apply preparsing from plugins
	if ( $foundPlugin && function_exists('preParse') ) {
		$document = preParse($document, $fetch->parseType);
	}

	# Load the main parser
	require GLYPE_ROOT . '/includes/parser.php';

	# Create new instance, passing in the options that affect parsing
	$parser = new parser($options, $jsFlags);

	# Method of parsing depends on $parseType
	switch ( $fetch->parseType ) {

		# HTML document
		case 'html':

			# Do we want to insert our own code into the document?
			$inject = 
			$footer = 
			$insert = false;

			# Mini-form only if NOT frame or sniffed
			if ( $flag != 'frame' && $fetch->sniff == false ) {

				# Showing the mini-form?
				if ( $options['showForm'] ) {
					$toShow = array();

					# Prepare the options
					foreach ( $CONFIG['options'] as $name => $details ) {

						# Ignore if forced
						if ( ! empty($details['force']) )  {
							continue;
						}

						# Add to array
						$toShow[] = array(
							'name'		=> $name,
							'title'		=> $details['title'],
							'checked'	=> $options[$name] ? ' checked="checked" ' : ''
						);

					}

					# Prepare variables to pass to template
					if ($options['encodePage']) {
						$vars['url'] = ''; # Currently visited URL
					} else {
						$vars['url'] = $URL['href']; # Currently visited URL
					}
					$vars['toShow']	= $toShow; # Options
					$vars['return']	= rawurlencode(currentURL()); # Return URL (for clearcookies) (i.e. current URL proxied)
					$vars['proxy']	= GLYPE_URL; # Base URL for proxy directory

					# Load the template
					$insert = loadTemplate('framedForm.inc', $vars);

					# Wrap in enable/disble override to prevent the overriden functions
					# affecting anything in the mini-form (like ad codes)
					if ( $CONFIG['override_javascript'] ) {
						$insert = '<script type="text/javascript">disableOverride();</script>'
								  . $insert
								  . '<script type="text/javascript">enableOverride();</script>';
					}
				}

				# And load the footer
				$footer = $CONFIG['footer_include'];

			}

			# Inject javascript unless sniffed
			if ( $fetch->sniff == false ) {
				$inject = true;
			}

			# Run through HTML parser
			$document = $parser->HTMLDocument($document, $insert, $inject, $footer);

			break;


		# CSS file
		case 'css':

			# Run through CSS parser
			$document = $parser->CSS($document);

			break;


		# Javascript file
		case 'javascript':

			# Run through javascript parser
			$document = $parser->JS($document);

			break;

	}

	# Apply postparsing from plugins
	if ( $foundPlugin && function_exists('postParse') ) {
		$document = postParse($document, $fetch->parseType);
	}

	# Send output
	if ( ! DEBUG_MODE ) {

		# Do we want to gzip this? Yes, if all of the following are true:
		#	  - gzip option enabled
		#	  - client supports gzip
		#	  - zlib extension loaded
		#	  - output compression not automated
		if ( $CONFIG['gzip_return'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip') !== false && extension_loaded('zlib') && ! ini_get('zlib.output_compression') ) {

			# Send compressed (using level 3 compression - can be adjusted
			# to give smaller/larger files but will take longer/shorter time!)
			header('Content-Encoding: gzip');
			echo gzencode($document, 3);

		} else {

			# Send uncompressed
			echo $document;

		}

	}

}

if ( DEBUG_MODE ) {
	# Just dump the $fetch object in DEBUG_MODE
	$fetch->return = $document;
	echo '<pre>', print_r($fetch, 1), '</pre>';
}


/*****************************************************************
* Log the request
******************************************************************/

# Do we want to log? Check we want to log this type of request.
if ( $CONFIG['enable_logging'] && ( $CONFIG['log_all'] || $fetch->parseType == 'html' ) ) {

	# Is the log directory writable?
	if ( checkTmpDir($CONFIG['logging_destination'], 'Deny from all') ) {

		# Filename to save as
		$file = $CONFIG['logging_destination'] . '/' . date('Y-m-d') . '.log';

		# Line to write
		$write = str_pad($_SERVER['REMOTE_ADDR'] . ', ' , 17) . date('d/M/Y:H:i:s O') . ', ' . $URL['href'] . "\r\n";

		# Do it
		file_put_contents($file, $write, FILE_APPEND);

	}

}

Só queria clarear as idéias, se eu tivesse outro amigo que também fosse programador PHP eu o incomodava rs

mas como ainda falta eu abranger coisas no meu curso, se encontro meio perdido.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Consegui alterar os valores pra "1.00" pra testar, e me deparo com outro problema:

O javascript não recupera esse valor "1.00" e sim o valor original do site.

Se a requisição é feita pelo https://br.sportingbet.com/services/Multiples.mvc/GetCoupon?couponAction=AMACMARKET&sportIds=0&marketTypeId=&eventId=&bookId=&eventClassId=1239&sportId=0&eventTimeGroup=

 

Como vou alterar os valores?

Tenho que recriar a parte de cálculo ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.