file_exists - Groß-/Kleinschreibung ignorieren
crischa
- php
Hi,
ich habe ein Script zur Registrierung in einem Flatfile-Blog. Der Username wird als Datei angelegt (username.txt). Bei der Formularprüfung teste ich, ob der Benutzername (= Dateiname) bereits existiert. Ich möchte allerdings keine Unterscheidung zwischen Groß- und Kleinschreibung (GKS). Also registriert sich jemand als MondGesicht, soll auch MONDGESICHT, mondgesicht, usw. als der gleiche Benutzername gelten. Ich könnte natürlich alle Benutzernamen bei Registrierung in z.B. Kleinschreibung umwandeln, aber ich möchte dem Nutzer die Freiheit über GKS überlassen.
Wie kann ich den Benutzernamen überprüfen, ohne dass nach GKS unterschieden wird?
$pfad = "data/users/".$name.".txt";
$Fehler = array("name"=>"","email"=>"","passwort"=>"","zip"=>"",);
if (isset($_POST["submit"])) {
$Fehler["name"] .= !preg_match("/^[0-9a-zA-Z]{3,}+$/i", $_POST["name"]) ? "Geben Sie für Ihren Benutzernamen nur Buchstaben und Ziffern ein. Verwenden Sie keine Umlaute oder Sonderzeichen. Bitte tragen Sie min. 3 Zeichen ein.<br>" : "";
$Fehler["name"] .= file_exists($pfad) ? "Der Benutzername existiert bereits.<br>" : "";
}
Schöne Grüße
crischa
Hello,
Wie kann ich den Benutzernamen überprüfen, ohne dass nach GKS unterschieden wird?
indem Du eine Transformationstabelle zwischenschaltest.
Im Filesystem wird grundsätzlich nur eine Schreibweise (GROSS|klein) benutzt und außerdem in konsolidierter ("normalisierter") Form, also ausschkliesslich mit einer Untermenge von ASCII-Zeichen.
In einer anderen Datei (odr einer Datenbank) hältst Du eine Tabelle, in der die echten Namen stehen.
Beim Anlegen einer neuen Userdatei benutzt Du bitte _nicht_ file_exists()
, denn das ist für diesen Zweck MIST! Du schaffst Dir damit ein "TOCTTOU"-Problem
https://de.wikipedia.org/wiki/Time-of-Check-to-Time-of-Use-Problem
Der richtige Weg wäre es, die Kontrolle dem Betriebssystem/Filesystem selber zu überlassen und dann die Fehlermeldung auszuwerten.
Schau dir dazu die Filefunktionen von PHP genauer an:
http://de2.php.net/manual/en/function.fopen.php
Für deinen Fall kommt der Open-Mode 'xb+' in Frage.
Bei der Fehlerauswertung ist PHP leider fast kurz vor Schrott, da es keine eindeutigen Fehlernummern für derartig wichtige Operationen liefert, aber es gibt eine Möglichkeit durch die Hintertür:
ini_set('track_errors', 1)
$php_errormsg = '';
$fh = @fopen($normalized_username . '.txt', 'xb+');
if (!$fh)
{
# error_handling($php_errormsg);
# oder zum Testen:
echo htmlscpecialchars($php_errormsg);
}
Probier das Scriptlein mal aus und schreib Dir dann eine Funktion error_handling()...
Einfach ein paarmal hintereinander aufrufen.
http://www.php.net/manual/de/reserved.variables.phperrormsg.php
Wenn die Operation erfolgreich war, kannst Du anschließend in ein Array eintragen
# normalisieren
# nachschlagen
# es ist nicht notwendig, eine Case-Insensitive Arrayabfrage durchzuführen, da der
# Filename ohnehin nur in einer Schreibweise angenommen werden soll
# Es kann ja auch nicht sichergestellt werden, ob der Host ein Filesystem führt,
# das Groß-/Kleinschreibung unterscheidet... WinDOOF machts möglich :-O
if (!isset($_filenames[$normalized_username]))
{
$_filenames[$normalized_username] = $real_username;
}
$userfilenames = serialize($_filenames);
# und wegschreiben in Datei.
Lies Dir bitte auch den Artikel von Christian Seiler durch zum Thema File-Locking. Das solltest Du nämlich strikt beachten!
http://aktuell.de.selfhtml.org/artikel/programmiertechnik/dateisperren/
Viel Erfolg.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hallo Tom,
danke für deine ausführliche Hilfe. Ich werde mir das ganze mal zu Gemüte führen!
Schöne Grüße
crischa
Hello Crischa,
danke für deine ausführliche Hilfe. Ich werde mir das ganze mal zu Gemüte führen!
Dann noch einen kleinen Nachtrag:
Die User-Spezial-Files sollten dann tunlichst nicht per http/s direkt erreichbar sein, also am besten außerhalb der Dokument Root gespeichert werden.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hi,
ich habe ein Script zur Registrierung in einem Flatfile-Blog.
Wenn du dir Toms Antwort durchgelesene hast, wird dir sicher klar, dass das nicht so trivial ist wie du vielleicht gedacht haben magst – also überleg dir mal, ob du nicht lieber gleich eine Datenbank benutzen willst. (Dafür kannst du auch SQLite nehmen, dann bleibt das ganze quasi auf „Datei-Ebene“, und braucht keinen „richtigen“ Datenbank-Server.)
Der Username wird als Datei angelegt (username.txt). Bei der Formularprüfung teste ich, ob der Benutzername (= Dateiname) bereits existiert. Ich möchte allerdings keine Unterscheidung zwischen Groß- und Kleinschreibung (GKS).
Das können file_exists und die anderen Dateisystem-Funktionen nicht leisten, wenn ein case-sensitive Dateisystem darunter liegt.
Wenn du das machen wolltest, müsstest du den ganzen Verzeichnis-Inhalt einlesen, und dir alle Dateinamen selber anschauen. (Und die von Tom angesprochenen weiteren Probleme löst das dann immer noch nicht.)
MfG ChrisB