PHP: Error in your SQL syntax

Gast #3736428
Lesenswert?

Hallo,

ich versuche seit einigen Stunden vergeblich einen leeren Return von 
einer SQL Abfrage abzufangen.

Vereinfacht mache ich folgendes:
1
<?php
2
$user_agent = $_SERVER['HTTP_USER_AGENT'];
3
$connection = mysql_connect($server,$user,$password);
4
$db = mysql_select_db($database,$connection);
5
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent'";
6
$browser_result = mysql_query($browser_sql) OR die(mysql_error());
7
  
8
if(mysql_num_rows($browser_result)<1){
9

10
$insert_sql = "INSERT INTO BrowserOS (browser) VALUES ($user_agent);";
11
$insert_result = mysql_query($insert_sql) OR die(mysql_error());
12
};

Also den Browser des Aufrufenden ermitteln, wenn dieser noch nicht in 
der Tabelle BrowserOS steht, dann eintragen.

Jedoch bekomme ich jedes mal wenn der Browser noch nicht in der Tabelle 
steht, folgende Fehlermeldung bei der Abfrage 
"if(mysql_num_rows($browser_result)<1){" --> You have an error in your 
SQL syntax; check the manual that corresponds to your MySQL server 
version for the right syntax to use near '(Windows NT 6.1; 
WOW64).....1985.' at line 1

Sobald ich die Abfrage auskommentiere und damit diesen Wert in die 
Datenbank schreiben lasse, kommt keine Fehlermeldung.

Also kommt der Fehler nur wenn der Mysql keine Tabellen zurückliefert.


Habt hier noch jemand einen Tip für mich?
Gast #3736438
Lesenswert?

Flo schrieb:
> Also kommt der Fehler nur wenn der Mysql keine Tabellen zurückliefert.

dann liefere doch einfach einen wert zurück:

$browser_sql  = "SELECT Count(*) as Anz FROM `BrowserOS` WHERE browser = 
'$user_agent'";

und dann solltest du dich mir Prepared SQL beschäftigen, denn so hast du 
schon die erste Sicherheitslücke in deinem Programm.
Gast #3736456
Lesenswert?

eingast schrieb:
> versuche es mal damit:
>
> $insert_sql = "INSERT INTO BrowserOS (browser) VALUES ('$user_agent');";

Der Insert ist nicht das Problem, wenn ich die if Abfrage auskommentiere 
dann trägt er den Wert richtig ein, das Problem liegt nur in der Abfrage 
wenn es noch keinen Eintrag gibt..

Das mit Count ist eine gute Idee, das werde ich ausprobieren
#3736484
Lesenswert?

Vor allen Dingen fehlt hier ein ; im SQL Statement
1
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent'";

--->
1
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent';";


Wie MySQL das handhabt kann ich nicht sagen, aber in den Command Line 
Tools wirkt sich so ein fehlender ; so aus, dass damit das SQL Statement 
noch nicht vollständig ist und mit der nächsten Eingabe weiter geht. 
Wenn das dazu führt, dass damit in einem einzigen SQL Statement sowohl 
ein SELECT als auch ein INSERT vorkommt, dann setzt das einen Fehler.
Gast #3736486
Lesenswert?

das war dann ein Copy&Paste Fehler von mir... habe mir teilweise die 
Querys aus PHPMyadmin kopiert.

ich habe es jetzt mal mit count versucht, an das Ergebnis (im moment 0 
weil die Tabelle leer ist) komme ich noch nicht ganz:
1
$browser_result = mysql_query($browser_sql) OR die(mysql_error());
2
$count = mysql_result($browser_result);
3
  
4
if($count == 0){
5
  $insert_sql = "INSERT INTO BrowserOS (browser) VALUES $user_agent);";
6
  $insert_result = mysql_query($insert_sql) OR die(mysql_error());
7
  echo "Wird hinzugefuegt";    
8
    };


Ich glaube mysql_result($browser_result); ist hier nicht das richtige 
oder?
Es kommt weiterhin:You have an error in your SQL syntax; check the 
manual that corresponds to your MySQL server version for the right 
syntax to use near '(Windows NT 6.1; WOW64)...'
Gast #3736496
Lesenswert?

Flo schrieb:
> Der Insert ist nicht das Problem, wenn ich die if Abfrage auskommentiere
> dann trägt er den Wert richtig ein, das Problem liegt nur in der Abfrage
> wenn es noch keinen Eintrag gibt..

Würde ich jetzt mal so nicht behaupten, denn die Fehlermeldung deutet 
auf das ";" in der Browserbezeichnng hin, welches als SQL-Kommandoende 
interpretiert wird. Deshalb versuche es erstmal mit den "'" und dann 
kann man weiter diskutieren!
Persönliche Seite #3736501
Lesenswert?

Flo schrieb:
> Ich glaube

Lieber Doku lesen als glauben... Dein Problem ist NICHT irgendwelche 
Funktionsaufrufe oder existierende Tabelle(spalten) sondern das dein 
Query falsch ist. String müssen IMMER mit 
http://php.net/manual/de/function.mysql-real-escape-string.php escaped 
(und in Hochkomma eingeschlossen o.ä.) werden weil sonst teile des 
String (wie er dir ja auch sagt) als SQL Befehl interpretiert werden.

> Also kommt der Fehler nur wenn der Mysql keine Tabellen zurückliefert
Wenn der keine Tabbellen mehr hat ist was anderes kaputt...

> bei der Abfrage "if(mysql_num_rows($browser_result)<1){"
Höchst unwahrscheinlich, da hier ÜBERHAUPT kein SQL ausgeführt wird!
Gast #3736516
Lesenswert?

eingast schrieb:
> Würde ich jetzt mal so nicht behaupten, denn die Fehlermeldung deutet
> auf das ";" in der Browserbezeichnng hin, welches als SQL-Kommandoende
> interpretiert wird. Deshalb versuche es erstmal mit den "'" und dann
> kann man weiter diskutieren!

SUPER, danke, der Fehler kam vom insert...

Jetzt habe ich es so:
1
    
2
$browser_sql  = "SELECT count(*) FROM `BrowserOS` WHERE browser = $user_agent'";
3
   
4
$browser_result = mysql_query($browser_sql) OR die(mysql_error());
5
$count = mysql_result($browser_result);
6
  
7
if($count == 0){
8
  $insert_sql = "INSERT INTO BrowserOS (browser) VALUES    ('$user_agent')";
9
  $insert_result = mysql_query($insert_sql) OR die(mysql_error());
10
  echo "Wird hinzugefuegt";    
11
    };

leider Ignoriert er jetzt das if($count == 0) und macht den Insert bei 
jedem aufruf.
#3736655
Lesenswert?

Und: mach das unbedingt noch sicher!

Wie oben schon geschrieben: So ist das eine Sicherheitslücke.

Der "User Agent" ist vom Webseiten-Besucher frei vorgebbar,

Der Erste Besucher mit User-Agent
1
'; drop database; --

Bereitet dir viel Freude.

Und ja: Es gibt Tools um solche Lücken automatisch zu finden und 
auszunutzen.
Angehängte Dateien:
Gast #3737539
Lesenswert?

Das Problem lag nur am Insert, ich habe es jetzt wie folgt gelöst:
1
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent'";
2
$browser_result = mysql_query($browser_sql) OR die(mysql_error());
3
    
4
    if(mysql_num_rows($browser_result)<1){  
5
    $insert_sql = "INSERT INTO BrowserOS (browser) VALUES  
6
                ('$user_agent')";
7
    $insert_result = mysql_query($insert_sql) OR 
8
                die(mysql_error());
9
    echo "Wird hinzugefuegt";    
10
    };

Εrnst B✶ schrieb:
> Und: mach das unbedingt noch sicher!
>
> Wie oben schon geschrieben: So ist das eine Sicherheitslücke.
>
> Der "User Agent" ist vom Webseiten-Besucher frei vorgebbar,

Wäre das eine mögliche Lösung?
$user_agent = str_replace("'","Einbruchsversuch",$user_agent);
#3737557
Lesenswert?

Flo schrieb:
> Wäre das eine mögliche Lösung?
> $user_agent = str_replace("'","Einbruchsversuch",$user_agent);

Nein! Schmeiß deinen SQL Kram komplett weg! Die mysql_ / mysqli_ 
funktionen stammen aus den Anfängen von PHP und werden leider durch 
unzählige Tutorials so weitergegeben...heute benutzt man die Funktionen 
nur noch für eigene DB-Abstraktionsschichten...

Du solltest konkret PDO mit "Prepared Statements" benutzen - siehe 
http://php.net/manual/de/book.pdo.php - das verhindert jegliche Probleme 
dieser Art! Jede Variable wird über "bind(key, value)" dem Statement 
hinzugefügt und automatisch escaped

Dazu gibts auch unmengen an Tutorials im Internet...wenn du dir selber 
einen gefallen tun willst befolge den Rat...
#3737558
Lesenswert?

Flo schrieb:
> Wäre das eine mögliche Lösung?
> $user_agent = str_replace("'","Einbruchsversuch",$user_agent);

Nicht wirklich.
etwas besser wäre "addslashes", "mysql_escape_string", oder besser 
"mysql_real_escape_string".

Eine Richtige Lösung sind alle drei auch nicht.
Besser: Ein neueres mysql-Interface nehmen, nicht das steinalte 
"mysql_*"-Zeuchs. Gerade bei Neuentwicklungen gibt es da eigentlich 
garkeinen Grund mehr für.

http://php.net/manual/de/mysqli.quickstart.prepared-statements.php
Oder besser gleich PDO-Mysql.
Gast #3737615
Lesenswert?

Super, danke für den Tip! Ich habe mir mal eben ein Beispiel gesucht und 
es auf meine Anwendung angepasst, das mit dem schließen ist mir noch 
etwas unklar...
1
<?php 
2
$handler = new mysqli("dbhost", "dbuser", "dbpass", "db");
3

4
$getuseragent = $handler->prepare("SELECT * FROM people WHERE (user_agent = ?)");
5
$getuseragent->bind_param('s', $user_agent);
6
$user_agent = $_SERVER['HTTP_USER_AGENT'];
7
$getuseragent->execute();
8
  
9
if (!$getuseragent->get_result()) {
10
    echo("Browser nicht vorhanden, wird hinzugefuegt...");
11
    $insertbrowser = $handler->prepare("INSERT INTO BrowserOS (browser) VALUES (?)");
12
  $insertbrowser->bind_param("s", $browsername);
13
  $name = $user_agent;
14
    $insertbrowser->execute();
15
  //nicht sicher ob das hier stimmt
16
  $insertbrowser->close();
17
    
18
}; 
19
  //nicht sicher ob das hier stimmt
20
$getuseragent->close();
21
 ?>
Gast #3737626
Lesenswert?

Flo schrieb:
> if (!$getuseragent->get_result()) {
>     echo("Browser nicht vorhanden, wird hinzugefuegt...");

das sieht mir komisch aus. Auch ein leeres Result ist auch ein Result. 
Es kommt aus einen Select immer eine Result zurück, eventuell hat es 
aber 0 Zeilen.
Gast #3747376
Lesenswert?

Falls du noch keine Lösung hast:

http://php.net/manual/de/function.mysql-num-rows.php


<?php

$link = mysql_connect("localhost", "mysql_user", "mysql_password");
mysql_select_db("database", $link);

$result = mysql_query("SELECT * FROM table1", $link);
$num_rows = mysql_num_rows($result);

echo "$num_rows Zeilen\n";

?>

Auf ersten Augenblick schein mir so zu sein (ich hab nicht ausprobiert):
Du hast den Connection ($link) für mysql_query nicht übergeben. Damit 
ist es ein Aufrufproblem (kein SQL Problem an der Stelle), $result war 
undefiniert, und dann bei mysql_num_rows ist es rausgestiegen.

Das ist nur ein Tipp ;)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren