OVH Cloud OVH Cloud

STDIN et CRLF selon OS

11 réponses
Avatar
Asterbing
Bonjour. Dans le cadre de l'extraction des données utiles venant d'un
formulaire multiparties envoyé par méthode POST, je commence ansi :

binmode STDIN; # pour windows
read(STDIN, $buff, $ENV{'CONTENT_LENGTH'});

Puis, je split sur le boundary trouvé dans $ENV{CONTENT_TYPE}
et enfin analyse ligne à ligne chaque partie (sans détailler ici car ce
n'est pas l'objet de ma question).

Sachant que CRLF est \015\012 sous Windows, \012 sous Unix et \015 sous
MacOS (dixit "44.2.1 Les retours chariots" de la doc Perl en français
venant de <http://www.enstimac.fr/Perl/>, version du 10 avril 2005)

Dois-je extraire mes lignes via un "split(/$crlf/, $block)" avec $crlf
adapté selon l'OS ?

Cette question parce que j'ai vu plusieurs exemples (chacuns avec sa
manière) concernant l'analyse de STDIN ne reconnaissant la fin de ligne
qu'avec "\r\n" et sans passer en binmode (je suppose donc en ignorant le
cas Windows).

10 réponses

1 2
Avatar
Nicolas George
Asterbing wrote in message :
Sachant que CRLF est 1512 sous Windows, 12 sous Unix et 15 sous
MacOS (dixit "44.2.1 Les retours chariots" de la doc Perl en français
venant de <http://www.enstimac.fr/Perl/>, version du 10 avril 2005)

Dois-je extraire mes lignes via un "split(/$crlf/, $block)" avec $crlf
adapté selon l'OS ?


Puisqu'il y a un binmode, la chaîne contient exactement les octets envoyés
sur le réseau, de manière totalement indépendante de l'OS où le script
tourne. Il faut donc regarder ce que spécifie le protocole. S'agissant d'un
formulaire POST, il me semble qu'il n'y a pas de séparation des lignes
normalement, donc ça doit être autre chose.

Avatar
Paul Gaborit
À (at) Wed, 19 Apr 2006 16:02:07 +0200,
Asterbing écrivait (wrote):
Bonjour. Dans le cadre de l'extraction des données utiles venant d'un
formulaire multiparties envoyé par méthode POST, je commence ansi :

binmode STDIN; # pour windows
read(STDIN, $buff, $ENV{'CONTENT_LENGTH'});

Puis, je split sur le boundary trouvé dans $ENV{CONTENT_TYPE}
et enfin analyse ligne à ligne chaque partie (sans détailler ici car ce
n'est pas l'objet de ma question).

Sachant que CRLF est 1512 sous Windows, 12 sous Unix et 15 sous
MacOS (dixit "44.2.1 Les retours chariots" de la doc Perl en français
venant de <http://www.enstimac.fr/Perl/>, version du 10 avril 2005)

Dois-je extraire mes lignes via un "split(/$crlf/, $block)" avec $crlf
adapté selon l'OS ?

Cette question parce que j'ai vu plusieurs exemples (chacuns avec sa
manière) concernant l'analyse de STDIN ne reconnaissant la fin de ligne
qu'avec "rn" et sans passer en binmode (je suppose donc en ignorant le
cas Windows).


Il vous faut absolument lire *et* comprendre les protocoles HTTP et
CGI ainsi que le MIME. Une fois que vous aurez compris cela, vous
saurez comment gérer vous-même ces données.

CGI: <http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html>
HTTP: <http://www.w3.org/Protocols/rfc2616/rfc2616.html>

Si vous ne voulez pas (n'avez pas le temps, n'arrivez pas à,...) faire les
efforts nécessaires, appuyez-vous sur du code proprement conçu comme
le module CGI (ou CGI::Lite).

Personnellement, je vous conseille *très* fortement de passe par cette
seconde solution !

Pour répondre précisément à votre question : l'interprétation du
contenu (body) de la requête (dont la taille est donnée par la
variable CONTENT_LENGTH) dépend, entre autres, du contenu de la
variable d'environnement CONTENT_TYPE. Si ce contenu est multi-part,
l'interprétation de chaque partie dépend aussi de son type MIME, etc.

Tout autre manière de faire est vouée à l'échec...

PS: en relisant les spécifications CGI, je trouve la phrase suivante
au sujet de CONTENT_TYPE.

Servers MUST provide this metavariable to scripts if a
"Content-Type" field was present in the original request header. If
the server receives a request with an attached entity but no
"Content-Type" header field, it MAY attempt to determine the correct
datatype, or it MAY omit this metavariable when communicating the
request information to the script.

Donc même en CGI la variable CONTENT_TYPE peut ne pas être
renseignée...

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français -
<http://perl.enstimac.fr/>

Avatar
Paul Gaborit
À (at) Wed, 19 Apr 2006 17:09:41 +0200,
Paul Gaborit écrivait (wrote):
Donc même en CGI la variable CONTENT_TYPE peut ne pas être
renseignée...


Lire CONTENT_LENGTH à la place de CONTENT_TYPE !

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Asterbing
In article <e25jef$2sv0$, nicolas$
s.org says...
S'agissant d'un
formulaire POST, il me semble qu'il n'y a pas de séparation des lignes
normalement, donc ça doit être autre chose.



Si j'en crois <http://www.vivtek.com/rfc1867.html>, je cite : "The data
itself appears in blocks that are made up of lines separated by CR/LF
pairs.", il semblerait que si.

Avatar
Asterbing
In article ,
says...
Il vous faut absolument lire *et* comprendre les protocoles HTTP et
CGI ainsi que le MIME. Une fois que vous aurez compris cela, vous
saurez comment gérer vous-même ces données.

CGI: <http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html>
HTTP: <http://www.w3.org/Protocols/rfc2616/rfc2616.html>


Merci bien pour les liens, Paul. Je les lirai précautionneusement.

Si vous ne voulez pas (n'avez pas le temps, n'arrivez pas à,...) faire les
efforts nécessaires, appuyez-vous sur du code proprement conçu comme
le module CGI (ou CGI::Lite).


Quoique mon domaine initial soit orienté firmware et assembleur, je ne
vois pas d'autre obstacle que le temps dans ces sujets HTTP, CGI et Perl
: je prendrai donc le temps qu'il faudra quand bien même faut-il passer
par quelques solutions intermédiaires d'attente tel CGI::Lite.

Pour répondre précisément à votre question : l'interprétation du
contenu (body) de la requête (dont la taille est donnée par la
variable CONTENT_LENGTH) dépend, entre autres, du contenu de la
variable d'environnement CONTENT_TYPE. Si ce contenu est multi-part,
l'interprétation de chaque partie dépend aussi de son type MIME, etc.


C'est bien sur cette base que je suis parti : il s'agit bien d'un POST
provenant d'un formulaire de type multipart/form-data et je me préoccupe
bien du type MIME du fichier uploadé, exprimé clairement dans la partie
comprenant ses data.

Tout autre manière de faire est vouée à l'échec...


Comprend pas le mot :-) Joke bien sûr pour ceux qui n'auraient pas
compris l'adage selon lequel les plus sérieux ne sont pas les plus
tristes.

PS: en relisant les spécifications CGI, je trouve la phrase suivante
au sujet de CONTENT_TYPE.

Servers MUST provide this metavariable to scripts if a
"Content-Type" field was present in the original request header. If
the server receives a request with an attached entity but no
"Content-Type" header field, it MAY attempt to determine the correct
datatype, or it MAY omit this metavariable when communicating the
request information to the script.

Donc même en CGI la variable CONTENT_TYPE peut ne pas être
renseignée...



De même que pour CONTENT-LENGTH, ceci est facheux ! Zut, alors pourquoi
donc tous les exemples de script CGI écrit en Perl gérant un upload (tel
<http://www.vivtek.com/cgi/_getargs.txt>) s'appuient-ils sur ces deux
variables d'environnement ? Faut que j'aille voir les sources de
CGI::Lite.

Avatar
Paul Gaborit
À (at) Wed, 19 Apr 2006 17:19:24 +0200,
Asterbing écrivait (wrote):
Si j'en crois <http://www.vivtek.com/rfc1867.html>, je cite : "The data
itself appears in blocks that are made up of lines separated by CR/LF
pairs.", il semblerait que si.


Ce document n'a aucune valeur normative. Et les bouts de code Perl
fournis à côté ne laissent rien présager de bon...

Lisez donc la RFC correspondante (la RFC 1867).

Petit extrait d'un exemple de cette RFC :

--BbC04y
Content-disposition: attachment; filename="file2.gif"
Content-type: image/gif
Content-Transfer-Encoding: binary

...contents of file2.gif...
--BbC04y--

Quand je lis '...contents of file2.gif...' précédé de
'Content-Transfer-Encoding: binary', je sais que cette partie peut
contenir n'importe quelle suite de caractères (c'est du binaire
quelconque). La seule chose qui est garantie par MIME, c'est que la
'boundary' choisie (ici '--BbC04y--<CR><LF>') l'a été justement parce
qu'elle n'apparaît pas dans les données binaires !

Donc un découpage en ligne n'a strictement aucun sens !

Pourquoi tenez-vous absolument à refaire tout cela vous-même 'à la
main' ?

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Asterbing
In article ,
says...
Donc même en CGI la variable CONTENT_TYPE peut ne pas être
renseignée...



De même que pour CONTENT-LENGTH, ceci est facheux ! Zut, alors pourquoi
donc tous les exemples de script CGI écrit en Perl gérant un upload (tel
<http://www.vivtek.com/cgi/_getargs.txt>) s'appuient-ils sur ces deux
variables d'environnement ? Faut que j'aille voir les sources de
CGI::Lite.



Paul, je viens de lire votre réponse dans le fil 'existence et taille
fichier client' qui certainement clarifie le sujet. Je vous cite :

En HTTP, l'entête Content-Length n'est pas obligatoire. En CGI, il est absolument
requis. C'est le serveur Web qui complète l'information lorsqu'elle
manque. Ce qui signifie que si le serveur reçoit une requête sans
Content-Length, il attendra d'avoir reçu toute l'info avant d'activer
le programme CGI.



et vous répond donc : "Très intéressant Paul : voilà l'info essentielle.
Donc, au positif : je suis sûr d'avoir toujours ce Content-Length. Au
négatif : lorsque je l'ai, toutes les data du fichier à uploader sont
déjà transmises et je n'ai pas vraiment d moyen d'alerter l'utilisateur
d'un fichier trop gros avant ça."


Avatar
Paul Gaborit
À (at) Wed, 19 Apr 2006 17:53:14 +0200,
Asterbing écrivait (wrote):
Paul, je viens de lire votre réponse dans le fil 'existence et taille
fichier client' qui certainement clarifie le sujet. Je vous cite :

En HTTP, l'entête Content-Length n'est pas obligatoire. En CGI, il
est absolument requis.



Et je me trompais... Les spécifications CGI n'imposent pas la présence
de cette information. Elles n'est donc obligatoire ni pour HTTP ni
pour CGI.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>


Avatar
Asterbing
In article ,
says...
Pourquoi tenez-vous absolument à refaire tout cela vous-même 'à la
main' ?



Pour l'apprentissage, l'intérêt intellectuel et parce que je viens du
bas niveau (firmware pour instruments de labo) et qu'on ne se refait
pas.

Avatar
Asterbing
In article ,
says...
Donc un découpage en ligne n'a strictement aucun sens !



Je suis d'accord, mais la lecture d'une façon ou d'une autre (y compris
selon la notion de ligne texte qui alors n'en ai pas) n'a pas
d'influence sur le contenu (il n'y a pas de transformation, juste une
lecture impropre et peu élégante) ne sert qu'à saisir le contenu du
fichier et évite d'avoir à saisir ligne à ligne les premières lignes de
chaque partie (celles avec Content-*) et changer de méthode pour la
suite.

1 2