Beiträge von tk1234

    Gibt es eine Möglichkeit, zu überprüfen ob in der DB eine E-Mail Adresse bereits vorhanden ist, um doppelte Einträge zu verhindern?

    Vor dem Speichern abfragen ob es Datensätze es mit der Adresse gibt, wenn ja -> Fehlermeldung. Alternativ kannst du auch prüfen ob das execute fehlschlägt oder nicht (mit deinem Unique-Index wird jeder weitere Eintrag eine Adresse einzutragen ja fehlschlagen, das lässt sich abfangen).


    Übrigens: du denkst an sowas wie Double-Opt-in damit nicht jeder beliebige Adresse da eintragen kann die vielleicht gar keinen Newsletter haben wollen?

    man könnte ja, weil es ein Affenformular ist ja auch den Code nutzen PHP
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">

    Das hat man auch schon 1000 mal gesehen.

    … und war schon 10000mal falsch: das ist eine gefährliche Sicherheitslücke, auch hier muss der (doppelte!) Kontextwechsel beachtet werden!

    Die von dir genannten Varianten PHP_SELF, SCRIPT_NAME und REQUEST_URI enthalten alle unterschiedliche Werte. Mit »/index.php/"onmouseover="alert('hi')« als URI und ohne Behandlung der Kontextwechsel bekommst du als Ergebnis jeweils (ich habe mal ein a-Element genommen, das gleiche gilt natürlich für form):

    HTML
    <a href="/index.php/"onmouseover="alert('hi')">PHP_SELF</a><br>
    <a href="/index.php/%22onmouseover=%22alert('hi')">REQUEST_URI</a><br>
    <a href="/index.php">SCRIPT_NAME</a><br>

    Wie du siehst, ist PHP_SELF gefährlich: das ist eine Sicherheitslücke da sich beliebiger HTML-Code (und damit auch JS-Code) einschleusen lässt. Bei REQUEST_URI wird der Wert URL-Codiert (macht PHP anscheinend von alleine, nachgeforscht warum und weshalb habe ich da jetzt nicht, meine lokale PHP-Installation (aktuell PHP 8.0) spuckt das aber so aus) und bei SCRIPT_NAME wird alles nach dem Dateinamen abgeschnitten (auch ein evtl. vorhandene path-info).

    Wenn man allerdings alle URIs auf die index.php umschreibt (was bei aktuellen Scripten oft/meist der Fall ist) und die entscheidet was geladen wird, fallen zwei Varianten weg: beim Aufruf von z.B. »/training/«, spucken PHP_SELF und SCRIPT_NAME nur »/index.php« aus - was natürlich unbrauchbar ist. Nur REQUEST_URI enthält den hier benötigten Wert »/training/«.


    Was hältst du von der Methode?

    Viel. Viel Abstand. Soweit ich mich erinnere hat das historische Gründe: früher war das action-Attribut notwendig und konnte/durfte nicht weggelassen werden - in HTML5 darf das Attribut weggelassen werden, in dem Fall ist automatisch die aktuelle URI das Ziel des Formulars - warum soll man sich die Mühe machen die URI von Hand da reinzubasteln?

    - Sonderzeichen wie ', oder < und > im Eintrag werden immer noch an die db übertragen, ist das normal?

    Davon ausgehen dass du mit type=text getestet hast: ja. Die Zeichen sollen ja nur so behandelt werden, dass sie keinen Schaden anrichten können, entfernt werden sie aber natürlich nicht.

    In der newsletter.php befindet sich das prepared statement.

    Wie m.scatello schon schrieb: du hast das mit dem Affenformular noch nicht begriffen. Außerdem hast du schon wieder Code kopiert ohne ihn zu lesen/zu verstehen - sonst hättest du nämlich den Kommentar "Registrierung ausführen..." gesehen: der muss natürlich durch den Code für die Speicherung der Daten ersetzt werden. Auch die Zeile »$statement->execute(array($mail));« in der newsletter.php zeigt dass du es noch nicht wirklich verstanden hast: ich habe bereits mehrfach geschrieben, dass ein umkopieren von $_POST['mail'] nicht nötig ist, du verwendest aber trotzdem immer noch $mail statt $_POST['mail'].

    Ich bin dann erstmal raus hier, eine Antwort gibt es erst wieder wenn deutlich wird, dass das Verständnis da ist.

    bis jetzt programmiert in HTML & CSS.

    Garantiert nicht: HTML und CSS sind keine Programmiersprachen, damit kann man da auch nichts programmieren :)

    Zur Verständnis: Mein Code hat mit htmlspezialchars() den kompletten echo String eingebunden.

    Du hingegen nimmst nur die Variable - so würde ich es mir erklären - weil diese an die DB weitergeleitet wird und durch htmlspezialchars() nicht manipuliert werden kann!?

    Ich nehme nur die Variable weil nur die von außen kommt und damit als potentiell gefährlich anzusehen ist - was sonst mit dem Inhalt passiert ist egal. Der Rest von dem Text steht ja fest im PHP-Code und enthält damit garantiert keine gefährlichen Daten. Den kompletten String zu behandeln ist nicht nötig, schadet aber auch nicht.

    Ich habe hier ein Affenformular gefunden.

    Kann ich es verwenden wenn ich es auf mein Formular anpasse?

    Ich würde davon abraten: die Seite beachtet das EVA-Prinzip nicht. Schau dir mal das Beispiel bei SELFHTML an, ganz optimal ist das (wegen dem die()) auch nicht aber definitiv besser als das bei php-kurs.

    Aber Frage, wie verknüpfe ich dann das Affenformular mit der newsletter.php? Oder reicht es wenn am Server eine affenformular.php -Datei liegt?

    Ich kenne deine aktuellen Dateien nicht, irgendwas "verknüpfen" musst du aber nicht: es gibt halt eine Datei in der die komplette Verarbeitung der Daten sowie das Formular steht. Vielleicht hilft die entsprechende Seite im Wiki von SELFHTML bzw. die dort verlinkte Seite bei php.de beim Verständnis.

    Was noch dazukommen wird ist eine DSGVO-Zustimmung...

    So eine Checkbox sollte ja kein Problem sein … Hinweis: das Name/Value-Paar von Checkboxen wird nur übertragen wenn diese ausgewählt wurde, andernfalls steht zu der Checkbox nichts in $_POST drin. Hilfreich könnte übrigens noch das required-Attribut sein (auch für das E-Mail-Feld).

    Abfragen will ich gar nichts. Es soll nur ein Eintrag in die DB gemacht werden, deswegen habe ich die Select * From Abfrage durch ein INSERT INTO ersetzt.

    Dann lass die drei Zeilen mit der while-Schleife einfach ersatzlos weg, du brauchst sie hier nicht. Aber genau das meinte ich: nicht einfach nur blind kopieren/abändern sondern auch genau anschauen und verstehen was das Script eigentlich macht.

    so, jetzt habe ich das Formular mit dem anfälligen script als eigene homepage am lokalen Server angelegt. Die Eingabe kommt auch in der db an, aber sobald ich ein ' oder es zB. mit order+by versuche kommt folgendes....

    Um das zu testen brauchst du ein input mit type=text (oder ohne type-Attribut) - bei type=email sorgt der Browser schon dafür dass da eine E-Mail-Adresse drin steht, allerdings kannst du dich nicht darauf verlassen das der Browser die Prüfung übernimmt: Formulare lassen sich manipulieren bzw. nachbauen, die Daten können also auch von wo anders her kommen.

    Ok, dann weiß ich leider nicht wieder der Code korrekt aussehen soll

    So wie ich es in der Code-Zeile geschrieben habe: htmlspezialchars() wird nur auf die Variable mit den Daten angewandt.

    Die Idee mit der Ziel Weiterleitung habe ich schon begonnen. Aktuell ist es auch so, dass ab dem Absenden des Formulars eine weiße Seite (so wie Du sagst) mit der Fehlermeldungen bzw. Erfolgsmeldung ausgegeben wird. Da eine Extraseite erstellt und auf die dann umgeleitet, damit es dann für den Benutzer freundlicher aussieht

    Falscher Ansatz. Vergiss die Weiterleiterei. Das ist ja gerade der Vorteil bei Affenformularen: die Fehlerbehandlung findet in einem Script statt, irgendwelche Weiterleitungen sind nicht nötig. Wenn das Script nach dem Abschicken des Formulars wieder aufgerufen wird, wird geprüft ob die Daten ok sind. Wenn ja werden sie gespeichert, wenn nein, wird eine Fehlermeldung ausgegeben und anschließend wieder das Formular (einschließlich bereits eingegebener Daten). Beschäftige dich mit dem Thema EVA-Prinzip.

    Ich verstehe Deine Frage nicht, das INSERT soll den Eintrag in die Datenbank übernehmen!?

    Die beiden Zeilen mit prepare und execute sind völlig ok und können so bleiben (laut #13 funktioniert das Speichern ja auch). Das "Problem" ist der while-Block danach: da versuchst du mit fetch() irgendwelche Daten zu holen ohne vorher mit SELECT welche abgefragt zu haben. Was an der Stelle richtig ist weiß ich nicht: du hast noch nicht verraten was nach dem Speichern überhaupt passieren soll. Und wenn du irgendwo Code kopierst: du musst den dann schon auch verstehen, sonst kommst du nie auf einen grünen Zweig, immer nur irgendwo Fetzen zusammen zu kopieren funktioniert nicht.

    mein Verständnisproblem bezieht sich auf die injection welche ich nicht auffinden konnte.

    Mir ist nicht ganz klar wie du die "auffinden" willst. Um zu sehen ob ein Code für SQL-Injection anfällig ist, reicht es idR wenn man mal ein ' in das entsprechende Eingabefeld eingibt und sich dann den daraus entstehenden Query anschaut - aber mit prepared Statements bist du da auf der sichern Seite.

    Da ich das alte Script abgespeichert habe, werde ich zu einem späteren Zeitpunkt nochmal darauf zurückkommen und mich versuchen

    Als Tipp am Rande: um auf alte Versionsstände zurückgreifen zu können ist eine Versionsverwaltung wie git ganz hilfreich - nur als Hinweis für die Zukunft.

    Funktioniert das so wie ich es beim zweiten echo versucht habe?
    Oder müsste ich den Text in eine $text Variable umwandeln und erst dann mit htmlspecialchars($text) behandeln?

    Jein. Klar kannst du den kompletten String durch htmlspecialchars() jagen - bei den festen Texten ist es aber unnötig. Ich weiß nicht was du mit "$text Variable" meinst, aber wie schon gesagt, das Umkopieren von Werten aus $_POST (bzw. auch $_GET) ist und war schon immer völlig überflüssig:

    Code
    echo 'E-Mail: ' . htmlspecialchars($_POST['mail']) . ' erfolgreich registriert!';


    - Der Text in "die" war nur ein 0815-placeholder damit etwas da steht.

    Ich versuche noch eine Weiterleitung zum footer, wo sich das Newsletter-Formular befindet wird zu bauen.

    Der jetzige Text ist noch schlechter, in der Ausgabe die beim Browser landet steht kein Link.

    Und wenn die Fehlermeldungen am Ende der Seite stehen, kannst du als Ziel des Formulars auch eine ID als Ziel angeben (action="#newsletter" und id="newsletter" für das Formular) - ich würde vom Formular im Footer aber eher auf eine extra Seite verweisen welche Fehlermeldungen bzw. Erfolgsmeldung ausgibt (das Formular im Footer verweist also auf die extra Seite, das (bei Fehlern nochmal ausgegebene) Formular auf der Extraseite verweist auf sich selbst.

    - Danke, für die Info. Ich wüsste jetzt nur nicht was ich damit machen soll

    Das kommt darauf an was du nach dem INSERT überhaupt vorhast. Der while-Block sieht mir auch eher danach aus als wäre er blind irgendwo zusammenkopiert - eine while-Schleife ist nämlich völlig überflüssig wenn es nur einen anzuzeigenden Datensatz gibt … Vielleicht lernst du erstmal weiter Grundlagen …

    Auch wenn ich (vermutlich) dieses Problem unten mit meiner zweiten Antwort beseitigt haben, möchte ich Dich trotzdem bitte fragen wie ich diese Lücke überhaupt auffinde. Ok SQL-Injection aber wie?? Führe ich die Injektion schon im Eingabefeld, oder erst nach Absenden des Formulars durch? Wie komme ich zu einer Fehlerausgabe? mit " ' ", oder "order by" komme ich zu keinem Fehler

    Ich verstehe dein Verständnisproblem nicht.

    Ist der Code jetzt passend und safe?

    Jein. Das Speichern der Daten bzw. die Übergabe der Daten an die Datenbank ist richtig (mit benannten Parametern (deswegen hatte ich PDO empfohlen) in den prepared Statements wäre der Code noch besser lesbar aber so ist es auch ok) - du hast aber den Kontextwechsel nach HTML nicht beachtet: die beiden echo-Zeilen geben Daten in den HTML-Code aus, Ausgaben müssen hier deswegen mit htmlspecialchars() behandelt werden.


    Außerdem:

    - warum verwendest du auf einmal $_GET? bleib (in diesem Fall) bei $_POST

    - das Umkopieren von Daten aus $_GET/$_POST war schon immer überflüssig - du kannst auch direkt Daten aus $_POST an execute übergeben

    - das "die" ist keine benutzerfreundlichen Fehlerbehandlung

    - das fetch() wird wohl so nicht funktionieren (hab es jetzt nicht ausprobiert) da du vorher keine Daten abgefragt hast

    Ok, hier kann ich momentan nur Raten, aber ich denke der eingebaute Wert in der Tabelle Newsletter wäre VALUES ('$mail').

    Deswegen wäre hier eine Entschärfung nötig, richtig?

    Ja, das was in $mail steht muss entschärft werden.

    Was ist die falsche Stelle und was wäre die richtige Stelle?

    Schrieb ich doch: richtig wäre die Stelle an der die Adresse als Teil des HTML-Codes ausgegeben wird (was allerdings garnicht passiert), falsch ist in der validate-Funktion (die ohnehin Unsinn ist).

    Der angesprochene Inhalt ist in diesem Fall die eingetragene E-Mail Adresse, korrekt? Wenn ja, dann reicht es wenn die Datenbank mit Mails befüllt wird - eine Text Ausgabe ist nicht nötig!

    Korrekt. Eben, die Datenbank soll mit Mails befüllt werden, nicht mit HTML-Code - und du kannst nicht wissen als was irgendwelche Daten in Zukunft mal ausgegeben werden sollen. (Und ja, mir ist bewusst dass in den meisten Fällen in E-Mail-Adressen keine Zeichen vorkommen werden die von htmlspecialchars() verändert würden, aber das Prinzip der korrekten Behandlung von Kontextwechseln sollte *immer* angewendet werden)


    In send.php Zeile 15-18 wird eine Weiterleitung definiert, wenn Eingabe 'empty'. Momentan ist dies auf index.html vorgesehen, aber dazu werde ich noch eine eigene Fehlerseite erstellen

    Mach es dir nicht unnötig schwer: verwende genau eine Datei (Stichwort Affenformular von oben) und behandle dort alle Fälle, einschließlich aller zu behandelnden Fehlerfälle - du willst nicht wirklich für jeden Fehlerfall eine eigene Fehlerseite erstellen (die hier auch den Nachteil haben dass bereits eingegebene Daten nicht übernommen werden).

    ich vermute du wolltest *braucht keinen Text als....* schreiben

    Nein. Das war schon richtig wie ich es geschrieben habe: ein Label-Element enthält die Beschriftung die dem Client sagt was in ein Eingabefeld hineingehört (und hat auch noch den Vorteil dass ein Klick auf den Beschriftungstext den Fokus auf das Eingabefeld setzt, was besonders bei Checkboxen die Bedienung erleichtert).

    Code
    <section class="news">
      <h3>Jetzt registrieren</h3>
      <form method="post">
        <label for="mail">E-Mail-Adresse</label>
        <input type="email" id="mail" name="mail">
        <button name="btn">Abschicken</button>
      </form>
    </section>

    Als input-type habe ich email verwendet (das verbessert die Bedienbarkeit auf Mobilgeräten da die dann wissen was da rein gehört), das fehlende id-Attribut von input ergänzt (sonst fehlt die Zuordnung zwischen label und input), außerdem habe ich alle überflüssigen Attribute weggelassen:

    - input/placeholder -> da stand ohnehin nur das drin was im label ohnehin schon steht

    - button/class -> unnötig, der button ist zum Formatieren über den Selector ".news button" erreichbar

    - button/type -> submit ist der Standardwert

    - form/action -> bei einem Affenformular wird immer die gleiche URL aufgerufen, das geschieht ohne action-Attribut automatisch


    ohne for-/id-Attribut geht es auch wenn du das label erst nach dem Input wieder schließt:

    Code
    <label>E-Mail-Adresse <input type="email" name="mail"></label>

    Ich habe im Internet gesucht wie ich einen Pfeil mache, weil "-->" nicht so gut aussieht. Da bin ich dann auf eine Website gestoßen auf dieser man Emojis etc. für HTML finden kann mit allen Codes.

    »-->« meinte ich auch nicht, aber du brauchst keine HTML-Codes, schreib→ einfach direkt in den Quellcode, nicht &rarr; - das geht mit allen UTF-8 Zeichen und das sind deutlich mehr als es HTML-Referenzen gibt.

    font-color und <center> hatte ich schon weggemacht.

    Und was ist mit <h1> und der div-Suppe?

    Unwissenheit ist mein Problem gewesen, ich programmiere mit VS Code und nutzte bis vor meinem ersten Posting immer nur Live Server als Vorschau-Plugin. Dass da Standart solche Fehlermeldungen nicht angezeigt werden war mir nicht ganz bewusst,

    VS Code zeigt deinen Syntaxfehler (das fehlende Semikolon) bereits an - der Fehler ist in deinem Code in #9 immernoch/wieder drin! Ansonsten habe ich den Server von VS Code noch nicht benutzt, ich verwende immer den lokalen Indianer. Übrigens: in PHP-Dateien die aussschließlich PHP-Code enthalten lässt man das ?> am Ende weg.

    btw: "Standard" schreibt sich schon immer mit "d" am Ende.

    Nachdem ich keine wirklichen PHP und MySQL Kenntnisse habe tu ich mich von Grund auf schwer.

    Dann eigne dir erstmal die Grundkenntnisse an - dazu die zu vermitteln ist das Forum nicht da.

    - Wo soll ein Kontextwechsel zu SQL durchgeführt werden und warum?

    An der Stelle an der ein Wert in einen SQL-Query eingebaut wird und um Zeichen zu "entschärfen" die in SQL eine spezielle Bedeutung haben. Das einfachste wäre übrigens prepared Statements zu verwenden, das macht die Behandlung des Kontextwechsels einfacher/lesbarer - da würde ich aber PDO statt mysqli für den Datenbankzugriff empfehlen.

    - Wo befindet sich für den Kontextwechsel die falsche Stelle zu HTML

    Der Satz ist etwas durcheinander geraten. Aber der Autor des Videos verwendet zwar die richtige Funktion (htmlspecialchars()) für den Kontextwechsel nach HTML aber leider an der völlig falschen Stelle (in der validate-Funktion). So wird Inhalt der für die Ausgabe in HTML aufbereitet wurde so in der Datenbank gespeichert - aber was ist wenn der Inhalt mal als Text (z.B. in einer Mail) ausgegeben werden soll? Dann hast du da die HTML-Zeichen drin und die Mail wird u.U. etwas seltsam aussehen …

    - Ein Affenformular soll überprüfen (in meinem Fall) ob bei 'mail' eine gültige Eingabe vorhanden ist und sonst den Vorgang so oft neu wiederholen lässt bis der Wert passt, korrekt? Ist es zwingend, oder einfach nur Benutzerfreundlicher?

    Korrekt, ja. Zwingend ist es nicht, aber es ist benutzerfreundlicher: der Kot[sic!] aus dem Video leitet bei einem Fehler (z.B. leeres Feld) einfach kommentarlos auf das Formular weiter wobei auch schon korrekt eingegebene Inhalte einfach verworfen werden - findest du das benutzerfreundlich? Ja, ein Formular so zu gestallten dass es benutzerfreundlich ist, ist etwas aufwendiger aber die Bedienbarkeit darf niemals leiden nur weil es für den Programmierer aufwendiger ist.

    - Das Label-Element war Sinnfrei und hätte dort nicht hingehört. Als "Beschriftung" wird ein H3-Element verwendet

    Nein! Das label-Element *muss* da hin, braucht aber einen Text als Beschriftung (nein, das placeholder-Attribut ersetzt diese nicht!). Das h3 ist (hier) die Überschrift des Formulars, hat aber mit der Beschriftung des Eingabefeldes nichts zu tun. Dein input mit type=submit wäre übrigens gerne ein richtiger <button> - gibt auch mehr Freiheiten mit der Beschriftung.

    - Kodierung passt nicht weil und wie korrigiere ich es?

    Auf Internetseiten sollte immer und überall UTF-8 verwendet werden (nicht nur in der Datenbank, auch die Scripte), damit ist jedes Zeichen abgedeckt welches du mal brauchen könntest. Eingestellt wird das beim Erstellen von Tabellen (oder auch Datenbanken), in Adminer gibt es dafür ein select "Kollationen" bzw. auf Spaltenebene bei den Optionen (unter phpMyAdmin wird das ähnlich heißen, aber das verwende ich schon länger nicht mehr). Bei schon bestehenden Tabellen lässt sich das auch ändern, ggf. muss es aber für die Spalten auch extra geändert werden. Als SQL direkt geht das natürlich auch, da musst du das hinter COLLATE entsprechend angeben - aber du wirst es ja vermutlich ohnehin über eine Admin-Oberfläche machen.

    Sorry für die späte Antwort, aber bei mir in Visual Studio Code zeigt der mir keine Fehler an.

    den Fehler mit font-color zeigt VS Code an, die Fehler im HTML nicht da der Code (standardmäßig) nicht validiert wird, nur das <center> wäre anhand der anderen Farbe als falsch erkennbar (wobei der farbliche Unterschied etwas gering ist). Semantisch falsche Elemente kann VS Code (und auch der Validator) nicht erkennen, woher sollen die beiden wissen was da genau geschrieben wurde?

    Was mir gerade noch auffällt: warum schreibst du statt &rarr; nicht den Pfeil direkt in den Code? Mit UTF-8 ist das kein Problem …

    Ich habe die Seite zwar noch nicht Online, aber ich kann dir den Code eben schicken:

    Ich weiß dass dein Problem (zumindest anscheinend) bereits gelöst ist, aber trotzdem: Bevor du die Seite mit CSS entsprechend formatierst, solltest du erstmal die Fehler im HTML beseitigen: der Code enthält 12 Fehler und 2 Warnungen. Auch Semantisch ist der Code eine Katastrophe und eine einzige div-Suppe: verwende semantisch passende Elemente mit dem du dem Client auch mitteilst was da steht. Die Links zum Beispiel wären gerne eine Liste (<ul>) in einem nav-Element - der Kommentar "Links" ist dann auch überflüssig da das Element selbsterklärend ist. Jeder Link ist dann in einem <li> wobei <h1> und <center> ersatzlos entfallen (vergiss dass es <center> überhaupt mal gab und <h1> ist für die Hauptüberschrift der Seite, nicht für die Navigationslinks).

    Übrigens: eine CSS-Eigenschaft "font-color" gibt es nicht.

    Über MAMP habe ich die php_error.log Datei in der mir die auftretenden Fehler in einer Konsole angezeigt werden. Wie ich selbst so ein funktionierendes reporting erstelle ist mir noch ein Rätsel bzw. fehlt mir da noch viel an Wissen

    Ich verstehe dein Problem nicht wirklich. Fehlermeldungen werden in die php_error.log geschrieben (abhängig von den Einstellungen, die Datei kann auch andere Namen haben), wenn display_errors eingeschalten ist, werden die Fehler gleichzeitig auch ausgegeben. Mit der Konsole hat das erstmal nichts zu tun (wenn auch die unter Zuhilfenahme von tail ganz praktisch sein kann).

    Den Link Kontextwechsel habe ich mir durchgelesen, aber momentan ist es noch viel "Bahnhof" für mich dabei. Ich bin für jede weitere Erklärung sehr dankbar!

    So läuft das nicht. Du musst schon konkreter werden was genau du nicht verstehst (auch dass ich bzw. jemand anderes bei dem Artikel nachbessern kann), so wäre es ziemlich sinnlos irgendwas erklären zu wollen.

    Dazu habe ich ein PHP-Script auf Youtube gefunden, welches ich nachbauen versucht habe.

    Finger weg von dem Video! Es ist enthält eine gefährliche Sicherheitslücke: der Autor hat das Prinzip von Kontextwechseln nicht verstanden und behandelt den Kontextwechsel zu SQL nicht (und den zu HTML an der falschen Stelle).

    Dazu kommen dann noch Dinge wie kein Affenformular (kein Muss, aber das Prinzip vereinfacht imho die Verarbeitung von Formulardaten), fehlende Beschriftung der Formularfelder (label-Element ist vorhanden, hat aber keine Verbindung zum input; bei dir ist die Verbindung da, aber die Beschriftung fehlt) und die Verwendung von latin1 als Zeichenkodierung statt UTF-8.

    […] ist das sehr wohl bedienbar.

    Nein, nicht jeder Besucher hat eine Maus und kann sehen wo er klicken muss. Per Tastatur lässt sich der Focus nicht auf jedes beliebige Element setzen und automatisch auswerten/erkennen lässt sich das schon garnicht.