.NET HTTPRequest -> PHP -> MySQL Problem

Hi All,
ich bin gerade dabei mir eine Anwendung in .NET zu schreiben welches über ein PHP-Script auf eine MySQL Anwendung zugreifen soll, da der MySQL-Connector ja hier (und auch bei anderen Hostern) ja nicht funktioniert.
Im Voraus gesagt: bei PHP / MySQL bin ich noch relativ neu und kämpfe mich durch die üblichen Anfängerprobleme, während ich bei .NET wohl schon eher zu den Fortgeschrittenen gehöre.

Ich habe mich mittels Trial & Error durchgewuselt, hänge jetzt aber schon seit einigen Stunden an UTF8-Encoding Problemen .

Meine Datenbank ist simpel:

  • DB Inventar mit 2 Tabellen (Schlüssel,Bezeichnung)
  • alles auf Collation UTF8_Generall_ci gesetzt was ging ( DB-Interface,Tabellen)

Der Zugriff auf die DB soll über httpWebRequest POST erfolgen, wobei

  • Content-Type = “application/x-www-form-urlencoded”
  • Cookies werden nicht akzeptiert (CookieContainer=Nothing)
  • Post-Encoding auf UTF8

Das PHP-Script ist leider das Kernproblem (oder die Übertragung dahin):

  • das PHP-Script ist in einer UTF8-Datei (ohne Byte-Order-Mark)
  • ich habe alle Verbuindungen auf UTF8 gesetzt die mir einfielen
// valid connection: connect to database
	$db=@mysql_connect($host, $username, $password) or die (sqlerror(mysql_errno(), mysql_error() ));
	@mysql_select_db($db_name) or die (sqlerror(mysql_errno(), mysql_error() ));
	mysql_set_charset('utf8',$db); 
	mysql_query("SET character_set_results = 'utf8', character_set_client = 'utf8', character_set_connection = 'utf8', character_set_database = 'utf8', character_set_server = 'utf8'", $db);
	mysql_query("SET NAMES 'utf8'");
	// query empty ?
	if(empty($_POST['query'])) die(sqlerror(0, "Query is empty") );
	// send query
	$query = $_POST['query'];
	//$query="INSERT INTO Inventar (Schlüssel,Bezeichnung) VALUES('H-AX-3272','KIA Sorento')";
	$result = mysql_query($query)or die (sqlerror(mysql_errno(), mysql_error() ));

Schicke ich die INSERT-Query aus dem PHP-Script ab, so läuft alles sauber. Schicke ich die identische Query als HTTP POST ab, so bekomme ich den Fehler:

1064|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 '\'H-AX-3272\',\'KIA Sorento\')' at line 1|

Hat jemand eine Idee was ich noch ausprobieren könnte ? Hab so ziemlich alles hier im Forum und eine Menge Links in Google durchgeackert, aber komme irgendwie nicht weiter.

Ausserdem bin ich auch wirklich nicht zufrieden mit dieser Lösung, da alles supergenau aufeinander abgestimmt sein muss. Eine robustere Lösung wäre mir lieber …

Wie habt Ihr das gemacht ?

Gruss, Peter

Hast du die Daten URL-gerecht kodiert?

Gute Frage, nur was meinst Du damit ?

Wie gesagt werden die Daten per HTTPRequest mit Content-Type “application/x-www-form-urlencoded” geschickt, die Daten werden per Dim postDataBytes As Byte() = Encoding.UTF8.GetBytes(postString)als UTF8-Bytestream geschrieben.

Was nun wirklich in PHP ankommt ist mir nicht klar, ansonsten würde ich auch nicht so rumrätseln. Eigentlich schreibe ich ja die Daten als UTF8, was bewirkt der ContentType da noch ?

Was erwartet PHP wenn ich die Daten so sende ? Muss ich sicherheitshalber noch dieUTF8-Decode/Encode Methoden benutzen ?

Ich hatte angenommen , die Daten trudeln als UTF8 in PHP ein. Aber wie ist der Vergleich , wenn ich z.B. per empty($_POST('QUERY')) die übergebenen Parameter abfrage ? Dachte hier wäre das Datei-Encoding wichtig …

Wenn Du da etwas Licht ins Dunkel bringen könntest. wäre ich Dir überdankbar :unamused:

[size=85]Fragen über Fragen - ein Teufelskreis (TV-Kaiser)[/size]

Alles, was nicht ASCII ist und/oder ggf. eine Sonderbedeutung in URLs hat, muss entsprechend kodiert werden - Prozentzeichen, gefolgt von hexadezimalem Bytewert.

Ob sich .NET hier automatisch um diese Kodierung kümmert weiß ich nicht - das müsstest du in der Dokumentation nachlesen.

Hast du dir denn erst mal mit print_r angeschaut, was $_POST überhaupt alles enthält?

Mit empty prüfst du einen Wert darauf, ob er überhaupts nichts enthält.
Nichts ist nichts, in egal welcher Zeichenkodierung …

Erst einmal Danke für die Antwort, ich habe allerdings wohl mein Problem nicht richtig rüberbringen können:

Das ist klar wenn es um URL-encoded geht, ist schliesslich eine ziemlich alte Form der Codierung die alle Abweichungen vom klassischen ASCII (<128) mit % escaped.

[quote]Ob sich .NET hier automatisch um diese Kodierung kümmert weiß ich nicht - das müsstest du in der Dokumentation nachlesen.[/quote]Leider nicht so einfach, da das ja eher die Kommunikation mit dem Browser betrifft: klassisch ist hier, wie Du schon gesagt hattest, ASCII URL codiert, wobei UTF8 URL-encoded ja normalerweise wenig Sinn macht.

[quote]Hast du dir denn erst mal mit print_r angeschaut, was $_POST überhaupt alles enthält?[/quote]Klar, habe ich, genauso das $_SESSION Array, nur ist das ja auch kein Encoding Problem. Nehmen wir ein Beispiel:

if ($_POST['SID']='Query'){ irgendwas } ;

Ist jetzt der Wert von $_POST[‘SID’], der ja vom request kommt, ASCII oder UTF encoded ? Und ist ‘Query’ nicht unterschiedlich je nachdem ob ich es in einer ASCII-Datei oder einer UTF-Datei verwende ? In solche (nie erwarteten) Probleme laufe ich momentan permanent rein, und die sind a) schwierig zu finden und b) mit meiner mangelnden PHP Erfahrung noch schwieriger zu lösen. In .NET ist es einfach, da ist die Basis immer UTF, während wie ich verstanden habe PHP nur als eine Folge von Bytes aufzufassen ist. Vergleiche ich evtl (ASCII-)Äpfel mit (UTF-) Birnen …

Mit empty prüfst du einen Wert darauf, ob er überhaupts nichts enthält. Nichts ist nichts, in egal welcher Zeichenkodierung ...Stimmt, das Beispiel war wirklich schlecht gewählt.

Aber warum bekomme ich in meinem oben geposteten Code unterschiedliche Ergebnisse, wenn ich die Query im PHP Code formuliere oder die Query als $_POST Argument übernehme ?

Gibt es eine robustere Methode die Datenbank anzusprechen ?

Nein - es betrifft die Übermittlung von Daten über HTTP.

Selbstverständlich müssen auch in UTF-8 kodierte Daten URL-gerecht kodiert werden, wenn sie auf diesem Weg übertragen werden sollen.

Du hast anfangs geschrieben, du hättest ein Encoding-Problem …

[quote] if ($_POST['SID']='Query'){ irgendwas } ;
Ist jetzt der Wert von $_POST[‘SID’], der ja vom request kommt, ASCII oder UTF encoded ?[/quote]
Das kommt darauf an, in welcher Zeichenkodierung die absendende Stelle ihre Daten kodiert hat.
Sie könnte diese Information zwar noch explizit mitliefern - das passiert im Web-Umfeld (Browser) aber meistens nicht.

Der per POST übermittelte Parameterwert ist eine Folge von Bytes, mehr nicht.
Wie du ihn interpretierst, ist eine andere Frage.
Wenn du nicht weißt, in welcher Zeichnkodierung sein Inhalt zu interpretieren ist, dann bleibt dir nur noch raten.

Wenn es da noch grundsätzliche Verständnisprobleme gibt, empfehle ich diesen Artikel: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
Das ist vornehmlich auf’s Web bezogen, aber auch darüber hinaus sollte man sich über das dort gesagte im Klaren sein.

Du kannst keine Query „per POST abschicken“, zumindest nicht an die Datenbank.
Drücke dich bitte präziser aus. Ich nehme an, du meinst das Absetzen der Query an die Datenbank aus .NET heraus?

Bekommst du denn überhaupt Ergebnisse - ich dachte, du bekommst eine Fehlermeldung?

Die gezeigte Fehlermeldung sah übrigens stark danach aus, als ob schlicht und einfach die kontextgerechte Behandlung der Daten für den Kontext MySQL-Query vergessen wurde.

Wenn die fehlende kontextgerechte Behandlung der Daten wirklich das Problem war, dann solltest du dir ggf. mal prepared statements anschauen - die trennen Befehl und Daten voneinander, so dass diese (Versäumnis-)Fehlerquelle schon mal wegfällt.

Chris,
so langsam komme ich mir vor wie in einem Pinkel-Wettbewerb :unamused: Ich liege in keinem Wettstreit mit Deinem Experten-Wissen, sondern suche nach Antworten zu einem Verständnis-Problem.
Insofern lass uns mal auf die Zitate aus den jeweiligen Posts verzichten und vielleicht mal auf eine sachliche Ebene kommen.

Ich weiss was ich vom Client abschicke, einen UTF8 String. Ich weiss nicht unbedingt was der Server (APACHE) daraus macht und an PHP übergibt, wenn der Content-Header (x-www-url-encoded) und Charset (UTF8) mitgegeben werden. Normalerweise würde ich erwarten dass APACHE beim Empfang des Bytestreams eine Umwandlung vornimmt. (s. The Secret of Character Encoding).

Ich gehe also davon aus dass Du das damit meinst wenn Du von “URL-gerecht übertragen” sprichst. Falls nein erklär’s einfach …

Und wenn ich jetzt den Vergleich if ($_POST['SID']='Query'){ irgendwas } ; nehme, so weiss ich weder was APACHE aus dem linken Teil gemacht hat, noch weiss ich ob ‘Query’ jetzt vom Datei-Encoding abhängig ist. Noch mehr interessiert es mich wie ich den übergebenen Query-String sauber an die MySQL-DB übergebe.

Vielleicht kannst Du mir ja dazu Tips geben.

Ich bekomme unterschiedliche Ergebnisse wenn ich die Query direkt in PHP formuliere oder den per HTTP übermittelten Query-String an die DB übergebe:

  • PHP Query liefert korrektes Ergebnis beim Insert oben
  • http String liefert Fehlermeldung ( auch ein Ergebnis, wenn auch leider unerwünscht)

[quote]Die gezeigte Fehlermeldung sah übrigens stark danach aus, als ob schlicht und einfach die kontextgerechte Behandlung der Daten für den Kontext MySQL-Query vergessen wurde.[/quote]Durchaus möglich, dann wäre es nett wenn Du mir erklären würdest wie das aussehen würde.

Gruss

Ich weiß, dass manche Leute diese Art zu Zitieren für „böswilliges Zerpflücken“ von Beiträgen halten …
Ich halte es aber für die sinnvollste Art, in Foren/Boards zu Zitieren - so kann man ohne großen sprachlichen Aufwand Bezug zu einzelnen Aussagen herstellen, gezielte Rückfragen stellen, etc. Mit „Unsachlichkeit“ hat das nichts zu tun.
Deshalb, sei mir nicht böse, werde ich das beibehalten.

Die wesentliche Frage ist: Hast du es denn url-encoded abgeschickt, wenn du das im Content-Type-Header behauptest?

Außerdem lautet die Header-Angabe korrekt und vollständig “application/x-www-form-urlencoded”. Wenn das noch nicht der Fall ist, behebe das bitte erst mal.

PHP kümmert sich darum, die URL-Kodierung der Daten rückgängig zu machen, bevor sie dir in $_POST (oder auch $_GET/$_COOKIE) zur Verfügung gestellt werden.

FYI: Das ist kein Vergleich, sondern eine Zuweisung :wink:

Dann kontrolliere es doch mal mittels einer Testausgabe … am besten, in dem du dir die hexadezimalen Bytewerte ausgeben lässt.

Das geht bspw. ganz einfach mit so einem Schnippsel, wobei $t die Variable ist, die den übergebenen Text enthält:

for($i=0, $l=strlen($t); $i<$l; ++$i) { printf('%x ', ord($t[$i])); }

Natürlich ist es das - du hast die Datei doch in einer bestimmten Zeichenkodierung abgespeichert.
(Bzgl. ‘Query’ macht das natürlich keinen großen Unterschied, weil alle darin enthaltenen Zeichen sowohl in ASCII, einer der ISO-8859-Kodierungen als auch UTF-8 die gleichen Bytewerte haben. Aber wenn ‘Query’ nur ein Beispiel ist, und du in Wirklichkeit dort etwas stehen hast, was „Sonderzeichen“ enthält, sieht das natürlich anders aus.)

Kontextwechsel ist hier das Stichwort. Wann immer du Daten in einen anderen Kontext bringst, musst du sie nach dessen Regeln behandeln.
wiki.selfhtml.org/wiki/Artikel:Kontextwechsel

Die Alternative Prepared Statements nannte ich auch schon.

Ich weiß, dass manche Leute diese Art zu Zitieren für „böswilliges Zerpflücken“ von Beiträgen halten ... Ich halte es aber für die sinnvollste Art, in Foren/Boards zu Zitieren - so kann man ohne großen sprachlichen Aufwand Bezug zu einzelnen Aussagen herstellen, gezielte Rückfragen stellen, etc. Mit „Unsachlichkeit“ hat das nichts zu tun. Deshalb, sei mir nicht böse, werde ich das beibehalten.
Nun jeder nach seiner Facon, wenn es Dich denn glücklich macht. Allerdings vermisse ich bei Dir sowohl qualifizierte Rückfragen , die sich in den vorangegangenen Posts nicht bei etwas gutem Willen hätten beantworten lassen, als auch qualifizierte Ratschläge ( und sei es auch nur als Verweise) zu den gestellten Fragen.

Was Du bisher geboten hast, war entweder pure Semantik und/oder arrogantes Halbwissen (wenn überhaupt):

Pardon ? Wenn schon müssen Requests Webserver-gerecht codiert werden, dazu gibt es die verschiedensten Content-Types, Mime-Types,Charsets und Metatags… URL Encodierung spielt mehr und mehr nur noch eine Aussenseiterrolle (ausser bei GET).

[quote]Wenn es da noch grundsätzliche Verständnisprobleme gibt, empfehle ich diesen Artikel: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
Das ist vornehmlich auf’s Web bezogen, aber auch darüber hinaus sollte man sich über das dort gesagte im Klaren sein.[/quote] Auch wieder eine pompöse Antwort, die mit der gestellten Frage nicht zu tun hat. Ausserdem kenne (und schätze) ich diesen Artikel schon sehr lange …

[quote]Du kannst keine Query „per POST abschicken“, zumindest nicht an die Datenbank.
Drücke dich bitte präziser aus. Ich nehme an, du meinst das Absetzen der Query an die Datenbank aus .NET heraus?[/quote]

Beides wurde im Eingangspost beschrieben und erklärt. Da Du dieses Wort anscheinend so liebst empfehle ich auch Dir für die Zukunft solche Posts vielleicht präziser zu lesen.

So, das musste jetzt einfach mal raus, auc wenn es natürlich nichts ändert.

Das Problem ist mittlerweile glücklicherweise gelöst, auch wenn es mit ein paar Hinweisen vermutlich schneller gegangen wäre:

  • POST Requests vom Client können durchaus mit verschiedenen Content-Types (text/html , www-url-encoded,…) abgesetzt werden. Allerdings werden die Key/Value Paare nur beim Content-Type(www-URL-encoded) im Array $_POST gespeichert , ansonsten landen sie im Array $HTTP_RAW_POST_DATA.
  • nur die charset Angabe ist entscheidend (UTF, ASCII, iso-8859-1) bei der Stream Codierung, URL codiert wird bei Post-Daten nichts (kann man im Sniffer nachvollziehen)
  • Datenbank Interface wird die Verbindung mit mysql_set_charset(‘utf8’,$db); auf UTF-8 festgelegt.

Tja , und die Unterschiede zwischen meiner im PHP Code definierten Query und der per POST übermittelten ergab sich aus den Magic Quotes (Escape Slashes), die PHP freundlicherweise meinen Argumenten hinzugefügt hatte. Nachdem diese mit stripslahes entfernt wurden, liefen die gesendeten Queries auch sauber durch und lieferten korrekte Rückgabewerte.

… and thx

"Wissen macht souverän, Halbwissen nur arrogant "

Wieder mal typisch … Problem mit viel Herumraterei irgendwie gelöst - also Zeit, große Töne zu spucken.

Pardon ? Wenn schon müssen Requests Webserver-gerecht codiert werden, dazu gibt es die verschiedensten Content-Types, Mime-Types,Charsets und Metatags… URL Encodierung spielt mehr und mehr nur noch eine Aussenseiterrolle (ausser bei GET).[/quote]
Von Content-Types oder URL-Encoding habe ich an dieser Stelle gar nicht gesprochen, sondern von der verwendeten Zeichenkodierung.
Mache dir den Unterschied bitte klar - er ist wichtig.

Was meinst du wohl, warum es “application/x-www-form-urlencoded” heißt …?

http://en.wikipedia.org/wiki/POST_(HTTP)#Use_for_submitting_web_forms:

Ohne URL-Kodierung könntest du auf diese Weise gar kein & als Bestandteil der Daten übertragen, weil es den Parameterwert beenden und den Beginn des nächsten Parameternamens einleiten würde.

Gut, dass du dein Verhalten hier wenigstens realistisch einschätzen kannst.