CGI/URL mit split in Parameter zerlegen

CGI/URL mit split in Parameter zerlegen

am 11.01.2007 15:13:01 von Helmut Wollmersdorfer

Ich möchte einen String der Form 'key1=value1&key2=value2&key3=value3'
sauber und einfach zerlegen, wobei der Delimiter '&' in value vorkommen
kann. Sonst wäre es mit 'split(/&/,$string)' einfach.

Diese Regex funktioniert einigermassen

print join("\n", split(/&([^&=]+=[^=]+(?=&))/,
'For=foo5&Query=Foo & Bar GmbH&Str=*&Db=*'));
print "\n";

jedoch gibt es dann ein leeres Element im Output

For=foo5
Query=Foo & Bar GmbH

Str=*
&Db=*

und ein '&' als Überbleibsel.

Wo hab ich da meine Denkfehler?

Helmut Wollmersdorfer

Re: CGI/URL mit split in Parameter zerlegen

am 11.01.2007 15:21:15 von Frank Seitz

Helmut Wollmersdorfer wrote:
>
> Wo hab ich da meine Denkfehler?

Deine URLs sind nicht sauber encoded.
Eingebettete Zeichen wie & und = sollten als %26
und %3D repräsentiert sein.

Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Re: CGI/URL mit split in Parameter zerlegen

am 11.01.2007 17:19:42 von ReneeB

Warum nicht die Vars()-Methode von CGI.pm nehmen?

Re: CGI/URL mit split in Parameter zerlegen

am 11.01.2007 18:06:32 von Helmut Wollmersdorfer

Frank Seitz wrote:

> Deine URLs sind nicht sauber encoded.

So kommen sie nun mal daher.
Und das war eigentlich nicht meine Frage.

> Eingebettete Zeichen wie & und = sollten als %26
> und %3D repräsentiert sein.

Ok, wenn wir schon Off Topic sind:
Im von mir erzeugten HTML sind sie sauber encoded,
z.B. als



Das schicke ich dann im Apache 2.2 mittels

RewriteRule ^([^/]*)$
/cgi-bin/Dict?Form=Dict2&Database=*&Query=$1

an mein CGI.

Dort lese ich es mit

$in = $ENV{'QUERY_STRING'};

und da sind die '&' bereits decoded:

Form=Dict2&Database=*&Query=Green & Gold Tanager

Im access.log steht brav drinnen

"GET /Green%20%26%20gold%20tanager HTTP/1.1"

Helmut Wollmersdorfer

Re: CGI/URL mit split in Parameter zerlegen

am 11.01.2007 18:12:15 von Frank Seitz

Helmut Wollmersdorfer wrote:
> Frank Seitz wrote:
>>
>>Deine URLs sind nicht sauber encoded.
>
> So kommen sie nun mal daher.

Das ist schlecht.

> Und das war eigentlich nicht meine Frage.

Weiß ich, aber dann kann ich nur sagen:
Die Aufgabe nicht allgemeingültig lösbar.

> Dort lese ich es mit
>
> $in = $ENV{'QUERY_STRING'};
>
> und da sind die '&' bereits decoded:

Das darf und sollte IMO nicht so sein.
Irgendwo ist da ein Bug.

Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Re: CGI/URL mit split in Parameter zerlegen

am 11.01.2007 18:35:35 von Helmut Wollmersdorfer

ReneeB wrote:
> Warum nicht die Vars()-Methode von CGI.pm nehmen?

Weil die das nicht kann.

Helmut Wollmersdorfer

Re: CGI/URL mit split in Parameter zerlegen

am 11.01.2007 18:42:13 von Helmut Wollmersdorfer

Frank Seitz wrote:
> Helmut Wollmersdorfer wrote:

>> Dort lese ich es mit
>>
>> $in = $ENV{'QUERY_STRING'};
>>
>> und da sind die '&' bereits decoded:

> Das darf und sollte IMO nicht so sein.
> Irgendwo ist da ein Bug.

Jedenfalls nicht in meinem CGI.

Wenn ich die ReWrite Rule nicht triggere, dann kommt es brav encoded an.

Werd mal weiter Apache Doku lesen.

Helmut Wollmersdorfer

Re: CGI/URL mit split in Parameter zerlegen

am 11.01.2007 18:44:30 von Bjoern Hoehrmann

* Helmut Wollmersdorfer wrote in de.comp.lang.perl.misc:
>Das schicke ich dann im Apache 2.2 mittels
>
> RewriteRule ^([^/]*)$
> /cgi-bin/Dict?Form=Dict2&Database=*&Query=$1
>
>an mein CGI.
>
>Dort lese ich es mit
>
> $in = $ENV{'QUERY_STRING'};
>
>und da sind die '&' bereits decoded:

Dann machst entweder du oder mod_rewrite was falsch. Es gibt diverse
Methoden das Maskieren bei mod_rewrite zu kontrollieren, u.a. die
Option NE und die RewriteMap int:escape. Du solltest das Problem an
der Stelle lösen, ansonsten gibt es hier keine allgemeine Lösung, du
müsstest sie schon auf deinen Spezialfall ausrichten, wenn das über-
haupt möglich ist.
--
Björn Höhrmann · mailto:bjoern@hoehrmann.de · http://bjoern.hoehrmann.de
Weinh. Str. 22 · Telefon: +49(0)621/4309674 · http://www.bjoernsworld.de
68309 Mannheim · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

Re: CGI/URL mit split in Parameter zerlegen

am 11.01.2007 21:03:36 von Helmut Wollmersdorfer

Bjoern Hoehrmann wrote:
> * Helmut Wollmersdorfer wrote in de.comp.lang.perl.misc:

>> $in = $ENV{'QUERY_STRING'};
>>
>> und da sind die '&' bereits decoded:

> Dann machst entweder du oder mod_rewrite was falsch. Es gibt diverse
> Methoden das Maskieren bei mod_rewrite zu kontrollieren, u.a. die
> Option NE und die RewriteMap int:escape.

Danke für den Hinweis.
Mit int:escape bekomme ich jetzt zwar die Blanks encoded, aber nicht die '&'

Green%20&%20Gold%20Tanager
^

NE oder nicht hat darauf keinen Einfluss.

> Du solltest das Problem an
> der Stelle lösen, ansonsten gibt es hier keine allgemeine Lösung, du
> müsstest sie schon auf deinen Spezialfall ausrichten, wenn das über-
> haupt möglich ist.

Also ich sehe das nicht als Spezialfall, sondern offensichtlich(?) als
Spezifikations- oder Implementierungsfehler von mod_rewrite. Zumindest
ist es sehr schlecht dokumentiert, wenn es irgendwie funktionieren könnte.

Helmut Wollmersdorfer

Workaround für "&" im Suchstring (was: CGI/URL mit split in Parameter zerlegen)

am 12.01.2007 15:25:06 von Helmut Wollmersdorfer

Helmut Wollmersdorfer wrote:

> Das schicke ich dann im Apache 2.2 mittels

> RewriteRule ^([^/]*)$
> /cgi-bin/Dict?Form=Dict2&Database=*&Query=$1

> an mein CGI.
[...]
> und da sind die '&' bereits decoded:

Nachdem das Problem mit diversen Optionen von mod_rewrite nicht lösbar
war, war dann folgendes mein 'dirty hack':

$in = $ENV{'QUERY_STRING'};
$SCRIPT_URL = '';
$SCRIPT_URL = $ENV{'SCRIPT_URL'} if $ENV{'SCRIPT_URL'};
$SCRIPT_URL =~ s|^/||;
$in =~
s|^(.*Query=)($SCRIPT_URL)(.*)$|$1.uri_escape(uri_unescape($ 2)).$3|se;

Was auf der Testmaschine (Debian/Sid) funktionierte, aber dann auf der
Produktionsmaschine nicht (Etch).

Deshalb ein noch schlimmerer Hack, der stabil funktioniert:

$in = $ENV{'QUERY_STRING'};
$in =~ s|^(.*Query=)([^=]*)$|$1.uri_escape(uri_unescape($2))|se;

Ab da kann man die Parameter sauber zerlegen, entweder mit split oder
CGI.pm.

Helmut Wollmersdorfer