CGI/URL mit split in Parameter zerlegen

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
Helmut Wollmersdorfer [ Do, 11 Januar 2007 15:13 ] [ ID #1592692 ]

Re: CGI/URL mit split in Parameter zerlegen

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
Frank Seitz [ Do, 11 Januar 2007 15:21 ] [ ID #1592693 ]

Re: CGI/URL mit split in Parameter zerlegen

Warum nicht die Vars()-Methode von CGI.pm nehmen?
ReneeB [ Do, 11 Januar 2007 17:19 ] [ ID #1592699 ]

Re: CGI/URL mit split in Parameter zerlegen

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

Green & Gold Tanager

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
Helmut Wollmersdorfer [ Do, 11 Januar 2007 18:06 ] [ ID #1592701 ]

Re: CGI/URL mit split in Parameter zerlegen

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
Frank Seitz [ Do, 11 Januar 2007 18:12 ] [ ID #1592702 ]

Re: CGI/URL mit split in Parameter zerlegen

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

Weil die das nicht kann.

Helmut Wollmersdorfer
Helmut Wollmersdorfer [ Do, 11 Januar 2007 18:35 ] [ ID #1592704 ]

Re: CGI/URL mit split in Parameter zerlegen

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
Helmut Wollmersdorfer [ Do, 11 Januar 2007 18:42 ] [ ID #1592706 ]

Re: CGI/URL mit split in Parameter zerlegen

* 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 [at] 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/
Bjoern Hoehrmann [ Do, 11 Januar 2007 18:44 ] [ ID #1592707 ]

Re: CGI/URL mit split in Parameter zerlegen

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
Helmut Wollmersdorfer [ Do, 11 Januar 2007 21:03 ] [ ID #1592709 ]

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

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
Helmut Wollmersdorfer [ Fr, 12 Januar 2007 15:25 ] [ ID #1593857 ]
Perl » de.comp.lang.perl.misc » CGI/URL mit split in Parameter zerlegen

Vorheriges Thema: Verzeichnisbaum ohne Dateien auslesen
Nächstes Thema: lange Listen vergleichen - Performancefrage