cgi-Datenfluß
HP-User
- perl
Abend zusammen,
Ein paar kleine Fragen...
Wenn ich Daten von meiner Webseite via cgi mit einem Script entgegen nehmen möchte, so mach ich das normalerweise so:
my $name = CGI::param('name');
Der Skalar "$name" bekommt die Daten vom Html-Inputfeld mit dem Namen "name" zugespielt. Soweit klar.
1. Besondenderheit: Ich hab auf der Html-Seite ein "textarea"-Feld mit dem Namen "xyz". Werden die Eingaben von Textarea genauso wie die Inputdaten mit Perl eingesammelt?
Also:
my $xyz = CGI::param('xyz');
Oder geht das nicht?
----------------------------------------------------------
2. Besonderheit: Ein Checkboxfeld mit Value "on":
<input class="input_style" type="checkbox" name="tbgelesen" value="on">
Ergibt bei:
my $tbgelesen = CGI::param('tbgelesen');
Ein Skalarwert von "on".
Wenn jetzt kein haken gesetzt ist, wird ja nicht off übermittelt, sondern wahrscheinlich "" (nichts). Die Perlabfrage ob "tbgelesen" angeklickt wurde kann ja auch nur auf das "on" bezogen werden.
Quasi:
if($tbgelesen eq "on") {mach was in den Klammern steht / goto Sprungmarke};
goto Fehlerhaken;
Naja, daß mit dem Textarea hatte ich noch nie, deswegen die Frage, bevor ich am Wochenende loslege.
Gruß
HP-User
ein "textarea"-Feld mit dem Namen "xyz". Werden die Eingaben von Textarea genauso wie die Inputdaten mit Perl eingesammelt? […] Oder geht das nicht?
Kurze Antwort: ja, es funktioniert so, wie es du dir vorstellst. Warum hast du das nicht einfach probiert? Durch 10 Stunden warten auf eine Antwort hast du dir 10 Minuten experimentieren gespart.
Lange Antwort: es liegt hier ein Verständnisproblem vor. Das CGI-Programm kümmert nicht, wie das HTML aussieht. Das CGI-Programm weiß gar nichts über den Empfang von Formularen per se! Es nimmt bloß eine schon vom Server etwas aufbereitete HTTP-Anfrage entgegen, im wesentlichen z.B. so:
GET /foo.pl?tbgelesen=on&xyz=foobar HTTP/1.1
Hier sind gar keine verschiedenen Typen von Formularelementen sichtbar, bloß Schlüssel-Wert-Paare. Die API, so z.B. die Funktion param, schnippelt sich das benötigte heraus. So eine Anfrage kann auf vielfältige Weise erstellt werden; HTML-Formulare sind im Web eher in der Minderheit.
<input class="input_style" type="checkbox" name="tbgelesen" value="on">
Das ist unüblich, sogar seltsam für mein Empfinden. Stattdessen setzt man das Attribut checked.
Wenn jetzt kein haken gesetzt ist, wird ja nicht off übermittelt, sondern wahrscheinlich "" (nichts).
Das ist nicht richtig. Der Schlüssel wird gar nicht übermittelt.
GET /foo.pl?xyz=foobar HTTP/1.1
Die Perlabfrage ob "tbgelesen" angeklickt wurde kann ja auch nur auf das "on" bezogen werden.
Das ist nicht richtig. Du sollst Checkboxen einfach im Boolkontext auswerten.
<form action="http://localhost:5000/foo.pl">
<input type="checkbox" name="tbgelesen" checked>
<textarea name="xyz">foobar</textarea>
<input type="submit">
</form>
#!/usr/bin/env perl
use 5.014;
use CGI qw();
use Data::Dumper qw(Dumper);
my $c = CGI->new;
STDOUT->print(
$c->header('text/plain'),
Dumper($c),
'Das Feld mit dem Namen xyz hat den Inhalt '
$c->param('xyz'),
' und das Feld mit dem Namen tbgelesen '
$c->param('tbgelesen')
? 'existiert/ist wahr/selektiert.'
: 'existiert nicht/ist falsch/nicht selektiert.'
);
# alternativ:
# if ($c->param('tbgelesen')) {
# # an
# } else {
# # aus
# }
Hi,
<input class="input_style" type="checkbox" name="tbgelesen" value="on">
Das ist unüblich, sogar seltsam für mein Empfinden. Stattdessen setzt man das Attribut checked.
Dein Empfinden ist wirklich seltsam.
checked und value sind doch zwei volllllkommmmmen verschiedene Dinge.
checked regelt, ob die Checkbox angehakt ist.
Der value legt fest, was übertragen wird, falls die Checkbox angehakt ist.
cu,
Andreas
Du hast Recht. Ich habe mich davon verwirren lassen, dass "on" der Standardwert ist, wenn das value-Attribut wegbleibt.
Hi,
Du hast Recht. Ich habe mich davon verwirren lassen, dass "on" der Standardwert ist, wenn das value-Attribut wegbleibt.
Was aber bei type="checkbox" gar nicht sein darf (Laut HTML 4.01):
value = cdata [CA]
This attribute specifies the initial value of the control. It is optional except when the type attribute has the value "radio" or "checkbox".
cu,
Andreas
Hi zusammen,
Kurze Antwort: ja, es funktioniert so, wie es du dir vorstellst. Warum hast du das nicht einfach probiert? Durch 10 Stunden warten auf eine Antwort hast du dir 10 Minuten experimentieren gespart.
Keine Angst, ich hab nicht 10 h gewartet. Hab ja auch noch andere Dinge zu tun (Arbeit, Family, Haushalt, Hausmeister, uvm...)
Ich will eben am Wochenende mit dem vorletzen Programm anfangen ...
Gruß HP-User
...short from work
hi,
Ein paar kleine Fragen...
Hier eine Antwort auf eine Frage, die Du nicht gestellt hast:
Was passiert mit mehreren Checkboxen, die alle den gleichen Namen haben?
<input type="checkbox" name="jack" value="Otto">
<input type="checkbox" name="jack" value="Heinz" checked>
<input type="checkbox" name="jack" value="Horst" checked>
<input type="checkbox" name="jack" value="Ulli">
A; Für die Checkboxen, die "checked" sind, bekommst Du eine Liste mit den Values:
my @names = CGI::param('jack'); # Heinz, Horst in @names
Wenn keine der Boxen ge-checkt wurde, ist die Liste leer. Und was sagt uns das? CGI::param kann Listen-Kontext ;)
Das gilt übrigens nicht nur für Checkboxen. Manchmal bietet es sich an, auch mehrere <input type="text"> Felder mit gleichem Namen einzusetzen.
Horst Valü
Hi hotti
Wenn keine der Boxen ge-checkt wurde, ist die Liste leer. Und was sagt uns das? CGI::param kann Listen-Kontext ;)
Hehe, so hab ich das noch nie gesehen *g*
Mal was anderes:
Wenn ich viiieeele Zeichen übergeben will (sagen wir mal so max 4000 Stück), und diese auch noch in einem teaxtarea stecken möchte, packt das das cgi noch in einer akzeptablen Zeit?
Und wenn wir gerade bei Perl sind: wie würdest du sowas in einer Datei speichern? Ich dachte an eine CSV-Datei. Allerdings würde die warscheinlich bei 4000 Zeichen zum manuell auslesen etwas - na sagen wir - unübersichtlich werden?
Gruß
hi,
Mal was anderes:
Wenn ich viiieeele Zeichen übergeben will (sagen wir mal so max 4000 Stück), und diese auch noch in einem teaxtarea stecken möchte, packt das das cgi noch in einer akzeptablen Zeit?
4 kB rund, das ist nicht viel, sieht nur viel aus.
Und wenn wir gerade bei Perl sind: wie würdest du sowas in einer Datei speichern? Ich dachte an eine CSV-Datei.
MySQL oder Binärdateien. Guck Dir mal das Modul Storable an und Beispiele von Algorithmen, die binär serialisieren (findest Du auf meiner Seite)
Mit Perl können sehr große Datenmengen über den RAM abgewickelt werden, ich habe Scripts entwickelt, die lesen 300 MB XML-Dateien locker auf eine einzige Datenstruktur (Hashreferenz). Dieselbe Menge aus einer Binärdatei geht natürlich viel schneller, weil nicht geparst werden muss.
Was das Web betrifft: Eine DB Verbindung _herstellen, also der Connect kostet die meiste Zeit, was einen reinen CGI-Betrieb ausbremst. Alternativen sind FastCGI und mod_perl.
Meine Website (CGI) nimmt das URL-Map aus einer Binary, schneller gehts nicht. MySQL wird nur bei Bedarf verbunden, z.B. für die Perlbase. Kannst ja mal ein bischen klicken ;)
Hotti
hi again,
Mit Perl können sehr große Datenmengen über den RAM abgewickelt werden, ich habe Scripts entwickelt, die lesen 300 MB XML-Dateien locker auf eine einzige Datenstruktur (Hashreferenz). Dieselbe Menge aus einer Binärdatei geht natürlich viel schneller, weil nicht geparst werden muss.
Beispiel:
Nutzdaten 50 MB
in XML verpackt als Datei: 300 MB, mit Perl in 50s geparst und auf einen Hash gelesen.
in einer Binärdatei gespeichert: je nach Struktur ca 70 MB. Das ist 50..100mal schneller auf einen Hash gelesen, in 1..2 Sekunden.
Alternative zu einer CSV-Datei: Recordfile
Hotti
Hallo zusammen
4 kB rund, das ist nicht viel, sieht nur viel aus.
Wieviel sind 4kB in Zeichen? Reichts für 4000 Stück?
MySQL oder Binärdateien. Guck Dir mal das Modul Storable an und Beispiele von Algorithmen, die binär serialisieren (findest Du auf meiner Seite)
MySQL bin ich noch am Anfang - ganz am Anfang! Reicht noch nocht für ein sicheres Projekt. Ich hab bisher alles in CSV gemacht - vom Gästebuch über Ersatzteilprogramme und sonstiges. Aber ich werde das lernen - früher oder später *g*
Was das Web betrifft: Eine DB Verbindung _herstellen, also der Connect kostet die meiste Zeit, was einen reinen CGI-Betrieb ausbremst. Alternativen sind FastCGI und mod_perl.
Fast-cgi hab ich schon mal gehört. mod_Perl sagt mir nichts.
Meine Website (CGI) nimmt das URL-Map aus einer Binary, schneller gehts nicht. MySQL wird nur bei Bedarf verbunden, z.B. für die Perlbase. Kannst ja mal ein bischen klicken ;)
Excuse me - ich war so frei, deine Seite zu "bookmarken". Man weis ja nie was man noch gebrauchen könnte *g*
Jetzt zum eigentlichen Geschehen:
Ich bastel gerade an einem Formular, das soweit ich das seh, clientseitig fertig ist. Link ist hier.
Die Felder Story-Code, Titel, E-Mail und Spamschutz sind kein Problem. Ich bin nur unsicher, ob der eigentliche, lange Geschichtstext (max 4000 Zeichen), über cgi geht, oder nicht.
Gruß HP-User
hi,
Wieviel sind 4kB in Zeichen? Reichts für 4000 Stück?
Das hängt von der Kodierung ab. Bei einer 8-bit-Kodierung ist ein Zeichen == 1 Byte.
Du kriegst Deinen Input in UTF-8. Da gibt es Zeichen, die haben mehr als ein Byte, ein Umlaut hat 2 byte, das Eurozeichen hat 3 byte.
... Ich hab bisher alles in CSV gemacht - vom Gästebuch über Ersatzteilprogramme und sonstiges.
Wenn die Datei editierbar sein soll, darf es auch eine CSV-Datei sein.
Jetzt zum eigentlichen Geschehen:
Ich bastel gerade an einem Formular, das soweit ich das seh, clientseitig fertig ist. Link ist hier.
Sieht doch gut aus. Und UTF-8, auch gut!
Die Felder Story-Code, Titel, E-Mail und Spamschutz sind kein Problem. Ich bin nur unsicher, ob der eigentliche, lange Geschichtstext (max 4000 Zeichen), über cgi geht, oder nicht.
Natürlich geht das. Selbst wenn das alles 'ä's sind, sind das nur 8 kb ;)
Wenn Du utf-8 auch in der DB haben möchtest, gibt es Einiges zu beachten. Das Modul CGI kann ab einer bestimmten Version (muss nachgucken) die Eingaben als UTF-8-Strings liefern. Im Default kriegst Du natürlich auch UTF-8 aber als Oktetten (bytes).
Dann hängts von der DBD::mysql Version ab, ob Dein Perl-Script als DB-Client mit MySQL utf-8 reden kann.
Wenn das Alles nicht möglich ist, speichere einfach die Eingaben als Oktetten in Tabellen, die mit charset latin1 getagged sind. Umtaggen kannst Du auch später (alter table...).
Kriegste das hin?
Viele Grüße,
Hotti
Hi hotti
Das hängt von der Kodierung ab. Bei einer 8-bit-Kodierung ist ein Zeichen == 1 Byte.
Und utf-8 bedeutet doch 4000 Zeichen = 4000 Byte = 4kb - was nach deinem vorherigen Post bereits die Grenze darstellt?
Du kriegst Deinen Input in UTF-8. Da gibt es Zeichen, die haben mehr als ein Byte, ein Umlaut hat 2 byte, das Eurozeichen hat 3 byte.
Umlaute: Wenn alles Umlaute wären, wäre ich bei 8kb. Das ist doppelt so viel wie elaubt?
Wenn die Datei editierbar sein soll, darf es auch eine CSV-Datei sein.
Genau!
Sieht doch gut aus. Und UTF-8, auch gut!
Prima!
Die Felder Story-Code, Titel, E-Mail und Spamschutz sind kein Problem. Ich bin nur unsicher, ob der eigentliche, lange Geschichtstext (max 4000 Zeichen), über cgi geht, oder nicht.
Siehe oben: 4000 Zeichen für die Geschichte und dann hat es kein Platz mehr für den Storycode (6 Zeichen), Titel (max 40 Zeichen), E-Mail (max 40 Zeichen), Spamschutz (8 Zeichen), Checkbox (2 Zeichen "on"). Ergibt grob:
4096 Zeichen. Und das nur Input/Textarea. Wenn bei dieser Rechnung der Feldname auch mitgezählt wird, sieht es noch übler aus.
Laut Internet Recherche:
-Einige sagen Get ist begrenzt, weil eine URL nicht unendlich sein kann.
-Ein anderer behauptet alte Browser können max 255 Zeichen übertragen.
-Noch ein anderer sagt es sind 2048 Zeichen.
-Weitere Meinungen setzten Werte je nach Serverfähigkeit von 255,1024 und 2048 Zeichen.
Dann wird noch empfohlen, bei größeren Datenmengen lieber Post statt get zu verwenden. Was soll man von all diesen Infos halten, bzw. was stimmt jetzt???
Hier die Quelle, die diese Infos bereitstellt:chip-forum
Dann hängts von der DBD::mysql Version ab, ob Dein Perl-Script als DB-Client mit MySQL utf-8 reden kann.
Ich mach nichts mit DBD::mysql - wie gesagt tehe noch am Anfang. Ich mach noch den ganzen lese und Schreibverkehr zum File per "Hand" mit hilfe von mit
use Fcntl ':flock'; und open usw...
Kriegste das hin?
Wenn ich weis, wieviel ich meiner cgi an Zeichen zumuten kann, bestimmt ;-)
Gruß HP-User
hi,
-Einige sagen Get ist begrenzt, weil eine URL nicht unendlich sein kann.
-Ein anderer behauptet alte Browser können max 255 Zeichen übertragen.
-Noch ein anderer sagt es sind 2048 Zeichen.
-Weitere Meinungen setzten Werte je nach Serverfähigkeit von 255,1024 und 2048 Zeichen.
Das kann schon sein, ist aber letztendlich kein Thema.
Dann wird noch empfohlen, bei größeren Datenmengen lieber Post statt get zu verwenden. Was soll man von all diesen Infos halten, bzw. was stimmt jetzt???
Die Empfehlung hat einen anderen Grund: Bei GET liegen die Daten im URI als sog. Query_String. Das landet bei jedem Proxy und zuletzt beim Webserver in der Logdatei ;)
Deswegen: Post. Da wird nur der Locator geloggt. Die Datenmenge ist jedoch dieselbe wie bei GET, wenn bei einem POST encode="application/x-www-form-urlencoded", das ist der Default, benutzt wird. Da wird aus einem 'ä' => %C3%A4 (sog. Percent-Encoding). Kurzum: Was bei einem POST gesendet wird, sieht mit o.g. encode="application/x-www-form-urlencoded" genauso aus wie ein QUERY_STRING. Aus den 2 Bytes eines UTF-8-'ä's werden nunmehr 6 Bytes und der Euro ist noch teurer ;)
Kleinere Datenmengen bekommst Du mit encode="multipart/form-data", da werden die Roh-Bytes gesendet, allerdings kommt dann zwischen den einzelnen Parts noch die Boundary (Textstring und Leerzeilen) dazwischen.
Kurzum: Begrenze die Eingabe mit Javascript (das ist zeichenorientiert) und mach Dir keine Sorgen wegen der Datenmenge, die brutto übertragen wird, die dürfte geschätzterweise stets doppelt bis dreimal so groß sein, es kommen ja auch noch die Header hinzu für den Request.
Serverseitig gibts fürs CGI-Modul noch
$CGI::POST_MAX=1024 * 100; # max 100K posts
zum Vermeiden kleinerer Denial of Service attacks. Und da haben wir noch einen Grund, die method="POST" zu verwenden: POST::MAX kannst Du selbst festlegen.
Ein QUERY_STRING (GET) hat sicher auch eine max. Länge aber es wäre jetzt müßig die einschlägigen RFCs zu wälzen und das rauszusuchen.
Viele Grüße!
Hi hotti
Die Empfehlung hat einen anderen Grund: Bei GET liegen die Daten im URI als sog. Query_String. Das landet bei jedem Proxy und zuletzt beim Webserver in der Logdatei ;)
Aha, das wusste ich nicht. Da sind ja dann alle versendeten Parameter gleich mit gespeichert. Das wäre schlecht, da entsprechende Programme aus der Logdatei (Proxy) die E-Mail des Geschichteneinreichers auslesen könnten. Und dann bekäme dieser Spampost. Danke für den Hinweis zu get!
Also mal Butter bei die Fische...
Html würde aus:
<form id="eingabe_formular" name="selfautor" onsubmit="return chkselfautor()" action="http://www.einschlafzeit.de/cgi-bin/perlprogramm.pl" method="get">
Die Post Version:
<form id="eingabe_formular" name="selfautor" onsubmit="return chkselfautor()" action="http://www.einschlafzeit.de/cgi-bin/self-creator.pl" method="post">
Und Serverseitig:
my $benutzergeschichte = CGI::param('benutzergeschichte');
Was ich damit sagen will ist, ob die Wertübergabe in Perl genauso serfolgt, wie bei get, oder muss ich da was speziell abändern, weil jetzt post verwendet wird?
Gruß HP-User
hi,
Was ich damit sagen will ist, ob die Wertübergabe in Perl genauso serfolgt, wie bei get, oder muss ich da was speziell abändern, weil jetzt post verwendet wird?
Das ist ja das Schöne an CGI.pm:
$valü = param('name'); # egal ob POST oder GET ;)
Schönes Wochenende,
Hotti
Hi hotti
Post funktioniert. Bei der Länge der zu übertragene Daten gibt es aber noch starke Schwankungen. Siehe meine Testseite.
Hier die Serverseite (kleiner Auszug):
########################
# Parameter einsammeln #
########################
my $customstorycode = CGI::param('customstorycode');
my $headline = CGI::param('headline');
my $benutzergeschichte = CGI::param('benutzergeschichte');
my $zaehler = CGI::param('zaehler');
my $internetpost = CGI::param('internetpost');
my $tbgelesen = CGI::param('tbgelesen');
my $spamschutz = CGI::param('spamschutz');
###########################################
# Evil-Input-Filter (EIF) / Längenbezogen #
###########################################
my $size = length($customstorycode);
if($size != 6){
goto StoryCodeUmfangError;
}
my $size = length($headline);
if($size > 41){
goto TitelUmfangError;
}
my $size = length($benutzergeschichte);
if($size > 4001){
goto TextUmfangError;
}
my $size = length($zaehler);
if($size > 4){
goto AnzeigeUmfangError;
}
my $size = length($internetpost);
if($size > 41){
goto EmailUmfangError;
}
my $size = length($tbgelesen);
if($size > 2){
goto TBUmfangError;
}
my $size = length($spamschutz);
if($size != 8){
goto SpamUmfangError;
}
############################################
# Evil-Input-Filter (EIF) / Zeichenbezogen #
############################################
$customstorycode =~ s/;//g;
$customstorycode =~ s/<//g;
$customstorycode =~ s/>//g;
$customstorycode =~ s/\*//g;
$customstorycode =~ s/|//g;
$customstorycode =~ s/\[//g;
$customstorycode =~ s/\]//g;
$customstorycode =~ s/{//g;
$customstorycode =~ s/}//g;
$customstorycode =~ s/@//g;
$customstorycode =~ s/&//g;
$customstorycode =~ s/\\//g;
$headline =~ s/;//g;
$headline =~ s/<//g;
$headline =~ s/>//g;
$headline =~ s/\*//g;
$headline =~ s/|//g;
$headline =~ s/\[//g;
$headline =~ s/\]//g;
$headline =~ s/{//g;
$headline =~ s/}//g;
$headline =~ s/@//g;
$headline =~ s/&//g;
$headline =~ s/\\//g;
$benutzergeschichte =~ s/;//g;
$benutzergeschichte =~ s/<//g;
$benutzergeschichte =~ s/>//g;
$benutzergeschichte =~ s/\*//g;
$benutzergeschichte =~ s/|//g;
$benutzergeschichte =~ s/\[//g;
$benutzergeschichte =~ s/\]//g;
$benutzergeschichte =~ s/{//g;
$benutzergeschichte =~ s/}//g;
$benutzergeschichte =~ s/@//g;
$benutzergeschichte =~ s/&//g;
$benutzergeschichte =~ s/\\//g;
$zaehler =~ s/;//g;
$zaehler =~ s/<//g;
$zaehler =~ s/>//g;
$zaehler =~ s/\*//g;
$zaehler =~ s/|//g;
$zaehler =~ s/\[//g;
$zaehler =~ s/\]//g;
$zaehler =~ s/{//g;
$zaehler =~ s/}//g;
$zaehler =~ s/@//g;
$zaehler =~ s/&//g;
$zaehler =~ s/\\//g;
$internetpost =~ s/;//g;
$internetpost =~ s/<//g;
$internetpost =~ s/>//g;
$internetpost =~ s/\*//g;
$internetpost =~ s/|//g;
$internetpost =~ s/\[//g;
$internetpost =~ s/\]//g;
$internetpost =~ s/{//g;
$internetpost =~ s/}//g;
$internetpost =~ s/&//g;
$internetpost =~ s/\\//g;
$tbgelesen =~ s/;//g;
$tbgelesen =~ s/<//g;
$tbgelesen =~ s/>//g;
$tbgelesen =~ s/\*//g;
$tbgelesen =~ s/|//g;
$tbgelesen =~ s/\[//g;
$tbgelesen =~ s/\]//g;
$tbgelesen =~ s/{//g;
$tbgelesen =~ s/}//g;
$tbgelesen =~ s/@//g;
$tbgelesen =~ s/&//g;
$tbgelesen =~ s/\\//g;
$spamschutz =~ s/;//g;
$spamschutz =~ s/<//g;
$spamschutz =~ s/>//g;
$spamschutz =~ s/\*//g;
$spamschutz =~ s/|//g;
$spamschutz =~ s/\[//g;
$spamschutz =~ s/\]//g;
$spamschutz =~ s/{//g;
$spamschutz =~ s/}//g;
$spamschutz =~ s/@//g;
$spamschutz =~ s/&//g;
$spamschutz =~ s/\\//g;
###############################################
# Cleanup-Input-Filter (CIF) / Umbruchbezogen #
###############################################
chomp($customstorycode);
chomp($headline);
chomp($benutzergeschichte);
chomp($zaehler);
chomp($internetpost);
chomp($tbgelesen);
chomp($spamschutz);
####################
# HTML-Textausgabe #
####################
Wenn ich nur "normale Buchstaben verwende, komme ich so auf ca 3959 Zeichen. Wenn ich nur "Umlaute" verwende (ä,ö,ü), reichte es für ca. 2200 Zeichen. Das Post- und Get-System kommt hier an seine Grenzen. Vielleicht muss ich da auf E-Mail-Verkehr umstellen. Oder alternativ dem Schreiber ein Fileupload anbieten?
Hast du hotti oder die anderen Leser noch eine Idee, wie man 4000 Zeichen durch die Internetleitung knüppelt?
So Schluß für heute. Morgen ist auch noch ein Tag!
Gruß HP-User
Ach Ja,
Wer die Werte Testen möchte:
Bei Storycode bsp. "KG123J" eingeben.
Titel= egal (40 Zeichen).
Text egal.
Teinahmebedingungen abhaken
E-Mail egal, muss "@" und "." enthalten.
Spamschutz irgend eine 8-stellige Zahl eingeben.
Gruß HP-User
moin,
Hast du hotti oder die anderen Leser noch eine Idee, wie man 4000 Zeichen durch die Internetleitung knüppelt?
Wie ich schon schrieb: Mit der _Datenmenge an sich_ sehe ich kein Problem.
Dein Problem sehe ich woanders: Das _Ermitteln der Zeichenanzahl_ für UTF-8.
Also. Wenn es nur ASCII-Zeichen sind, liefert
length($str);
die Anzahl der Zeichel als Anzahl der Oktetten (Bytes).
UTF-8: Du kbekommst mit CGI::param die Oktetten in Dein CGI-Script. Diese stellen UTF-8-kodierte Zeichen dar, weil Dein Formular mit dieser Kodierung ausgeliefert wird. Die Funktion length($input)
würde Dir die Anzahl der Oktetten liefern. Wenn Du jedoch die Anzahl der Zeichen haben möchtest, musst Du da was tun, z.B. sowas:
use Encode;
# $string = decode(ENCODING, OCTETS[, CHECK]) # s. Docu
# Example:
my $utf8oktetten = CGI::param('input');
my $utf8str = decode('utf-8', $utf8oktetten);
my $anzahl_bytes = length($utf8oktetten);
my $anzahl_zeichen = length($utf8str);
# Bemerke den Unterschied, wenn Umlaute drin sind
Anderer Weg:
use CGI qw(-utf8); # This makes CGI.pm treat all parameters as UTF-8 strings.
# Achtung: Upload (multipart/form-data) ist damit nicht mehr möglich!!!
my $cgi = CGI->new;
my $utf8str = $cgi->param('input');
Und noch ein kleiner Tipp: Ein Code mit vielen globalen Variablen wird sehr schnell unübersichtlich. Fasse die alle zusammen in einer einzigen Referenz:
# Main Object mit allen Variablen
my $mo = {
CGI => CGI->new, # CGI-Objekt als Attribut
name => 'otto',
foo => 'bar',
};
# in einer sub
my $v = $mo->{CGI}->param('name_inputfeld');
Jetzt könntest Du in Dein Script noch die CGI::param-Methode delegieren, notiere einfach diese Funktion in Deinem Script:
# DELEGATION
sub param{
return $mo->{CGI}->param(@_);
}
Dann kannst Du die Funkion CGI::param einfach so aufrufen:
$mo->param();
Und letztlich ergibt das alles einen aufgeräumten Code ;)
Schönen Sonntag,
Horst Hausr
Morgen hotti
Wie ich schon schrieb: Mit der _Datenmenge an sich_ sehe ich kein Problem.
Dann war ich bei der Problemanalyse auf dem falschen Dampfer. *g*
Also. Wenn es nur ASCII-Zeichen sind, liefert
length($str);
die Anzahl der Zeichel als Anzahl der Oktetten (Bytes).
So, jetzt hier mal langsam - in Zeitlupe - sozusagen:
Was ich aus meinen Basic-Zeiten noch weiß ist, daß ASCII eine 3-stellige Zahl ist, die für ein Zeichen steht. Beispiel: großes "Ä" = 142 (extended ASCII-Codes)oder großes "A" =065 (normal ASCII-Codes).
Hier die entsprechende AsciiTabelle.
Wo ist jetzt hier der Octettenwert? Sind nicht alle ASCII-Codes 3-Stellig? Auch dein Einwand daß Umlaute mehr Platz berauchen stimmt zwar mit meinem "Praxistest" überein, aber nach der ASCII-Tabelle sind doch auch die Umlaute 3-stellig?
UTF-8: Du kbekommst mit CGI::param die Oktetten in Dein CGI-Script.
Bis hierher kann ich dir folgen. Das heißt meine Zeichen liegen im Perl als Octetten vor? (was immer das sein mag)
Diese stellen UTF-8-kodierte Zeichen dar, weil Dein Formular mit dieser Kodierung ausgeliefert wird.
Auch das verstehe ich noch. Browser an cgi in utf-8
Die Funktion
length($input)
würde Dir die Anzahl der Oktetten liefern.
Aha, da kommen wir der Sache schon näher: Das heißt mein Programm zählt aktuell die Octetten?
Wenn Du jedoch die Anzahl der Zeichen haben möchtest, musst Du da was tun,
Also ist der 3-stellige ASCII-Wert nicht gleich dem Octettenwert - sprich - das sind zwei verschiedene paar Schuhe?
z.B. sowas:
use Encode;
my $utf8oktetten = CGI::param('input'); #Übergabe Input an Skalar
my $utf8str = decode('utf-8', $utf8oktetten); # decodiert utf8oktteten in utf-8 und übergibt an $utf8str
> my $anzahl_bytes = length($utf8oktetten); # mit diesen beiden Skalaren willst du
> my $anzahl_zeichen = length($utf8str); # mir den Unterschied verdeutlichen?
Bemerke den Unterschied, wenn Umlaute drin sind
Alles Klar. Ich werde deinen Code in mein Programm implementieren. Vielleicht finde ich auf google eine Oktettenerklärung und wie sich diese vom ACII Zeichen differenzieren.
Gruß HP-User
hi,
Wo ist jetzt hier der Octettenwert?
ASCII ist eine 7-Bit-Codierung, Wertebereich 0..127
ISO-8859 ist eine 8-Bit-Codierung, Wertebereich 0..255
Oktetten sind Bytes, ein Byte hat 8 Bit. Bei ASCII werden von diesen 8 Bit nur 7 Bit genutzt. Sowohl bei ASCII als auch bei ISO-8859 entspricht
1 Byte == 1 Zeichen
Sind nicht alle ASCII-Codes 3-Stellig?
Zahlen von 100 bis 999 sind dreistellig SCNR ;)
In der Welt der Zeichen geht es darum, wieviele Bytes ein Zeichen zum Darstellen braucht. Und in der Welt der Bytes geht es darum, welchen zahlenmäßgen Wert ein Byte als Oktette annehmen kann: 0..255 (zwei hoch acht).
Auch dein Einwand daß Umlaute mehr Platz berauchen stimmt zwar mit meinem "Praxistest" überein, aber nach der ASCII-Tabelle sind doch auch die Umlaute 3-stellig?
Umlaute in der ASCII-Tabelle? Die 7 Bit reichen nicht mal für alle Zeichen die mit der Tastatur erzeugt werden können ;)
Und jetzt genug der Theorie, ab in die PRAXIS!!!!!
Hotti
hi,
Und jetzt genug der Theorie, ab in die PRAXIS!!!!!
(ist noch nicht ganz fertig, aber ich komme ja nicht dazu)
Hi,
############################################
Evil-Input-Filter (EIF) / Zeichenbezogen
############################################
$customstorycode =~ s/;//g;
$customstorycode =~ s/<//g;
$customstorycode =~ s/>//g;
$customstorycode =~ s/\*//g;
$customstorycode =~ s/|//g;
$customstorycode =~ s/[//g;
$customstorycode =~ s/]//g;
$customstorycode =~ s/{//g;
$customstorycode =~ s/}//g;
$customstorycode =~ s/@//g;
$customstorycode =~ s/&//g;
$customstorycode =~ s/\//g;
Warum nicht per Zeichenklasse?
$customstorycode =~ s/[;<>*|[]{}@&\]//g;
Und das dann noch in eine Funktion, dann braucht man nur einmal den Regex angeben. Und die dann für die verschiedenen Variablen aufrufen.
cu,
Andreas
Hi MudGuard
Heißt das etwas, das dies hier:
Warum nicht per Zeichenklasse?
$customstorycode =~ s/[;<>*|[]{}@&\]//g;
All das hier ersetzt:
############################################
Evil-Input-Filter (EIF) / Zeichenbezogen
############################################
$customstorycode =~ s/;//g;
$customstorycode =~ s/<//g;
$customstorycode =~ s/>//g;
$customstorycode =~ s/\*//g;
$customstorycode =~ s/|//g;
$customstorycode =~ s/[//g;
$customstorycode =~ s/]//g;
$customstorycode =~ s/{//g;
$customstorycode =~ s/}//g;
$customstorycode =~ s/@//g;
$customstorycode =~ s/&//g;
$customstorycode =~ s/\//g;
Da spar ich ja ein haufen Zeilen Code ein!
Und das dann noch in eine Funktion, dann braucht man nur einmal den Regex angeben. Und die dann für die verschiedenen Variablen aufrufen.
Das ist mir dann wieder zu hoch. Aber ich Ahne was du damit erreichen willst. Quasi ein Block, in dem ich den Skalar hineinwerfe. Dort wird er dann gewaschen, gebügelt und gefaltet, und kommt dann perfekt wieder heraus?
Leider keine Ahnung wie ich so eine Waschmaschiene bauen soll *g*
Ich hab noch ein ganz anderes Problem. Nun hab ich nach "hotties" Vorschlag die cgi-Daten von utf-8 decodiert in ASCII. Und die Längenangabe passt jetzt auch-> Ich kann tatsächlich 4000 Zeichen exakt übermitteln.
Nur die Test-Ausgabe des PerlSkripts liefert mir anstelle von Umlauten ein Fragezeichen in einer auf dem Kopf stehenden Quadrat.
Laß mich raten: Nach dem (erfolgreichen)Längencheck darf ich wieder alles zurückwandel? Ihr macht mir Spass *LOL*
Gruß
HP-User
Hi MudGuard
Laß mich raten: Nach dem (erfolgreichen)Längencheck darf ich wieder alles zurückwandel? Ihr macht mir Spass *LOL*
Habs hinbekommen: Gegenteil von decode ist encode!
Gruß und bye
HP-User
Abend zusammen
Ich habe in meinem Formular eine Zeichenabfrage über JavaSkript. Diese scheint auch korrekt zu sein. Ein Umbruch (Return) wird als ein Zeichen gezählt, ebenso wird für ein Leerzeichen (Space) ein Zeichen berechnet. So scheint es clientseitig korrekt zu zählen.
Serverseitig sieht das ganze etwas anders aus. Ich habe eine Länge von 4000 Zeichen eingestellt. Wenn es mehr sind, bricht das Perlprogramm momentan ab. Ich las es auf exit laufen (vorerst!).
Je nach dem, was im großen Textfeld (textarea) eingegeben wird, scheint das Perl die übermittelten Zeichen nicht korrekt zu zählen.
Ich habe schon von oktetten über ASCII und wieder zurück probiert. Ich kann den Fehler nicht finden!
Durch Probieren mit verschiedenen Zeichen vermute ich folgende Diskrepanz:
Umlaute, Umbrüche und Leerzeichen müssen irgendwie das Perl durcheinander bringen.
Gruß HP-User
Abend zusammen
So, ich bin fündig geworden. Ihr habt das Problem soger selber schon beschrieben. Nämlich ganz genau an dieser Stelle.
Ersetze alle Umbrüche verschiedenster Systeme durch den Perleigenen Umbruch "\n":
------------------------------------
$text =~ s/\015\012|\015|\012/\n/g;
------------------------------------
Ich musste dann nur noch den Perleigenen Umbruch durch "nichts" ersetzen:
------------------------------------
$text =~ s/\015\012|\015|\012//g;
------------------------------------
Und schon stimmte die Zeichenanzahl vom HTML-Formular, mit den in Perl gezählten Zeichen überein.
Gruß
HP-User