Datei-Informationen @ PHP

Existenz, Größe, Alter usw.

Auf dieser Seite finden sie eine Sammlung von Funktionen, mit deren Hilfe Informationen über Dateien (files) erhalten werden. PHP arbeitet meistens mit Webservern zusammen. Am eigenen PC installiert, können diese Funktionen jedoch auch für den eigenen PC eingesetzt werden.
PHP PHP Hypertext Processor (File Input / Output)
Pfad-Analyse Zerlegung von Datei-Pfaden in Verzeichnis, Dateiname, Erweiterung
URL-Analyse Zerlegung von Web-Adressen
Pfad-Synthese Erstellung von Pfad-Strings
Existenz, Type Existiert eine Datei ? Welche Datei-Art, -Type ?
Größe Datei-Größe in Byte
Zugriffsrechte Was ist für wen erlaubt ?
Zeiten Datum und Zeit von Erzeugung, Änderung, Zugriff
Info-Array Funktionen stat und fstat liefern ein Array von Datei-Informationen
Referrer & Caller Daten über die anfragende Web-Adresse oder Datei
Bilder Spezielle Informationen zu Bild-Dateien
Resourcen Sparsamer Umgang mit Resourcen: Schließen & Freigeben

Pfad-Analyse:   Aufspaltung in die Bestandteile

Aktuelles Verzeichnis:

Der absolute Pfad zum aktuellen Verzeichnis (current working directory, cwd) wird von PHP-Funktion getcwd() zurückgegeben.
Dieses Verzeichnis ist der Ausgangspunkt für die Erstellung relativer Pfade:
Man kann es mit Funktion chdir() ändern.
Details auf der Seite File-I/O.
$cwd = getcwd();

Datei-Pfad-Analyse:

Ein Pfad ist ein String (Text), welcher den Namen einer Datei und den Pfad dorthin durch den Verzeichnis-Baum angibt.
Ein relativer Pfad nimmt als Bezugspunkt das aktuelle Verzeichnis (cwd), d.i. normalerweise jenes Verzeichnis, in welchem sich das PHP-Script selbst befindet.
Ein absoluter Pfad nimmt als Bezugspunkt die "Wurzel" des Dateibaums, das ist bei Linux / , bei Windows der 'Arbeitsplatz'.
__FILE__ gibt den absoluten Pfad zur eigenen Datei (hier gekürzt) zurück.

$mypath = __FILE__;
$dir = dirname($mypath);
$bas = basename($mypath);
$pinf = pathinfo($mypath);
$dir = $pinf['dirname'];
$bas = $pinf['basename'];
$ext = $pinf['extension'];
Diese Funktionen zerlegen einen beliebigen Pfad-String in seine Teile:
dirname() gibt den Verzeichnis-Pfad ohne Dateinamen zurück.
basename() gibt den Dateinamen ohne Pfad zurück.
pathinfo() gibt ein Array mit diesen Elementen zurück: dirname, basename, extension (Datei-Erweiterung, falls vorhanden).
Falls diese Funktionen für speziellen Bedarf nicht ausreichen, kann man einen Pfad vorteilhaft mit einem → Regulären Ausdruck analysieren.
Live-Live-PHP-PHP:
__FILE__ = /srv/www/htdocs/.../php/file_info.php
$dir = /srv/www/htdocs/.../php
$bas = file_info.php
$pinf['dirname'] = /srv/www/htdocs/.../php
$pinf['basename'] = file_info.php
$pinf['extension'] = php

URL-Analyse (von Web-Adressen)

Demo-URL mit allen erlaubten Bestandteilen:
http://anton:geheim@www.demo.com:8080/test/file.php?a=12&z=34#kapitel_3
Die Funktion parse_url() dient zur Zerlegung von → URLs (Internet-Adressen, komplett mit http://... ) in ihre Bestandteile.
Die Elemente scheme, host, path müssen immer vorhanden sein.
Das Element path darf leer bleiben ('Homepage'), oder kann mit den oben angeführten Methoden weiter zerlegt werden.
Wenn ein Datei-Name fehlt, wird vom Webserver automatisch eine Datei mit einem Standard-Namen gesucht, meist index.html
Diese URL-Elemente sind optional: user, pass, query, fragment
Das Element query zeigt → GET-Argumente an.
Element fragment entspricht einem Sub-Link (Anker) auf der gleichen Webseite.
Analyse der oben angegebenen Demo-URL mit PHP:
$ua = parse_url($url);
Ergebnis:
$ua['scheme'] = http
$ua['user'] = anton
$ua['pass'] = geheim
$ua['host'] = www.demo.com:8080 $ua['path'] = /test/file.php $ua['query'] = a=12&z=34 $ua['fragment'] = kapitel_3
Fake-URL
Jeder Host-Adresse kann mit den Separator-Zeichen : @ Username und Passwort vorangestellt werden.
Das wird oft zur Täuschung über das wahre URL-Ziel verwendet:
Das Ziel ist nicht die scheinbar auf http:// folgende Adresse, sondern der Teil nach dem @
Einige Beispiele:
http://www.microsoft.com:free_office_download@mafia.com
http://www.google.de:q=gratis_mp3@198.81.129.100 http://www.freeware.xyz&alles:gratis@0306.0121.0201.0144

Details zu URLs und Exotischen URLs (Obfuscation, Non-dotted URLs, ...

Die eigene URL

Man kann das → Globale Array $_SERVER verwenden, um einen String der momentanen eigenen URL herzustellen.

$h='http';
$h.=$_SERVER['HTTP_HOST'];
$h.=$_SERVER['REQUEST_URI'];
Ergebnis für diese Webseite:
$h = http://www.topsoft.at/pstrainer/entwicklung/php/inout/file_info.php

Pfad-Synthese:   Zusammensetzung aus den Bestandteilen

Pfad-Separator:

In der Variablen $path wird ein Pfad zur Datei 'test.dat' im Verzeichnis 'buffer' zusammengesetzt.
Die Konstante DIRECTORY_SEPARATOR enthält für Linux das Zeichen '/', für Windows '\'. Alternativ können sie das Pfad-Trennzeichen auch nach dem Wert der Konstanten PHP_OS oder der Funktion getenv('PATH') festlegen.
Dieser Pfad wird in allen folgenden Beispielen dieser Seite verwendet.
$path = 'buffer';
$path .= DIRECTORY_SEPARATOR;
$path .= 'test.dat';
Live-Live-PHP-PHP:
$path = buffer/test.dat

Portable absolute Pfade:

Wenn sie absolute Pfade benötigen (ist bei erhöhter Sicherheit geboten) und portablen Code (andere Webserver) erzeugen wollen, dann muss der Pfad programmiert werden.
In diesem Beispiel wird ein absoluter Pfad zum Verzeichnis buffer erstellt, auf gleicher Ebene wie das Verzeichnis php, in dem sich das aktuelle Script befindet. Der gesamte Anfang des Pfades wird unabhängig von seiner 'Tiefe' aus dem eigenen Pfad __FILE__ übernommen.
Details zum Thema Reguläre Ausdrücke (preg-Funktionen)
$path = dirname(__FILE__);
$path = preg_replace('/php.*$/','',$path).'buffer';
$path = $buffer.DIRECTORY_SEPARATOR.'test.dat';
So entsteht aus dem String
/srv/www/htdocs/.../php/file_info.php
der gewünschte String
/srv/www/htdocs/.../buffer/test.dat

Windows-BadSlash

Ein System-unabhängiges Programm müsste bei jeder Anweisung, die einen Pfad betrifft, den Windows-Separator \ (Backslash) getrennt berücksichtigen.

Tipp: Es ist besser, in allen Pfaden den Standard-Separator / (Slash) zu verwenden. Das macht PHP-Programme einfacher und sicherer.

Erzeugung System-unabhängiger Pfade, z.B.
$path = getcwd();
$path = preg_replace("/\\\\/","/",$path);
Derartige Pfade kann man einheitlich (ohne Rücksicht auf Windows) verarbeiten und verwenden, da PHP bei einem Zugiff auf das Dateisystem automatisch den passenden Separator verwendet.
Beachten sie: Ein \ Backslash in einem Regulären Ausdruck in PHP wird durch 3 zusätzliche Backslash-Zeichen maskiert !

Windows-Arbeitsplatz

Die Wurzel des gesamten Dateisystems wird auf Linux stets mit einem einfachen Slash bezeichnet, z.B.
$path = '/';
Alle 'Volumes' und Verzeichnisse liegen in einem Sub-Verzeichnis, bzw. lassen sich an jeder beliebigen Stelle in das Dateisystem einhängen, z.B.
$path = '/home/ich/festplatte';

Das Wurzel-Verzeichnis von Windows-Systemen ('Arbeitsplatz') ist nicht so einfach zugänglich. Das Beispiel rechts zeigt, wie man mit einem System-Programm eine Liste aller 'Volumes' herstellen kann, d.h. aller verwendbaren Laufwerks-Buchstaben.
Einschränkungen: Der Befehl gibt im Gegensatz zur manuellen Ausführung keine Netzlaufwerke zurück.

Liste aller verwendbaren Windows Laufweks-Buchstaben:
$cmd = 'fsutil fsinfo drives';
$t = exec($cmd,$ra,$rc);
$t = preg_replace("/^Laufwerke:/",'',$t);
$t = preg_replace("/\x{0}/",' ',$t);
$t = preg_replace("/\\\\/",'',$t);
print $t;
Aus dem Ergebnis-Text des Programms fsutil werden einige Teile entfernt: Der führende Text, die als Separatoren verwendeten Null-Bytes und die Backslash-Zeichen.
Die Liste lässt sich zur weiteren Verabeitung mit preg_split() in ein Array aufspalten.

Hinweis: Jedes Betriebssystem kann auch leere Volumes verwalten, z.B. CD/DVD-Laufwerke ohne Datenträger.

Datei-Existenz, -Art (Datei, Verzeichnis), -Type

PHP-Funktion file_exists() kann dazu verwendet werden, die Existenz einer Datei oder eines Verzeichnisses zu testen.
if(file_exists($path)) {
{..}
}
else {print 'Fehler..';}
Funktion filetype() gibt die Datei-Type zurück: ein Element aus
{fifo, char, dir, block, link, file, unknown}
$ft = filetype($path);
Mit den Funktionen is_dir,is_file() kann gezielt festgestellt werden, ob es sich um ein Verzeichnis (Ordner, directory) oder eine Datei (file) handelt.
Alle Funktionen benötigen einen Pfad (s.o.) als Argument.
Ähnliche PHP-Funktionen: is_link(), is_executable()
if(is_dir($path)) {..}
if(is_file($path)) {..}
Live-Live-PHP-PHP:
file_exists($path) = 1
filetype($path) = file
is_dir($path) =
is_file($path) = 1

Datei-Größe

Die Größe in Byte ist die meist-gebrauchte Information über eine Datei. Die Funktion filesize() benötigt einen Pfad als Argument.
$fs = filesize($path);
Live-Live-PHP-PHP:
$fs = 40

Datei-Zugriffsrechte

Die PHP-Funktionen is_readable(),is_writable() stellen fest, ob PHP die entsprechenden Rechte hat. Da mit is_writable() häufig Syntax-Fehler programmiert wurden, steht ein äquivalentes Alias mit dem Namen is_writeable() zur Verfügung.
Weitere Informationen über Zugriffsrechte bieten die ↓ Funktionen stat(), fstat()
$rok = is_readable($path);
$wok = is_writable($path);
// $wok = is_writeable($path);
Funktion fileperms() gibt die Datei-Zugriffsrechte zurück. Das Ergebnis ist identisch mit ↓ stat($path)['mode']
$fperm = fileperms($path);
Mit Funktion umask() werden die PHP-Zugriffsrechte gelesen und gesetzt. Ohne Argument wird die aktuelle PHP-Maske ausgegeben - sie wird hier wie auf Linux üblich als Oktalzahl angezeigt.
$um = umask();
$umokt = sprintf('&0%03o',$um);
Live-Live-PHP-PHP:
is_readable($path) = 1
is_writable($path) = 1
fileperms($path) = 33188 = &x81A4
umask = &0022

Datei - Zeiten: Erstellung, Änderung, Zugriff

Zur Live-Demonstration wird die Datei datum_zeit.dat verwendet.
Falls sie nicht existiert, wird sie von dieser Webseite neu erzeugt.
In jedem Fall wird zur Änderung eine Text-Zeile (mit dem aktuellen Datum) an die Datei angehängt. Die erste Text-Zeile enthält daher das Erstellungsdatum, jede weitere Zeile ein Änderungsdatum.
Beim Öffnen dieser Webseite wird die Datei gelesen - damit wird das Zugriffs-Datum auf die aktuelle Server-Zeit gesetzt.
Am ↓ Ende dieser Webseite wird bei jedem Aufruf eine weitere Zeile (das aktuelle Datum) als Änderung hinzugefügt.
$path = 'buffer/datum_zeit.dat';
Datei datum_zeit.dat existiert
Erste Zeile = 2012-05-20 09:33:12

Berechnung des Alters einer Datei:
Differenz der UNIX-Timestamps von Datei-Datumj und aktueller Uhrzeit in Sekunden.
Für die Test-Datei ist Alter = 23448 sec
Für jedes Verzeichnis (Ordner) und jede Datei werden vom Dateisystem einige Datum & Zeit - Daten geführt, üblicherweise Erstellungszeit (creation), letzte Änderung (modification) und letzte Verwendung (access). Allerdings scheint es schwierig, die Erstellungszeit zu erhalten - diese sollten sie im Dateinamen oder in der Datei selbst notieren, falls benötigt. Die nachfolgend gezeigten PHP-Funktionen verwenden als Argument den Datei-Pfad, ↓ Funktion fstat() verwendet ein Datei-Handle.

Letzter Zugriff:

PHP-Funktion fileatime() liefert einen UNIX-Timestamp des letzten Zugriffs (access) auf eine Datei. Mit der → Datum und Zeit - Funktion strftime() wird der Timestamp zu einem Standard → ISO-String decodiert. Der dabei verwendete Format-String $fmt wird auch bei allen weiteren Beispielen dieses Kapitels eingesetzt.
$at = fileatime($path);
clearstatcache();
$fmt = '%Y-%m-%d %T';
$as = strftime($fmt,$at);
Live--PHP:
$at = 1337522640
$as = 2012-05-20 16:04:00

Letzte Änderung (inode change time):

PHP-Funktion filectime() liefert einen UNIX-Timestamp der letzten Änderung einer Datei. Der Name deutet auf Erzeugung (creation) hin, diese Funktion liefert jedoch normalerweise nicht das Erzeugungsdatum, sondern das gleiche Ergebnis wie filemtime
$ct = filectime($path);
clearstatcache();
$cs = strftime($fmt,$ct);
Live--PHP:
$ct = 1337521999
$cs = 2012-05-20 15:53:19

Letzte Änderung:

PHP-Funktion filemtime() liefert einen UNIX-Timestamp der letzten Änderung (modification) einer Datei.
$mt = filemtime($path);
clearstatcache();
$ms = strftime($fmt,$mt);
Live-Live-PHP-PHP:
$mt = 1337521999
$ms = 2012-05-20 15:53:19
Die ↓ PHP-Funktionen stat(),fstat() liefern Arrays zur Datei-Information. In den Elementen dieser Arrays sind auch die Datei-Zeit-Daten enthalten.
Änderung der Test-Datei:
Zur Demonstration wird eine Zeile mit dem aktuellen Datum hinzugefügt.
Damit wird eine 'Änderung' zum Zeitpunkt der Erstellung dieser Webseite gesetzt.
Bei Erreichen einer eingestellten maximalen Länge wird die Datei gelöscht.
Details zu diesen Funktionen auf Seite File-IO.
filesize($path) = 200 byte
Neuer Eintrag = 2012-05-20 16:04:00

Daten-Änderung

Mit der PHP-Funktion touch() können die Zeit-Daten einer Datei beliebig geändert werden. Das Beispiel zeigt, wie ein → UNIX-Timestamp mit beliebigen Datum- und Zeit-Daten als Änderungs-Datum einer Datei $path gesetzt wird. Wenn kein Timestamp angegeben ist, dann wird die aktuelle Systemzeit verwendet. Die Zugriffszeit der Datei wird in jedem Fall auf die aktuelle Zeit gesetzt.
$mt = mktime($hm,$mi,$ss,$mo,$dd,$yy);
touch($path,$mt);
Details zu Datum & Zeit @ PHP

Informations-Array

Informations-Array:

Die Funktionen stat(),fstat() liefern die gleichen Arrays zur Datei-Information.
stat() verwendet einen Datei-Pfad (String) als Argument, fstat() verwendet ein file-handle, wie es von Funktion fopen() zurückgeggeben wird.
$sta = stat($path);
/* Alternative
$fp = fopen($path,'r');
$sta = @fstat($fp);
@fclose($fp);
*/
Details zu den Array-Elementen finden sie auf der PHP-Homepage, in Manuals und Tutorials. Live--PHP:
$sta = @stat(test.dat);
$sta['dev'] = 65040
$sta['ino'] = 776494928
$sta['mode'] = 33188
$sta['nlink'] = 1
$sta['uid'] = 3354
$sta['gid'] = 1012
$sta['rdev'] = 0
$sta['size'] = 40
$sta['atime'] = 1337509552 = '2012-05-20 12:25:52'
$sta['mtime'] = 1337509552 = '2012-05-20 12:25:52'
$sta['ctime'] = 1337509552 = '2012-05-20 12:25:52'
$sta['blksize'] = 4096
$sta['blocks'] = 8

Referrer und Caller

Referrer

Ist die URL Internet-Adresse jener Webseite, auf welcher der Link zur aktuellen Seite angeklickt wurde.
Diese Adresse wird von Javascript als Eigenschaft angegeben:
var ref = document.referrer;
PHP (und andere moderne Script-Sprachen) erhält diese Information in einem Globalen Array:
$ref = $_SERVER['HTTP_REFERER'];
Perl verwendet das Globale Hash %ENV
$ref = $ENV{HTTP_REFERER};
Beachten sie, dass REFERRER manchmal irrtümlich als REFERER bezeichnet wurde. Der Fehler wurde nie korrigiert, damit man bestehende Software nicht ändern muss.

Tracker

Diese Information ist wertvoll, da man in jedem halbwegs professionell geführten Web daran interessiert ist, von welchen Seiten die BesucherInnen hierher verwiesen werden. Man findet dazu im internet zahlreiche Counter- und Tracker-Programme, welche diese Daten sammeln und auswerten.

Das Hauptproblem dabei ist, nur den ersten Referrer zu erfassen, da nur diese Adresse interessant ist.

Wenn ein/e BesucherIn im eigenen Web von einer Seite zur nächsten surft, dann wird als Referrer stets das eigene Web angegeben: In diesem Fall interessiert zwar, welche Seiten besucht werden, jedoch nicht der Referrer.

Caller

Ist je nach Definition jene Datei oder Funktion, welche ein Programm aufgerufen hat. Das kann wichtig sein, weil PHP-Programme oft in zahlreiche Module gegliedert sind, die mit include-Anweisungen kombiniert werden.
PHP bietet dazu wenige Möglichkeiten. Das Globale Array liefert nur in bestimmten Fällen die gewünschten Daten:
$cal = $_SERVER['PHP_SELF'];

Lösungs-Möglichkeit:
Das aufrufende Programm sendet selbst die gewünschten Daten, z.B. mit
call_function(__FILE__);
Im Beispiel wird der eigene Pfad zur Caller-Datei als Argument an die Funktion übergeben und kann von dieser ausgewertet werden.

Manipulation

Referrer, Caller und ähnliche Daten lassen sich vergleichsweise leicht manipulieren. Man sollte die erhaltenen Daten daher vor Gebrauch säubern und niemals ungeprüft für wichtige Zwecke verwenden.

Beispiel rechts: Säuberung eines Strings von Sonderzeichen und Backslash mit Hilfe von → Regulären Ausdrücken:
function clean($s) {
$s = trim($s);
$s=preg_replace("/[\x{00}-\x{1F}]/",'',$s);
$s=preg_replace("/[\x{7E}-\x{FF}]/",'',$s);
$s = preg_replace("/[\x{5C}]/",'',$s);
return $s;
}
// Anwendung:
$ua = clean($_SERVER['HTTP_USER_AGENT']);
Anm.: Alle 3 RegExp lassen sich zusammenfassen. Diese Darstellung soll der besseren Übersicht dienen.

Bild-Informationen

Die PHP-Funktion getimagesize() aus dem Modul gd liefert ein Array von Bild-Informationen. Die Adresse (hier $path) kann zu einer Datei am Webserver-PC führen, wahlweise aber auch zu einer Adresse im Netzwerk oder zu einer Internet-Adresse (Beispiele rechts).
$path = '/img/test.jpg';
$path = 'Z:/img/test.gif';
$path = 'http://web.org/img/test.png';
$ia = getimagesize($path);
FreePatents Live--PHP: rechts die Muster-Grafik
[0]= Breite in px, [1]= Höhe in px,
[2]= Type {1..16} für {GIF,JPG,PNG,...}
['bits']= Bit/Kanal (nicht bei AnimatedGIF !)
['channels']= Kanäle (GIF immer 3)
['mime']= → MIME-Type der Grafik
$ia[0] = 80
$ia[1] = 48
$ia[2] = 1
$ia[3] = width="80" height="48"
$ia['bits'] = 6
$ia['channels'] = 3
$ia['mime'] = image/gif

EXIF:

Das PHP-Modul exif bietet einige Funktionen zur Bild-Information.
exif_imagetype() liefert das gleiche Ergebnis wie getimagesize[2], jedoch rascher.

exif_imagetype($imgpath) = 1
Funktion exif_read_data() liefert EXIF-Daten: Das sind Bild-Informationen, die von den meisten professionellen Bildquellen zusammen mit dem Bild gespeichert werden (z.B. Datum, Zeit und Kamera-Einstellung für DigiCams). Diese Funktion ist nur auf Bild-Dateien der Typen JPEG,TIFF anwendbar.

Einige der EXIF-Daten sind Arrays, einige davon selbst wieder Arrays. Das Beispiel rechts zeigt, wie diese chaotische Mischung von Variablen und Arrays (bei jedem Hersteller anders) wenigstens erfasst werden kann.

Details zur Herstellung und Bearbeitung von Grafik mit PHP.
if(exif_imagetype==2) {
$ia = exif_read_data($imgpath);
foreach ($ia as $n1=>$v1) {
if(is_array($v1)) {
foreach ($v1 as $n2=>$v2) {
print "$n1.$n2 = $v2<br>";
}
}
else {print "$n1 = $v1<br>";}
}
 
Leider ist Art und Struktur der EXIF-Daten nicht standardisiert.
Rechts einige typische Beispiele der (>100) EXIF-Daten von Bildern aus einer DigiCam. Die Daten sind chaotisch aufgebaut, häufig redundant, schlecht dokumentiert.
Schade um so viel Aufwand, den man zwar bezahlen muss, aber nicht sinnvoll nutzen kann.
Immerhin sind wenigstens die Daten der Bilder eines DigiCam-Modells untereinander vergleichbar...

Eine einfache Möglichkeit zum Schreiben von EXIF-Daten scheint nicht vorgesehen, vermutlich als Urheber-Schutz.
Beispiel für EXIF Meta-Daten
COMPUTED.Height = 1536
COMPUTED.Width = 2048
COMPUTED.ApertureFNumber = f/2.8
ImageDescription = DIGITAL CAMERA
DateTime = 2012-05-20 16:04:00
ExposureTime = 10/50
ExifImageWidth = 2048
ExifImageLength = 1536
...

Resourcen sparen !

PHP-Funktion clearstatcache gibt die verwendeten Resourcen wieder frei. Sie sollten diese Funktion nach dem Aufruf jeder auf dieser Webseite gezeigten Funktion aufrufen.
clearstatcache();

Letzte Änderung dieser Seite: 2011-10-13 14:33:32