downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Verbindungssteuerung> <PUT-Unterstützung
[edit] Last updated: Mon, 01 Nov 2010

view this page in

Kapitel 39. Zugriff auf entfernte Dateien

Wenn die Unterstützung für den "URL fopen wrapper" bei der Konfiguration von PHP vorhanden ist (welche standardmäßig eingestellt ist, es sei denn, die Option --disable-url-fopen-wrapper wurde bei der Installation verwendet (Versionen bis 4.0.3) oder der Parameter allow_url_fopen in der php.ini deaktiviert wurde (neuere Versionen), können HTTP und FTP URLs bei den meisten Funktionen verwendet werden, die einen Dateinamen als Parameter benötigen, inklusive require() und include() Anweisungen.

Anmerkung: remote files funktionieren nicht mit include() und require() Anweisungen unter Windows.

Beispielsweise kann eine Datei auf einem anderen Webserver geöffnet und verarbeitet werden. Diese Daten können zur Abfrage einer Datenbank benutzt werden oder passend zum Rest der eigenen Website ausgegeben werden.

Beispiel 39.1. Den Titel einer entfernten Seite auslesen

<?php
$file
= fopen ("http://www.example.com/", "r");
if (!
$file) {
    echo
"<p>Datei konnte nicht geöffnet werden.\n";
    exit;
}
while (!
feof ($file)) {
   
$line = fgets ($file, 1024);
   
/* Funktioniert nur, wenn Titel und title-Tags in einer Zeile stehen */
   
if (eregi ("<title>(.*)</title>", $line, $out)) {
       
$title = $out[1];
        break;
    }
}
fclose($file);
?>

Auch eine Datei auf einem FTP-Server kann geschrieben werden, solange man sich über einen Benutzer mit entsprechenden Zugriffsrechten verbindet und die Datei noch nicht existiert. Um sich mit einem anderen Benutzer als 'anonymous' zu verbinden muß ein username (und möglichst ein Passwort) innerhalb der URL angegeben werden, wie z.B. 'ftp://user:password@ftp.example.com/pfad/zur/datei'. (Die selbe Syntax kann verwendet werden, um auf Daten via HTTP zuzugreifen, wenn diese eine Basic Authentication benötigen.)

Beispiel 39.2. Daten auf einen entfernten Server speichern

<?php
$file
= fopen ("ftp://ftp.example.com/incoming/outputfile", "w");
if (!
$file) {
    echo
"<p>Datei konnte zum schreiben nicht geöffnet werden.\n";
    exit;
}
/* Schreibe die Daten hier hin. */
fputs ($file, "$HTTP_USER_AGENT\n");
fclose ($file);
?>

Anmerkung: Obiges Beispiel könnte dazu verleiten, dieses Verfahren zu benutzen, um in ein 'remote log-file' zu schreiben. Wie oben erwähnt kann man jedoch ausschließlich neue Dateien anlegen, wenn man URL fopen() wrapper benutzt. Für 'distributed logging' sollte man sich die Funktion syslog() anschauen.



Verbindungssteuerung> <PUT-Unterstützung
[edit] Last updated: Mon, 01 Nov 2010
 
add a note add a note User Contributed Notes Zugriff auf entfernte Dateien
mail at 3v1n0 dot net 28-Apr-2008 06:18
I've changed the function below to support the 4xx errors and the 30x redirects... This is a partial implementation yet but it's sufficient for the normal usage.

I've made a recursive implementation (if a 30x redirect is found), but it could be easily reverted to an iterative way (simple put something like while (!empty $url) at the beginning, and set the $url to an empty string if no 3xx/4xx status are found).

<?
function http_get($url, $range = 0)
{
   
$url_stuff = parse_url($url);
   
$port = isset($url_stuff['port']) ? $url_stuff['port'] : 80;
   
   
$fp = @fsockopen($url_stuff['host'], $port);
   
    if (!
$fp)
        return
false;
   
   
$query  = 'GET '.$url_stuff['path'].'?'.$url_stuff['query']." HTTP/1.1\r\n";
   
$query .= 'Host: '.$url_stuff['host']."\r\n";
   
$query .= 'Connection: close'."\r\n";
   
$query .= 'Cache-Control: no'."\r\n";
   
$query .= 'Accept-Ranges: bytes'."\r\n";
    if (
$range != 0)
       
$query .= 'Range: bytes='.$range.'-'."\r\n"; // -500
    //$query .= 'Referer: http:/...'."\r\n";
    //$query .= 'User-Agent: myphp'."\r\n";
   
$query .= "\r\n";
   
   
fwrite($fp, $query);
   
   
$chunksize = 1*(1024*1024);
   
$headersfound = false;

    while (!
feof($fp) && !$headersfound) {
       
$buffer .= @fread($fp, 1);
        if (
preg_match('/HTTP\/[0-9]\.[0-9][ ]+([0-9]{3}).*\r\n/', $buffer, $matches)) {
           
$headers['HTTP'] = $matches[1];
           
$buffer = '';
        } else if (
preg_match('/([^:][A-Za-z_-]+):[ ]+(.*)\r\n/', $buffer, $matches)) {
           
$headers[$matches[1]] = $matches[2];
           
$buffer = '';
        } else if (
preg_match('/^\r\n/', $buffer)) {
           
$headersfound = true;
           
$buffer = '';
        }

        if (
strlen($buffer) >= $chunksize)
            return
false;
    }

    if (
preg_match('/4[0-9]{2}/', $headers['HTTP']))
        return
false;
    else if (
preg_match('/3[0-9]{2}/', $headers['HTTP']) && !empty($headers['Location'])) {
       
$url = $headers['Location'];
        return
http_get($url, $range);
    }

    while (!
feof($fp) && $headersfound) {
       
$buffer = @fread($fp, $chunksize);
        echo
$buffer;
       
ob_flush();
       
flush();
    }

   
$status = fclose($fp);

    return
$status;
}
?>
geoffrey at nevra dot net 06-May-2006 03:53
Really, you should not send headers terminated by \n - it's not per-rfc supported by a HTTP server.

Instead, send as \r\n which is what the protocol specifies, and that regular expression would be matched anywhere, so match for something like /^Content-Length: \d+$/i on each header-line (headers are terminated by the regular expression  /(\r\n|[\r\n])/ - so preg_split on that. Remeber to use the appropriate flags, I can't be arsed to look them up)
heck at fas dot harvard dot edu 14-Sep-2004 12: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.
geoffrey at nevra dot net 04-Aug-2003 05: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 ;)

 
show source | credits | sitemap | contact | advertising | mirror sites