Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Découpage d'un fichier texte et binaire.

29 réponses
Avatar
Kevin Denis
Bonjour,

j'ai un très longue capture HTTP. Dans cette capture, j'ai des
parties texte (HTML, javascript, etc..) et des parties binaires (jpg,
gif, etc..).

La structure est connue:

HTTP/1.1 200 OK
(..des données d'entête)
<-- une ligne vide
des données (texte ou binaire, donc).HTTP/1.1 200 OK (et entetes, ligne
vide etc..)

J'ai donc bien un délimiteur de début (la ligne vide) et un de fin (le
HTTP/1.1 200 OK ou la fin de fichier).

Avec des outils "classiques" (ni perl, ni python donc) comment extraire
les données?

Merci
--
Kevin

10 réponses

1 2 3
Avatar
Cyrille Lefevre
Le 23/11/2010 21:12, Benoit Izac a écrit :
Bonjour,

le 22/11/2010 à 15:52, Kevin Denis a écrit dans le message
:

j'ai un très longue capture HTTP. Dans cette capture, j'ai des
parties texte (HTML, javascript, etc..) et des parties binaires (jpg,
gif, etc..).

La structure est connue:

HTTP/1.1 200 OK
(..des données d'entête)
<-- une ligne vide
des données (texte ou binaire, donc).HTTP/1.1 200 OK (et entetes, li gne
vide etc..)

J'ai donc bien un délimiteur de début (la ligne vide) et un de fin (le
HTTP/1.1 200 OK ou la fin de fichier).



Sur l'exemple que tu présentes, c'est l'inverse (d'abord le HTTP/1.1 200
OK puis la ligne vide).

Avec des outils "classiques" (ni perl, ni python donc) comment extrair e
les données?





facile :-)

Si j'ai bien compris (supprimer tout ce qui est entre HTTP/1.1 200 OK e t
la ligne vide) :

sed -e '/^HTTP/1.1 200 OK$/,/^$/d'



non portable, sed ne permet pas de traiter les données binaires, hormis
GNU sed.

un simple shell suffit (non testé, mais doit le faire... :)

while read -r line; do
case $line in
# reponse ok
HTTP/1.1?200?OK) echo ok ;;
# autres reponses (ko?)
HTTP/1.1*) echo ko; break ;;
# taille des donnees
Contents-Length:*) sz=${line#Contents-Length: }; echo $sz ;;
# lecture des donnees
'') dd bs count=1x$sz of=file; break ;;
# alternative
# '') dd count=1 bs=1x$sz of=file; break ;;
# autres entetes
# *) : rien a faire, en commentaire, donc ;;
esac

Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
remove "%nospam" and ".invalid" to answer me.
Avatar
Benoit Izac
Bonjour,

le 23/11/2010 à 13:03, Kevin Denis a écrit dans le message
:

Le 23-11-2010, Xavier a écrit :

Pourtant, son problème se torche en 10 lignes de Perl...



bon, s'il faut en passer par là, je prends les 10 lignes de perl.



Un peu plus de 10 lignes mais c'est lisible (je pense) :

#!/usr/bin/perl

use strict;
use warnings;

my $filename = "capture_";
my ($in_header, $i, $fd) = (0, 1);

while (<>) {
if ($in_header) {
$in_header = 0 if /^$/;
} else {
if (/HTTP/1.1 200 OK/) {
open $fd, '>', "$filename" . $i++;
$in_header = 1;
} else {
print $fd $_ if defined $fd;
}
}
}
__END__

Ça écrit dans un fichier nommé "capture_XXX" avec XXX incrémenté
à chaque nouvelles données. J'ai considéré qu'il y avait toujours un
en-tête avant chaque donnée.

--
Benoit Izac
Avatar
Alain Ketterlin
j'ai un très longue capture HTTP. Dans cette capture, j'ai des
parties texte (HTML, javascript, etc..) et des parties binaires (jpg,
gif, etc..).

La structure est connue:

HTTP/1.1 200 OK
(..des données d'entête)
<-- une ligne vide
des données (texte ou binaire, donc).HTTP/1.1 200 OK (et entetes, ligne
vide etc..)

J'ai donc bien un délimiteur de début (la ligne vide) et un d e fin (le
HTTP/1.1 200 OK ou la fin de fichier).



sed -e '/^HTTP/1.1 200 OK$/,/^$/d'



non portable, sed ne permet pas de traiter les données binaires, hor mis
GNU sed.

un simple shell suffit (non testé, mais doit le faire... :)


[...]

Je me demande si vous ne sous-estimez pas HTTP. Par exemple, quid du
codage "chunked" ? (RFC 2616, section 3.6.1)

Autrement dit, la description du problème ci-dessus est un chouia
simpliste, et je ne pense pas qu'il y ait de solution simple dans le cas
général. Il faut un vrai client HTTP, moins la partie réseau . Une rapide
recherche m'a amené à ça :

http://www.mail-archive.com//msg04065.html

et un autre truc pour perl :

http://search.cpan.org/~mala/HTTP-Response-Parser-0.02/

-- Alain.
Avatar
Kevin Denis
Le 23-11-2010, Benoit Izac a écrit :
bon, s'il faut en passer par là, je prends les 10 lignes de perl.



Un peu plus de 10 lignes mais c'est lisible (je pense) :

#!/usr/bin/perl

use strict;
use warnings;

my $filename = "capture_";
my ($in_header, $i, $fd) = (0, 1);

while (<>) {
if ($in_header) {
$in_header = 0 if /^$/;
} else {
if (/HTTP/1.1 200 OK/) {
open $fd, '>', "$filename" . $i++;
$in_header = 1;
} else {
print $fd $_ if defined $fd;
}
}
}
__END__



Ok

Ça écrit dans un fichier nommé "capture_XXX" avec XXX incrémenté
à chaque nouvelles données. J'ai considéré qu'il y avait toujours un
en-tête avant chaque donnée.



C'est le cas. Mais le résultat n'est pas super convaincant. Voici le
début de la capture:
$ hexdump -C bigflow | head -20
00000000 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d |HTTP/1.1 200 OK.|
00000010 0a 53 65 72 76 65 72 3a 20 41 70 61 63 68 65 0d |.Server: Apache.|
00000020 0a 4c 61 73 74 2d 4d 6f 64 69 66 69 65 64 3a 20 |.Last-Modified: |
00000030 46 72 69 2c 20 32 31 20 41 75 67 20 32 30 30 39 |Fri, 21 Aug 2009|
00000040 20 31 34 3a 35 31 3a 34 36 20 47 4d 54 0d 0a 41 | 14:51:46 GMT..A|
00000050 63 63 65 70 74 2d 52 61 6e 67 65 73 3a 20 62 79 |ccept-Ranges: by|
00000060 74 65 73 0d 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e |tes..Content-Len|
00000070 67 74 68 3a 20 38 38 37 0d 0a 43 6f 6e 74 65 6e |gth: 887..Conten|
00000080 74 2d 54 79 70 65 3a 20 69 6d 61 67 65 2f 70 6e |t-Type: image/pn|
00000090 67 0d 0a 44 61 74 65 3a 20 46 72 69 2c 20 31 39 |g..Date: Fri, 19|
000000a0 20 4e 6f 76 20 32 30 31 30 20 31 34 3a 33 31 3a | Nov 2010 14:31:|
000000b0 32 35 20 47 4d 54 0d 0a 43 6f 6e 6e 65 63 74 69 |25 GMT..Connecti|
000000c0 6f 6e 3a 20 6b 65 65 70 2d 61 6c 69 76 65 0d 0a |on: keep-alive..|
000000d0 43 61 63 68 65 2d 43 6f 6e 74 72 6f 6c 3a 20 6d |Cache-Control: m|
000000e0 61 78 2d 61 67 65 3d 33 31 35 33 36 30 30 30 30 |ax-age15360000|
000000f0 0d 0a 45 78 70 69 72 65 73 3a 20 53 75 6e 2c 20 |..Expires: Sun, |
00000100 32 35 20 4f 63 74 20 32 30 32 30 20 31 38 3a 31 |25 Oct 2020 18:1|
00000110 34 3a 33 32 20 47 4d 54 0d 0a 0d 0a 89 50 4e 47 |4:32 GMT.....PNG|

On lit les entêtes, et il s'agit d'une image PNG, on a bien
0d 0a 0d 0a (les deux retours chariots successifs signifiant bien la ligne
vide entre les en-têtes et les données). Puis le 89 50 4e 47 qui est
l'en tête PNG standard, cf le fichier /etc/file/magic/images:
0 string x89PNGx0dx0ax1ax0a PNG image

Et capture_1 ne ressemble déjà pas à ça:
$ hexdump -C capture_1 | head -1
00000000 16 24 92 03 98 28 ba 99 3c 85 10 40 a1 78 46 11 |.$...(º.<..@¡xF.|

(Je lis mal le perl, mais ça me semblait bon, pourtant (?))
--
Kevin
Avatar
Kevin Denis
Le 23-11-2010, Cyrille Lefevre a écrit :
j'ai un très longue capture HTTP. Dans cette capture, j'ai des
parties texte (HTML, javascript, etc..) et des parties binaires (jpg,
gif, etc..).

J'ai donc bien un délimiteur de début (la ligne vide) et un de fin (le
HTTP/1.1 200 OK ou la fin de fichier).



Sur l'exemple que tu présentes, c'est l'inverse (d'abord le HTTP/1.1 200
OK puis la ligne vide).





La partie entre HTTP/1.1 200 et la ligne vide représente les en-têtes. Donc
le fichier est bien compris entre la ligne vide et le HTTP/1.1 200 OK suivant.

Avec des outils "classiques" (ni perl, ni python donc) comment extraire
les données?





facile :-)

Si j'ai bien compris (supprimer tout ce qui est entre HTTP/1.1 200 OK et
la ligne vide) :

sed -e '/^HTTP/1.1 200 OK$/,/^$/d'





Il n'y a pas qu'un seul fichier, mais une grande quantité:
$ grep -a Content-Type bigflow | wc -l
11380

L'idéal est donc d'avoir 11380 fichier en fin de traitement.

non portable, sed ne permet pas de traiter les données binaires, hormis
GNU sed.

un simple shell suffit (non testé, mais doit le faire... :)

while read -r line; do
case $line in
# reponse ok
HTTP/1.1?200?OK) echo ok ;;



Difficile. Les fichiers ne terminent pas forcément par un retour Chariot,
ce qui signifie que le HTTP/1.1 200 OK peut être directement accolé à
la fin d'un fichier binaire, cf:
000007a0 04 05 10 00 00 00 2c 00 00 00 00 01 00 01 00 00 |......,.........|
000007b0 02 02 04 01 00 3b 48 54 54 50 2f 31 2e 31 20 32 |.....;HTTP/1.1 2|
000007c0 30 30 20 4f 4b 0d 0a 53 65 72 76 65 72 3a 20 41 |00 OK..Server: A|
000007d0 70 61 63 68 65 0d 0a 4c 61 73 74 2d 4d 6f 64 69 |pache..Last-Modi|

Et là, le readline ne passera sans doute pas..

Je vais essayer d'aller dans ce sens quand même, je ne savais pas que
GNU sed traitait le binaire aussi, merci
--
Kevin
Avatar
Nicolas George
Kevin Denis , dans le message
, a écrit :
Difficile. Les fichiers ne terminent pas forcément par un retour Chariot,
ce qui signifie que le HTTP/1.1 200 OK peut être directement accolé à
la fin d'un fichier binaire



Le « HTTP/1.1 200 OK » peut aussi faire partie du contenu d'un fichier. Tu
ne couperas pas à l'interprétation rigoureuse du protocole.
Avatar
Kevin Denis
Le 23-11-2010, Alain Ketterlin a écrit :
Je me demande si vous ne sous-estimez pas HTTP. Par exemple, quid du
codage "chunked" ? (RFC 2616, section 3.6.1)

Autrement dit, la description du problème ci-dessus est un chouia
simpliste, et je ne pense pas qu'il y ait de solution simple dans le cas
général.



Sans doute. Généralement, soit un problème est trivial et aucun outil
existe, soit c'est compliqué et un dev à pris le temps de coder un outil
génial pour le résoudre.
Là, ça ne semble pas trivial et aucun outil n'existerait?

Il faut un vrai client HTTP, moins la partie réseau. Une rapide
recherche m'a amené à ça :
http://www.mail-archive.com//msg04065.html

et un autre truc pour perl :

http://search.cpan.org/~mala/HTTP-Response-Parser-0.02/



Je vais voir, merci.
--
Kevin
Avatar
Antoine Leca
Kevin Denis écrivit :
Je n'ai pas envie de sortir l'interpréteur de commande pour ça.
Autant les classiques (awk, sed, etc..) sont bons pour traiter du
texte, autant je me demande comment ils vont réagir lorsqu'il y a du
binaire au milieu du texte. D'où ma question.



« comment ils vont réagir » ? Mal. À la base, l'intérêt d'outils comme
awk ou sed, c'est de programmer des petits scripts pour les appliquer
sur pleins de fichiers texte, autrement dit organisés en lignes. Leur
mode de fonctionnement, c'est de construire un automate, puis de lire
les fichiers à traiter ligne par ligne, donc en utilisant un tampon.
Tampon qui est souvent implémenté comme une chaîne C, avec un pour
indiquer la fin. Historiquement, c'était avant que l'on dispose de
mémoire virtuelle et autres projections en mémoire (mmap).
Et quand on invoque le critère « historiquement », tu dois lire que cela
signifie aussi des problèmes de portabilité en perspective...

Là, ta volonté c'est d'interpréter le début d'un fichier (l'entête HTTP)
pour y lire la structure du reste (en particulier les tailles), pour
ensuite pouvoir « découper » le reste de ton fichier ; puis de
recommencer avec le reste. Je ne vois pas l'intérêt d'aller chercher
l'interpréteur de commandes pour cela, mais par contre je vois assez
bien que cette tâche correspond tout-à-fait à l'utilisation basique de
perl ou python, des outils un poil plus récent et qui en particulier
dédaignent les problèmes liés à la taille des fichiers ou aux . Et si
tu n'as plus de problème avec la taille des fichiers ou les tampons, la
distinction entre binaire et texte sous Unix devient assez ténue...
En fait, tu vas peut-être plutôt avoir à traiter des soucis lié à cette
même distinction mais sur d'autres systèmes, comme par exemple la
présence de caractères r en fin de ligne dans les parties « textes ».
Et là encore, le fait d'utiliser des outils récents va te simplifier la vie.


Antoine
Avatar
Tonton Th
On 11/24/2010 10:50 AM, Kevin Denis wrote:

000007a0 04 05 10 00 00 00 2c 00 00 00 00 01 00 01 00 00 |......,.........|
000007b0 02 02 04 01 00 3b 48 54 54 50 2f 31 2e 31 20 32 |.....;HTTP/1.1 2|
000007c0 30 30 20 4f 4b 0d 0a 53 65 72 76 65 72 3a 20 41 |00 OK..Server: A|
000007d0 70 61 63 68 65 0d 0a 4c 61 73 74 2d 4d 6f 64 69 |pache..Last-Modi|

Et là, le readline ne passera sans doute pas..



C'est pour ça que tu as, dans le header, un champ :

Content-Length: 2808

--
Ma coiffeuse est formidable - http://sonia.buvette.org/
Avatar
Benoit Izac
Bonjour,

le 24/11/2010 à 10:41, Kevin Denis a écrit dans le message
:

Ça écrit dans un fichier nommé "capture_XXX" avec XXX incrémenté
à chaque nouvelles données. J'ai considéré qu'il y avait toujours un
en-tête avant chaque donnée.



C'est le cas. Mais le résultat n'est pas super convaincant. Voici le
début de la capture:
$ hexdump -C bigflow | head -20
00000000 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d |HTTP/1.1 200 OK.|
00000010 0a 53 65 72 76 65 72 3a 20 41 70 61 63 68 65 0d |.Server: Apache.|



Ok, donc c'est "HTTP/1.1 200 OKrn"

00000110 34 3a 33 32 20 47 4d 54 0d 0a 0d 0a 89 50 4e 47 |4:32 GMT.....PNG|



Et ici "rnrn".

Remplace /^$/ par /^r$/ et /HTTP/1.1 200 OK/ par
/^HTTP/1.1 200 OKr$/

--
Benoit Izac
1 2 3