kostenloser Webspace werbefrei: lima-city


Script Error - unecspected...

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    Hallo, ich hab eine Frage und zwar habe ich das unten gezeigte Script schon lange auf meinem Webspace laufen. Es soll in eine Datenbank einfügen bzw. wenn schon eingefügt ist Fehler anzeigen. Hat bis jetzt auch geklappt aber jetzt wird immer Error unecspected ... angezeigt und das sogar an mehreren Stellen. Ich weiß nicht wie ich das beheben soll weil der jeweilige Scriptabschnitt auf einer leeren Seite fehlerfrei funktioniert.

    <?php
    
      $servername = "###";
      $username = "###";
      $password = "###";
      $dbname = "###";
      $conn = new mysqli($servername, $username, $password, $dbname);
    
      $option = $_POST["option"];
      $name = $_COOKIE["logname"];
    
             $sqlv = 'SELECT Status FROM challenge WHERE Status="not started" AND name1="'.$name.'";
             $result = mysqli_query($conn, $sqlv);
             if (mysqli_num_rows($result) > 0) {
                while($row = mysqli_fetch_assoc($result)) {
                   die('<title>Raum schon vorhanden!</title><h1>Fehler!</h1>
                        <p>Sie haben bereits einen offenen Raum erstellt!</p><br>
                        <a href="room.php?id=' . $row["ID"] . '">Zum Raum</a>');
                }
             }
    
      $sql = "INSERT INTO `challenge` (`name1`, `Ext1`, `Status`, `Option`)
    VALUES ('" . $name . "', 'Game', 'not started', '" . $option . "')";
      if ($conn->query($sql) === TRUE) {
         $query = "SELECT * FROM challenge WHERE name1='" . $name . "'";
         if ($result = $conn->query($query)) {
        while ($row = $result->fetch_assoc()) {
         $id = $row["ID"];
          }}
       echo('<script>window.location = "room.php?id=' . $id . '";</script>');
       }
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. witze-dschungel

    witze-dschungel hat kostenlosen Webspace.

    Grundsätzlich ist bei einer Fehlerbehebung die komplette Fehlermeldung hilfreich. Im Fall von PHP wird dir meist die Zeile des Fehlers angezeigt.

    Ohne die exakte Fehlermeldung zu kennen, liegt in jedem Fall ein Fehler in Zeile 12:

    $sqlv = 'SELECT Status FROM challenge WHERE Status="not started" AND name1="'.$name.'";

    Du hast vor dem Semikolon ein schließendes Anführungszeichen vergessen (oder versehentlich gelöscht). Deshalb interpretiert PHP das nächste Anführungszeichen (bei die('<title>...) als schließendes.

    Der korrigierte Code wäre:

    $sqlv = 'SELECT Status FROM challenge WHERE Status="not started" AND name1="'.$name.'"';

    Ich weiß nicht wie ich das beheben soll weil der jeweilige Scriptabschnitt auf einer leeren Seite fehlerfrei funktioniert.

    Der Code kann nicht fehlerfrei auf einer leeren Seite funktionieren, da Zeile 9 und 10 Nutzereingaben erwarten (Post und Cookie). Ein direkter Aufruf würde also ein Undefined index erzeugen.

    Nebenbei erwähnt validierst du die Nutzereingaben nicht. Mich würde nichts davon abhalten, den Cookie "logname" in "dfjil" zu ändern.

    Beitrag zuletzt geändert: 29.7.2019 13:28:47 von witze-dschungel
  4. horstexplorer

    horstexplorer hat kostenlosen Webspace.

    Zudem sollte man gar nicht selbst seine Statements mit Variablen füllen sondern Prepared-Statements dafür benutzen.
    "Es muss ja nicht unbedingt... " Doch, es muss. Niemand möchte das die Datenbank weg ist nur weil man dort einige Sekunden gespart hat und dann jemand die komplette Seite auseinander nimmt.
    https://www.php.net/manual/de/mysqli.quickstart.prepared-statements.php
    //
    Genauso wenig sollte man Passwörter unverschlüsselt speichern. Seit dem du deine Datenbanken raus gepustet hast hast immer noch ned deine Passwörter geändert. Mit dem _906 er kommt man super auf dein Lima Account und deine Webseiten. Und von dort aus auf so ziemlich alles andere. Eventuell solltest das langsam mal ändern. :wink:

    Beitrag zuletzt geändert: 29.7.2019 13:36:29 von horstexplorer
  5. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    Also, ich hab mir eure Tipps zu Herzen genommen und auf Prepared Statements umgestellt (überall). Pws sind auch geändert. Cookies werden per 'sec.php' auf Richtigkeit geprüft (username-password) per Datenbank.

    Jetzt zum eigentlichen Thema: den script error bin ich mittlerweile los, aber jetzt habe ich ein anderes Problem: Bedingung
    if($statement->rowCount() > 0){
    wird wenn nötig ausgeführt, Prepared Statements funktionieren auch. Aber die das INSERT im
    else{
    funktioniert nicht, aus diesem Grund auch das nachfolgende SELECT, Weiterleitung aber schon:

    <?php
    include('sec.php');
    
      $option = $_POST["option"];
      $name = $_COOKIE["logname"];
    
    $pdo = new PDO('mysql:host=localhost;dbname=xxxx', 'xxxx', 'xxxx');
     $statement = $pdo->prepare("SELECT * FROM challenge WHERE Status = 'not started' AND name1 = :name");
     $statement->execute(array('name' => $name));   
     if($statement->rowCount() > 0){
         while($row = $statement->fetch()){
    
                   die('<title>Raum schon vorhanden!</title><h1>Fehler!</h1>
                        <p>Sie haben bereits einen offenen Raum erstellt!</p><br>
                        <a href="room.php?id=' . $row["ID"] . '">Zum Raum</a>');
         }
        }
    else {
     $statementx = $pdo->prepare("INSERT INTO challenge (name1, Ext1, Status, Option)
    VALUES (:name, 'game', 'not started', :option)");
     $statementx->execute(array('name' => $name, 'option' => $option));   
     $statementz = $pdo->prepare("SELECT * FROM challenge WHERE Status = 'not started' AND name1 = :name");
     $statementz->execute(array('name' => $name));   
         while($rowz = $statementz->fetch()){
         $id = $rowz["ID"];
    }
          
       echo('<script>window.location = "room.php?id=' . $id . '";</script>');
    }
  6. horstexplorer

    horstexplorer hat kostenlosen Webspace.

    Das sieht doch schon einmal deutlich besser aus, allerdings scheint mir der wichtigste Teil bei Prepared Statements zu fehlen.
    First stage: prepare
    Second stage: bind and execute
    Also als Beispiel mal an deinem Select:
    $mysqli = new mysqli("example.com", "user", "password", "database");
    $statement = $mysqli>prepare("SELECT * FROM challenge WHERE Status = 'not started' AND name1 = ?");
    if(!$statement->bind_param("s", $name){   // hierbei wird das erste ? gegen einen String aus name eingesetzt
       die("prep.failed");
    }
    $statement->execute();
    ...

    Wenn du jetzt mehrere Variablen hast funktioniert das genau so.
    $statementx = $mysqli->prepare("INSERT INTO challenge (name1, Ext1, Status, Option) VALUES (?, 'game', 'not started', ?)");
    if(!$statementx->bind_param("si", $name, $option){   // hierbei wird das erste ? gegen einen String aus name und das zweite durch einen integer aus $option eingesetzt (nur damit das mit dem s, i etc ersichtlich wird)
       die("prep.failed");
    }
    ......

    Das ganze geht mit PDO auch mit den :name wie du das gelöst hast aber diese werden anders eingesetzt, da finde ich die mysqli Lösung sauberer anzuschauen.
    $stmt->bindParam(':first_name', $first_name, PDO::PARAM_STR);
    $stmt->bindParam(':last_name', $last_name, PDO::PARAM_STR);


    Beitrag zuletzt geändert: 11.8.2019 14:48:57 von horstexplorer
  7. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    Nur zu meinem Verständnis:
    Was hätte die von mir angewandte Methode denn für Nachteile, weil auf allen anderen meinen Seiten funktioniert es.
    (Sonst müsste ich nämlich alle seiten wieder ändern)
    Anmerkung: Daher hab ich das https://www.php-einfach.de/mysql-tutorial/php-prepared-statements/
  8. horstexplorer

    horstexplorer hat kostenlosen Webspace.

    Dazu findet man nicht so viel wie ich dachte. Die Beispiele bei pdo sind alle für execute(var) aber genutzt wird meist doch bind. Macht also evtl ned mal nen so großen Unterschied :confused:.
    https://www.php.net/manual/de/pdostatement.execute.php
    https://stackoverflow.com/questions/29423281/what-is-the-differences-and-advantages-between-bindparam-bindvalue-and-exec
    Pdo verhält sich da doch noch etwas anders als mysqli :D.

    Aber so oder so klärt das nicht wirklich wieso dein Insert nicht funktioniert, versuch da doch mal zu kucken ob es nen Fehler wirft.
    https://www.lima-city.de/hilfe/ich-bekomme-einen-fehler-angezeigt-was-kann-ich-tun
    https://www.php.net/manual/de/pdo.errorcode.php

    Beitrag zuletzt geändert: 11.8.2019 22:38:59 von horstexplorer
  9. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    So, hier die beiden Fehlermeldungen:
    Notice: Undefined index: new in /home/webpages/lima-city/xxxxxxx on line 28

    Ich sehe im Script nur das new bei new pdo, aber in den vorherigen Abfragen hat es ja auch funktioniert.
    Allerdings liegt das INSERT ja auch gar nicht in line 28!

    PDO::errorInfo(): Array ( [0] => 00000 [1] => [2] => )

    Daraus werde ich gar nicht schlau ... Aray scheint für mich nicht falsch zu sein...

    Beitrag zuletzt geändert: 12.8.2019 18:56:00 von mehralsnurradio
  10. horstexplorer

    horstexplorer hat kostenlosen Webspace.

    Wenn ich das richtig nachgezählt habe ist Zeile 28 ja dein echo.
    :confused:

    // Das wird irgendwie nicht logischer für mich..

    Der Fehlercode sagt ja das alles funktioniert (hast du den an der richtigen Stelle abgefragt also nach dem insert?)

    Kann es sein das die Bedingung nicht false wird und deswegen nicht der Teil in else ausgeführt wird?
    Um dafür mal die Dokumentation zu nutzen:
    For most databases, PDOStatement::rowCount() does not return the number of rows affected by a SELECT statement

    Instead, use PDO::query() to issue a SELECT COUNT(*) statement with the same predicates as your intended SELECT statement, then use PDOStatement::fetchColumn() to retrieve the number of rows that will be returned.


    Beitrag zuletzt geändert: 12.8.2019 20:17:20 von horstexplorer
  11. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    Das else wird ja ausgeführt, es wird ja auch weitergeleitet.

    Mit der Zeile 28 hast du aus deiner Perspektive Recht, aber da ich noch ein bisschen was geändert habe ... aber auch ich lag falsch, nach erneutem Kontrollieren hab ich die als Zeile 28 gezählt:
    $statementz->execute(array('name' => $name));


    Das verstehe ich zwar nicht, weiterbringen würde uns eine Lösung aber wahrscheinlich eh nicht .

    Das ist ja das execute vom SELECT am Ende und nicht das vom INSERT ...
  12. horstexplorer

    horstexplorer hat kostenlosen Webspace.

    Wie sieht der Code denn jetzt aus mit dem du das testest (also mit dem debug zeug)? Ich kann mir kaum vorstellen das die Ausführung der Statements erfolgreich ist aber sie nicht funktionieren. Woher kommt das Undefined index new? Wie sieht denn die sec.php aus?

    Beitrag zuletzt geändert: 12.8.2019 21:53:58 von horstexplorer
  13. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    sec.php:

    if($_COOKIE['data'] != "yes"){
     die('<script>window.location = "https://xxxx/xxxx/datadie.php";</script>');
    }
    
    
    if($_SERVER['HTTP_X_REQUESTED_WITH'] == "com.xxxx"){
    }
    else{
     die('<script>window.location = "https://play.google.com/store/apps/details?id=com.xxxx";</script>');
    }
    
    
    $pdo = new PDO('mysql:host=localhost;dbname=xx', 'xx', 'xx');
    if(isset($_COOKIE['logname'])){
     $statement = $pdo->prepare("SELECT * FROM users WHERE Name = :username");
     $statement->execute(array('username' => $_COOKIE["logname"]));   
     while($row = $statement->fetch()) {
     if ($_COOKIE["logpass"] != $row["Passwort"]){
      die('<title>Cookie gef&aumllscht!</title>
           <p>Bitte App neu installieren, der Username wurde gef&aumllscht!</p>');
      }
     }
    }
    
    
    
    if ($_GET['new'] == "yes" AND $_GET['id'] != "3-0"){
    die('<meta name="viewport" content="width=device-width">
    <title>UPDATE ERFORDERLICH!</title>
    <h1>Update erforderlich!</h1>
    <a href="market://details?id=com.hundretsix.games.xxx">Zum Store</a>');
    }


    Neuer Code:

    <?php
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    
    include('sec.php');
    
      $option = $_POST["option"];
      $name = $_COOKIE["logname"];
    
    $pdo = new PDO('mysql:host=localhost;dbname=xxxx', 'xxxx', 'xxxx');
     $statement = $pdo->prepare("SELECT COUNT(*) AS anzahl FROM challenge WHERE Status = 'not started' AND name1 = :name");
     $statement->execute(array('name' => $name));   
         while($row = $statement->fetch()){
          if($row["anzahl"] > 0){
                   die('<title>Raum schon vorhanden!</title><h1>Fehler!</h1>
                        <p>Sie haben bereits einen offenen Raum erstellt!</p><br>
                        <a href="room.php?id=' . $row["ID"] . '">Zum Raum</a>');
         }
    else {
     $statementx = $pdo->prepare("INSERT INTO challenge (name1, Ext1, Status, Option)
    VALUES (:name, 'OIMELkill', 'not started', :option)");
     $statementx->execute(array('name' => $name, 'option' => $option));   
    
        echo "\nPDO::errorInfo():\n";
        print_r($pdo->errorInfo());
    
     $statementz = $pdo->prepare("SELECT * FROM challenge WHERE Status = 'not started' AND name1 = :name");
     $statementz->execute(array('name' => $name));   
         while($rowz = $statementz->fetch()){
         $id = $rowz["ID"];
          }
    echo('<script>window.location = "room.php?id=' . $id . '";</script>');
    }
    }
  14. witze-dschungel

    witze-dschungel hat kostenlosen Webspace.

    Vermutlich liegt der Fehler in Zeile 28 in der sec.php:
    if ($_GET['new'] == "yes" AND $_GET['id'] != "3-0"){

    Sofern die Seite ohne den Get-Parameter "new" angerufen wird, existiert auch der index "new" nicht in der get superglobal ($_GET).

    Du kannst mit isset() überprüfen, ob der index existiert:
    if (isset($_GET['new']) && $_GET['new'] == "yes" AND $_GET['id'] != "3-0"){

    Die selbe funktionsweise könntest du auch bei $_GET['id'] anwenden, falls dieser nicht angegeben wurde.


    Kleiner Tipp:
    Wenn du hier im Forum deinen Code statt [code][/code] mit [code=php][/code] einbettest, werden auch Zeilenummern angezeigt und der Code wird entsprechend formatiert.

    Beitrag zuletzt geändert: 13.8.2019 11:41:49 von witze-dschungel
  15. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    OK, danke!
    Dann hatte sich Zeile 28 wegen dem include verschoben...

    Bringt mich jetzt aber auch nicht weiter!

    Das INSERT ist immer noch nicht gelöst
  16. witze-dschungel

    witze-dschungel hat kostenlosen Webspace.

    Das INSERT ist immer noch nicht gelöst


    Auf den ersten Blick sehe ich da keine Fehler.

    Du scheinst die PDO Fehler an dieser Stelle auszugeben. Du kannst die Weiterleitung weiter unten auskommentieren und dann schauen, ob dich die Fehlermeldung weiterbringt.

    Beitrag zuletzt geändert: 13.8.2019 11:59:13 von witze-dschungel
  17. witze-dschungel schrieb:
    Du kannst mit isset() überprüfen, ob der index existiert:
    if (isset($_GET['new']) && $_GET['new'] == "yes" AND $_GET['id'] != "3-0"){
    Zum ersten eine rein semantische Anmerkung: Die funktion
    isset
    überprüft nicht, ob ein index existiert, sondern ob er auf etwas anderes als null gesetzt ist. Dies impliziert natürlich seine Existenz, aber in bestimmten Fällen kann das zu Verwirrung führen - beispielsweise wenn der Index auf
    null
    gesetzt ist - hier gibt
    isset
    false zurück, obwohl der Index rein technisch existiert. Die Existenz wird mit array_key_exists geprüft.
    Zum anderen:
    [...] AND $_GET['id'] != "3-0") [...]
    - es sollte
    !==
    heißen, sonst hast du nur einen einfachen Vergleich, wo herumgecastet werden darf, wie es will.

    Was ich empfehlen würde wäre eine vollständige Klasse zum Umgang mit Get-Variablen. Sowas wie...
    class GetVar{
        private $m_key = null;
        private $m_default = null;
    
        public function __construct($key, $default = null)
        {
            $this->m_key = $key;
            $this->m_default = $default;
        }
    
        public function int($default = null)
        {
            if($default === null) $default = $this->m_default;
            if(!isset($_GET[$this->m_key])) return $default;
            if(!ctype_digit($_GET[$this->m_key])) return $default;
            return (int) $_GET[$this->m_key];
        }
    
        public function limitedString($allowedCharacters, $default = null)
        {
            if($default === null) $default = $this->m_default;
            if(!isset($_GET[$this->m_key])) return $default;
            if(preg_match('/[^' . $allowedCharacters . ']/', $_GET[$this->m_key])) return $default;
            return $_GET[$this->m_key];
        }
    
        public function value($default = null)
        {
            if($default === null) $default = $this->m_default;
            if(!isset($_GET[$this->m_key])) return $default;
            return $_GET[$this->m_key];
        }
    
        [...]
    
    }
    
    $get_new = new GetVar("new", "no");
    $get_id = new GetVar("id", "whatever")
    
    if ( ( $get_new->limitedString("A-Za-z") == "yes") && ( $get_id->limitedString("rule") !== "3-0") ) [...]
    Wobei die nur Quick&Dirty geschrieben ist - kann man sicher noch eleganter machen.
  18. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    Zwei Sachen:

    1. Was stellt meine jetzige Anwendung für Sicherheitslücken / Risiken dar?

    2. Wir sind Mal wieder vom eigentlichen Thema abgewichen:
    - Die PDO-Meldung ist mit ausgeklammerter Weiterleitung weiter vorne im Thread

    Gibt's hier eventuell jemanden der sich mit PDO auskennt???
  19. mehralsnurradio schrieb:
    Zwei Sachen:

    1. Was stellt meine jetzige Anwendung für Sicherheitslücken / Risiken dar?
    Lässt sich so mit den paar Code-Schnipseln nicht sagen. Allgemein ist das ganze ein großes Ratespiel - deine Fehlermeldungen sind zensiert, deine Dateien unübersichtlich...
    Ich würde damit anfangen, den Code aufzuräumen.

    mehralsnurradio schrieb:
    2. Wir sind Mal wieder vom eigentlichen Thema abgewichen:
    - Die PDO-Meldung ist mit ausgeklammerter Weiterleitung weiter vorne im Thread
    Das Problem ist: Es ist keine Fehlermeldung - es ist eine "Alles okay"-Meldung. Das ist aber - so wie ich das sehe - kein PDO-Problem, sondern ein Logik-Problem. Du hast:
    $pdo = new PDO('mysql:host=localhost;dbname=xxxx', 'xxxx', 'xxxx');
    $statement = $pdo->prepare("SELECT COUNT(*) AS anzahl FROM challenge WHERE Status = 'not started' AND name1 = :name");
    $statement->execute(array('name' => $name)); 
    while($row = $statement->fetch()){
        if($row["anzahl"] > 0){
            // ...
        }else {
            $statementx = $pdo->prepare("INSERT INTO challenge (name1, Ext1, Status, Option)
            VALUES (:name, 'OIMELkill', 'not started', :option)");
            $statementx->execute(array('name' => $name, 'option' => $option));   
    
            echo "\nPDO::errorInfo():\n";
            print_r($pdo->errorInfo());
            // ...
        }
    }
    Was bedeuted, dass du möglicherweise keinen PDO-Fehler hast, aber einen Ausgibst. Kurzum: Kein Wunder, dass er dir da eine "alles okay"-Meldung liefert. Dazu kommt, dass das ganze nicht so funktionieren sollte, wie du denkst. Denn in der Zeile
    $statement->execute(array('name' => $name));
    fehlt ein Doppelpunkt. Es sollte heißen:
    $statement->execute(array(':name' => $name));
    . Dasselbe an der Stelle mit
    $statementx->execute(array('name' => $name, 'option' => $option));
    .Dazu kommt - hier weniger wichtig, aber an anderer Stelle - dass keine ordentlichen Type-Checks stattfinden. Richtiger wäre - wie weiter oben schon bemerkt wurde - mit PDOStatement::bindParam zu arbeiten und die Datentypen zu übergeben.
    Des weiteren zu SQL allgemein: Auch, wenn ich jetzt grade keine ernsthaften Konflikte sehe, sollte man um mögliche Konflikte zu vermeiden, die Namen von Tabellen und Spalten in Gravis verpacken. Des weiteren bietet es sich an, die Enden von SQL-Befehlen mit einem Semikolon zu beenden - es ist nicht notwendig, aber ich würde es als... "Höflich" bezeichnen.
    So wird aus
    SELECT COUNT(*) AS anzahl FROM challenge WHERE Status = 'not started' AND name1 = :name
    ein
    SELECT COUNT(*) AS `anzahl` FROM `challenge` WHERE `Status` = 'not started' AND `name1` = :name;
    Ganz davon abgesehen bietet es sich natürlich immer an, entsprechende Datenbank-Modelle als Klasse aufzusetzen, wo man dann die entsprechenden Daten anfordern kann. Zum einen vermindert das etwaige Fehler, man muss Fehler nur ein mal beheben und es macht den Code übersichtlicher, wenn man Logik von Daten trennt.
  20. Autor dieses Themas

    mehralsnurradio

    mehralsnurradio hat kostenlosen Webspace.

    Nach vergleichen mit anderen PDO-Syntaxen in meiner Seite konnte ich keinen Unterschied feststellen und habe mich so an den Inhalt gemacht.
    Ich bin dann darüber gestolpert, dass es gar nicht funktionieren konnte, weil ich die Spalte "Option" erwähne, "Option" ist aber ein reserviertes MYSQL-Wort.
    Ich habe daher alles mit Anführungszeichen versehen und jetzt funktioniert es.

    (Thread kann geschlossen werden)
  21. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!