#1 16-05-2008 00:17:19

Thibow
Administrateur
Lieu: Nord
Date d'inscription: 17-12-2007
Messages: 633
Site web

Cacher vous derriere votre ftp perso [proxy]

Bon je viens de faire une découverte vraiment pas mal du tout...

Un script, qui permet d'établir un anonymat discret. D'abord le code:

Code:

<?php
/* Local Socket Configuration */
$port        = 8888; # Port of your local listening socket
$max_conn    = 10;    # Maximum number of connections to your local socket
$header_max    = 1000; # Max header size.

#
# Part #1 [] Local Socket
#

# Client -> HTTP Request -> Local Socket -> Remote PHP file -> Local Socket -> HTTP Response -> Client
if(isset($argc) && $argc>1)
{
    $url = $argv[1];
    
    $handle = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    socket_bind($handle, '127.0.0.1', $port);
    socket_listen($handle,$max_conn);
    
    print "RProxy ready, listening on port $port";
    
    while(TRUE)
    {
        $packet = '';
        
        # Client -> HTTP Request -> Local Socket
        # The Local Socket receives an HTTP Request from Client
        
        if(!$_client = socket_accept($handle)) exit("socket_accept(): error ($handle).");
        
        $client_request = '';
        
        while( (eregi("Content-type.*boundary",$client_request) && !eregi("--[0-9]+--\r?\n",$client_request)) || (eregi("^POST",$client_request) && !ereg("\r\n\r\n.+\r\n\r\n",$client_request)) || !ereg("\r\n\r\n",$client_request) )
            { $client_request .= socket_read($_client, 2048, PHP_BINARY_READ); }
            
        preg_match("#Host: +([^\t\r\n]+)#i",$client_request,$client_host) or exit();
        $client_host = $client_host[1];
            
        print "\n".d()." -> $client_host ".strlen($client_request);
        
        # Local Socket -> Remote PHP file
        # The Local Socket sends the HTTP Request to the PHP file
        
        $infos      = parse_url($url);
        $phpf_host  = $infos['host'];
        $phpf_port  = isset($infos['port']) ? $infos['port'] : 80;
        
        $total = str_split(base64_encode($client_request),$header_max);
        
        $request  = "GET $url HTTP/1.1\r\n";
        $request .= "Host: $phpf_host\r\n";
        $request .= "User-Agent: Mozilla Firefox 5.0\r\n";
        
        for($i=0;$i<sizeof($total);$i++)
            $request .= "HTTP-Request-$i: ".$total[$i]."\r\n";

        $request .= "Connection: Close\r\n";
        $request .= "\r\n";
        
        # Remote PHP file -> Local Socket
        # The Local Socket receives the HTTP Response from the PHP file
        
        $_phpf = fsockopen($phpf_host,80);
        fputs($_phpf,$request);
        
        # Local Socket -> Client
        # The HTTP Response is transmitted by the Local Socket to the Client
        
        $http_response = '';
        while(!feof($_phpf)) $http_response .= fgets($_phpf);
        fclose($_phpf);
        
        
        # Remove HTTP Headers from PHP file's HTTP Response
        $code = explode("\r\n\r\n",$http_response);
        $http_response = '';
        for($i=1;$i<sizeof($code);$i++)
            $http_response .= $code[$i]."\r\n\r\n";
            
        $http_response = preg_replace("#^.*[\r\n]*HTTP#i","HTTP",$http_response);
        $http_response = preg_replace('#0[\r\n]*$#','',$http_response);
        
        socket_write($_client,$http_response,strlen($http_response));
        
        print "\n".d()." <- $client_host ".strlen($http_response);
        
        socket_close($_client);
    }
    
    
    exit();
}

#
# Part #2 [] Remote PHP File
#

if(!isset($_SERVER['HTTP_HTTP_REQUEST_0']))
{
    header("Location: http://google.com/");
    exit();
}

# Local Socket -> Remote PHP file -> Remote Host -> Remote PHP file -> Local Socket

# Local Socket -> Remote PHP file
# The PHP File receive the HTTP Request he must do


$client_request = '';
for($i=0;isset($_SERVER["HTTP_HTTP_REQUEST_$i"]);$i++)
    $client_request .= $_SERVER["HTTP_HTTP_REQUEST_$i"];
    
$client_request = base64_decode($client_request);

preg_match("#Host: +([^\t\r\n]+)#i",$client_request,$rhostname) or exit();
$rhostname = $rhostname[1];

# Clear client request

$clearheaders = array('Keep-Alive','Proxy-Connection');
for($i=0;$i<sizeof($clearheaders);$i++) $clearheaders[$i] = '#'.$clearheaders[$i].':.+\r\n#i';

$client_request = preg_replace($clearheaders,'',$client_request);
$client_request = preg_replace("#(Host:.+\r\n)#i","$1Connection: close\r\n",$client_request);

# Remote PHP file -> Remote Host
# The PHP file sends the HTTP Request

$_rhost = fsockopen($rhostname,80);
fputs($_rhost,$client_request);

# Remote Host -> Remote PHP file
# The PHP file receives the HTTP Response

$rhost_response = '';
while(!feof($_rhost)) $rhost_response .= fgets($_rhost);
fclose($_rhost);

# Remote PHP file -> Local Socket
# The PHP file displays the HTTP Response,
# which is recovered by the Local Socket

print $rhost_response;

function d()
{
    return date("H:i:s");
}

?>

Voila le principe, uplaodez ce script php sur votre serveur ftp.
Maintenant, exécutez en local ce script suivi l'adresse ou vous avez uploadé le script:

$ php proxy.php http://server.com/proxy.php

Le proxy est prêt, il vous suffit de configurer votre navigateur :

localhost:8888 (A savoir qu'en mattant la source on peut aisément changer le port)

Vous voici donc caché derriere l'ip de votre serveur web smile
Pas mal non ?

Hors ligne

 

#2 16-05-2008 16:26:26

conqueror
Modérateur
Date d'inscription: 02-02-2008
Messages: 124

Re: Cacher vous derriere votre ftp perso [proxy]

En effet smile


http://www.enregistrersous.com/images2/vignettes_images/17662858520080322212002.jpg
Conq` for raivheur ?

Hors ligne

 

#3 27-08-2010 15:05:46

bossno
Invité

Re: Cacher vous derriere votre ftp perso [proxy]

Bonjour, après des heures et des heures de recherches google, j'arrive enfin à un endroit où il y a exactement ce que je cherche, merci smile

Bien que ce post date d'il y a deux ans, j'espère que vous pourrez m'apporter une réponse aux questions (sachant que je suis assez débutant là dedans) :


J'ai copié le code, sauvegardé en *.php. Une fois uploadé, quand jessaie de l'ouvrir via mon navigateur, cela me redirige directement sur google. Jusque là ca me va, cependant, mon ip n'a pas l'air d'avoir été changé d'après "l'image de danasoft".

J'essaie alors de configurer mon navigateur (IE pour le test) comme dit dans ce post, "localhost:8888" selon le script, et pouf je suis comme "hors connection".

J'ai peut être fait quelque chose de mal dans ma manip, si je pouvais avoir quelques informations supplémentaires ?

(L'objectif étant de créer un proxy sur mon ftp afin qu'il ne soit jamais bloqué et ainsi obtenir un accès complet à internet dans les lieux où cela n'est pas possible, comme les ordinateurs de bureaux, écoles, publics ... Car souvent en plus de bloquer les sites sensibles et "ludiques", ils bloquent les accès aux sites proxys les plus courants, s'il existe une autre solution que celle que j'envisage, je suis preneur smile )

Je vous remercie d'avance pour toute l'aide que vous pourrez m'apporter smile

 

#4 02-09-2010 18:25:34

cabusar
Administrateur
Date d'inscription: 18-01-2008
Messages: 430

Re: Cacher vous derriere votre ftp perso [proxy]

Pour une fois que nous avons une question intéressante il n'y a pas de réponse. hmm

Je m'en vais de ce pas contacter l'auteur de ce topic pour qu'il vienne faire un tour. wink


smile big_smile lol tongue wink

Hors ligne

 

#5 02-09-2010 18:40:23

coyotus
#! Gourou Linux
Lieu: fort fort lointain
Date d'inscription: 16-05-2009
Messages: 184
Site web

Re: Cacher vous derriere votre ftp perso [proxy]

bossno a écrit:

Bonjour, après des heures et des heures de recherches google, j'arrive enfin à un endroit où il y a exactement ce que je cherche, merci smile

tu as pas du chercher tant que ça

http://www.glype.com/

pour ton souci tu as bien créer le script local additionnel ?

Dernière modification par coyotus (02-09-2010 18:42:38)


http://img705.imageshack.us/img705/5671/coyotusign.gif

Hors ligne

 

#6 04-09-2010 14:32:13

bossno
Invité

Re: Cacher vous derriere votre ftp perso [proxy]

Merci pour les réponses, vu que je n'ai pas eu de réponses ici, je suis allé sur le "site du zero" transférer ce topic afin d'obtenir une réponse. C'est là que l'on m'a aussi proposé glype, que bizarrement je n'ai pas trouvé par google.

De plus, selon un utilisateur du site du zero, et ce que j'ai pu comprendre en lisant le code proposé par thibow, le script ne transfert effectivement que le texte mais pas les images ou autres dont le nom du site bloqué apparaisse dans la source, du type "http://mon-site.com/image.jpg"

Et le script additionnel, mmh, pas bien compris comment il fallait procéder.


Glype a l'air efficace et simple, j'ai cependant plusieurs erreurs qui apparaissent lorsque je tente d'accéder à la page.

http://img409.imageshack.us/img409/4696/erreurd.jpg

Le problème de php 5 est résolu, mais les autre erreurs persistent.

 

#7 10-09-2010 13:22:21

Thibow
Administrateur
Lieu: Nord
Date d'inscription: 17-12-2007
Messages: 633
Site web

Re: Cacher vous derriere votre ftp perso [proxy]

Salut Bossno smile

Désolé pour le manque de réponse, le site est un peu au ralenti, on est en pleine de refonte de celui ci... smile

Sinon, je vais regarder a ce problème de plus prêt.

Pour t'es erreurs php, je pense que le problème vient de ton header...
Les entête doivent être placé avant TOUT le code de t'as page, en haut... sinon, sa plante.

De plus, il semblerai aussi qu'il y es une mauvaise gestion des sessions...

Peux tu balancer ton code ici pour qu'on regarde ?

Hors ligne

 

#8 10-09-2010 20:37:00

bossno
Invité

Re: Cacher vous derriere votre ftp perso [proxy]

Merci d'être passé ^^

J'ai résolu ces erreurs en recréant le dossier des sessions, plus d'erreur sur la page, cependant, lorsque je tente une recherche voici ce que j'obtiens :

Avec une url, ici (http://www.google.fr/) :

Code:

<br />
<b>Notice</b>:  Use of undefined constant CURLOPT_SSL_VERIFYPEER - assumed 'CURLOPT_SSL_VERIFYPEER' in <b>/mnt/114/sdb/a/5/edm92/unlock/browse.php</b> on line <b>447</b><br />
<br />
<b>Notice</b>:  Use of undefined constant CURLOPT_SSL_VERIFYHOST - assumed 'CURLOPT_SSL_VERIFYHOST' in <b>/mnt/114/sdb/a/5/edm92/unlock/browse.php</b> on line <b>448</b><br />
<br />
<b>Warning</b>:  curl_setopt_array() [<a href='function.curl-setopt-array'>function.curl-setopt-array</a>]: Array keys must be CURLOPT constants or equivalent interger values. in <b>/mnt/114/sdb/a/5/edm92/unlock/browse.php</b> on line <b>1008</b><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERREUR&nbsp;: L'URL demand&eacute;e n'a pu &ecirc;tre charg&eacute;e</TITLE>
<STYLE type="text/css"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}PRE{font-family:sans-serif}--></STYLE>
</HEAD><BODY>
<H1>ERREUR</H1>
<H2>L'URL demand&eacute;e n'a pu &ecirc;tre charg&eacute;e</H2>
<HR noshade size="1px">
<P>
En essayant de charger l'URL&nbsp;:
<A HREF="http://www.google.fr/">http://www.google.fr/</A>
<P>
L'erreur suivante a &eacute;t&eacute; rencontr&eacute;e&nbsp;:
<UL>
<LI>
<STRONG>
Acc&egrave;s interdit.
</STRONG>
<P>
La configuration du contr&ocirc;le d'acc&egrave;s interdit &agrave; votre requ&ecirc;te d'&ecirc;tre
accept&eacute;e &agrave; cette heure-ci. Veuillez contacter votre
prestataire de service si vous pensez que ceci n'a pas lieu d'&ecirc;tre.
</UL>
</P>


<br>
<hr>
<div id="footer">
Generated Wed, 08 Sep 2010 14:11:57 GMT by pageperso.priv.free.fr (squid/3.0.STABLE21)
</div>
</body></html>

Avec des mots, ici "aa" :

Code:

<br />
<b>Notice</b>:  Use of undefined constant CURLOPT_SSL_VERIFYPEER - assumed 'CURLOPT_SSL_VERIFYPEER' in <b>/mnt/114/sdb/a/5/edm92/unlock/browse.php</b> on line <b>447</b><br />
<br />
<b>Notice</b>:  Use of undefined constant CURLOPT_SSL_VERIFYHOST - assumed 'CURLOPT_SSL_VERIFYHOST' in <b>/mnt/114/sdb/a/5/edm92/unlock/browse.php</b> on line <b>448</b><br />
<br />
<b>Warning</b>:  curl_setopt_array() [<a href='function.curl-setopt-array'>function.curl-setopt-array</a>]: Array keys must be CURLOPT constants or equivalent interger values. in <b>/mnt/114/sdb/a/5/edm92/unlock/browse.php</b> on line <b>1008</b><br />
<br />
<b>Warning</b>:  Cannot modify header information - headers already sent by (output started at /mnt/114/sdb/a/5/edm92/unlock/browse.php:447) in <b>/mnt/114/sdb/a/5/edm92/unlock/includes/init.php</b> on line <b>818</b><br />
<br />
<b>Warning</b>:  Cannot modify header information - headers already sent by (output started at /mnt/114/sdb/a/5/edm92/unlock/browse.php:447) in <b>/mnt/114/sdb/a/5/edm92/unlock/includes/init.php</b> on line <b>819</b><br />
<br />
<b>Warning</b>:  Cannot modify header information - headers already sent by (output started at /mnt/114/sdb/a/5/edm92/unlock/browse.php:447) in <b>/mnt/114/sdb/a/5/edm92/unlock/includes/init.php</b> on line <b>820</b><br />
<br />
<b>Warning</b>:  Cannot modify header information - headers already sent by (output started at /mnt/114/sdb/a/5/edm92/unlock/browse.php:447) in <b>/mnt/114/sdb/a/5/edm92/unlock/includes/init.php</b> on line <b>864</b><br />

Je suis bien conscient que le script demande de taper une url, mais cest peut etre une piste ? Vu que je n'arrive pas a comprendre l'erreur hmm

"browse.php" au complet :

Code:

<?php
/*******************************************************************
* Glype Proxy Script
*
* Copyright (c) 2008, http://www.glype.com/
*
* Permission to use this script is granted free of charge
* subject to the terms displayed at http://www.glype.com/downloads
* and in the LICENSE.txt document of the glype package.
*******************************************************************
* 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';

// 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
* NB: flag and bitfield already extracted in /includes/init.php
******************************************************************/

switch ( true ) {

   // Try query string for URL
   case ! empty($_GET['u']) && ( $toLoad = deproxifyURL($_GET['u'], true) ):
      break;
      
   // Try path info
   case ! empty($_SERVER['PATH_INFO'])  && ( $toLoad = deproxifyURL($_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', $toLoad);

}

// Rename parts to more useful names
$URL  =  array('scheme_host' => $tmp[1],
               'scheme'      => $tmp[2],
               'auth'        => $tmp[3],
               'host'        => $tmp[4],
               'domain'      => 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);

// Protect LAN from access through proxy (protected addresses copied from PHProxy)
if ( preg_match('#^(?:127\.|192\.168\.|10\.|172\.(?:1[6-9]|2[0-9]|3[01])\.|localhost)#i', $URL['host']) ) {
   error('banned_site', $URL['host']);
}

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


/*****************************************************************
* Protect us from hotlinking
******************************************************************/

// Protect only if option is enabled and we don't have a verified session
if ( $CONFIG['stop_hotlinking'] && empty($_SESSION['no_hotlink']) ) {

   // Assume hotlinking to start with, then check against allowed domains
   $tmp = true;

   // Ensure we have valid referrer information to check
   if ( ! empty($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], 'http') === 0 ) {
      
      // Examine all the allowed domains (including our current domain)
      foreach ( array_merge( (array) GLYPE_URL, $CONFIG['hotlink_domains'] ) as $domain ) {

         // Do a case-insensitive comparison
         if ( stripos($_SERVER['HTTP_REFERER'], $domain) !== false ) {
            
            // This referrer is OK
            $tmp = false;
            break;
            
         }
      
      }

   }
   
   // Redirect to index if this is still identified as hotlinking
   if ( $tmp ) {
      error('no_hotlink');
   }

}

// If we're still here, the referrer must be OK so set the session for next time
$_SESSION['no_hotlink'] = true;


/*****************************************************************
* 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']);

      }

   }

}


/*****************************************************************
* Show SSL warning
* This warns users if they access a secure site when the proxy is NOT
* on a secure connection and the $CONFIG['ssl_warning'] option is on.
******************************************************************/

if ( $URL['scheme'] == 'https' && $CONFIG['ssl_warning'] && empty($_SESSION['ssl_warned']) && ! HTTPS ) {

   // Remember this page so we can return after agreeing to the warning
   $_SESSION['return'] = currentURL();

   // Don't cache the warning page
   sendNoCache();

   // Show the page
   echo loadTemplate('sslwarning.page');

   // All done!
   exit;

}


/*****************************************************************
* Plugins
* Load any site-specific plugin.
******************************************************************/

// Check for plugin file with the current domain name
$foundPlugin = file_exists($tmp = GLYPE_ROOT . '/plugins/' . $URL['domain'] . '.php') ? $tmp : false;

// Load now for increased flexibility (i.e. allows changing of curlopts, etc)
if ( $foundPlugin ) {
    include $foundPlugin;
}


/*****************************************************************
* 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();

}


/*****************************************************************
* Load resource from cache if possible
******************************************************************/

$saveAs = false;

// Look at our config to see if we want to cache this request
if ( $CONFIG['use_cache'] && in_array($URL['extension'], $CONFIG['cache_file_types']) ) {

   // Caching enabled and file type OK but do we want to cache for this site?
   if ( $CONFIG['cache_all'] ) {

      // Caching all sites
      $useCache = true;

   } else {

      // Look at our list of to-cache-for sites
      foreach ( $CONFIG['cache_sites'] as $domain ) {

         // Does this match our current URL?
         if ( strpos($URL['domain'], $domain) !== false ) {

            // Flag it and break out the loop to save redundant comparisons
            $useCache = true;
            break;

         }

      }

   }

   // Use the cache
   if ( ! empty($useCache) ) {

      // Generate the cached name. Take into account our URL encodings. Javascript
      // creates links on the fly and images obviously don't matter. CSS documents
      // however hardcode the links so we need to know the different encoding styles.
      $tmp = '';

      // Determine the suffix if necessary
      if ( $options['encodeURL'] && $URL['extension'] == 'css' ) {

         // Add 'p' for path info
         if ( $CONFIG['path_info_urls'] ) {
            $tmp = 'p';
         }

         // And 'u' for unique
         if ( $CONFIG['unique_urls'] ) {
            $tmp .= 'u';
         }

      }

      // And hash with sha1 to protect the actual URL.
      $cacheName = sha1($URL['href']) . $tmp . '.' . $URL['extension'];

      // Generate the appropriate path
      $saveAs = $CONFIG['cache_path'] . $cacheName;

      // Now we know what name the file would be saved as, see if it exists
      $foundCache = file_exists($saveAs);

      // Found cache, prepare to serve
      if ( $foundCache ) {

         // Even though the cache exists, we don't want to use it if we received no cache headers
         if ( ( ! isset($_SERVER['HTTP_CACHE_CONTROL']) || strpos($_SERVER['HTTP_CACHE_CONTROL'], 'no-cache') === false ) && ( ! isset($_SERVER['HTTP_PRAGMA']) || strpos($_SERVER['HTTP_PRAGMA'], 'no-cache') === false ) ) {

            // CSS documents have a problem with unique URLs because we
            // obviously can't save anyone's unique URL key in the CSS cache
            if ( $URL['extension'] == 'css' && $CONFIG['unique_urls'] ) {

               // Load up the file into a string
               $tmp = file_get_contents($saveAs);
            
               // Send headers - this is why we don't serve all cache hits through the script,
               // a webserver can do this much more efficiently and accurately!
               header('Content-Type: text/css');
               header('Content-Length: ' . strlen($tmp));
               header('Expires: ' . gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME']+216000) . ' GMT');
               header('Cache-Control: public, max-age=216000');
               header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($saveAs)) . ' GMT');

               // Is there a If-Modified-Since condition?
               if ( isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) <= filemtime($saveAs) ) {

                  // Simply send back Not Modified and finish
                  header("HTTP/1.1 304 Not Modified", true, 304);
                  exit;

               }

               // Create a callback function for replacements (see next comment)
               function reparseSalt($input) {
                  return proxifyURL($input[1]);
               }

               // Do a regex search replace to replace our URL markers with unique proxified URLs
               $tmp = preg_replace_callback('#<UNIQUE\[([^\]]+)\]URL>#', 'reparseSalt', $tmp);

               // And print the file
               echo $tmp;

            } else {

               // Everything else can be served as normal by the server
               header('Location: ' . $CONFIG['cache_url'] . $cacheName);

            }

            // Read from cache so stop running now
            exit;

         }

      }

      // If we're here that means we're going to write to the cache later
      // (i.e. cache should be used for this request but no cached file exists,
      // or was a hard refresh) so prepare the temporary directory.
      if ( ! checkTmpDir($CONFIG['cache_path']) ) {

         // The cache folder is not writable so disable caching
         $useCache = $foundCache = $saveAs = false;
      }

   }

}


/*****************************************************************
* 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'))
    ) {

   // 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'] ) {

       // Show error
       error('server_busy');

   }

}


/*****************************************************************
* * * * * * * * * * 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.
* NB: 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 = deproxifyURL($_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 = '';
}

// Tunnel through another proxy
if ( $_SESSION['custom_browser']['tunnel'] ) {

   $toSet[CURLOPT_PROXY]     = $_SESSION['custom_browser']['tunnel'];
   $toSet[CURLOPT_PROXYPORT] = $_SESSION['custom_browser']['tunnel_port'];
   $toSet[CURLOPT_PROXYTYPE] = $_SESSION['custom_browser']['tunnel_type'] == 'http' ? CURLPROXY_HTTP : CURLPROXY_SOCKS5;

}


/*****************************************************************
* 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'] . 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) ) {

   // 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;

   // Save the downloaded file (if no $parseType) for the cache with this path
   private $saveAs = false;

   // File handle for cache file
   private $cacheHandle;

   // 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] : '';
      }

   }

   // Save our cache filename
   public function saveCache($as) {
      $this->saveAs = $as;
   }

   // 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
      [color=red][b]curl_setopt_array($ch, $this->curlOptions);[/b][/color]

      // 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);

      // Close our cache file handle
      if ( $this->cacheHandle ) {

         fclose($this->cacheHandle);

         // This may have been forced to download with a hard refresh
         // so an existing cache file may exist. Delete it.
         if ( file_exists($this->saveAs) ) {
            unlink($this->saveAs);
         }

         // Now rename the temp name to the final name
         rename($this->saveAs . '.tmp', $this->saveAs);

      }

      // 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',
                        'application/javascript'   => 'javascript',
                        'application/x-javascript' => 'javascript',
                        'application/xhtml+xml'    => 'html',
                        'text/html'                => 'html',
                        'text/css'                 =>    'css');

         // Extract mimetype from charset (if exists)
         list($mime) = explode(';', $this->headers['content-type'], 2);

         // Remove whitespace
         $mime = trim($mime);

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

      } 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 {

         // No parsing so print immediately
         echo $data;

         // And add to cache if applicable
         if ( $this->cacheHandle ) {
            fwrite($this->cacheHandle, $data);
         }

      }

      // 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? Determines if ascii or binary.
      if ( $this->sniff ) {

         // Take a sample of 100 chars chosen at random
         $length = strlen($data);
         $sample = $length < 150 ? $data : substr($data, rand(0, $length-100), 100);

         // Assume ASCII if more than 95% of bytes are "normal" text characters
         if ( strlen(preg_replace('#[^A-Z0-9!"£$%\^&*\(\)=+\\\\|\[\]\{\};:\\\'@\#~,.<>/?-]#i', '', $sample)) > 95 ) {

            // To do: expand this to detect if html/js/css
            $this->parseType = 'html';

         }

      }

      // 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']);
      }

      // Create a file handle for the cache if required
      if ( $this->saveAs && ! $this->parseType ) {

         // Prepare a temporary name (help avoid concurrency issues)
         $tmp = $this->saveAs . '.tmp';

         // Check for existing temp file (i.e. download of this file in progress)
         if ( ! file_exists($tmp) ) {

            // Doesn't already exist so try to create it
            $this->cacheHandle = fopen($tmp, 'wb');

         }

      }

   }


   /*****************************************************************
   * 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);

// Caching?
if ( $saveAs ) {
   $fetch->saveCache($saveAs);
}

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


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

if ( $fetch->abort ) {

   switch ( $fetch->abort ) {

      // Do a redirection
      case 'redirect':

         // Proxify the location
         $location = proxifyURL($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
   ******************************************************************/

   // 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
               $vars['toShow']   = $toShow;                    // Options
               $vars['url']      = $URL['href'];               // Currently visited URL
               $vars['return']   = rawurlencode(currentURL()); // Return URL (for clearcookies) (i.e. current URL proxified)
               $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);
   }

   // Apply the "badwords" filter
   if ( $CONFIG['censor_words'] ) {
      $document = str_replace($CONFIG['censor_words'], '####', $document);
   }

   // 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;

      }

   }


   /*****************************************************************
   * Save parsed files in the cache
   ******************************************************************/

   if ( $saveAs ) {

      // If this is a CSS document and we're using unique URLs, save
      // the file with the original URLs ready for reparsing - NOT with
      // the current individual's unique URLs.
      if ( $fetch->parseType == 'css' && $CONFIG['unique_urls'] ) {
         $document = $parser->CSS($fetch->return, true);
      }

      // Find the last-modified date
      $modified = false;

      // Check for an existing cache that's different
      if ( $foundCache && file_get_contents($saveAs) != $document ) {

         // Yes, set the modified date to now
         $modified = $_SERVER['REQUEST_TIME'];

      } else if ( isset($fetch->headers['last-modified']) ) {

         // Use the sent value, if one exists
         $modified = strtotime($fetch->headers['last-modified']);

      }

      // Create and save the file
      file_put_contents($saveAs, $document);

      // And update the timestamp
      if ( $modified ) {
         touch($saveAs, $modified);
      }

   }

}

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);

   }

}

Vu que j'utilise glype le script en entier est là http://www.glype.com/ ; L'erreur vient peut-être d'ailleurs.


Quelques informations complémentaires qui peuvent peut-être servir :
-Hébergement ftpperso.free.fr
-http://edm92.free.fr/info.php ci-contre la configuration php du ftp

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr