IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Manipulation de fichiers : perte de données


Sujet :

C++

  1. #1
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut Manipulation de fichiers : perte de données
    Bonjour,

    j'essaye de faire un petit programme qui fait un XOR en 1 fichier et 1 mot de passe. Quand le fichier n'est pas trop gros ça marche, mais dès que ca dépasse une certaine taille, j'ai des pertes.

    La manip est la suivante : j'ai un fichier A, je fais un XOR avec un mot de passe quelconque, ça me donne un fichier B. Je refait la manip pour le fichier B, ça me donne un fichier C qui devrait être identique au fichier A.

    J'ai testé avec un fichier de 163ko, ça marche, avec un fichier de 3Mo j'ai plein de différences en A et C.

    Mon main ressemble à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    void main(void)
    {
    	CFichier fichierIn("test.txt", std::ios::in | std::ios::binary);
    	CFichier fichierOut("resultat.txt", std::ios::out | std::ios::binary);
     
    	CXOR xor(pass);
     
    	const long int nbChunk = fichierIn.getNbChunk(BUF_LEN);
    	const long int lastChunkSize = fichierIn.getLastChunkSize(BUF_LEN);
     
    	for(long int i = 0 ; i<nbChunk ; i++)
    	{
    		fichierIn.read(i*nbChunk, BUF_LEN);
    		fichierOut.write(fichierIn.getBuffer());
    	}
     
    	fichierIn.read(i*nbChunk, lastChunkSize);
    	fichierOut.write(fichierIn.getBuffer());
    }
    Les autres fichiers sont en pièces attachées.

    Merci d'avance pour votre aide !

    Andy.
    Fichiers attachés Fichiers attachés

  2. #2
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    j'ai regardé rapidement ton code, et ça me semble beaucoup, beaucoup trop compliqué pour ce qu'il est censé faire.
    Qu'entends-tu exactement par faire "un XOR en 1 fichier et 1 mot de passe"?

  3. #3
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut
    Bonjour,

    l'idée c'est de prendre le premier octet du fichier, le premier octet du mot de passe, de faire un XOR, et d'écrire le résultat dans le fichier de sortie, et ainsi de suite jusqu'à la fin du fichier d'entrée.

  4. #4
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut
    Alors en fait je viens de me rendre compte d'un truc là, j'ai pas filé la bonne version du prog. Mais finalement c'est mieux, ça simplifie les choses.

    Je crée un objet CXOR mais je n'en fais rien. Tout ce que je fais c'est lire le fichier d'entrée et le recopier dans le fichier de sortie, malgré tout j'ai des différences entre les 2 fichiers, pas de taille mais de contenu.
    Donc la classe CXor on s'en fout, le problème doit se situer dans CFichier. J'avais fais cette modif là justement pour isoler le problème.

    Sinon, quel est le souci quand a la complexité de mon prog ?

  5. #5
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Je ne comprends toujours pas ce que tu entends par XOR. Pour moi XOR c'est un ou exclusif ( A XOR B = (A ET non B) OU (non A ET B) ), et je ne vois pas le rapport avec ton histoire de fichiers.

    Ensuite, de ce que je comprends pour l'instant de ton problème, il s'agit de parcourir un fichier et de remplacer un token par un autre. Cela se fait très simplement en C++:
    1. Lire le fichier et stocker son contenu en mémoire (par exemple, lire ligne par ligne et stocker dans un std::vector<std::string>
    2. Parcourir le texte stocké et remplacer les token par le motif souhaité (par exemple avec find et replace).
    3. Ecrire le résultat dans un nouveau fichier.

    S'il n'y a pas de cas particulier compliqué à gérer, cela se fait en quelques lignes.

  6. #6
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut
    Il s'agit bien du ou exclusif.
    Je prends le premier caractère de mon fichier, disons "A", je prends le premier caractère de mon mot de passe, disons "?", je fais un XOR entre eux et ça me donne "~" que j'écris dans le fichier résultat. Et je fais de même avec tous les octets du fichier source en cyclant sur le mot de passe.

    Le fichier résultant est alors un version chiffrée du fichier source. Pour retrouver le fichier source, je prends le fichier résultant et je fais la même manip qu'avec le fichier source : je prends le premier caractère, ici "~", je fais un XOR avec le premier caractère du mot de passe, "?", et je retrouve mon "A".

    Je suis bien d'accord avec les points 1,2 et 3.
    Ce que je fais c'est que j'utilise un buffer de taille BUF_LEN.
    Pour copier mon fichier, procède par tronçons de taille BUF_LEN que je lis dans la source puis que j'écris dans le fichier destination.
    Puis à la fin je lis ce qui reste éventuellement et je l'écris de même.

    Seulement les 2 fichiers ne sont pas identiques et je ne vois pas d'où ça vient.

    Je fais un read :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    std::streamsize CFichier::read(std::streampos pos, std::streamsize len)
    {
    	if(!_File.is_open())
    	{
    		return -1;
    	}
    	if(pos<0)
    	{
    		return -2;
    	}
    	if(len<0)
    	{
    		return -3;
    	}
     
    	if(!len) len=size();
     
    	_File.seekg(pos);
     
    	char *charBuffer = new char [len];
    	_File.read(charBuffer, len);
    	std::streamsize actuallyRead = _File.gcount();
     
    	_buffer.clear();
    	if(actuallyRead>0) _buffer.assign(charBuffer, actuallyRead);
     
    	delete [] charBuffer;
     
    	return actuallyRead;
    }
    puis j'écris le contenu du buffer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    std::streamsize CFichier::write(const std::string &s) const
    {
    	std::ostream outStream(_File.rdbuf());
     
    	outStream.write(s.c_str(), (std::streamsize)s.length());
     
    	return (std::streamsize) s.length();
    }

  7. #7
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Tu veux dire que même sans faire le XOR (donc sans modifier les données lues), le fichier de sortie (résultat du write) est différent du fichier lu?

    ps: je ne comprends toujours pas cette histoire de XOR. Le résultat d'un XOR c'est vrai ou faux, donc si ça n'a pas de sens si toi tu souhaites avoir un char.

  8. #8
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut
    Oui, c'est ce que je disais dans mon post de 14h32 :

    "Je crée un objet CXOR mais je n'en fais rien. Tout ce que je fais c'est lire le fichier d'entrée et le recopier dans le fichier de sortie, malgré tout j'ai des différences entre les 2 fichiers, pas de taille mais de contenu."

    C'est exactement ce que tu as compris, je fais une bête copie mais j'ai des différences, et je vois pas en regardant mon code où le bât blesse.

    Alors pour le XOR, ça a un sens si on considère que le char c'est en fait 8bits, je reprends avec mon exemple :

    Mon caractère A vaut 65 en ASCII, soit 1000001
    Mon caractère ? vaut 63 en ASCII, soit 0111111
    Mon caractère ~ vaut 65 en ASCII, soit 1111110

    Quand on les voit comme ça alignés, on se rend compte que :

    A ^ ? = ~

    1 ^ 0 = 1
    0 ^ 1 = 1
    0 ^ 1 = 1
    0 ^ 1 = 1
    0 ^ 1 = 1
    0 ^ 1 = 1
    0 ^ 1 = 1
    1 ^ 1 = 0

    Et du coup, forcément :

    ~ ^ ? = A

    1 ^ 0 = 1
    1 ^ 1 = 0
    1 ^ 1 = 0
    1 ^ 1 = 0
    1 ^ 1 = 0
    1 ^ 1 = 0
    1 ^ 1 = 0
    0 ^ 1 = 1


    A étant le contenu du fichier source, et ~ le contenu du fichier destination, le fichier destination est une version chiffrée du fichier source avec la clé "?".

    L'opération A ^ ? chiffre le fichier source, le résultat est stocké dans le fichier de destination.
    L'opération ~ ^ ? récrée le fichier source à partir du fichier de destination.

    Vois-tu ?

  9. #9
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Ha ok je vois maintenant. Oui bien sûr, où avais-je la tête...
    Oui alors effectivement, c'est un peu plus compliqué que je ne le pensais.
    Je n'ai pas le temps de regarder en détail, mais effectivement, il faut faire attention à la façon dont tu lis et écris les données, parce que là tu effectues des manipulations en binaire. Il faut donc éviter les char, et ne manipuler que des unsigned char (le signe dans le char fausse les opérations). Pas de char => pas de std::string. A la limite, des std::biset, mais je sais pas trop si c'est une bonne idée ici. Essaie de lire et écrire tes fichiers en mode binaire (std::ios::bin) et vois ce que ça donne.

  10. #10
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut
    Mes fichiers sont déjà ouverts en binaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	CFichier fichierIn("test.txt", std::ios::in | std::ios::binary);
    	CFichier fichierOut("resultat.txt", std::ios::out | std::ios::binary);
    Par contre je vais passer mes char en unsigned char.

    Le truc c'est que pour l'instant je ne fais aucune manip sur les données : je lis un fichier, je stock le résultat dans un buffer, puis j'écris le buffer dans un autre fichier.

    Le problème situe peut-être lors de la conversion char* vers string, notamment si je colle des 0 dans un string je sais pas trop ce que ça fait.

    Je vais donc aussi virer les std::string.

    Merci pour ton aide précieuse !

    Je

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2006
    Messages : 412
    Par défaut
    Citation Envoyé par r0d Voir le message
    Ha ok je vois maintenant. Oui bien sûr, où avais-je la tête...
    Oui alors effectivement, c'est un peu plus compliqué que je ne le pensais.
    Je n'ai pas le temps de regarder en détail, mais effectivement, il faut faire attention à la façon dont tu lis et écris les données, parce que là tu effectues des manipulations en binaire. Il faut donc éviter les char, et ne manipuler que des unsigned char (le signe dans le char fausse les opérations). Pas de char => pas de std::string. A la limite, des std::biset, mais je sais pas trop si c'est une bonne idée ici. Essaie de lire et écrire tes fichiers en mode binaire (std::ios::bin) et vois ce que ça donne.
    hello
    Cela voudrai dire que std::string a un bug que je considère comme grave (tout est relatif)
    car si la conversion ce fait mal pas mal d'appli aurai du souci a ce faire, je pense que sa doit venir des pointeur et le C qui son a mon avis la source du problème.

  12. #12
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par panthere noire Voir le message
    Cela voudrai dire que std::string a un bug
    Non, ça veut dire que le type char n'est pas fait pour manipuler des données en binaire. De même que le type float n'est pas fait pour manipuler des entiers, c'est aussi simple que cela.

  13. #13
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut
    Le type char me semble pas mal du tout pour lire du binaire, après on peut se poser la question de unsigned ou non.
    Le problème doit plutôt se situer autour de std::string qui est gaulé je présume pour manipuler du texte plutôt que du binaire.

    Si en C pur on utilise un fopen() pour lire un fichier dans un buffer char*, puis qu'on écrit le contenu du buffer dans un autre fichier, ça marche. Un fichier binaire bien sûr.

    J'aurais aimé éviter de manipuler des char* dans mon prog C++, notamment pour l'allocation, j'aurais préférer utiliser des objets. Peut-être avec bitset ?

    En tous cas dans un premier temps je vire tout ce qui est std::string et je remplace par du char* pour valider le concept.

  14. #14
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Tu fais comme tu veux, mais d'expérience, je peux t'assurer que le problème n'est pas dans la classe string (qui n'est qu'un vector de char un peu amélioré) mais du type char.

    Parfois (selon les plateforme, les libs, etc.) on trouve un type BYTE, qui n'est qu'un define sur un unsigned char.

    Dans ma lib perso, j'ai des fonctions de traitements de string d'unsigned char (des std::basic_string<unsigned char> avec la politique qui va bien, je rappelle que la classe std::string est un basic_string<char>) et qui fonctionnent bien (elles sont utilisées en production sur plusieurs applis).

    Il faut bien comprendre que le premier bit d'un char est son signe, du coup les traitements (à niveau du compilateur, pas à niveau de la classe string) son faussé si on souhaite manipuler des octets (en binaire quoi), puisque le premier bit n'a pas la même signification dans un cas que dans l'autre.

  15. #15
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Vojenbon Voir le message
    Le type char me semble pas mal du tout pour lire du binaire, après on peut se poser la question de unsigned ou non.
    Il arrive souvent qu'on aie des pbs lorsqu'on manipule des octets avec des char signés. C'est pour ça qu'on essaie en général d'utiliser des unsigned char.

    Pour ton problème, ça se fait rapidement avec la STL :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    #include <fstream>
    #include <iterator>
    #include <algorithm>
    #include <functional>
    #include <string>
     
    typedef std::basic_string<unsigned char> byte_string;
     
    struct my_key
    {
       my_key(byte_string const&key_)
       :key(key_),index(0),len(key_.size())
       {}
       unsigned char operator()(unsigned char c_)
       {
          unsigned char c_ret = c_^key[index];
          ++index;
          if(index>len){index=0;}
     
          return c_ret;
       }
       byte_string const key;
       int index;
       int const len;
     
    };
     
     
    int main()
    {
       std::basic_ifstream<unsigned char> input("input_file",std::ios::binary);
       std::basic_ofstream<unsigned char> output("output_file",std::ios::binary);
     
       unsigned char const key[]="coucou";
       std::transform(
          std::istreambuf_iterator<unsigned char>(input.rdbuf())
          ,std::istreambuf_iterator<unsigned char>()
          ,std::ostreambuf_iterator<unsigned char>(output.rdbuf())
          ,my_key(key)
       );
     
       return 0;
     
    }
    dont r0d propose un excellent tutoriel

  16. #16
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Merci pour la pub chef

  17. #17
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut
    En tous cas merci pour vos réponses.

    Je vais essayer le bout de code de 3DArchi (et demander à la doc ce qu'elle pense de std::transform parce que je sais même pas à quoi ça sert =) ).
    Alors Rod, pour etayer ma théorie sur les char, j'ai viré tous les string, j'ai mis que des char ! Et voilà ! Ca marche pas du tout ... hm... bon ok donc voilà ma théorie -> poubelle, je vais me coucher.
    Le truc aussi c'est qu'on peut difficilement utiliser du unsigned char avec du ostream comme je faisais, parce qu'ostream attend du char signé. Et le cast là je le sens pas... enfin bon on s'en fout, je vais comme je disais, quand j'aurais fini de raconter ma vie, tester le code de 3DArchi.

    Et re merci !

  18. #18
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 15
    Par défaut
    J'essaye de comprendre le code là, et comme je suis habitué au C j'ai du mal.
    En regardant sur le site ce microsoft, je vois que basic_ifstream::rdbuf() retourne l'adresse du buffer du flux.
    Je suppose qu'en utilisant le transform, on va lire octet par octet le fichier, et à chaque fois écrire l'octet encodé généré.

    Par contre du coup je vois pas du tout ce que ça fait, c'est boîte noire.
    En C, tu dis je veux prendre 127 octets du fichier d'entrée, je mets ça dans mon buffer, je m'amuse avec, et puis j'écris 127 octets. dans le fichier de sortie.

    Là, il prend tout le fichier d'un coup dans un buffer ? Il lit ça au goutte à goutte ? Comment ça marche si je veux lire des tronçons de données ?

  19. #19
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Indépendamment des différentes remarques qui t'ont déjà été faite et de différentes erreurs dans le code (void main(void), utilisation de xor, etc.), l'erreur que tu décris me semble provenir de la ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fichierIn.read(i*nbChunk, BUF_LEN);
    Qui devrait plutôt être :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fichierIn.read(i*BUF_LEN, BUF_LEN);

  20. #20
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Vojenbon Voir le message
    [...]
    std::transform est un algorithme de la STL qui construit un ensemble en appliquant un foncteur à chacun des éléments de l'ensemble de départ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    OutputIterator transform( 
       InputIterator first, 
       InputIterator last,
       OutputIterator result, 
      UnaryOperator op 
    )
    {
      while (first != last){
        *result++ = op(*first++);
       }
      return result;
    }
    my_key jour le rôle de opération.
    std::istreambuf_iterator présente le buffer comme un itérateur (InputIterator). Schématiquement, l'opérateur '*' retourne le caractère courant et ++ lit le caractère suivant.
    std::ostreambuf_iterator fait la même chose mais pour un buffer de sortie. Au lieu de lire, on écrit.
    Un streambuffer peut se comprendre comme ... un buffer. Est-ce qu'il lit caractère par caractère, par bloc de 127 octets ou tout d'un coup ? A la limite, tant que tu n'as pas identifié de problème de perf à ce niveau, ce n'est pas ton problème. C'est un détail d'implémentation de ta STL

Discussions similaires

  1. TCP et transfert de fichiers : Perte de données ?
    Par Latoof dans le forum Réseau
    Réponses: 2
    Dernier message: 31/10/2011, 14h30
  2. Réponses: 5
    Dernier message: 18/10/2009, 13h42
  3. "Erreur de fichier : risque de perte de données"
    Par Carmiel dans le forum Excel
    Réponses: 2
    Dernier message: 20/03/2009, 20h18
  4. Erreur de fichier : Risque de perte de données
    Par sefilote dans le forum Excel
    Réponses: 4
    Dernier message: 20/03/2009, 11h22
  5. Réponses: 3
    Dernier message: 16/02/2006, 18h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo