suche nach in der

fpassthru> <fnmatch
Last updated: Sat, 07 Jan 2012

view this page in

fopen

(PHP 4, PHP 5)

fopenÖffnet eine Datei oder URL

Beschreibung

resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )

fopen() bindet eine benannte Ressource, die durch filename spezifiziert wurde, an einen Stream.

Parameter-Liste

filename

Hat filename die Form "schema://..." wird angenommen, dass es sich hier um einen URL handelt und PHP sucht nach einem Protokollhandler (auch als Wrapper bekannt) für dieses Schema. Sind keine Wrapper für dieses Protokoll registriert, gibt PHP als Hilfe zum Verfolgen potentieller Probleme in Ihrem Skript einen Hinweis aus und setzt dann weiter fort, als wenn filename eine reguläre Datei spezifiziert.

Ist PHP zu dem Schluss gekommen, dass filename eine lokale Datei spezifiziert, wird es versuchen, einen Stream an dieser Datei zu öffnen. Die Datei muss für PHP zugreifbar sein, weshalb Sie sicherstellen müssen, dass die Dateirechte diesen Zugriff ermöglichen. Wenn Sie Safe Mode oder open_basedir aktiviert haben, können weitere Einschränkungen zutreffen.

Kam PHP zum Schluss, dass es sich bei filename um ein registriertes Protokoll handelt, und ist dieses Protokoll als ein Netzwerk URL registriert, prüft PHP, ob allow_url_fopen aktiviert ist. Ist es nicht aktiviert, gibt PHP eine Warnung aus, und der Aufruf von fopen wird scheitern.

Hinweis:

Die Liste der unterstützten Protokolle können Sie unter Unterstützte Protokolle and Wrappers finden. Einige Protokolle (auch als Wrapper bezeichnet) unterstützen context und/oder php.ini Optionen. Beziehen sie sich auf die jeweilige Seite für das genutzte Potokoll, um eine Liste der Optionen, die gesetzt werden können, zu erhalten. (z.B. php.ini Wert user_agent genutzt vom http Wrapper).

Achten sie darauf, unter Windows alle Backslash-Zeichen, die in Pfaden genutzt werden, zu maskieren oder nutzen sie Schrägstriche (Slash).

<?php
$handle 
fopen("c:\\verzeichnis\\ressource.txt""r");
?>

mode

Der mode Parameter spezifiziert den Zugriffstyp, den sie auf den Stream anfordern. Es kann einer der folgenden sein:

Eine Liste der möglichen Modi von fopen() mittels mode
mode Beschreibung
'r' Nur zum Lesen geöffnet; platziere Dateizeiger auf Dateianfang.
'r+' Zum Lesen und Schreiben geöffnet; platziere Dateizeiger auf Dateianfang.
'w' Nur zum Schreiben geöffnet; platziere Dateizeiger auf Dateianfang und kürze die Datei auf eine Länge von 0. Existiert die Datei nicht, versuche, diese zu erzeugen.
'w+' Zum Schreiben und Lesen geöffnet; platziere Dateizeiger auf Dateianfang und kürze die Datei auf eine Länge von 0. Existiert die Datei nicht, versuche, diese zu erzeugen.
'a' Nur zum Schreiben geöffnet; platziere Dateizeiger auf Dateiende. Existiert die Datei nicht, versuche, diese zu erzeugen.
'a+' Zum Schreiben und Lesen geöffnet; platziere Dateizeiger auf Dateiende. Existiert die Datei nicht, versuche, diese zu erzeugen.
'x' Erzeuge und Öffne nur zum Schreiben; platziere Dateizeiger auf Dateianfang. Falls die Datei schon existiert, wird der fopen() Aufruf fehlschlagen durch Rückgabe von FALSE und dem Auslösen eines Fehlers der Stufe E_WARNING. Existiert die Datei nicht, versuche, diese zu erzeugen. Dies ist zur Angabe der O_EXCL|O_CREAT Flags für den darunterliegenden open(2) System Aufruf äquivalent.
'x+' Erzeuge und Öffne zum Schreiben und Lesen; ansonsten ist das Verhalten gleich wie bei 'x'.
'c' Öffne Datei nur zum Schreiben. Wenn die Datei nicht existiert, wird diese erzeugt. Wenn sie existiert, wird sie weder gekürzt (im Gegensatz zu 'w'), noch schlägt der Aufruf dieser Funktion fehl (wie dies mit 'x' der Fall ist). Der Dateizeiger wird auf den Dateianfang platziert. Dies kann nützlich sein, wenn man eine "beratende" (kooperative) Sperre erhalten möchte (siehe flock()) bevor man versucht, die Datei zu ändern, da die Nutzung von 'w' die Datei kürzen könnte, bevor die Sperre erhalten wurde (falls Kürzen gewünscht ist, kann ftruncate() genutzt werden, nachdem die Sperre angefragt wurde).
'c+' Öffne Datei zum Lesen und Schreiben; ansonsten ist das Verhalten gleich wie bei 'c'.

Hinweis:

Verschiedene Betriebssysteme haben unterschiedliche Zeilenende Konventionen. Wenn sie eine Text Datei schreiben und einen Zeilenumbruch einfügen möchten, müssen sie das/die korrekte(n) Zeilenende Zeichen für ihr Betriebssystem nutzen. Unix basierte Systeme nutzen \n als Zeilenende Zeichen, Windows basierte Systeme nutzen \r\n als Zeilenende Zeichen und Macintosh basierte Systeme nutzen \r als Zeilenende Zeichen.

Wenn sie die falschen Zeilenende Zeichen beim Schreiben ihrer Dateien nutzen, kann es sein, dass andere Anwendungen, die diese Dateien öffnen, "seltsam aussehen".

Windows bietet einen Text-Mode translations Flag ('t') an, der transparent \n zu \r\n übersetzt, wenn mit der Datei gearbeitet wird. Andererseits können sie auch 'b' nutzen, um Binärmode zu erzwingen, der ihre Daten nicht übersetzt. Um diese Flags zu nutzen, geben sie entweder 'b' oder 't' als das letzte Zeichen des mode Parameters an.

Der Standard Übersetzungsmodus hängt von der SAPI und der PHP Version ab, die sie nutzen, daher ist es empfehlenswert, immer den passenden Flag aus Portabilitätsgründen anzugeben. Sie sollten 't' Modus nutzen, wenn sie mit Textdateien arbeiten und sie nutzen \n um die Zeilenenden im Skript zu begrenzen, erwarten aber, dass ihre Dateien mit Anwendungen wie etwa Notepad lesbar sind. Ansonsten sollten sie 'b' nutzen.

Wenn sie beim Arbeiten mit binären Dateien nicht das 'b' Flag angeben, können sie seltsame Probleme mit ihren Daten erleben, einschließlich zerstörter Bild Dateien und merkwürdiger Probleme mit \r\n Zeichen.

Hinweis:

Aus Portabilitätsgründen wird dringend empfohlen, dass sie immer das 'b' Flag nutzen, wenn sie Dateien mit fopen() öffnen.

Hinweis:

Außerdem wird aus Gründen der Portabilität dringend empfohlen, dass sie Code umschreiben, der den 't' Modus nutzt oder sich darauf verlässt, so dass die korrekten Zeilenendungen und der 'b' Modus stattdessen genutzt werden.

use_include_path

Der optionale dritte Parameter use_include_path kann auf '1' oder TRUE gesetzt werden, wenn sie wollen, dass nach der Datei auch im include_path gesucht wird.

context

Hinweis: Die Kontext-Unterstützung gibt es seit PHP 5.0.0. Eine Beschreibung von Kontexten finden Sie unter Stream Funktionen.

Rückgabewerte

Gibt bei Erfolg eine Dateizeiger Ressource zurück oder FALSE bei Fehlern.

Fehler/Exceptions

Wenn das Öffnen fehlschlägt, wird ein Fehler der Stufe E_WARNING erzeugt. Sie können @ um diese Warnung zu unterdrücken.

Changelog

Version Beschreibung
4.3.2 Seit PHP 4.3.2 ist der Standard Modus auf binär für alle Plattformen, die zwischen binärem und Text Modus unterscheiden, gesetzt. Wenn sie Probleme mit ihren Skripten nach einem Upgrade haben, versuchen sie als Übergangslösung das 't' Flag zu nutzen bis sie ihr Skript wie zuvor beschrieben portabler umgeschrieben haben.
4.3.2 Die 'x' und 'x+' Optionen wurden hinzugefügt.
5.2.6 Die 'c' und 'c+' Optionen wurden hinzugefügt.

Beispiele

Beispiel #1 fopen() Beispiele

<?php
$handle 
fopen("/home/rasmus/file.txt""r");
$handle fopen("/home/rasmus/file.gif""wb");
$handle fopen("http://www.example.com/""r");
$handle fopen("ftp://user:password@example.com/somefile.txt""w");
?>

Anmerkungen

Warnung

Bei SSL-Verbindungen zusammen mit Microsoft IIS hält sich dieser Webserver nicht an das Protokoll und schließt die Verbindung ohne ein close_notify zu senden. PHP quittiert dieses Fehlverhalten mit "SSL: Fatal Protocol Error", wenn das Ende der Daten erreicht ist. Eine mögliche Lösung besteht darin, den Level von error_reporting herabzusetzten und Warnings auszuschließen. Ab PHP 4.3.7 kann PHP fehlerhafte IIS-Serversoftware erkennen, wenn Sie einen Stream mit dem https://-Wrapper öffnen, und unterdrückt die Warnung für Sie. Falls Sie fsockopen() benutzen, um einen ssl://-Socket zu öffnen, müssen Sie selbst dafür Sorge tragen, die Warnung zu erkennen und diese zu unterdrücken.

Hinweis: Wenn Safe Mode aktiviert ist überprüft PHP, ob das Arbeitsverzeichnis, die gleiche UID (Eigentümer) hat wie das Skript selbst.

Wenn sie Probleme beim Lesen und Schrieben von Dateien haben und sie nutzen die Server Modul Version von PHP, denken sie daran, sicherzustellen, dass die Dateien und Verzeichnisse, die sie nutzen, für den Server Prozess zugänglich sind.

Siehe auch



add a note add a note User Contributed Notes
fopen
Jordan [Seraskier]
08-Jul-2007 08:46
Is it possible to move the cursor to a certain line, or move it back 3 spots from the last line?

Please help me.
msn/email - jomar@carolina.rr.com
Elliott Brueggeman
02-Jul-2007 08:43
I did some basic performance testing of fopen() + fread() versus file_get_contents() when opening a remote file for reading, and it looks like fread() is actually a little bit faster than fopen(). While it may be because of my GoDaddy hosting server’s configuration, it makes me favor using fopen() over file_get_contents(). Fopen() also has the added benefit of greater PHP version compatibility.

Test results: http://www.ebrueggeman.com/php_benchmarking_fopen.php
JB
07-Jun-2007 12:30
A note on pflaume dot NOSPAM at NOSPAM dot gmx dot de's proxy application for fopen, which was very handy.
I found with Tor on OSX that the Host request header to the proxy (set to the Proxy IP) was not necessary, and was passed on to the target site causing most to return a 404 Error.
simon dot allen at swerve dot co dot nz
10-Apr-2007 04:56
using fopen to upload a file through ftp cannot overwrite that file - use curl instead
naidim at gmail dot com
29-Mar-2007 12:54
While PHP does not have a function to insert text into the middle of a file, it is not that complicated to do.

<?php
function addRSSItem($rssFile, $firstItem, $item){
   
// Backup file
   
if(!copy($rssFile, 'backup.rss')) die('Backup failed!');
   
// Store file contents in array
   
$arrFile = file($rssFile);
   
// Open file for output
   
if(($fh = fopen($rssFile,'w')) === FALSE){
        die(
'Failed to open file for writing!');
    }
   
// Set counters
   
$currentLine = 0;
   
$cntFile = count($arrFile);
   
// Write contents, inserting $item as first item
   
while( $currentLine <= $cntFile ){
        if(
$currentLine == $firstItem) fwrite($fh, $item);
       
fwrite($fh, $arrFile[$currentLine]);
       
$currentLine++;
    }
   
// Delete backup
   
unlink('backup.rss');
}

$data = "    <item>\n<title>$_POST['title]</title>\n".
 
"        <description>$_POST['description']</description>\n".
 
"        <pubDate>$_POST['date']</pubDate>\n".
 
"        <link>http://www.site.com/mp3s/".
 
basename($_FILES['fullPath']['name'])."</link>".
 
"        <enclosure url=\"http://www.site.com/mp3s/".
 
basename($_FILES['fullPath']['name']).
 
"\" length=\"$_FILES[fullPath][size]\" type=\"audio/mpeg\" />".
 
"    </item>\n";
addRSSItem('/var/www/html/rss/podcast.rss',20,$data);
?>
21-Mar-2007 01:45
If you want to download a file from a URL to a local file, you could just as well use copy() :)
andrew at NOSPAM dot neonsurge dot com
10-Feb-2007 03:22
My recent findings on high-performance fopen/fsockopen usage.

Note #1: The performance comparison below regarding curl is obsolete when utilizing certain things in this comment.  My performance tests download and upload about 97% as fast as curl with a custom non-socket blocking HTTP Transport class written for a high performance system in PHP5.

Note #2: fopen and fsockopen have a "feature' that always forces DNS resolution.  Check this code...

<?php for ($i = 0; $i < 50; $i++) {
   
$errno = $errstr = "";
   
//$ip = gethostbyname("php.net");  $a = fsockopen($ip,22,$errno,$errstr,10);  //FAST way
   
$a = fsockopen("php.net",22,$errno,$errstr,10); //SLOW way
   
$ab = fread($a,4096); unset($a, $ab);
}
?>

fsockopen() and fopen() always force php.net to be resolved every time and in this example above it resolves the name 50 seperate times and does not use the local cache.  To get around this, gethostbyname() does use your local DNS cache properly, it will not try to get the IP from your DNS server 50 times.  The above code for me to a personal server took 87 seconds the fast way, and 5.74 seconds the slow way, a 650% increase.  And this is single-threaded!  ;)

Note #3: I see a lot of notes and people mentioning non-blocking sockets, especially for HTTP transport.  I thought I would share a little from my experience.  First, the above command fsockopen() allows you to specify a timeout, after you check if it's  opened properly (as you should _always_) you just need to...

<?php stream_set_blocking($a,0);?>

From this point on certain considerations must be taken.  Remember you are not blocking anymore, so when you want to write or read a lot of data it will always return to you instantly.  Which is important since you need to check the return value of your writes and reads against how much you expect to read/write.  For reading if you do not know how long it is, checking for EOF works also.

This is in fact a neat feature and state, since you can now make a read/write loop to send/receive a lot of data and check the time/timeout value(s) constantly.  If that timeout is hit you can throw back errors properly to whatever function/method/code called your transport function/class.  The graceful failure with custom shorter failure times allows your application to continue, especially web-based applications where fopen alone and even curl under certain circumstances does not follow your requested timeouts, it will wait a full 60-90 seconds, depending on your OS.

Good ways to test a custom non-blocking timeout supported transport method described above is to make one first, and then transfer a large file with it, and halfway through unplug your network cable.  Curl or fopen/fread/fwrite alone will croak and make your applications wait a full 60-90 seconds, whereas a nice custom class will check if no data has been transferred for 15 seconds (or less!) and will fail gracefully with a error.

If anyone is interested in chatting about this feel free to contact me or add to this comment.
download dot function at nospam dot com
22-Jan-2007 11:34
Thanks very much to flobee (15-Jan-2006) who provided a download() function with realtime writing instead of buffering the result, very clever. However, your function is too basic, it has almost zero error checking, and also forgets to close file handles in one case(!). Not only that, but you have mixed up the meaning of return values, where you have made false = no errors and true = error occured. I've added full error checking, optimized the code, and of course corrected the return values. True = Success. Here are the changes:

1. If the file that we are saving to already exists it removes any read-only flag so that it can be overwritten.
2. Correctly formats the URL we are downloading from so that fopen() understands it. For instance, if you pass a URL with spaces, those have to be encoded to %20, and any html entities such as &amp; have to be decoded to & or the fopen() call fails, I've added these transformations so that the user does not have to pre-format the URL before passing it to download().
3. I've added the closing of file handles at a point where you forgot to.
4. The error messages are all handled by fopen/fwrite, so if the function has returned false for an error, you need to enable "Display_Errors" in the INI to see what happened, or alternatively use "ini_set('display_errors', 1);" at the top of your PHP file.

I don't think there is _anything_ else that can be improved, but if you can think of something then you are welcome to submit your version.

function download ($file_source, $file_target)
{
  // Preparations
  $file_source = str_replace(' ', '%20', html_entity_decode($file_source)); // fix url format
  if (file_exists($file_target)) { chmod($file_target, 0777); } // add write permission

  // Begin transfer
  if (($rh = fopen($file_source, 'rb')) === FALSE) { return false; } // fopen() handles
  if (($wh = fopen($file_target, 'wb')) === FALSE) { return false; } // error messages.
  while (!feof($rh))
  {
    // unable to write to file, possibly because the harddrive has filled up
    if (fwrite($wh, fread($rh, 1024)) === FALSE) { fclose($rh); fclose($wh); return false; }
  }

  // Finished without errors
  fclose($rh);
  fclose($wh);
  return true;
}
perrog at gmail dot com
21-Jan-2007 01:05
Note: If you have opened the file in append mode ("a" or "a+"), any data you write to the file will always be appended, regardless of the file position. But PHP distinguish between read and write position, and you may freely read at any position, but when you write it will always append at the end.

If you don't want that write restriction, open the file in read-write mode ("r+") and then start by moving the file pointer to the end.

if (($fp = fopen($filename, "r+") === FALSE) {
  // handle error
  exit;
}

if (fseek($fp, 0, SEEK_END) === -1) {
  // handle error
  exit;
}
patryk dot szczyglowski at gmail dot com
20-Sep-2006 04:02
Watch out not to specify empty string as filename. It seems PHP is trying to get data from stdin which may end up in script timeout. It may not be trivial to find.

<?php
$fp
= fopen('', 'r'); // wrong
?>
roman dot nastenko at gmail dot com
19-May-2006 05:09
php 4.4.2 realy introduced a blocker problem with fopen() (http://bugs.php.net/bug.php?id=36017)

In that case you can use sockets for file open.

Example. Not

   $viart_xml = fopen("http://www.viart.com/viart_shop.xml", "r");

But

   $viart_xml = fsockopen("www.viart.com", 80, $errno, $errstr, 12);

   fputs($viart_xml, "GET /viart_shop.xml HTTP/1.0\r\n");
   fputs($viart_xml, "Host: www.viart.com\r\n");
   fputs($viart_xml, "Referer: http://www.viart.com\r\n");
   fputs($viart_xml, "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n\r\n");

After that you can use $viart_xml as a simple file :)
puneet at puneetarora dot com
03-May-2006 12:25
Refering to the note by [info at b1g dot de]
on (24-Oct-2005 11:54)

sometimes you may also want HTTP error code returned from the server. The code of the HTTPRequest class can be modified as followed to do so ..

1. Add another member variable to the class

var $_error;       // HTTP Error code

2. After  the lines
.
.
       // parse headers
       $headers = array();
       $lines = explode($crlf, $header);
.
.

add

list($proto, $this->_error, $reply) = explode(" ", $lines[0]);

$proto and $reply can be treated as junk variables.

once DownloadToString() is called, the HTTP error code will be contained in the _error property of the object.
ceo at l-i-e dot com
11-Apr-2006 05:13
If you need fopen() on a URL to timeout, you can do like:
<?php
  $timeout
= 3;
 
$old = ini_set('default_socket_timeout', $timeout);
 
$file = fopen('http://example.com', 'r');
 
ini_set('default_socket_timeout', $old);
 
stream_set_timeout($file, $timeout);
 
stream_set_blocking($file, 0);
 
//the rest is standard
?>
zerkella at mi6 dot com dot ua
05-Apr-2006 04:02
During development of a set of non-blocking functions for downloading files from http-servers I've discovered that it's not possible to set timeout for fopen('http://somesite.com/somefile', 'rb').

All functions for controlling non-blocking mode (stream_set_blocking, stream_set_timeout, stream_context_set_option) use resource handle that is created via fopen(). But fopen() for HTTP connections internally makes quite a big set of actions: it creates socket, resolves webserver name, establishes actual connection. So hanging can occur anywhere in resolving and creating tcp-connection but you cannot control it.

Solutions:
1) Use socket functions. Set socket in non-blocking mode just after creation. Implement HTTP-protocol yourself. In source code use these manually created functions.
2) Write a wrapper for myprotocol://, which internally will use first solution, but in source code you'll use fopen('myprotocol://somesite.com/somefile', 'rb') with some way to set timeout before calling it.
Jeff McKenna
28-Feb-2006 10:26
It seems php 4.4.2 introduced a blocker problem with fopen() (http://bugs.php.net/bug.php?id=36017).
Paul Yanchenko
22-Jan-2006 02:16
I found a strange behaviour of PHP when several scripts trying to fopen a file for writing access simultaneously. I expect that this will result file sharing violation, but it's not and all scripts can open and write that file. I'd like to use sharing violation to control uniqueness of script instance, but now I even do know how to do this. The only idea is to use "x" flag in fopen(), but if that lock-file somehow will not be deleted - script will never run.

PHP 5.0.5, Windows XP Pro SP2
flobee
15-Jan-2006 04:58
download: i need a function to simulate a "wget url" and do not buffer the data in the memory to avoid thouse problems on large files:
<?php
function download($file_source, $file_target) {
       
$rh = fopen($file_source, 'rb');
       
$wh = fopen($file_target, 'wb');
        if (
$rh===false || $wh===false) {
// error reading or opening file
          
return true;
        }
        while (!
feof($rh)) {
            if (
fwrite($wh, fread($rh, 1024)) === FALSE) {
                  
// 'Download error: Cannot write to file ('.$file_target.')';
                  
return true;
               }
        }
       
fclose($rh);
       
fclose($wh);
       
// No error
       
return false;
    }
?>
anonymous at anonymous dot com
27-Dec-2005 12:11
Contrary to a note below the concept of what the preferred line ending is on mac os x is a little bit fuzzy.  I'm pretty sure all the bsd utils installed by default are going to use \n but that is not necessarily the norm.  Some apps will use that while others will use \r.

You should be prepared to deal with either.
Camillo
19-Dec-2005 06:58
Contrary to what this page says, the preferred line ending on Macintosh systems is \n (LF). \r was used on legacy versions of the Mac OS (pre-OS X), and I don't think PHP even runs on those.
151408626 dot unique at servux dot org
19-Dec-2005 01:05
I found a nice trick how to work around the issue (mentioned here: http://www.php.net/manual/en/function.fopen.php#41243) that the PHP  process will block on opening a FIFO until data is sent to it:

Simply do send some data to the FIFO, using an echo command started in background (and ignoring that spedific data, when parsing whatever read from the FIFO).

A very simple example of that:
<?

// path & name of your FIFO-file
$someFIFO = "path/to/your/fifo"

// some string, that won't be found in your regular input data
$uniqueData = "some specific data";

// this statement actually does the trick providing some data waiting in the FIFO:
//   start echo to send data to the FIFO in the background!!
//   NOTE: parenthesis & second redirection (to /dev/null) are
//   important to keep PHP from waiting for echo to terminate! 
system("(echo -n '$uniqueData' >$someFIFO) >/dev/null &");

// now you can safely open the FIFO, without the PHP-process being blocked
$handle = fopen($someFIFO, 'r');

// loop reading data from the FIFO
while (TRUE) {
   
$data = fread($handle, 8192);

   
// eliminate the initially sent data from our read input
    //   NOTE: this is done only in a very simplyfied way in this example,
    //   that will break if that data-string might also be part of your regular input!!
   
if (!(strpos($inp, $uniqueData) === FALSE))    $data = str_replace($uniqueData, '', $data);

// here comes your processing of the read data...
}

?>
info at b1g dot de
24-Oct-2005 01:54
Simple class to fetch a HTTP URL. Supports "Location:"-redirections. Useful for servers with allow_url_fopen=false. Works with SSL-secured hosts.

<?php
#usage:
$r = new HTTPRequest('http://www.php.net');
echo
$r->DownloadToString();

class
HTTPRequest
{
    var
$_fp;        // HTTP socket
   
var $_url;        // full URL
   
var $_host;        // HTTP host
   
var $_protocol;    // protocol (HTTP/HTTPS)
   
var $_uri;        // request URI
   
var $_port;        // port
   
    // scan url
   
function _scan_url()
    {
       
$req = $this->_url;
       
       
$pos = strpos($req, '://');
       
$this->_protocol = strtolower(substr($req, 0, $pos));
       
       
$req = substr($req, $pos+3);
       
$pos = strpos($req, '/');
        if(
$pos === false)
           
$pos = strlen($req);
       
$host = substr($req, 0, $pos);
       
        if(
strpos($host, ':') !== false)
        {
            list(
$this->_host, $this->_port) = explode(':', $host);
        }
        else
        {
           
$this->_host = $host;
           
$this->_port = ($this->_protocol == 'https') ? 443 : 80;
        }
       
       
$this->_uri = substr($req, $pos);
        if(
$this->_uri == '')
           
$this->_uri = '/';
    }
   
   
// constructor
   
function HTTPRequest($url)
    {
       
$this->_url = $url;
       
$this->_scan_url();
    }
   
   
// download URL to string
   
function DownloadToString()
    {
       
$crlf = "\r\n";
       
       
// generate request
       
$req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
           
.    'Host: ' . $this->_host . $crlf
           
.    $crlf;
       
       
// fetch
       
$this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
       
fwrite($this->_fp, $req);
        while(
is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
           
$response .= fread($this->_fp, 1024);
       
fclose($this->_fp);
       
       
// split header and body
       
$pos = strpos($response, $crlf . $crlf);
        if(
$pos === false)
            return(
$response);
       
$header = substr($response, 0, $pos);
       
$body = substr($response, $pos + 2 * strlen($crlf));
       
       
// parse headers
       
$headers = array();
       
$lines = explode($crlf, $header);
        foreach(
$lines as $line)
            if((
$pos = strpos($line, ':')) !== false)
               
$headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));
       
       
// redirection?
       
if(isset($headers['location']))
        {
           
$http = new HTTPRequest($headers['location']);
            return(
$http->DownloadToString($http));
        }
        else
        {
            return(
$body);
        }
    }
}
?>
admin at sellchain dot com
17-Oct-2005 04:34
TIP: If you are using fopen and fread to read HTTP or FTP or Remote Files, and experiencing some performance issues such as stalling, slowing down and otherwise, then it's time you learned a thing called cURL.

Performance Comparison:

10 per minute for fopen/fread for 100 HTTP files
2000 per minute for cURL for 2000 HTTP files

cURL should be used for opening HTTP and FTP files, it is EXTREMELY reliable, even when it comes to performance.

I noticed when using too many scripts at the same time to download the data from the site I was harvesting from, fopen and fread would go into deadlock. When using cURL i can open 50 windows, running 10 URL's from each window, and getting the best performance possible.

Just a Tip :)
nefertari at nefertari dot be
20-Sep-2005 02:47
Important note:

You have always to use the real path name for a file with the command fopen [for example: fopen($filename, 'w')], never use a symbolic link, it will not work (unable to open $filename).
francis dot fish at gmail dot com
10-Sep-2005 05:10
None of the examples on the page test to see if the file has been opened successfully. Fopen will return false if it failed. To quickly extend one of the examples in the manual:

  $filename = "some.dat" ;
  $dataFile = fopen( $filename, "r" ) ;

  if ( $dataFile )
  {
    while (!feof($dataFile))
    {
       $buffer = fgets($dataFile, 4096);
       echo $buffer;
    }

    fclose($dataFile);
  }
  else
  {
    die( "fopen failed for $filename" ) ;
  }

Hope this is some use.
durwood at speakeasy dot NOSPAM dot net
07-Sep-2005 08:43
I couldn't for the life of me get a certain php script working when i moved my server to a new Fedora 4 installation. The problem was that fopen() was failing when trying to access a file as a URL through apache -- even though it worked fine when run from the shell and even though the file was readily readable from any browser.  After trying to place blame on Apache, RedHat, and even my cat and dog, I finally ran across this bug report on Redhat's website:

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=164700

Basically the problem was SELinux (which I knew nothing about) -- you have to run the following command in order for SELinux to allow php to open a web file:

/usr/sbin/setsebool httpd_can_network_connect=1

To make the change permanent, run it with the -P option:

/usr/sbin/setsebool -P httpd_can_network_connect=1

Hope this helps others out -- it sure took me a long time to track down the problem.
ericw at w3consultant dot net
02-Sep-2005 08:49
RE: using fopen to read an http doc
I beat my head against the wall trying to figure out why i couldn't fopen("http://www.mainserver.com/mySettings.php","r");
on just 1 webserver. It was working on all the other webservers, but on this one, it would just hang, then fail.

Finally i figured out the machine i was doing it on was unable to look up domain names!
If you are having this problem try an nslookup to the website you are having from the command line.
ie: nslookup www.yahoo.com

If that fails, the fopen will not work either.
I changed to an IP (temp solution) and it works like a charm.
-e
Luiz Miguel Axcar (lmaxcar at yahoo dot com dot br)
17-Aug-2005 10:11
If you are getting message "Warning: fopen(): URL file-access is disabled in the server configuration", you can use function below to get the content from a local or remote file.

Function uses CURL lib, follow the link to get help: http://www.php.net/curl

<?php
/*
   * @return string
   * @param string $url
   * @desc Return string content from a remote file
   * @author Luiz Miguel Axcar (lmaxcar@yahoo.com.br)
*/

function get_content($url)
{
   
$ch = curl_init();

   
curl_setopt ($ch, CURLOPT_URL, $url);
   
curl_setopt ($ch, CURLOPT_HEADER, 0);

   
ob_start();

   
curl_exec ($ch);
   
curl_close ($ch);
   
$string = ob_get_contents();

   
ob_end_clean();
   
    return
$string;    
}

#usage:
$content = get_content ("http://www.php.net");
var_dump ($content);
?>
zachajc at yahoo dot com (Zealot)
05-Aug-2005 10:35
When designing a few flatfile databases and admin panels, I stumbled upon an interesting thing. If a file has been generated into a page or variable via the readfile or include methods (did not try require), an ereg or preg replace to replace \n with <br> does not detect any \n in the file. However, when attempting the same thing with fopen, fread, it works perfectly.
ideacode
03-Aug-2005 04:28
Note that whether you may open directories is operating system dependent. The following lines:

<?php
// Windows ($fh === false)
$fh = fopen('c:\\Temp', 'r');

// UNIX (is_resource($fh) === true)
$fh = fopen('/tmp', 'r');
?>

demonstrate that on Windows (2000, probably XP) you may not open a directory (the error is "Permission Denied"), regardless of the security permissions on that directory.

On UNIX, you may happily read the directory format for the native filesystem.
rafaelbc at matrix dot com dot br
23-May-2005 06:23
pflaume dot NOSPAM at NOSPAM dot gmx dot de's proxy_url() was very helpful to me!
Although, I still had a problem: proxy authentication.

So I added some code to enable http get through a proxy with user authentication.

<?php
function proxy_url($proxy_url)
{
  
$proxy_name = '127.0.0.1';
  
$proxy_port = 4001;
  
$proxy_user = "user";    // added
  
$proxy_pass = "password";    // added
  
$proxy_cont = '';

  
$proxy_fp = fsockopen($proxy_name, $proxy_port);
   if (!
$proxy_fp)    {return false;}
  
fputs($proxy_fp, "GET $proxy_url HTTP/1.0\r\nHost: $proxy_name\r\n");
  
fputs($proxy_fp, "Proxy-Authorization: Basic " . base64_encode ("$proxy_user:$proxy_pass") . "\r\n\r\n");    // added
  
while(!feof($proxy_fp)) {$proxy_cont .= fread($proxy_fp,4096);}
  
fclose($proxy_fp);
  
$proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
   return
$proxy_cont;
}
?>
francois AT crevola DOT com
11-May-2005 01:54
In reply to "pflaume dot NOSPAM at NOSPAM dot gmx dot de"
about  fopen() and PROXY

With PHP 5.0.0 and after, you can use a proxy by using a stream context. See the note about "Context support was added with PHP 5.0.0".
18-Apr-2005 05:41
This only relavant to those opening a remote file for writing using the PECL SSH2 for SFTP paths for the string filename.  Since SFTP has variations, most of which are non-secure, using this module is the only viable solution.  The optional FTP extension class that uses the function 'ftp_ssl_connect' uses openssl, which only encrypts the communication requests and not the data - or something close to that.  At any rate, many systems will not allow connection to their SFTP server using this method.

I think it's worth mentioning that some of the examples provided in various areas failed consistantly using the syntax given, using both possible methods of.
   ssh2.sftp://$sftp/example.com/path/to/file
   ssh2.sftp://user:pass@$sftp/example.com/path/to/file

It's just a small adjustment to correct this, but as most coding goes, a long road to find a stupid little oversight.  Apparently it is necessary to supply the port as well in the path.  Could just be the few systems I was testing against, but that would be three separate networks using three separate platforms (Windows Server, Linux, Unix).  At any rate, the following works like a charm, and was very simple to install the libssh2 library and PECL SSH2 module required to use this system.  Gotta love PHP.
   ssh2.sftp://$sftp/example.com:22/path/to/file
   ssh2.sftp://user:pass@$sftp:22/example.com/path/to/file

Hope this saves anyone some headache and time.
abesharp at yahoo dot co dot uk
05-Apr-2005 01:12
This function has a basic implementation of HTTP Digest Authentication (as per RFC 2617) to get a file from a web server which requires digest authentication (as opposed to basic authentication - the difference being that, with basic, your password is sent to the server as plain text, whereas with digest, it is hashed with a server-supplied nonce to protect against sniffing and replay attacks).

You just supply the host (e.g www.example.com), the name of the file you want (e.g protected_page.html), and the necessary username and password, and the function returns the contents of the protected file (or the error message that the server sends, if you supplied the wrong credentials).

If the server only supports a QOP of auth-int (rather then auth) this function won't work, but can be easily modified with reference to the RFC at http://www.ietf.org/rfc/rfc2617.txt

<?php
function readHTTPDigestAuthenticatedFile($host,$file,$username,$password)
{
    if (!
$fp=fsockopen($host,80, $errno, $errstr, 15))
        return
false;
       
   
//first do the non-authenticated header so that the server
    //sends back a 401 error containing its nonce and opaque
   
$out = "GET /$file HTTP/1.1\r\n";
      
$out .= "Host: $host\r\n";
      
$out .= "Connection: Close\r\n\r\n";

    
fwrite($fp, $out);

   
//read the reply and look for the WWW-Authenticate element
   
while (!feof($fp))
    {
       
$line=fgets($fp, 512);
       
        if (
strpos($line,"WWW-Authenticate:")!==false)
           
$authline=trim(substr($line,18));
    }
   
   
fclose($fp);
      
   
//split up the WWW-Authenticate string to find digest-realm,nonce and opaque values
    //if qop value is presented as a comma-seperated list (e.g auth,auth-int) then it won't be retrieved correctly
    //but that doesn't matter because going to use 'auth' anyway
   
$authlinearr=explode(",",$authline);
   
$autharr=array();
   
    foreach (
$authlinearr as $el)
    {
       
$elarr=explode("=",$el);
       
//the substr here is used to remove the double quotes from the values
       
$autharr[trim($elarr[0])]=substr($elarr[1],1,strlen($elarr[1])-2);
    }
   
    foreach (
$autharr as $k=>$v)
        echo(
"$k ==> $v\r\n");
   
   
//these are all the vals required from the server
   
$nonce=$autharr['nonce'];
   
$opaque=$autharr['opaque'];
   
$drealm=$autharr['Digest realm'];
   
   
//client nonce can be anything since this authentication session is not going to be persistent
    //likewise for the cookie - just call it MyCookie
   
$cnonce="sausages";
   
   
//calculate the hashes of A1 and A2 as described in RFC 2617
   
$a1="$username:$drealm:$password";$a2="GET:/$file";
   
$ha1=md5($a1);$ha2=md5($a2);
   
   
//calculate the response hash as described in RFC 2617
   
$concat = $ha1.':'.$nonce.':00000001:'.$cnonce.':auth:'.$ha2;
   
$response=md5($concat);
   
   
//put together the Authorization Request Header
   
$out = "GET /$file HTTP/1.1\r\n";
      
$out .= "Host: $host\r\n";
   
$out .= "Connection: Close\r\n";
   
$out .= "Cookie: cookie=MyCookie\r\n";
   
$out .= "Authorization: Digest username=\"$username\", realm=\"$drealm\", qop=\"auth\", algorithm=\"MD5\", uri=\"/$file\", nonce=\"$nonce\", nc=00000001, cnonce=\"$cnonce\", opaque=\"$opaque\", response=\"$response\"\r\n\r\n";
   
    if (!
$fp=fsockopen($host,80, $errno, $errstr, 15))
        return
false;
   
   
fwrite($fp, $out);
   
   
//read in a string which is the contents of the required file
   
while (!feof($fp))
    {
       
$str.=fgets($fp, 512);
    }
   
   
fclose($fp);
   
    return
$str;
}

?>
nuno at ideianet dot pt
04-Mar-2005 02:03
In IIS you must add the group Authenticated Users
with write and modify permissions in the file where
you want to write if you are in a Protected directory
(Basic or Digest authentication) and want to write to
a file in a Unprotected directory (Anonymous Access)
in order to get permission to do that. Otherwise you
will get the message: PHP Warning: fopen(x.txt): failed
to open stream: Permission denied in c:\web\x\x.php on
line 3 PHP Warning: fwrite(): supplied argument is not
a valid stream resource in c:\web\x\x.php on line 10
Thomas Candrian tc_ at gmx dot ch
12-Nov-2004 04:35
With this it isn't possible to get data from another port than 80 (and 443) - at least for me. Because of that I've made this function who gets data from every port you want using HTTP:

<?php;
function
getcontent($server, $port, $file)
{
   
$cont = "";
   
$ip = gethostbyname($server);
   
$fp = fsockopen($ip, $port);
    if (!
$fp)
    {
        return
"Unknown";
    }
    else
    {
       
$com = "GET $file HTTP/1.1\r\nAccept: */*\r\nAccept-Language: de-ch\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\nHost: $server:$port\r\nConnection: Keep-Alive\r\n\r\n";
       
fputs($fp, $com);
        while (!
feof($fp))
        {
           
$cont .= fread($fp, 500);
        }
       
fclose($fp);
       
$cont = substr($cont, strpos($cont, "\r\n\r\n") + 4);
        return
$cont;
    }
}
echo
getcontent("www.myhost.com", "81", "/"));
?>

Works fine for me. Had to do this especially for a shoutcast server, which only delivered the HTML-file if the user-agent was given.
pflaume dot NOSPAM at NOSPAM dot gmx dot de
07-Nov-2004 11:31
fopen() and PROXY

I wondered why there is no possibility to use fopen() through a proxy in php. The solution posted above did not work for me.

This little function gets http through a given proxy:

<?php
function proxy_url($proxy_url)
{
   
$proxy_name = '127.0.0.1';
   
$proxy_port = 4001;
   
$proxy_cont = '';

   
$proxy_fp = fsockopen($proxy_name, $proxy_port);
    if (!
$proxy_fp)    {return false;}
   
fputs($proxy_fp, "GET $proxy_url HTTP/1.0\r\nHost: $proxy_name\r\n\r\n");
    while(!
feof($proxy_fp)) {$proxy_cont .= fread($proxy_fp,4096);}
   
fclose($proxy_fp);
   
$proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
    return
$proxy_cont;
}
?>
justin at redwiredesign dot com
14-Jul-2004 09:03
One thing worth noting is that if you use the fopen command to open an HTTP stream, and the URL you're trying to access is invalid or generates an error response, (i.e. 404 Not found), the fopen call will return false.
Jem Tallon
14-Apr-2004 12:11
If you're using fopen to open a URL that requires authorization, you might need to force a HTTP/1.0 request for it since fopen won't support HTTP/1.1 requests. You can do that by setting your user_agent to one that is known only to support HTTP/1.0 (most webservers will be configured to force HTTP/1.0 for some browsers). Here's what worked for me:

<?php
$returned
=URLopen("http://$username:$password@example.com");

function
URLopen($url)
{
       
// Fake the browser type
       
ini_set('user_agent','MSIE 4\.0b2;');

       
$dh = fopen("$url",'r');
       
$result = fread($dh,8192);                                                                                                                            
        return
$result;
}
?>
php at gotdoof dot com
04-Apr-2004 06:19
Note that opening a fifo with fopen() will block the php process until data is sent to it. That means any function you have registered as a shutdown function (register_shutdown_function()) will not be called when the user disconnects, and the process will keep running in the background, waiting for input. I know of no way around this, besides using some other means of IPC.
richard dot quadling at carval dot co dot uk
04-Feb-2004 02:04
The issue involving some sites requiring a valid user-agent string when using fopen can easily be resolved by setting the user_agent string in the PHP.INI file.

If you do not have access to the PHP.INI file, then the use of

ini_set('user_agent','Mozilla: (compatible; Windows XP)');

should also work.

The actual agent string is up to you. If you want to identify to the sites that you are using PHP ...

ini_set('user_agent','PHP');

would do.

Regards,

Richard Quadling.
29-Jan-2004 08:34
If you are connecting to your ftp server through a router doing NAT (such as the Zyxel 128L prestige router/bridge we are using) by doing say an <? fopen("ftp://ftpusername:ftppassword@ftpserver/".$file_name, "w") ?>, then this could fail. You will get php_hostconnect connection failed error. This is because <?fopen() ?>function uses a passive ftp connection which the Zyxel router does not support, even though your ftp server may be configured to allow the passive connections which php <?fopen?> function is using. Note that $file_name is the file we want to ftp to the remote server eg could be file.txt.

Thus an alternative would be to do create the file you want in a local directory of your machine or in the webserver where your php files reside eg use <?fwrite()?> as documented in the manual. Once you have the $file_name you want to ftp created, do the following:

<?
ftp_connect
($ftp_server);
//which can connect to the ftp server using an active connection.
ftp_login ($conn_id, $ftp_username."@".$ftp_server, $ftp_password);
$fp = fopen($PATH."".$file_name, 'r');
// eg. $fp = fopen("http://www.yourwebsite.com/".$file_name, 'r');
//turn off passive mode transfers
ftp_pasv ($conn_id, false);
//now upload $file_name
ftp_fput($conn_id, $file_name, $fp, FTP_ASCII));
?>
Your file should now be in your ftp server, having used an active connection.
sergiopaternoster at tiscali dot it
27-Nov-2003 02:11
If you want to open large files (more than 2GB) that's what I did and it works: you should recompile your php with the CFLAGS="-D_FILE_OFFSET_BITS=64" ./configure etc... This tells to your compiler (I tested only gcc on PHP-4.3.4 binary on Linux and Solaris) to make the PHP parser binary large file aware. This way fopen() will not give you the "Value too large for defined data type" error message.
God bless PHP
ciao
Sergio Paternoster
ken dot gregg at rwre dot com
26-Nov-2003 12:03
PHP will open a directory if a path with no file name is supplied. This just bit me. I was not checking the filename part of a concatenated string.

For example:

$fd = fopen('/home/mydir/' . $somefile, 'r');

Will open the directory if $somefile = ''

If you attempt to read using the file handle you will get the binary directory contents. I tried append mode and it errors out so does not seem to be dangerous.

This is with FreeBSD 4.5 and PHP 4.3.1. Behaves the same on 4.1.1 and PHP 4.1.2. I have not tested other version/os combinations.
dan at cleandns dot com
19-Nov-2003 08:15
<?php
#going to update last users counter script since
#aborting a write because a file is locked is not correct.

$counter_file = '/tmp/counter.txt';
clearstatcache();
ignore_user_abort(true);     ## prevent refresh from aborting file operations and hosing file
if (file_exists($counter_file)) {
  
$fh = fopen($counter_file, 'r+');
    while(
1) {
      if (
flock($fh, LOCK_EX)) {
        
#$buffer = chop(fgets($fh, 2));
        
$buffer = chop(fread($fh, filesize($counter_file)));
        
$buffer++;
        
rewind($fh);
        
fwrite($fh, $buffer);
        
fflush($fh);
        
ftruncate($fh, ftell($fh));    
        
flock($fh, LOCK_UN);
         break;
      }
   }
}
else {
  
$fh = fopen($counter_file, 'w+');
  
fwrite($fh, "1");
  
$buffer="1";
}
fclose($fh);

print
"Count is $buffer";

?>
phpNO at SPAMperfectweb dot com
31-Jul-2003 10:39
I offer the following script for updating a counter, using methods gleaned from various posts on file operations...

<?
$counter_file
= 'somefile.txt';
clearstatcache();
ignore_user_abort(true);     ## prevent refresh from aborting file operations and hosing file
$fh = fopen($counter_file, 'r+b');     ## use 'r+b' so file can be read and written
if ($fh)
{
     if (
flock($fh, LOCK_EX))     ## don't do anything unless lock is successful
    
{
         
$count = fread($fh, filesize($counter_file));
         
rewind($fh);
         
$count++;
         
fwrite($fh, $count);
         
fflush($fh);
         
ftruncate($fh, ftell($fh));     ## better than truncating to 0 before writing, per 04-Mar-2003 comment below
         
flock($fh, LOCK_UN);
     } else echo
"Could not lock counter file '$counter_file'";
    
fclose($fh);
} else  echo
"Could not open counter file '$counter_file'";
ignore_user_abort(false);     ## put things back to normal

echo "counter is at $count";
?>
unshift at yahoo dot com
02-Jul-2003 01:58
It seems that fopen() errors when you attempt opening a url starting with HTTP:// as opposed to http:// - it is case sensitive.  In 4.3.1 anyway..."HTTP://", by not matching "http://" will tell the wrapper to look locally.  From the looks of the source, the same goes for HTTPS vs https, etc.
simon at gornall dot net
19-Jun-2003 09:24
If you're having problems with fopen("url...") but you can run 'host url' in a shell window and get the correct lookup, here's why...

This has had me banging my head against it all day - finally I found the answer buried in the bug reports, but figured it should really be more prominent!

The problem happens when you're on an ADSL line with DHCP (like our office)... When the ADSL modem renews the DHCP lease, you can also switch DNS servers, which confuses apache (and hence PHP) - meaning that you can't look up hosts from within PHP, even though you *can* from the commandline.... The short-term solution is to restart apache.

You'll get "php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution in ..." messages as symptoms. Restart apache, and they're gone :-)

Simon
RobNar
17-Jun-2003 05:15
This is an addendum to ibetyouare at home dot com's note about Apache directory permissions.  If you are on a shared host and cannot tweak Apache's permissions directives then you might try setting the same thing in a .htaccess file.  Failing that, if you are having trouble just creating files then  set the directory permissions to allow writing (for whatever directory the file is supposed to be in) and include the following before fopen():

`touch /path/to/myfile/myfile.txt`;

That will usually create a new empty file that you can write to even when fopen fails. - PHP 4.3.0
09-Jun-2003 12:50
If you have problems with safe mode creating errors

"Warning: SAFE MODE Restriction in effect. The script whose uid is.."

because one of your PHP scripts created the PHP file you are now trying to run, then you can use fopen() to create these files which will then be owned by you (not the server admin).

It must be done using the ftp method...

>> fopen('ftp://user:pass@domain.com', 'w+b');

But please remember that this only creates files, I haven’t found a way around setting the correct UID on folders (yet)

Krang
- http://www.krang.org.uk
Jhilton a at t nurv dot us
05-Jun-2003 09:54
Quick tip. If using fopen to make http requests that contain a querystring, it is advised that you urlencode() your values, else characters like @ can make fopen (or whatever wrapper it is using) throw an error.
04-Mar-2003 05:49
To overwrite a file with a new content without deleting it, and without changing the owner or access rights, it's best to not use:

$file = fopen($filename, 'r+b); // binary update mode
...
ftruncate($file, 0);
fwrite($file, $my_stuff);
...
fclose($file);

but instead the faster one:

$file = fopen($filename, 'r+b); // binary update mode
...
rewind($file);
fwrite($file, $my_stuff);
fflush($file);
ftruncate($file, ftell($file));
...
fclose($file);

The reason is that truncating a file at size 0 forces the OS to deallocate all storage clusters used by the file, before you write your content which will be reallocated on disk.

The second code simply overwrites the existing content where it is already located on disk, and truncates any remaining bytes that may exist (if the new content is shorter than the old content). The "r+b" mode allows access for both read and write: the file can be kept opened after reading it and before rewriting the modified content.

It's particularly useful for files that are accessed often or have a size larger than a few kilobytes, as it saves lots of system I/O, and also limits the filesystem fragmentation if the updated file is quite large.

And this method also works if the file is locked exclusively once opened (but I would rather recommend using another empty file for locking purpose, opened with "a+" access mode, in "/var/lock/yourapp/*" or other fast filesystems where filelocks are easily monitored and where the webserver running PHP is allowed to create and update lock files, and not forgetting to close the lock file after closing the content file).
draconumpb at hotmail dot com
07-Dec-2002 12:37
I just used explode() as an alternative to fscanf, since my only delimiter was | (pipe). I was having problems with it, since I use it in my news-management script. I found that it cut the last variable I was using, $body, a bit short when I posted a long news post. This would've been a real problem for anybody trying to make news posts longer than a paragraph or so.

However, I found that when I used:
list($variable1, $variable2, etc) = explode("|",$data);
it didn't cut any variables short, so.. what I'm really trying to say here is that for people who are experiencing problems with parsing simple files (i.e with only a single, simple delimiter such as : or |) using the unecessarily complex fscanf() and sscanf() functions, explode() is definately the way to go.

function get_news($filepath, $newsid)
{
$datafile = fopen("$filepath/news/$newsid.txt","r");
$data = fread($datafile, 1000000);
list($author, $email, $date, $subject, $body) = explode("|",$data);
$body = stripslashes("$body");
$subject = stripslashes("$subject");
echo "<a href=\"mailto:$email\">$author</a> -- $date -- $subject<hr>$body<p>";
}

sample file:

AdministratorMax|admin@somesite.com|Tuesday, March 5th @ 5:45 PM EST|Site Going Down Tomarrow|Well, folks, I\'m sorry to say that the site will indeed be down tomarrow for most of the day. Hang in there.

Output:

<a href="mailto:admin@somesite.com">AdministratorMax</a> -- Tuesday, March 5th -- Site Going Down Tomarrow<hr>Well, folks, I'm sorry to say that the site will indeed be down tomarrow for most of the day. Hang in there.

Thought that might be useful for anybody making a simple news-management script, ;)

By the way, feel free to correct me if I made any mistakes - I'm at my dad's work where I don't really have a way to check to see if it works or not. However, I use a more complex version of this on my portal project, and it works beautifully.
andyNO at SPAMuchicago dot edu
30-Aug-2002 11:42
Playing with fopen("https://xxx", "r") it seems that HTTPS is only supported with OpenSSL AND PHP 4.3 . Older versions of PHP don't seem to be able to do this.
suraj at _nospam_nospam_symonds dot net
17-Jul-2002 03:41
This note is relevant to the first few notes that talk about writing to files as user 'foobar'.

if one wanted to write to files as user 'foobar' when apache runs as 'root' the new POSIX fucntions. Here's a code snippet explaining how this can be done

<?

$x
= posix_getuid ();

if (
0 == $x) {
   echo
"I'm root\n";

  
$pw_info = posix_getpwnam ("foobar");
  
$uid = $pw_info["uid"];
  
posix_setuid ($uid);

  
$fp = fopen ("/tmp/test.file", "w");
  
fclose ($fp);
} else {
   echo
"I'm not root! I'm not worthy... I'm not worthy....\n";
}

?>

[Note:
1. This would only set the uid... not the gid. If you wanted to write to files as 'foobar:foobar' then you also have to do a posix_setgid ($gid);
2. If you are using the CGI version of php4, you should setuid your php4 interpreter: chmod 4755 /path/to/cgi-bin/php4 (generally, /usr/lib/cgi-bin/php4)]
01-Jul-2002 06:57
Note that if specifying the optional 'b' (binary) mode, it appears that it cannot be the first letter for some unaccountable reason. In other words, "br" doesn't work, while "rb" is ok!
jared at dctkc dot com
22-Apr-2002 10:33
<?php
// HOW TO USE PHP TO WRITE TO YOUR SERIAL PORT: TWO METHODS
$serproxy=true;
if (
$serproxy) {
   
// Use this code in conjunction with SERPROXY.EXE
    // (http://www.lspace.nildram.co.uk/freeware.html)
    // which converts a Serial stream to a TCP/IP stream
   
$fp = fsockopen ("localhost", 5331, $errno, $errstr, 30);
    if (!
$fp) {
        echo
"$errstr ($errno)";
    } else {
       
$e = chr(27);
       
$string  = $e . "A" . $e . "H300";
       
$string .= $e . "V100" . $e . "XL1SATO";
       
$string .= $e . "Q1" . $e . "Z";
        echo
$string;
       
fputs ($fp, $string );
       
fclose ($fp);
    }
} elseif (
$com1) {
   
// Use this code to write directly to the COM1 serial port
    // First, you want to set the mode of the port. You need to set
    // it only once; it will remain the same until you reboot.
    // Note: the backticks on the following line will execute the
    // DOS 'mode' command from within PHP
   
`mode com1: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
   
$fp = fopen ("COM1:", "w+");
    if (!
$fp) {
        echo
"Uh-oh. Port not opened.";
    } else {
       
$e = chr(27);
       
$string  = $e . "A" . $e . "H300";
       
$string .= $e . "V100" . $e . "XL1SATO";
       
$string .= $e . "Q1" . $e . "Z";
        echo
$string;
       
fputs ($fp, $string );
       
fclose ($fp);
    }
}
?>
16-Mar-2002 03:18
Also if you're server is useing htaccess to authticate users make sure to add the username and password to the http link you're trying to open. I forgot about this and took a while to find.
ie:

fopen("http://user:pass@www.mysite.com/mypage.php");
landrews at email dot com
21-Feb-2002 07:31
To the people haveing problems with opening "ftp:" url opens and files not being written.  It seems that PHP wants the complete path. Make sure your not referencing through a soft link or alias. Use the full path from /
ie
/usr/www/htdocs/data/blah.php
php at themastermind1 dot com
24-Oct-2001 07:37
I have found that I can do fopen("COM1:", "r+"); to open the comport in windows. You have to make sure the comport isn't already open or you will get a permission denied.

I am still playing around with this but you have to somehow flush what you send to the comport if you are trying to communicate realtime with a device.
keithm at aoeex dot NOSPAM dot com
31-Jul-2001 02:19
I was working on a consol script for win32 and noticed a few things about it.  On win32 it appears that you can't re-open the input stream for reading, but rather you have to open it once, and read from there on.  Also, i don't know if this is a bug or what but it appears that fgets() reads until the new line anyway.  The number of characters returned is ok, but it will not halt reading and return to the script.  I don't know of a work around for this right now, but i'll keep working on it.

This is some code to work around the close and re-open of stdin.

<?php
function read($length='255'){
    if (!isset(
$GLOBALS['StdinPointer'])){
       
$GLOBALS['StdinPointer']=fopen("php://stdin","r");
    }
   
$line=fgets($GLOBALS['StdinPointer'],$length);
    return
trim($line);
}
echo
"Enter your name: ";
$name=read();
echo
"Enter your age: ";
$age=read();
echo
"Hi $name, Isn't it Great to be $age years old?";
@
fclose($StdinPointer);
?>
icon at mricon dot com
09-Nov-1999 11:44
If you're running PHP as apache module, it will always write files as "nobody", "www", "httpd", (or whatever user your webserver runs as) unless you specify a different user/group in httpd.conf, or compile apache with suexec support.
However, if you run PHP as a CGI wrapper, you may setuid the PHP executable to whatever user you wish (*severe* security issues apply). If you really want to be able to su to other user, I recommend compiling with suexec support.
AFAIK, PHP can't NOT use SuEXEC if apache does. If PHP is configured as an apache module it will act as whatever user the apache is. If apache SuEXEC's to otheruser:othergroup (e.g. root:root), that's what PHP will write files as, because it acts as a part of apache code. I suggest you double-check your SuEXEC configuration and settings. Note: you can't su to another user within the PHP code -- it has to be an apache directive, either through <VirtualHost>, or through .htaccess. Also note: I'm not sure how it all works (if it works at all) on Win32 platforms.
Check www.apache.org to see how it's done.

fpassthru> <fnmatch
Last updated: Sat, 07 Jan 2012