Brombeermilchtrinker: Anfängerfragen zur PHP-MySQL

Hallo SELF-Community!

<vorwarnung>Ich bin, was PHP und MySQL betrifft, absoluter Anfänger und die personifizierte Unfähigkeit!</vorwarnung>

Nachdem ich mich jetzt ein paar Tage lang erstmals in die Materie eingelesen habe, habe ich heute Mein erstes Datenbankprojekt produziert. ( Ohne Sinn und in reinem xhtml ohne irgend welche Stylesheets ) Alles funktioniert so weit so gut.

Verzeiht, daß ich mich als Anfänger gleich wegen folgenden 4 Punkten auf ein mal an Euch wende:

1.) Nach dem Auslesen eines Datensatzes ordne ich die einzelnen Inhalte jeweils folgendermaßen einer Variablen zu :

$nachname=$row->tt01_nachname;

Jetzt habe ich aber beim Googeln oft auch folgendes Aussehen gefunden :

$nachname=$row['tt01_nachname'];

Frage : Es funktioniert nur die erste Version, nicht die zweite. Ich nehme an, das zweite Beispiel ist eine völlig andere verwendung. Nur welche? Ich habe im deutschen PHP-Handbuch leider überhaupt nichts zu row oder $row gefunden. Vielleicht hat wer einen Link für mich, damit ich mich damit beschäftigen kann.

2.) Alle meine Seiten sind utf-8 codiert, die Grundeinstellung meiner Datenbank ( MySQL - 4.1.21, Änderungen vorgenommen via phpMyAdmin - 2.8.0.2 ) sind :

MySQL-Zeichensatz: UTF-8 Unicode (utf8)
Zeichensatz / Kollation der MySQL-Verbindung: utf8_unicode_ci

Wenn man jetzt Daten mit Umlauten über das Webformular eingibt und aufspielt, werden diese bei der Datenauslese wieder völlig korrekt dargestellt. Wenn ich mir die Daten aber direkt im phpMyAdmin ansehe, sind sie dort verunstaltet ( zB "Müller" statt "Müller" ). Ist das normal? Und was ich auch nicht verstehe : Wenn ich "Müller" direkt über phpMyAdmin eingebe, dann sehe ich den Namen dort korrekt geschrieben, ausgegeben wird dann aber "M?ller". Es funktioniert also nur dann, wenn die Daten via Formular an die DB geschickt werden und dann mittels der entsprechenden Seite wieder abgerufen und ausgelesen werden. Ist das normal?

3.) Das Ganze besteht aus 4 Seiten. Der datenbank_start.html ( = valide ), der eingabe.html ( = valide ), der bestaetigung.php ( = valide ) und der ausgabe.php ( = NICHT validierbar !!! ) Wieso? Beide php-Seiten sind ohne dem php valide xhtml-Seiten und in beiden steckt ein php-Code. Wieso ist eine Seite valide und die andere nicht ( bzw. nicht validierbar ) ???

4.) Da ich niemanden persönlich kenne, der php - kompetent ist, vielleicht kann sich ja mal wer kurz den Code der beiden php-Seiten ansehen und mir sagen, ob das so in Ordnung ist, wie ich den php-Code geschrieben habe. Oder kann man das für ein und das Selbe Vorhaben besser machen?

Danke im Voraus für die Hilfe!

Liebe Grüße

Der Brombeermilchtrinker

  1. hi,

    1.) Nach dem Auslesen eines Datensatzes ordne ich die einzelnen Inhalte jeweils folgendermaßen einer Variablen zu :

    $nachname=$row->tt01_nachname;

    Jetzt habe ich aber beim Googeln oft auch folgendes Aussehen gefunden :

    $nachname=$row['tt01_nachname'];

    Frage : Es funktioniert nur die erste Version, nicht die zweite. Ich nehme an, das zweite Beispiel ist eine völlig andere verwendung. Nur welche?

    mysql_fetch_row liefert dir ein Objekt zurück, dann nimmst du die erste Schreibweise.
    mysql_fetch_assoc (oder mysql_fetch_array mit entsprechendem Parameter) liefern dir ein assoziatives Array zurück, dann ist die zweite Notation die angebrachte.

    Wenn man jetzt Daten mit Umlauten über das Webformular eingibt und aufspielt, werden diese bei der Datenauslese wieder völlig korrekt dargestellt. Wenn ich mir die Daten aber direkt im phpMyAdmin ansehe, sind sie dort verunstaltet ( zB "Müller" statt "Müller" ). Ist das normal?

    Auf der Einstiegsseite des PMA die Kodierung auswählen, in der du dich mit der DB unterhalten willst.

    Wieso ist eine Seite valide und die andere nicht ( bzw. nicht validierbar ) ???

    Der Validator sagt:

    Sorry, I am unable to validate this document because on line 73-74 it contained one or more bytes that I cannot interpret as utf-8 (in other words, the bytes found are not valid values in the specified Character Encoding).

    Das hängt mit den vermurkst eingetragenen Daten zusammen.
    Diese ergeben jetzt auch bei der Ausgabe keine gültigen Zeichen in UTF-8-Kodierung mehr.
    Bereinige diese Daten, so dass auch "überall UTF-8 drin ist, wo UTF-8 draufsteht", dann hat sich auch das erledigt.

    4.) Da ich niemanden persönlich kenne, der php - kompetent ist, vielleicht kann sich ja mal wer kurz den Code der beiden php-Seiten ansehen und mir sagen, ob das so in Ordnung ist, wie ich den php-Code geschrieben habe. Oder kann man das für ein und das Selbe Vorhaben besser machen?

    Habe ich im Augenblick nicht die Muße zu, aber viellicht schaut ja noch jemand anderes mal nach.

    SQL Injection ist auf jeden Fall ein Stichwort, über das du dich informiert haben bzw. informieren solltest, und entsprechende Sicherungsmaßnahmen sollte das Script enthalten bzw. bekommen.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hallo wahsaga! Danke für Deine Antworten und Hinweise!

      mysql_fetch_row liefert dir ein Objekt zurück, dann nimmst du die erste Schreibweise.
      mysql_fetch_assoc (oder mysql_fetch_array mit entsprechendem Parameter) liefern dir ein assoziatives Array zurück, dann ist die zweite Notation die angebrachte.

      Das sagt mir zwar _im Moment_ nichts, ich werde mir das aber spätestens gleich morgen genauer ansehen, um den Unterschied zwischen den beiden Dingen zu verstehen.

      Auf der Einstiegsseite des PMA die Kodierung auswählen, in der du dich mit der DB unterhalten willst.

      Tja, _das_ hab ich schon überprüft. Wenn ich bei meinem Anbieter (  DOMAINFACTORY ) mit dem FIREFOX über mein Kundenmenü zum PMA gehe, die Codierung auf utf-8 eingestellt ist, und ich dann direkt Umlaute eingebe, ist es das selbe. ( Gerade versucht, siehe Datensatz 44 )

      Das hängt mit den vermurkst eingetragenen Daten zusammen.
      Diese ergeben jetzt auch bei der Ausgabe keine gültigen Zeichen in UTF-8-Kodierung mehr.
      Bereinige diese Daten, so dass auch "überall UTF-8 drin ist, wo UTF-8 draufsteht", dann hat sich auch das erledigt.

      Das verstehe ich. Danke für den Gedankenanstoß!

      Habe ich im Augenblick nicht die Muße zu, aber viellicht schaut ja noch jemand anderes mal nach.

      Ich hab durch das Mitlesen der Postings hier schon _so_ viel von Dir lernen dürfen, daß Dir das natürlich verziehen ist! ;-)

      Liebe Grüße

      Der Brombeermilchtrinker

  2. echo $begrüßung;

    2.) Alle meine Seiten sind utf-8 codiert, die Grundeinstellung meiner Datenbank ( MySQL - 4.1.21, Änderungen vorgenommen via phpMyAdmin - 2.8.0.2 ) sind :

    MySQL-Zeichensatz: UTF-8 Unicode (utf8)
    Zeichensatz / Kollation der MySQL-Verbindung: utf8_unicode_ci

    Das sind die Werte, die der phpMyAdmin sich eingestellt hat. Sie gelten für die Verbindung zwischen PMA und dem MySQL-Server, jedoch nicht für andere Clients, wie beispielsweise deine Scripte.

    Der MySQL-Server geht davon aus, dass die Clients mit ihm in der Zeichenkodierung gemäß seiner Einstellung des Parameters character_set_client kommunizieren. Der PMA zeigt dir den aktuellen Wert und die Default-Einstellung (falls beide abweichen) auf der Seite "MySQL-System-Variablen anzeigen" an. MySQL wandelt gegebenenfalls Daten in dieser Kodierung (A) in die Kodierung um, die für die Felder eingestellt ist (B). Wenn die Daten doch nicht gemäß A kodiert sind oder auch, wenn sich A nicht verlustfrei nach B konvertieren lässt, gibt es Datenverlust.

    character_set_client gilt übrigens nur für die Richtung zum Server. Die Ergebnisdatensätze werden in der Kodierung gemäß character_set_results ausgeliefert, und dabei wieder ggf. aus der Kodierung der Felder in diese Kodierung umgewandelt.

    Die einfachste Lösung ist, nach dem Verbindungsaufbau explizit festzulegen, welche Kodierung auf der Verbindung verwendet werden soll. Dazu sendet man ein SET NAMES charset_name.

    Wenn man jetzt Daten mit Umlauten über das Webformular eingibt und aufspielt, werden diese bei der Datenauslese wieder völlig korrekt dargestellt. Wenn ich mir die Daten aber direkt im phpMyAdmin ansehe, sind sie dort verunstaltet ( zB "Müller" statt "Müller" ). Ist das normal?

    Es sieht ganz danach aus, dass der MySQL-Server annimmt, dass die Daten in ISO 8859-1 bzw. Latin1 vorliegen, und trägt sie, gegebenenfalls umkodiert, in die Felder des Datensatzes ein. Ohne eine Inhaltsanalyse lässt sich nicht feststellen, ob etwas tatsächlich gemäß ISO 8859-x kodiert ist, da sich dies nicht ohne weiteres anhand von Bytewerten oder Bytereihenfolgen erkennen lässt. Nur bei UTF-8 kann man erkennen, wenn ein Text nicht in dieser Kodierung vorliegt.

    Ich vermute, dass du die Kodierung deiner String-Felder (siehe PMA-Spalte Kollation) auf UTF-8 eingestellt hast. MySQL wird in deinem Fall annehmen, ISO 8859-1 geliefert zu bekommen (M(FC)ller), bekommt stattdessen aber ein UTF-8-M(C3-BC)ller, und wandelt dieses zum Speichern in UTF-8 um (M(C3-83-C2-BC)ller) und beim Ausliefern wieder zurück nach ISO 8859-1 (M(C3-BC)ller). PHP deklariert das dem Browser gegenüber als UTF-8, der freut sich, und alles ist in Ordnung.

    Der PMA kann dir nur Müller anzeigen, da er aus dem UTF-8-String M(C3-83-C2-BC)ller nur Müller (C3-83=Ã, C2-BC=¼) machen kann.

    Und was ich auch nicht verstehe : Wenn ich "Müller" direkt über phpMyAdmin eingebe, dann sehe ich den Namen dort korrekt geschrieben, ausgegeben wird dann aber "M?ller".

    Die Eingabe im PMA wird ordnungsgemäß als UTF-8 deklariert - der hat sein SET NAMES richtig gesendet - und auch so kodiert an den MySQL-Server ausgeliefert. Dieser kann den Wert nun ordentlich UTF-8-kodiert in das Feld eintragen. Beim Ausliefern an dein Script wandelt er es nach ISO-8859-1 um (M(FC)ller), was aber keine gültige UTF-8-Sequenz mehr ist und deinen Browser veranlasst, ein Fragezeichen statt des ü anzuzeigen. Stell mal deinen Browser über Ansicht->(Zeichen)kodierung auf ISO 8859-1 um und du wirst ein ü sehen.

    M(C3-BC)ller ... (C3-BC) soll die Byte-Werte darstellen.

    3.)  ausgabe.php ( = NICHT validierbar !!! ) Wieso?

    Das hat der Validator doch hingeschrieben. Du lieferst ihm Datenmüll aus und kein korrekt UTF-8-kodiertes Dokument.

    4.) Da ich niemanden persönlich kenne, der php - kompetent ist, vielleicht kann sich ja mal wer kurz den Code der beiden php-Seiten ansehen und mir sagen, ob das so in Ordnung ist, wie ich den php-Code geschrieben habe. Oder kann man das für ein und das Selbe Vorhaben besser machen?

    Dein Server liefert keinen PHP-Quelltext aus. Leg die Dateien nochmal mit der Erweiterung .phps an oder erzeuge einen Symlink.

    echo "$verabschiedung $name";

    1. Hallo dedlfix!

      Vielen Dank für deine ausführliche Antwort und Deine Erklärungen! Ich hab zwar beim ersten mal Durchlesen noch nicht alles verstanden, denke aber, daß ich jetzt den größten Teil aufgenommen habe. Danke für die Denkanstöße!

      Dein Server liefert keinen PHP-Quelltext aus. Leg die Dateien nochmal mit der Erweiterung .phps an oder erzeuge einen Symlink.

      Darum hab ich ja in meinem Primärposting extra aus den Seiten Links gemacht, damit man sich mit Rechtsklick und "speichern unter" die php-Dateien ansehen kann. War das falsch gedacht?

      Mit freundlichen Grüßen, schönes WE, bis nächste Woche

      Der Brombeermilchtrinker

      1. echo $begrüßung;

        Dein Server liefert keinen PHP-Quelltext aus. Leg die Dateien nochmal mit der Erweiterung .phps an oder erzeuge einen Symlink.

        Darum hab ich ja in meinem Primärposting extra aus den Seiten Links gemacht, damit man sich mit Rechtsklick und "speichern unter" die php-Dateien ansehen kann. War das falsch gedacht?

        Der Server kann nicht zwischen meiner Absicht, zu speichern oder die Seite einfach so aufzurufen, unterscheiden. Er bekommt eine Anforderung nach beispielsweise bestaetigung.php zu Gesicht, sieht das .php am Ende und schickt aufgrund seiner Konfiguration diese Datei erstmal zu PHP und liefert dessen Ergebnis aus. Wenn er das Dokument direkt und ungePHPt ausliefern soll, musst du ihn zumindest partiell umkonfigurieren. Normalerweise ist er aber so eingestellt, dass er bei .phps-Dateien den Quelltext PHP-syntaktisch koloriert und ausliefert. Dabei ist es egal, ob diese .phps-Datei physisch vorhanden ist oder nur per (Sym)Link auf eine vorhandene andere Datei zeigt.

        echo "$verabschiedung $name";

  3. Hallo SELF-Community!

    Ich wollte jetzt nicht extra einen neuen Beitrag erstellen und hoffe, daß dieses Posting hier jetzt noch von wem gesehen wird. :-)

    Mir ist hier geraten worden, Daten, die ein User über ein Formular eingegeben hat, zu überprüfen, bevor die Daten an die DB weitergegeben und gespeichert werden, um mich gegen SQL Injection und andere Bösartigkeiten zu schützen.

    Ich habe mich da jetzt schlau gemacht und würde die Sache folgendermaßen lösen : Angenommen, einer der über ein Formular per "POST" übermittelten Werte ist der Wert "$beispielwert". Dann folgender Code :  [...]

      
    $beispielwert=$_POST['beispielwert'];  
    $beispielwert=strip_tags($beispielwert);  
    if(get_magic_quotes_gpc())  
     {$beispielwert=stripslashes($beispielwert);}  
    if(!is_numeric($beispielwert))  
     {$vorname="'".mysql_real_escape_string($beispielwert)."'";}  
    
    

    ...und in weiterer Folge dann die Speicherung des Wertes "$beispielwert" in die DB.

    Nun 2 Fragen dazu :

    1.) Ist das der ideale und richtige Weg, um mich zu schützen, wenn ich dieses Codebeispiel bei jedem Teil, also jeder übergebenen Variable, eines Datensatzes anwende?

    2.) Was ich nicht hinbekomme : Angenommen, ich möchte, daß eine Eingabe einer URL mit oder ohne http:// als _anklickbarer Verweis_ wieder ausgegeben wird. Wie mache ich das?

    Mit bestem Dank im Votraus und freundlichen Grüßen

    Der Brombeermilchtrinker

    1. echo $begrüßung;

      Ich wollte jetzt nicht extra einen neuen Beitrag erstellen und hoffe, daß dieses Posting hier jetzt noch von wem gesehen wird. :-)

      Na klar.

      Mir ist hier geraten worden, Daten, die ein User über ein Formular eingegeben hat, zu überprüfen, bevor die Daten an die DB weitergegeben und gespeichert werden, um mich gegen SQL Injection und andere Bösartigkeiten zu schützen.

      Ich habe mich da jetzt schlau gemacht und würde die Sache folgendermaßen lösen : Angenommen, einer der über ein Formular per "POST" übermittelten Werte ist der Wert "$beispielwert". Dann folgender Code :  [...]

      $beispielwert=$_POST['beispielwert'];
      $beispielwert=strip_tags($beispielwert);
      if(get_magic_quotes_gpc())
      {$beispielwert=stripslashes($beispielwert);}
      if(!is_numeric($beispielwert))
      {$vorname="'".mysql_real_escape_string($beispielwert)."'";}

        
      Die Reihenfolge wäre zu ändern. Zuerst sollten die eventuallen Auswirkungen von Magic Quotes entfernt werden, da dies als letztes hinzugefügr wurde, bevor PHP die Daten an den Script übergeben hat. Ich würde das mit der [im Handbuch angeführten Funktion](http://de.php.net/manual/en/security.magicquotes.disabling.php) generell und für alle Eingabedaten einmalig am Scriptanfang durchführen. Das kann man dann leichter entfernen, wenn man später auf PHP6 umsteigt.  
        
      
      > $beispielwert=$\_POST['beispielwert'];  
        
      Das Anlegen einer extra-Variable ist immer noch ein unnötiger Zwischenschritt.  
        
      
      > $beispielwert=strip\_tags($beispielwert);  
        
      strip\_tags() ist eine ["grobe Wildsau"](/archiv/2006/4/t128030/#m826560). Es ist nicht unbedingt nötig, diese Funktion anzuwenden. Der Datenbank sind die Tags egal. Bei der Ausgabe solltest sowieso dem Ausgabemedium entsprechend kodieren, so dass die Tags keinen Schaden anrichten können. Für HTML gibt es da htmlspecialchars().  
        
      
      > if(!is\_numeric($beispielwert))  
      >  {$vorname="'".mysql\_real\_escape\_string($beispielwert)."'";}  
        
      SQL ist eine Text-Schnittstelle. Auch Zahlenwerte werden als String übertragen und müssen geparst werden. Es ist dabei unerheblich, ob sie in '' oder "" oder ohne dastehen. Du kannst sie also generell auch wie die anderen benutzereingegebenen Stringwerte behandeln.  
        
      Meine Empfehlung zusammengefasst lautet:  
      - Magic Quotes-Behandlung am Scriptanfang  
      - wenn nötig Plausibilitätsprüfung der eingegebenen Daten  
      - SQL-Statements in der Form:  
        
      ~~~php
      $sql = sprintf('SELECT ... FROM foo WHERE feld1="%s" AND feld2="%s"',  
        mysql_real_escape_string($_POST['feld1']),  
        mysql_real_escape_string($_POST['feld2']));
      

      1.) Ist das der ideale und richtige Weg, [...]

      Noch hübscher allerdings wäre die Verwendung der mysqli-Erweiterung oder PDO. Beide Systeme bieten eine Datenbindung an das vorbereitete, mit Platzhaltern versehene Statement, und kümmern sich selbständig um die richtige Maskierung der Variableninhalte.
      http://de.php.net/manual/en/function.mysqli-stmt-bind-param.php
      http://de.php.net/manual/en/ref.pdo.php#pdo.prepared-statements

      echo "$verabschiedung $name";

      1. Hallo dedlfix!

        Danke für die rasche Beantwortung! Leider bin ich jetzt als wirklicher PHP- und MySql-Newby etwas überfordert.

        Die Reihenfolge wäre zu ändern. Zuerst sollten die eventuallen Auswirkungen von Magic Quotes entfernt werden, da dies als letztes hinzugefügr wurde, bevor PHP die Daten an den Script übergeben hat. Ich würde das mit der im Handbuch angeführten Funktion generell und für alle Eingabedaten einmalig am Scriptanfang durchführen. Das kann man dann leichter entfernen, wenn man später auf PHP6 umsteigt.

        Das ist mir leider zu hoch, um es zu verstehen. :-( Mein bisheriges Wissen stammt unter anderem von der entsprechenden mysql_real_escape_string-Seite im php-Handbuch.

        Also wenn ich den vorigen von mir geschriebenen Code bezüglich Deiner Hinweise ändere, würde er jetzt mal so aussehen:

          
        if(get_magic_quotes_gpc())  
         {$beispielwert=stripslashes($_POST['beispielwert']);}  
        else  
         {$beispielwert=$_POST['beispielwert'];}  
        if(!is_numeric($beispielwert))  
         {$vorname="'".mysql_real_escape_string($beispielwert)."'";}  
        
        

        ...und anschließend das Speichern in die DB.

        Das Anlegen einer extra-Variable ist immer noch ein unnötiger Zwischenschritt.

        Das hab ich aber jetzt in der else-Anweisung wieder drin. :-( Für den Fall, daß die if-Bedingung _nicht_ erfüllt ist, _muß_ ich die Anweisung doch schreiben, oder?

        ist eine [link:/archiv/2006/4/t128030/#m826560@title="grobe Wildsau"]. Es ist nicht unbedingt nötig, diese Funktion anzuwenden.

        Also die entsprechenden von Dir gelinkten Postings hab ich jetzt gelesen und verstehe, warum [code lang=php]strip_tags()

          
        
        > Der Datenbank sind die Tags egal. Bei der Ausgabe solltest sowieso dem Ausgabemedium entsprechend kodieren, so dass die Tags keinen Schaden anrichten können. Für HTML gibt es da htmlspecialchars().  
          
        
        > SQL ist eine Text-Schnittstelle. Auch Zahlenwerte werden als String übertragen und müssen geparst werden. Es ist dabei unerheblich, ob sie in '' oder "" oder ohne dastehen. Du kannst sie also generell auch wie die anderen benutzereingegebenen Stringwerte behandeln.  
          
        Also was den 2. Absatz betrifft, verstehe ich nicht, was Du damit sagen willst. Ich hab die Anweisung genau so geschrieben wie in der oben von mir verklinkten php-Handbuch Seite.  
          
        
        > Meine Empfehlung zusammengefasst lautet:  
        > - Magic Quotes-Behandlung am Scriptanfang  
        > - wenn nötig Plausibilitätsprüfung der eingegebenen Daten  
        > - SQL-Statements in der Form:  
          
        Hmmmm .... also \_falls\_ Du die Zeit und Energie hast, bitte ich Dich, mir einen konkreten Beispielcode zu geben. ich glaub, wenn ich den php\_Code vor mir habe und mich dann von Zeile zu Zeile mit den Funktionen auseinandersetze, lerne ich es am Besten.  
          
        Bleiben wir dabei, daß über ein Formular per POST-Anweisung die Variable " $beispielvariable " übergeben wird. Was ist der kürzeste, simpelste und einfachste php\_Code, um zu erreichen, daß  
          
        1\.) KEINE html-Tags gespeichert und somit ausgegeben werden, aber zB eine Eingabe wie " 3>4 " oder " Beispiel -> " gespeichert und ausgegeben werden?  
          
        2\.) KEINE html-Tags gespeichert werden, aber alles, wass mit www oder http:// anfängt, bei der Ausgabe als anklickbarer Link ausgegeben wird?  
          
        3\.) zusätzlich <b>, <i> und <u> erlaubt sind?  
          
        In allen 3 Fällen soll die Speicherung der Daten halt gesichert sein gegen SQL-Injection und andere mögliche Bösartigkeiten.  
          
        Mit freundlichen Grüßen  
          
        Der Brombeermilchtrinker  
          
        PS : Wie gesagt, ich bin da \_echt\_ ein Newby!!
        
        1. echo $begrüßung;

          Die Reihenfolge wäre zu ändern. Zuerst sollten die eventuellen Auswirkungen von Magic Quotes entfernt werden, da dies als letztes hinzugefügt wurde, bevor PHP die Daten an dein Script übergeben hat. Ich würde das mit der im Handbuch angeführten Funktion generell und für alle Eingabedaten einmalig am Scriptanfang durchführen. Das kann man dann leichter entfernen, wenn man später auf PHP6 umsteigt.

          Das ist mir leider zu hoch, um es zu verstehen. :-( Mein bisheriges Wissen stammt unter anderem von der entsprechenden mysql_real_escape_string-Seite im php-Handbuch.

          Vielleicht möchtest du mit den Formularwerten noch etwas anderes machen, als sie nur in der Datenbank abzulegen. Zum Beispiel auch noch anzeigen ("Folgende Daten wurden gespeichert: ...").
          Es ist nicht immer günstig, alles auf einmal und so wie es gerade anfällt zu programmieren. Eine klare Strukturierung und Trennung/Abgrenzung der einzelnen Teilaufgaben erhöht die Wartbarkeit bei komplexer werdenden Scripten.
          Die Magic Quotes haben mit der eigentlichen Aufgabe deines Script nichts weiter zu tun. Sie zu beseitigen ist nur notwendiges Übel. Deswegen empfahl ich, sie aus dem eigentlichen Scriptverlauf auszuklammern und unabhängig von allem anderen am Scriptanfang zu erledigen. Example 31-2 wirkt direkt auf $_POST, $_GET, $_COOKIE und $_REQUEST. Du kannst also im weiteren Verlauf wie gewohnt auf $_XXX['foo'] zugreifen.

          Es ist ziemlich egal, ob du Zahlenwerte einfach so hinschreibst oder in Gänsefüße setzt

          SELECT ... FROM foo WHERE zahl=42    oder
            SELECT ... FROM foo WHERE zahl="42"

          INSERT INTO foo SET zahl=42    oder
            INSERT INTO foo SET zahl="42"

          Du musst also nicht den Aufwand treiben, bei den Benutzereingaben zwischen Zahlenwerten und Strings zu unterscheiden und sie unterschiedlich zu quoten. Einfach alle Benutzerwerte gänsefüßen und mysql_real_escape_string() drauf anwenden. Dann beschränkt sich das Statement-Zusammenbauen (ohne Plausibilitätsprüfung) auf das erwähnte (diesmal mit INSERT)

          $sql = sprintf('INSERT INTO foo SET feld1="%s", feld2="%s"',  
            mysql_real_escape_string($_POST['feld1']),  
            mysql_real_escape_string($_POST['feld2']));
          

          Einfache Plausibilitätsprüfungen kann man auch direkt auf die $_POST-Werte ansetzen, ohne sie umzukopieren:

          if (! valid($_POST['feld1']))  
            //...
          

          Vermutlich möchtest du ja dann sowieso die Benutzereingaben ignorieren und einen anderen Verlauf im Script nehmen, z.B. anstatt die Daten der Datenbank zu übergeben eine Fehlermeldung ausgeben und/oder sie per Affenformular dem Anwender wieder vor die Füße werfen.

          Das Anlegen einer extra-Variable ist immer noch ein unnötiger Zwischenschritt.

          Das hab ich aber jetzt in der else-Anweisung wieder drin. :-( Für den Fall, daß die if-Bedingung _nicht_ erfüllt ist, _muß_ ich die Anweisung doch schreiben, oder?

          Wenn eine neue Variable in einer bedingten Anweisung (if) angelegt wird ist es immer wichtig, alle Verzweigungen zu berücksichtigen. Oder man verwendet bei einfachen bedingten Deklarationen den ternary operator

          $var = bedingung ? 'erfüllt' : ' nicht erfüllt';

          Die Frage ist, ob es sich wirklich lohnt, eine neue Variable anzulegen. Bei meiner obigen Vereinfachung ist es nicht nötig.

          Bei deinem ursprünglichen Beispiel

          $beispielwert = $_POST['beispielwert'];
            $beispielwert = strip_tags($beispielwert);
            ...

          lassen sich beide Zeilen zu einer zusammenfassen.

          $beispielwert = strip_tags($_POST['beispielwert']);
            ...

          1.) KEINE html-Tags gespeichert und somit ausgegeben werden, aber zB eine Eingabe wie " 3>4 " oder " Beispiel -> " gespeichert und ausgegeben werden?

          Warum sollen sie nicht gespeichert werden? Wenn sie jemand in einem HTML-Code-Beispiel verwendet oder Dinge schreibt, die zufällig wie Tags aussehen, müssen sie nicht unbedingt verloren gehen. Du musst nur bei der Ausgabe darauf achten, dass sie mit htmlspecialchars() HTML-gerecht umgeschrieben werden. < als &lt;, > als &gt; und " als &quot; - erledigt der Fall. Es ist eine gute Idee, sich das htmlspecialchars() für die Ausgabe aller nicht direkt im Script notierten Daten anzugewöhnen.

          In allen 3 Fällen soll die Speicherung der Daten halt gesichert sein gegen SQL-Injection und andere mögliche Bösartigkeiten.

          Bei der Eingabe von Daten sollte im Vordergrund stehen, sie möglichst roh zu speichern, ohne irgendwelche Ausgabeformatierungen. Deswegen ist es ausreichend, die Benutzerangaben einfach mit mysql_real_escape_string() ins SQL-Statement einzubauen. Damit sind sie erstmal gegen SQL-Injection gesichert.
          Was zur Sicherung der Ausgabe nötig ist, wird erst bei der Ausgabe und für das dann verwendete Ausgabemedium bewertet und angewendet.
          Daten in einem Newsfeed müssen sicherlich anders aufbereitet werden als wenn sie auf der Webseite gezeigt werden sollen. Es wäre ungünstig, sich bereits beim Speichern auf ein bestimmtes Ausgabemedium festzulegen.

          2.) KEINE html-Tags gespeichert werden, aber alles, wass mit www oder http:// anfängt, bei der Ausgabe als anklickbarer Link ausgegeben wird?

          Dazu hab ich nebenan schon was gesagt. Diese Analyse und Umgestaltung der Daten soll direkt zum Ausgabezeitpunkt mit den aus der Datenbank geholten Rohdaten erfolgen. Ich denke, dass sich zu dem Thema schon mal jemand einen Kopf gemacht hat und sich im Web konkretere Vorschläge als meiner finden lassen.

          3.) zusätzlich <b>, <i> und <u> erlaubt sind?

          Das ist im Prinzip ähnlich handzuhaben wie die Suche nach dem www bzw. http://. Bedenke aber, das Benutzer doof sind und sich nicht unbedingt um eine korrekte Schachtelung der Tags kümmern. In dem Fall wäre sicherlich eine Analyse und Behandlung à la Christian Seilers BBCode-Parser notwendig und angebracht.

          Für 2. und 3. kann htmlspecialchars() natürlich nicht auf den gesamten String angewendet werden, weder vorher, da du ihn ja z.B. zum Einbau des <a>-Tags zerstückeln musst, und auch nicht nachher, da sonst das <a href...> verlorenginge. Du musst das also auf die Teilstücke einzeln anwenden.

          echo "$verabschiedung $name";

          1. Guten Morgen, dedlfix!

            echo $begrüßung;

            Ich hoffe, es steht nirgends ein $begrüßung="Nicht schon wieder dieser dumme Brombeermilchtrinker"; *g*

            Vielleicht möchtest du mit den Formularwerten noch etwas anderes machen, als sie nur in der Datenbank abzulegen. Zum Beispiel auch noch anzeigen ("Folgende Daten wurden gespeichert: ...").

            Wie gesagt, ich möchte derzeit nichts Spezifisches machen. Ich hab einfach angefangen, mich mit dieser PHP-MySql-Kombination auseinanderzusetzen und versuche jetzt, so gut es geht, mir die Sache autodidakt beizubringen. Deshalb bin ich ja auch, sobald es _etwas_ komplizierter wird, gleich so überfordert.

            Es ist nicht immer günstig, alles auf einmal und so wie es gerade anfällt zu programmieren. Eine klare Strukturierung und Trennung/Abgrenzung der einzelnen Teilaufgaben erhöht die Wartbarkeit bei komplexer werdenden Scripten.

            Das klingt logisch, ja.

            Die Magic Quotes haben mit der eigentlichen Aufgabe deines Script nichts weiter zu tun. Sie zu beseitigen ist nur notwendiges Übel. Deswegen empfahl ich, sie aus dem eigentlichen Scriptverlauf auszuklammern und unabhängig von allem anderen am Scriptanfang zu erledigen.

            Meinst Du damit, ich soll gleich ganz oben auf der Seite die Variablen in Kombination mit den Magic Quotes holen?

            Also so? =>

              
            <?php  
            if(get_magic_quotes_gpc())  
             {  
             $variable1=stripslashes($_POST['variable1']);  
             $variable2=stripslashes($_POST['variable2']);  
             $variable3=stripslashes($_POST['variable3']);  
             u.s.w.  
             }  
            else  
             {  
             $variable1=$_POST['variable1'];  
             $variable2=$_POST['variable2'];  
             $variable3=$_POST['variable3'];  
             }  
            ?>  
            
            
              
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
            u.s.w.  
            
            

            Und dann im Verlauf der Seite jenen PHP-Teil, der sich um die Weiterverarbeitung der Daten kümmert. Habe ich Dich da so richtig verstanden?

            Was Dein Beispiel betrifft : Wenn ich mir meine php.info Datei ansehe, steht da : PHP Version 4.4.1, magic_quotes_gpc ON - ON, magic_quotes_runtime OFF - OFF und magic_quotes_sybase OFF - OFF. Wenn ich die Sache richtig verstanden habe, liege ich damit auf der guten/sicheren Seite.

            Du musst also nicht den Aufwand treiben, bei den Benutzereingaben zwischen Zahlenwerten und Strings zu unterscheiden und sie unterschiedlich zu quoten.

            OK, verstanden habe.

            Vermutlich möchtest du ja dann sowieso die Benutzereingaben ignorieren und einen anderen Verlauf im Script nehmen, z.B. anstatt die Daten der Datenbank zu übergeben eine Fehlermeldung ausgeben und/oder sie per Affenformular dem Anwender wieder vor die Füße werfen.

            Mit _solchen_ Spielereien muß ich mich noch auseinandersetzen.

            Wenn eine neue Variable in einer bedingten Anweisung (if) angelegt wird ist es immer wichtig, alle Verzweigungen zu berücksichtigen. Oder man verwendet bei einfachen bedingten Deklarationen den ternary operator

            Hui, der ist cool! :-) Kannte ich noch nicht.

            Bei deinem ursprünglichen Beispiel
              $beispielwert = $_POST['beispielwert'];
              $beispielwert = strip_tags($beispielwert);
              ...
            lassen sich beide Zeilen zu einer zusammenfassen.
              $beispielwert = strip_tags($_POST['beispielwert']);
              ...

            Das hatte ich eh gemcht, ich hab mich auf den Teil in der ELSE-Schleife bezogen.

            Warum sollen sie nicht gespeichert werden? Wenn sie jemand in einem HTML-Code-Beispiel verwendet oder Dinge schreibt, die zufällig wie Tags aussehen, müssen sie nicht unbedingt verloren gehen. Du musst nur bei der Ausgabe darauf achten, dass sie mit htmlspecialchars() HTML-gerecht umgeschrieben werden. < als &lt;, > als &gt; und " als &quot; - erledigt der Fall. Es ist eine gute Idee, sich das htmlspecialchars() für die Ausgabe aller nicht direkt im Script notierten Daten anzugewöhnen.

            OK, also nimm mal an, ich möchte sowas wie ein Blog machen. Da sollen alle Leser-Kommentare gleich aussehen und ich will nicht, daß jemand mit <font size="12"> oder Ähnlichem da Unruhe stiftet. Gibt also jemand als Wert zB " <font size="9" color="red">Hallo Welt</font> ein, dann soll bei der Ausgabe einfach nur "Hallo Welt" stehen. Das muß doch gehen, oder?

            Auf der anderen Seite wiederum möchte ich, daß, wenn jemand einen Kommentar schreibt und da zB. www.meineseite.com vorkommt, dies bei der Ausgabe zu einem Link wird.

            Bei der Eingabe von Daten sollte im Vordergrund stehen, sie möglichst roh zu speichern, ohne irgendwelche Ausgabeformatierungen. Deswegen ist es ausreichend, die Benutzerangaben einfach mit mysql_real_escape_string() ins SQL-Statement einzubauen. Damit sind sie erstmal gegen SQL-Injection gesichert.

            OK, verstanden habe.

            Was zur Sicherung der Ausgabe nötig ist, wird erst bei der Ausgabe und für das dann verwendete Ausgabemedium bewertet und angewendet.
            Daten in einem Newsfeed müssen sicherlich anders aufbereitet werden als wenn sie auf der Webseite gezeigt werden sollen. Es wäre ungünstig, sich bereits beim Speichern auf ein bestimmtes Ausgabemedium festzulegen.

            Dann stehe ich jetzt aber spätestens dann, wenn ich die Seite für die Datensatzausgabe schreibe, vor dem selben Problem. :-)

            Dazu hab ich nebenan schon was gesagt.

            Ja, ich weiß. Aber ich hab nicht gewußt, wonach ich jetzt suchen soll.

            Ich denke, dass sich zu dem Thema schon mal jemand einen Kopf gemacht hat und sich im Web konkretere Vorschläge als meiner finden lassen.

            Ich google und surfe seit Tagen ( anstatt mich meinem Studium zu widmen, ich Tölpel ) ... habe aber bis jetzt nichts gefunden.

            Für 2. und 3. kann htmlspecialchars() natürlich nicht auf den gesamten String angewendet werden, weder vorher, da du ihn ja z.B. zum Einbau des <a>-Tags zerstückeln musst, und auch nicht nachher, da sonst das <a href...> verlorenginge. Du musst das also auf die Teilstücke einzeln anwenden.

            Das klingt super, aber wenn ich mir dann die entsprechenden Seiten im  PHP-manual oder Handbuch ansehe ( allgemein, nicht nur, was htmlspecialchars() betrifft ), dann muß ich leider feststellen, daß dort Sachen von Leuten erklärt werden, die sich offenbar nicht mehr in die Lage eines Menschen versetzen können, der _kein_ Technikguru ist und vielleicht noch neu in der Materie ist. :-(

            Nichts desto trotz war ich gestern natürlich nicht unfleißig und habe mich mal mit preg_replace() und mit ereg_replace() erstmalig beschäftigt. Schau Dir mal meine 2 Beispielseiten an :

            Seite 1

            Und hier der entsprechende Auszugs-Quelltext von deiser Seite :

              
            $liebesbrief=" ... ";  
            echo$liebesbrief;  
            $liebesbrief2=preg_replace('/Anna/','Helga',$liebesbrief);  
            echo$liebesbrief2;  
            
            

            sowie

              
            $paar=" ... ";  
            echo$paar;  
            $suchmuster[]='/Adam/';  
            $suchmuster[]='/Eva/';  
            $ersetzung='Mensch';  
            $paar2=preg_replace($suchmuster,$ersetzung,$paar);  
            echo$paar2;  
            $liebesbrief2=preg_replace('/Anna/','Helga',$liebesbrief);  
            echo$liebesbrief2;  
            
            

            Seite 2

            Und hier der entsprechende Auszugs-Quelltext von deiser Seite :

              
            $text1="..."  
            echo $text1;  
            $suchmuster='(^| )(www([-]*[.]?[a-zA-Z0-9_/-?&%])*)';  
            $ersatz='<a href="http://\\2">\\2</a>';  
            $text1_2=eregi_replace($suchmuster,$ersatz,$text1);  
            echo$text1_2;  
            
            

            Also die PHP-Anweisungen der beiden Beispiele von Seite 1 hab ich glaub ich soweit verstanden und erarbeitet. Das von Seite 2 ist einfach aus dem Web abgekupfert. Es funktioniert, ich hab aber keine Ahnung, wieso und wie der reguläre Ausdruck in der Anweisung zu deuten ist. *dummschau*

            Aber Du siehst, ich bemühe mich, zu lernen. :-)

            In diesem Sinne einen schönen Tag!

            Liebe Grüße

            Der Brombeermilchtrinker

            echo "$verabschiedung $name";

            Technokrat! *g* ;-)

            1. echo $begrüßung;

              Ich hoffe, es steht nirgends ein $begrüßung="Nicht schon wieder dieser dumme Brombeermilchtrinker"; *g*

              Ich habe keine Ahnung, was du da auf dem System eingestellt hast, auf /mit dem du meine Postings liest ... :-)

              Es ist nicht immer günstig, alles auf einmal und so wie es gerade anfällt zu programmieren. Eine klare Strukturierung und Trennung/Abgrenzung der einzelnen Teilaufgaben erhöht die Wartbarkeit bei komplexer werdenden Scripten.

              Das klingt logisch, ja.

              Die Magic Quotes haben mit der eigentlichen Aufgabe deines Script nichts weiter zu tun. Sie zu beseitigen ist nur notwendiges Übel. Deswegen empfahl ich, sie aus dem eigentlichen Scriptverlauf auszuklammern und unabhängig von allem anderen am Scriptanfang zu erledigen.

              Meinst Du damit, ich soll gleich ganz oben auf der Seite die Variablen in Kombination mit den Magic Quotes holen?

              Nein, ich meine, du sollst sie völlig unabhängig von deinem restlichen Script behandeln, so wie es das Example 31-2 macht. Das Feature Magic Quotes wird es ab PHP 6 nicht mehr geben und es ist auch jetzt schon auf manchen Systemen nicht mehr aktiviert. Ich sehe es nicht als sinnvoll an, die Bereinigungsmaßnahme mit dem restlichen Scriptverlauf zu verbinden. Deshalb Example 31-2 am Scriptanfang einbauen und im weiteren Verlauf davon ausgehen, dass $_GET, $_POST etc. frei von Magic Quotes sind.

              Warum sollen sie nicht gespeichert werden? Wenn sie jemand in einem HTML-Code-Beispiel verwendet oder Dinge schreibt, die zufällig wie Tags aussehen, müssen sie nicht unbedingt verloren gehen. Du musst nur bei der Ausgabe darauf achten, dass sie mit htmlspecialchars() HTML-gerecht umgeschrieben werden. < als &lt;, > als &gt; und " als &quot; - erledigt der Fall. Es ist eine gute Idee, sich das htmlspecialchars() für die Ausgabe aller nicht direkt im Script notierten Daten anzugewöhnen.

              OK, also nimm mal an, ich möchte sowas wie ein Blog machen. Da sollen alle Leser-Kommentare gleich aussehen und ich will nicht, daß jemand mit <font size="12"> oder Ähnlichem da Unruhe stiftet. Gibt also jemand als Wert zB " <font size="9" color="red">Hallo Welt</font> ein, dann soll bei der Ausgabe einfach nur "Hallo Welt" stehen. Das muß doch gehen, oder?

              Das kann man so machen, und wenn du mit den Nebenwirkungen von strip_tags() leben kannst, kannst du das auch einsetzen.

              Ich vertrete da eher eine andere Meinung. Wenn jemand <font size="12"> in seinem Text eingibt, egal ob er die Absicht hat, sich damit wichtig zu machen oder einfach nur darüber zu reden, so wie wir das grad tun, dann soll er das doch tun und dann auch genauso als reinen Text angezeigt bekommen. In einem Fall hat er Pech und seinen Text verunstaltet, im anderen muss er sich keine Verrenkung ausdenken, um doch noch irgendwie <font size="12"> schreiben zu können.

              Auf der anderen Seite wiederum möchte ich, daß, wenn jemand einen Kommentar schreibt und da zB. www.meineseite.com vorkommt, dies bei der Ausgabe zu einem Link wird.

              Du wirst das wesentlich einfacher haben, wenn du die bekannte BBCode-Syntax unterstützt. Da kann der Anwender selbst angeben, ob er einen Link haben möchte [url]www.example.com[/url] oder ob die Adresse unverlinkt stehen soll. [b][/b] und Konsorten können zur Formatierung verwendet werden. Und für BBCode weiß ich, dass es da bereits eine sehr gute Lösung gibt.

              Nichts desto trotz war ich gestern natürlich nicht unfleißig und habe mich mal mit preg_replace() und mit ereg_replace() erstmalig beschäftigt. Schau Dir mal meine 2 Beispielseiten an :

              Es gibt für PHP zwei RegExp-Maschinen, eine Posix- und eine Perl-kompatible (ereg* vs. preg*). Im Allgemeinen soll man die preg*-Funktionen nehmen, da diese schneller sind. Noch schneller sind bei einfachen Stringmanipulationen reine String-Funktionen (hier: str_replace()). So eignen sich deine ersten beiden Beispiele zwar zum Üben, aber nicht als gutes Beispiel für eine sinnvolle RegExp-Anwendung.

              $suchmuster='(^| )(www([-]*[.]?[a-zA-Z0-9_/-?&%])*)';
              $ersatz='<a href="http://\2">\2</a>';
              Es funktioniert, ich hab aber keine Ahnung, wieso und wie der reguläre Ausdruck in der Anweisung zu deuten ist.

              Die runden Klammern gruppieren. Sie fassen einen Teil zusammen, vor allem um ihn später im Ersetzungsausdruck einfügen zu können. In $ersatz weist das \2 an, den zweiten geklammerten Ausdruck zu verwenden.

              (^| )
              Gesucht wird der Text-Anfang ^ oder | ein Leerzeichen. (Man muss bei geklammerten URLs plenken, da ein www nur erkannt wird, wenn es am Anfang oder nach einem Leerzeichen steht. Dieses Problem hätte man mit BBCode nicht.)
              www
              steht für sich selbst.
              [-]
              steht für einen Bindestrich. Man hat ihn wahrscheinlich mangels besseren Wissens in eine Zeichenklasse [] getan. Er hätte auch einfach so dastehen können.
              Eine Zeichenklasse fasst mehrere Zeichen zusammen. Sie listet alle Zeichen auf, die an dieser Stelle vorkommen können.
              *
              steht für: Das vorhergehende Zeichen (oder auch eine Gruppe, hier: alle Zeichen der Zeichenklasse [-]) darf wegbleiben oder beliebig oft auftreten (0 oder mehr).
              [.]
              Dann kommt ein Punkt. Da ein Punkt für ein beliebiges Zeichen steht, hat kan ihn hier wieder in eine Zeichenklasse getan, wo er diese Bedeutung verliert. Das hätte auch ein vorangestellter \ getan.
              ?
              steht für: gar nicht oder höchstens einmal.
              [a-zA-Z0-9_/-?&%]
              Hier ist die Zeichenklasse mal sinnvoll angewendet, auch wenn sie einen Fehler enthält. Der Bindestrich steht für einen Bereich, a-z also für alle kleinen Buchstaben des lateinischen Alphabets. Will man den Bindestrich als solchen haben, muss er als erstes oder letztes Zeichen der Zeichenklasse notiert sein. Das /-? steht also nicht nur für diese drei Zeichen sondern für /0123456789:;<=>?

              Das sollte keine Einführung in Reguläre Ausdrücke werden. Einige Besonderheiten der erwähnten Regeln habe ich deshalb nicht genannt. SELFHTML hat im Perl-Teil ein Kapitel zu Regulären Ausdrücken.

              echo "$verabschiedung $name";

              1. Hi dedlfix!

                Danke für die ausführliche Antwort und die Geduld mit mir!

                Tja, unsere persönliche Anfänger-DB-Konferenz ( mit Anfänger meine ich natürlich nur _mich_ ! *g* ) neigt sich dem Ende zu, in Kürze wird dieses Posting im Archiv sein und ich bin ein paar Tage nicht online. Ich werde mir all das, was Du da geschrieben hast, speziell auch Dein abschließendes Posting, in Ruhe durchlesen und mich noch ausführlicher damit beschäftigen.

                Auf jeden Fall hab ich Einiges dazugelernt und dafür möchte ich mich recht herzlich bedanken!

                Mit lieben Grüßen

                Der Brombeermilchtrinker

                  
                $zeit=2006;  
                $dedlfix=netter_php_profi;  
                $brombbermilchtrinker=ueberforderter_php_newby;  
                while($brombeermilchtrinker<php_versteher)  
                 {  
                 $dedlfix echo "hilfe" for $brombbermilchtrinker;  
                 }  
                $zeit=2010;  
                
                

                ;-)

    2. echo $begrüßung;

      2.) Was ich nicht hinbekomme : Angenommen, ich möchte, daß eine Eingabe einer URL mit oder ohne http:// als _anklickbarer Verweis_ wieder ausgegeben wird. Wie mache ich das?

      Befindet sich die URL in einem eigens dafür vorgesehenen Feld? Dann prüfe doch, ob der Inhalt mit http:// beginnt und erzeuge ein <a href="...">... Soweit die Kurzform. Natürlich kannst du den eingegebenen Wert auch noch auf korrekte URL-Syntax prüfen. Wenn du dazu eine Funktion im Web suchst, achte darauf, dass sie die Prüfung gemäß RFC 2396 (ich hoffe, das ist die richtige) vornimmt. Ältere Funktionen beachten oft noch nicht, dass es Top Level Domains mit mehr als 3 Zeichen gibt.

      Befindet sich die URL mitten in einem Text wird es schwieriger. Woran erkennst du eine URL, wenn sie nicht mit http:// beginnend notiert ist? Vielleicht an einem www.? Ermittle die Position eines http:// bzw. www. und von da ab bis zum nächsten Whitespace-Zeichen. Das musst du dann mit dem Rest-Text fortsetzen.

      echo "$verabschiedung $name";