Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Défis] #8 : Tout en Base64

Pour tous les niveaux

    10 décembre 2011 à 11:21:08

    Bonjour à tous les zéros,

    Cette semaine, nous vous proposons d'étudier le codage Base64. N'ayez pas peur si vous ne savez pas ce que c'est : toutes les notions pré-requises et externes à la programmation seront expliquées.

    Si vous souhaitez plus de renseignements sur les défis, rendez vous sur le topic de recensement des défis, vous y trouverez également les règles principales.


    Tout en Base64



    Base64 est un codage permet de représenter une suite de bit quelconque avec seulement 65 caractères. Le but étant un gain de portabilité vu que les 65 caractères utilisés sont très courant. L'avantage le plus important étant qu'il permet de coder facilement des données binaires comme une image ou un exécutable par exemple, il permet dans ce cas, un gain de taille lors du codage.
    Le codage Base64 est utilisée par exemple dans l'envoi de Mail ou encore en CSS ;)

    Plus d'info sur Wikipédia ;)

    Comment ça marche ?



    Oui bonne question, on va voir cela ensemble.
    Vous savez que chaque caractère (char) est en fait un octet ? Sinon, je vous l'apprend :D Ainsi 'a' correspond à 91 en décimale ... La table de correspondante la plus courante (char-set en anglais) est l'ASCII, d'où la table ASCII ...
    Vous savez que chaque octet est codé sur 8 bits ? Et que par conséquent, 3 octets font 24 bits ?
    Mais si on se base sur 4 paquets de 6 bits ? On obtient aussi 24 bits.
    Le but du codage Base64 est de transformer les 3 octets de 24 bits en 4 paquets de 6 bits. Ensuite, on utilisera l'alphabet du Base64 qui est :
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
    Afin de faire correspondre les octets obtenus à des caractères.

    Le principe, on part de 3 octets par exemple :
    11011110 00110000 00101100 soit en décimal : 222 48 44
    et on va les découper ainsi :
    110111 100011 000000 101100 soit en décimal : 55 35 0 44

    Si on prend le 55 caractères de l'alphabet du codage Base64 on obtient le caractère '3'.
    Donc :
    55 -> 3
    35 -> j
    00 -> A
    44 -> s

    Donc la suite de bit 11011110 00110000 00101100 en Base64 donne 3jAs ;)

    Pour coder une suite plus longue, on répète l'opération pour chaque groupe de 3 caractères ;)

    Mais si le dernier groupe d'octet n'est pas composé de 3 octets mais de 1 ou 2 octets ?

    Tout est prévu ne vous en faites pas ;)
    Si cela arrive, on remplit le caractères manquant de 0.
    Par-contre, le paquet de 3 octets change ;)
    Si il manque 1 octet, seul les 3 premiers paquets de 6 bits sont utilisés. Le dernier est remplacé par '='.
    Si il manque 2 octets, seul les 2 premiers paquets de 6 bits sont utilisés. Les 2 derniers sont remplacés par '='.

    Plus d'info :

    Voir Google pour plus de ressources ;)

    Passons à l'exercice ;)

    Niveau 1 :
    Votre programme devra demander à l'utilisateur de rentrer une chaine de caractères que vous encoderez en Base64.
    Vous devez aussi laisser le choix à l'utilisateur de décoder ce code. Bon courage ...
    Exemple :
    Voulez-vous encoder(1) ou decoder ?
    1
    Quel chaine souhaitez-vous encoder ?
    Ache
    "Ache" en Base64 donne : "QWNoZQ=="

    Niveau 2 :
    Votre programme devra demander à l'utilisateur un nom de fichier, il encodera ce fichier en Base64. Peu importe le type du fichier original, souvenez-vous que ce n'est qu'une suite de bit.
    Exemple :
    Voulez-vous encoder(1) ou decoder ?
    1
    Quel fichier souhaitez-vous encoder ?
    ./a.out
    "./a.out" en Base64 ... 
    Retrouver le résultat dans le fichier "./a.out.base64"


    Bonne chance ;)

    Participants



    Participants Code
    yoch Niveau 2
    Niveau 2 - Bis
    Taurre Niveau 2
    Pouet_forever Niveau 2
    • Partager sur Facebook
    • Partager sur Twitter
      10 décembre 2011 à 12:19:55

      Salut,

      Il me semble qu'il y a une erreur dans l'énoncé:

      Citation : Exercices C


      Si il manque 1 octet, seul les 3 premiers octets du paquet de 4 octets sont utilisés. Le dernier est remplacé par '='.
      Si il manque 2 octets, seul les 2 premiers octets du paquet de 4 octets sont utilisés. Les 2 derniers sont remplacés par '='.



      Cela ne serait pas plutôt:

      Citation


      Si il manque 1 octet, seul les 3 premiers paquets de 6 bits sont utilisés. Le dernier est remplacé par '='.
      Si il manque 2 octets, seul les 2 premiers paquets de 6 bits sont utilisés. Les 2 derniers sont remplacés par '='.



      Sinon, très intéressant comme exercice :)
      • Partager sur Facebook
      • Partager sur Twitter
        10 décembre 2011 à 13:15:37

        Oui tout à fait :)
        Ça me semble plus logique de dire cela comme tu le fais ^^"
        • Partager sur Facebook
        • Partager sur Twitter
          10 décembre 2011 à 13:51:30

          Ce serait cool de corriger toutes les fautes aussi ! :)
          • Partager sur Facebook
          • Partager sur Twitter
            10 décembre 2011 à 14:18:46

            Citation : Pouet_forever

            Ce serait cool de corriger toutes les fautes aussi ! :)


            J'ai (re)essayé ^^" Il doit encore en rester ...

            Si tu pouvais m'aider par MP dès que tu en vois une qui te choque ce serrait sympa ;)

            PS: BonPatron.com n'est plus mon ami ...
            @che
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              10 décembre 2011 à 14:28:49

              Citation : Exercices C

              Citation : Pouet_forever

              Ce serait cool de corriger toutes les fautes aussi ! :)


              Il doit encore en resté ...


              :-°
              • Partager sur Facebook
              • Partager sur Twitter
                10 décembre 2011 à 14:40:45

                Citation

                Base64 est un codage permet de représenter


                :D
                J'ai pas relu, mais il doit en rester je pense. :-°
                Je connaissais pas bonpatron.com lol, ça n'a pas l'air de fonctionner à merveille. :p
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  10 décembre 2011 à 14:50:09

                  EDIT : Publicité ?

                  Sous Mac, et peut-être sous d'autres OS, il existe le logiciel (payant, hélas) Antidote, qui fait dictionnaire et correcteur orthographique. Et c'est bien... :-°
                  • Partager sur Facebook
                  • Partager sur Twitter
                    10 décembre 2011 à 15:15:47

                    Merci de l'attention que vous portez au défis :)
                    Je vous invite à m'indiquer les autres aberrations du genre par MP ;)
                    Histoire d'éviter d'être submergé par le flood ...
                    • Partager sur Facebook
                    • Partager sur Twitter
                    🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
                      10 décembre 2011 à 18:01:26

                      Bonsoir,

                      Pourquoi ne pas demander le décodeur qui va avec ?


                      Sinon, dommage, je l'ai fait il y a quelques années déjà (un de mes premiers contacts avec les opérateurs de décalage). Enfin, je crois que je n'ai fait que l'encodage, donc je peux toujours faire le décodeur si j'ai le temps. :)
                      • Partager sur Facebook
                      • Partager sur Twitter
                        10 décembre 2011 à 18:06:11

                        Citation : yoch


                        Pourquoi ne pas demander le décodeur qui va avec ?


                        Sinon, dommage, je l'ai fait il y a quelques années déjà (un de mes premiers contacts avec les opérateurs de décalage). Enfin, je crois que je n'ai fait que l'encodage, donc je peux toujours faire le décodeur si j'ai le temps. :)


                        C'est aussi demandé ;) Seulement, il n'y a pas d'explication à ce sujet (un peu de recherche n'as jamais fais de mal)... Relis la consigne de l'exercice 1. ;)

                        Tu peux toujours essayer de le refaire :D , c'est pas si compliqué que ça (c'est même très simple pour toi connaissant à peu prêt ton niveau ...)
                        • Partager sur Facebook
                        • Partager sur Twitter
                        🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
                          10 décembre 2011 à 20:28:15

                          Voici un code pour le niveau 2, avec codeur et décodeur inclus. Note : la partie encodage a été écrite il y a 2/3 ans dans le cadre d'un projet de mailer. Seul la partie décodage à été réalisée pour l'exo.

                          Je n'ai pas trouver comment écrire un décodeur sans utiliser une fonction spéciale pour donner la valeur d'un code b64. Ce ne doit pas être optimal. Je me souviens avoir vu un jour un code qui faisait autrement, mais la flemme de chercher.

                          #include <stdio.h>
                          #include <stdlib.h>
                          #include <string.h>
                          #include <getopt.h>
                          
                          
                          #define ENCODE  1
                          #define DECODE  2
                          
                          
                          static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
                          
                          
                          static void encode_b64 (char* in, char* out, int len)
                          {
                              out[0] = b64[in[0] >> 2];
                              out[1] = b64[(((in[0] << 6) | (in[1] >> 2)) >> 2) & 0x3f];
                              out[2] = (len > 1) ? b64[(((in[1] << 4) | (in[2] >> 4)) >> 2) & 0x3f] : '=';
                              out[3] = (len > 2) ? b64[in[2] & 0x3f] : '=';
                          }
                          
                          static unsigned val (char c)
                          {
                              if (c >= 'A' && c <= 'Z')
                                  return c - 'A';
                              else if (c >= 'a' && c <= 'z')
                                  return 26 + c - 'a';
                              else if (c >= '0' && c <= '9')
                                  return 52 + c - '0';
                              else if (c == '+')
                                  return 62;
                              else if (c == '/')
                                  return 63;
                              else
                                  return -1;
                          }
                          
                          static size_t decode_b64 (char* in, char* out)  // len == 4
                          {
                              unsigned v1 = val(in[1]);
                              unsigned v2 = val(in[2]);
                              out[0] = (val(in[0]) << 2) | (v1 >> 4);
                              if (in[1] == '=')
                                  return 1;
                              out[1] = (v1 << 4) | (v2 >> 2);
                              if (in[2] == '=')
                                  return 2;
                              out[2] = ((v2 & 0x03) << 6) | val(in[3]);
                              return 3;
                          }
                          
                          void traitement (const char* infile, const char* outfile, int flag)
                          {
                              if ( strcmp (infile,"-") != 0 )
                                  if ( freopen (infile, "r", stdin) == NULL)
                                  {
                                      perror("");
                                      exit(1);
                                  }
                              if ( strcmp (outfile,"-") != 0 )
                                  if ( freopen (infile, "w", stdout) == NULL)
                                  {
                                      perror("");
                                      fclose(stdin);
                                      exit(1);
                                  }
                          
                              if (flag == ENCODE)
                              {
                                  char ibuffer[4], obuffer[4];
                                  size_t n;
                                  while ( (n = fread(ibuffer, sizeof(char), 3, stdin)) != 0 )
                                  {
                                      ibuffer[n] = 0;
                                      encode_b64(ibuffer, obuffer, n);
                                      fwrite(obuffer, sizeof(char), 4, stdout);
                                  }
                              }
                              else if (flag == DECODE)
                              {
                                  char ibuffer[4], obuffer[4];
                                  size_t n, le;
                                  while ( (n = fread(ibuffer, sizeof(char), 4, stdin)) != 0 )
                                  {
                                      le = decode_b64(ibuffer, obuffer);
                                      fwrite(obuffer, sizeof(char), le, stdout);
                                  }
                              }
                          
                          
                              if ( strcmp (infile,"-") != 0 )
                                  fclose(stdin);
                              if ( strcmp (outfile,"-") != 0 )
                                  fclose(stdout);
                          }
                          
                          int main(int argc, char** argv)
                          {
                              int flag = 0, opt;
                              const char *file[2];
                              file[0] = file[1] = "-"; /* valeurs par défaut */
                          
                              while ((opt = getopt(argc, argv, "edi:o:")) != -1)
                              {
                                  switch (opt)
                                  {
                                  case 'e':
                                      if (flag != 0)
                                      {
                                          fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                  argv[0]);
                                          exit(EXIT_FAILURE);
                                      }
                                      flag = ENCODE;
                                      break;
                                  case 'd':
                                      if (flag != 0)
                                      {
                                          fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                  argv[0]);
                                          exit(EXIT_FAILURE);
                                      }
                                      flag = DECODE;
                                      break;
                                  case 'i':
                                      if (strcmp(file[0],"-") != 0)
                                      {
                                          fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                  argv[0]);
                                          exit(EXIT_FAILURE);
                                      }
                                      file[0] = optarg;
                                      break;
                                  case 'o':
                                      if (strcmp(file[1],"-") != 0)
                                      {
                                          fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                  argv[0]);
                                          exit(EXIT_FAILURE);
                                      }
                                      file[1] = optarg;
                                      break;
                                  default: /* '?' */
                                      fprintf(stderr, "Usage: %s [-i filename] [-o filename] name\n",
                                              argv[0]);
                                      exit(EXIT_FAILURE);
                                  }
                              }
                          
                              if (flag == 0)
                              {
                                  fprintf(stderr, "Expected argument after options\n");
                                  exit(EXIT_FAILURE);
                              }
                          
                              traitement (file[0], file[1], flag);
                          
                              return EXIT_SUCCESS;
                          }
                          


                          EDIT : Correction : ajout de l'option -o à getopt comme signalé par Taurre.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            11 décembre 2011 à 12:35:34

                            Il est vraiment bien construit ton code yoch, j'aime beaucoup :)
                            Il me semble juste qu'il y a deux petits soucis:

                            - tu as oublié de spécifier à getopt la présence de l'option "-o";
                            - si on lit sur l'entrée standard, le '\n' final est lu par fread alors que ce n'est pas forcément le comportement attendu par l'utilisateur si il entre une chaîne "à la main". EDIT: en fait, c'est même problématique dans le cas du décodage puisque le '\n' est lu et considéré comme encodé en base64.

                            Et aussi, pourquoi écrire (in[1] >> 2) >> 2 et (in[2] >> 4) >> 2 et pas simplement in[1] >> 4 et in[2] >> 6?

                            • Partager sur Facebook
                            • Partager sur Twitter
                              11 décembre 2011 à 13:12:31

                              Citation : Taurre

                              Il est vraiment bien construit ton code yoch, j'aime beaucoup :)


                              Merci ! :) L'organisation du code est inspirée des outils GNU dont j'ai eu l'occasion de lire les codes.

                              Citation : Taurre

                              - tu as oublié de spécifier à getopt la présence de l'option "-o";


                              Oups, je corrige de suite.

                              Citation : Taurre

                              - si on lit sur l'entrée standard, le '\n' final est lu par fread alors que ce n'est pas forcément le comportement attendu par l'utilisateur si il entre une chaîne "à la main". EDIT: en fait, c'est même problématique dans le cas du décodage puisque le '\n' est lu et considéré comme encodé en base64.


                              Oui, j'y ai pensé, mais je ne vois pas comment faire : si je traite les '\n' comme des cas particuliers, la lecture d'un fichier sera altérée.

                              Citation : Taurre

                              Et aussi, pourquoi écrire (in[1] >> 2) >> 2 et (in[2] >> 4) >> 2 et pas simplement in[1] >> 4 et in[2] >> 6?


                              Si tu fais attention aux parenthèses, tu verras que c'est plutôt un truc du genre : ((a << 6) | (b >> 2)) >> 2. Mais j'avoue une chose : j'ai écrit ce code sans vraie cohérence entre le choix de l'emploi des masques et celui des opérateurs de décalage, et n'ai pas la prétention que ce soit optimal.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                11 décembre 2011 à 14:27:21

                                Citation : yoch


                                Oui, j'y ai pensé, mais je ne vois pas comment faire : si je traite les '\n' comme des cas particuliers, la lecture d'un fichier sera altérée.



                                Mmmh... on devrait pouvoir y arriver en modifiant un peu la fonction traitement. Je pense que ceci devrait fonctionner:


                                void traitement (const char* infile, const char* outfile, int flag)
                                {
                                    int end = EOF;
                                
                                    if ( strcmp (infile,"-") != 0 )
                                    {
                                        if ( freopen (infile, "r", stdin) == NULL)
                                        {
                                            perror("");
                                            exit(1);
                                        }
                                    } else
                                        end = '\n';
                                
                                    if ( strcmp (outfile,"-") != 0 )
                                        if ( freopen (infile, "w", stdout) == NULL)
                                        {
                                            perror("");
                                            fclose(stdin);
                                            exit(1);
                                        }
                                
                                    if (flag == ENCODE)
                                    {
                                        char ibuffer[4], obuffer[4];
                                        size_t n;
                                        while ( (n = fread(ibuffer, sizeof(char), 3, stdin)) != 0 )
                                        {
                                            if ((unsigned char)ibuffer[n - 1] == end)
                                	        ibuffer[--n] = 0;
                                	    else
                                                ibuffer[n] = 0;
                                
                                            encode_b64(ibuffer, obuffer, n);
                                            fwrite(obuffer, sizeof(char), 4, stdout);
                                        }
                                    }
                                    else if (flag == DECODE)
                                    {
                                        char ibuffer[4], obuffer[4];
                                        size_t n, le;
                                        while ( (n = fread(ibuffer, sizeof(char), 4, stdin)) == 4 )
                                        {
                                	    le = decode_b64(ibuffer, obuffer);
                                            fwrite(obuffer, sizeof(char), le, stdout);
                                        }
                                    }
                                
                                
                                    if ( strcmp (infile,"-") != 0 )
                                        fclose(stdin);
                                    if ( strcmp (outfile,"-") != 0 )
                                        fclose(stdout);
                                    else
                                        putchar('\n'); /* juste pour l'esthétique */
                                }
                                



                                Il faut juste également modifié la fonction decode_b64 car il y a une petite erreur:


                                static size_t decode_b64 (char* in, char* out)  // len == 4
                                {
                                    unsigned v1 = val(in[1]);
                                    unsigned v2 = val(in[2]);
                                    out[0] = (val(in[0]) << 2) | (v1 >> 4);
                                    if (in[2] == '=') /* in[2] et non in[1] */
                                        return 1;
                                    out[1] = (v1 << 4) | (v2 >> 2);
                                    if (in[3] == '=') /* in[3] et non in[2] */
                                        return 2;
                                    out[2] = ((v2 & 0x03) << 6) | val(in[3]);
                                    return 3;
                                }
                                

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  11 décembre 2011 à 14:47:59

                                  Citation : Taurre

                                  Mmmh... on devrait pouvoir y arriver en modifiant un peu la fonction traitement. Je pense que ceci devrait fonctionner:
                                  [...]


                                  Joli ! Il manque la gestion pour le décodage, mais l'idée est sympa en soi. (perso, je suis un peu mitigé, car on introduit en quelque sorte une incohérence, mais il semble que ce soit justifié).

                                  <humour>Ce qui est bien aussi, c'est qu'on se rapproche encore un peu du style GNU. ;) </humour>


                                  Citation : Taurre

                                  Il faut juste également modifié la fonction decode_b64 car il y a une petite erreur:


                                  static size_t decode_b64 (char* in, char* out)  // len == 4
                                  {
                                      unsigned v1 = val(in[1]);
                                      unsigned v2 = val(in[2]);
                                      out[0] = (val(in[0]) << 2) | (v1 >> 4);
                                      if (in[2] == '=') /* in[2] et non in[1] */
                                          return 1;
                                      out[1] = (v1 << 4) | (v2 >> 2);
                                      if (in[3] == '=') /* in[3] et non in[2] */
                                          return 2;
                                      out[2] = ((v2 & 0x03) << 6) | val(in[3]);
                                      return 3;
                                  }
                                  


                                  Argh ! :honte:
                                  Re-oups, et merci ! :)
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    11 décembre 2011 à 16:24:39

                                    Citation : yoch


                                    Joli !



                                    Merci :)

                                    Citation : yoch


                                    Il manque la gestion pour le décodage, mais l'idée est sympa en soi.



                                    En fait, la gestion pour le décodage est également présente. La modification est très discrète, mais le fait de passer de fread(/* ... */) != 0 à fread(/* ... */) == 4 garantit que le '\n' final sera ignoré. En effet, comme on attends en entré une chaîne encodée en base64, on est certains de lire un multiple de 4 caractères. Donc, si on lit autre chose que 4 caractères c'est que l'on est arrivé à la fin (avec ou sans '\n') ;)

                                    Citation : yoch


                                    <humour>Ce qui est bien aussi, c'est qu'on se rapproche encore un peu du style GNU. ;) </humour>


                                    :D
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      11 décembre 2011 à 17:58:10

                                      Citation : Taurre

                                      En fait, la gestion pour le décodage est également présente. La modification est très discrète, mais le fait de passer de fread(/* ... */) != 0 à fread(/* ... */) == 4 garantit que le '\n' final sera ignoré. En effet, comme on attends en entré une chaîne encodée en base64, on est certains de lire un multiple de 4 caractères. Donc, si on lit autre chose que 4 caractères c'est que l'on est arrivé à la fin (avec ou sans '\n') ;)


                                      Ah oui, très bien vu. :)

                                      Bon, je pinaille un peu, mais on aura alors plus de mal à distinguer les entrées invalides (je n'ai d'ailleurs pas mis la gestion complète pour ce cas dans mon code, il faudrait remplacer la fonction val par :
                                      unsigned val (char c)
                                      {
                                          if (c >= 'A' && c <= 'Z')
                                              return c - 'A';
                                          else if (c >= 'a' && c <= 'z')
                                              return 26 + c - 'a';
                                          else if (c >= '0' && c <= '9')
                                              return 52 + c - '0';
                                          else if (c == '+')
                                              return 62;
                                          else if (c == '/')
                                              return 63;
                                          else
                                          {
                                              fprintf(stderr, "Invalid input file\n");
                                              exit(EXIT_FAILURE);
                                          }
                                      }
                                      


                                      EDIT :
                                      Version modifiée du code prenant en compte les erreurs éventuelles (attention, c'est déjà nettement plus moche) :

                                      #include <stdio.h>
                                      #include <stdlib.h>
                                      #include <string.h>
                                      #include <getopt.h>
                                      
                                      
                                      #define ENCODE  1
                                      #define DECODE  2
                                      
                                      
                                      static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
                                      
                                      
                                      static void encode_b64 (char* in, char* out, int len)
                                      {
                                          out[0] = b64[in[0] >> 2];
                                          out[1] = b64[(((in[0] << 6) | (in[1] >> 2)) >> 2) & 0x3f];
                                          out[2] = (len > 1) ? b64[(((in[1] << 4) | (in[2] >> 4)) >> 2) & 0x3f] : '=';
                                          out[3] = (len > 2) ? b64[in[2] & 0x3f] : '=';
                                      }
                                      
                                      static unsigned val (char c)
                                      {
                                          if (c >= 'A' && c <= 'Z')
                                              return c - 'A';
                                          else if (c >= 'a' && c <= 'z')
                                              return 26 + c - 'a';
                                          else if (c >= '0' && c <= '9')
                                              return 52 + c - '0';
                                          else if (c == '+')
                                              return 62;
                                          else if (c == '/')
                                              return 63;
                                          else
                                          {
                                              fprintf(stderr, "Invalid input file\n");
                                              exit(EXIT_FAILURE);
                                          }
                                      }
                                      
                                      static size_t decode_b64 (char* in, char* out)  // len == 4
                                      {
                                          unsigned v1 = val(in[1]);
                                          out[0] = (val(in[0]) << 2) | (v1 >> 4);
                                          if (in[2] == '=')
                                          {
                                              if (in[3] == '=')
                                                  return 1;
                                              else
                                              {
                                                  fprintf(stderr, "Invalid input file\n");
                                                  exit(EXIT_FAILURE);
                                              }
                                          }
                                          unsigned v2 = val(in[2]);
                                          out[1] = (v1 << 4) | (v2 >> 2);
                                          if (in[3] == '=')
                                              return 2;
                                          out[2] = ((v2 & 0x03) << 6) | val(in[3]);
                                          return 3;
                                      }
                                      
                                      void traitement (const char* infile, const char* outfile, int flag)
                                      {
                                          if ( strcmp (infile,"-") != 0 )
                                              if ( freopen (infile, "r", stdin) == NULL)
                                              {
                                                  perror("");
                                                  exit(EXIT_FAILURE);
                                              }
                                          if ( strcmp (outfile,"-") != 0 )
                                              if ( freopen (outfile, "w", stdout) == NULL)
                                              {
                                                  perror("");
                                                  fclose(stdin);
                                                  exit(EXIT_FAILURE);
                                              }
                                      
                                          if (flag == ENCODE)
                                          {
                                              char ibuffer[4], obuffer[4];
                                              size_t n;
                                              while ( (n = fread(ibuffer, sizeof(char), 3, stdin)) != 0 )
                                              {
                                                  ibuffer[n] = 0;
                                                  encode_b64(ibuffer, obuffer, n);
                                                  fwrite(obuffer, sizeof(char), 4, stdout);
                                              }
                                          }
                                          else if (flag == DECODE)
                                          {
                                              char ibuffer[4], obuffer[4];
                                              size_t n, le;
                                              while ( (n = fread(ibuffer, sizeof(char), 4, stdin)) == 4 )
                                              {
                                                  le = decode_b64(ibuffer, obuffer);
                                                  fwrite(obuffer, sizeof(char), le, stdout);
                                              }
                                              if (n != 0)
                                              {
                                                  fprintf(stderr, "Invalid input file\n");
                                                  exit(EXIT_FAILURE);
                                              }
                                          }
                                      
                                          if ( strcmp (infile,"-") != 0 )
                                              fclose(stdin);
                                          if ( strcmp (outfile,"-") != 0 )
                                              fclose(stdout);
                                      }
                                      
                                      
                                      int main(int argc, char** argv)
                                      {
                                          int flag = 0, opt;
                                          const char *file[2];
                                          file[0] = file[1] = "-"; /* valeurs par défaut */
                                      
                                          while ((opt = getopt(argc, argv, "edi:o:")) != -1)
                                          {
                                              switch (opt)
                                              {
                                              case 'e':
                                                  if (flag != 0)
                                                  {
                                                      fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                              argv[0]);
                                                      exit(EXIT_FAILURE);
                                                  }
                                                  flag = ENCODE;
                                                  break;
                                              case 'd':
                                                  if (flag != 0)
                                                  {
                                                      fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                              argv[0]);
                                                      exit(EXIT_FAILURE);
                                                  }
                                                  flag = DECODE;
                                                  break;
                                              case 'i':
                                                  if (strcmp(file[0],"-") != 0)
                                                  {
                                                      fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                              argv[0]);
                                                      exit(EXIT_FAILURE);
                                                  }
                                                  file[0] = optarg;
                                                  break;
                                              case 'o':
                                                  if (strcmp(file[1],"-") != 0)
                                                  {
                                                      fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                              argv[0]);
                                                      exit(EXIT_FAILURE);
                                                  }
                                                  file[1] = optarg;
                                                  break;
                                              default: /* '?' */
                                                  fprintf(stderr, "Usage: %s [-i filename] [-o filename] name\n",
                                                          argv[0]);
                                                  exit(EXIT_FAILURE);
                                              }
                                          }
                                      
                                          if (flag == 0)
                                          {
                                              fprintf(stderr, "Expected argument after options\n");
                                              exit(EXIT_FAILURE);
                                          }
                                      
                                          traitement (file[0], file[1], flag);
                                      
                                          return EXIT_SUCCESS;
                                      }
                                      


                                      EDIT2 : correction d'étourderies
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        13 décembre 2011 à 20:14:12

                                        yoch j'ai incorporé tes foctions encod64 et decod64 sache c'est tres rapide sur une application de 40Mo l'encodage fait entre 2 et 5 à 7 s pour le decodage c'est 4s je suis en admiration de ces codes c'est vraiment bien fait neamoins pour le decod64 j'ai du revoir
                                        static size_t decode_b64 (char* in, char* out)  // len == 4
                                        {
                                            unsigned v1 = val(in[0]);
                                            unsigned v2 = val(in[1]);    
                                            unsigned v3 = val(in[2]);
                                            unsigned v4 = val(in[3]);
                                            out[0] = (v1 << 2) | (v2 >> 4);
                                            if (in[2] == '=')
                                            return 1;
                                            out[1] = (v2 << 4) | (v3 >> 2);
                                            if (in[3] == '=')
                                            return 2;
                                            out[2] = ((v3 << 6) | v4);
                                            return 3;
                                        }
                                        
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          13 décembre 2011 à 21:04:09

                                          Citation : z@kesz@ko

                                          neamoins pour le decod64 j'ai du revoir

                                          static size_t decode_b64 (char* in, char* out)  // len == 4
                                          {
                                              unsigned v1 = val(in[0]);
                                              unsigned v2 = val(in[1]);    
                                              unsigned v3 = val(in[2]);
                                              unsigned v4 = val(in[3]);
                                              out[0] = (v1 << 2) | (v2 >> 4);
                                              if (in[2] == '=')
                                              return 1;
                                              out[1] = (v2 << 4) | (v3 >> 2);
                                              if (in[3] == '=')
                                              return 2;
                                              out[2] = ((v3 << 6) | v4);
                                              return 3;
                                          }
                                          

                                          Tu as simplement optimisé (ligne 13), ou il y avait un autre souci ? Merci en tout cas ! :)

                                          Sinon, j'ai aussi essayé de rendre ma fonction d'encodage un peu plus cohérente, comme ceci :
                                          static void encode_b64 (char* in, char* out, size_t len)
                                          {
                                              out[0] = b64[in[0] >> 2];
                                              out[1] = b64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
                                              out[2] = (len > 1) ? b64[((in[1] & 0x0f) << 2) | (in[2] >> 6)] : '=';
                                              out[3] = (len > 2) ? b64[in[2] & 0x3f] : '=';
                                          }
                                          


                                          Pour essayer de rendre la fonction de décodage un peu plus performante, on pourrait précalculer la table de correspondances dans un tableau.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            13 décembre 2011 à 23:45:55

                                            Bonsoir,

                                            Citation : yoch


                                            static void encode_b64 (char* in, char* out, int len)
                                            {
                                                out[0] = b64[in[0] >> 2];
                                            

                                            Si je comprends bien le source, in[0] peut avoir une valeur négative puisque que le type char peut être signé, et que du binaire est encodé, et que:

                                            Citation : C99 §6.5.7.5

                                            The result of E1 >> E2 is E1 right-shifted E2 bit positions. ... If E1 has a signed type and a negative value, the resulting value is implementation-defined.


                                            Ce source me paraît donc peu portable.

                                            Il y a aussi un soucis de portabilité avec une expression comme c >= 'A' && c <= 'Z', mais c'est un cas rare (encodage non compatible ASCII).
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              14 décembre 2011 à 0:34:32

                                              @Marc :
                                              Tu as 100% raison sur les deux points. J'y avais d'ailleurs pensé, mais la flemme...

                                              EDIT : Bon, allez, voici un code corrigé (1er point) :
                                              #include <stdio.h>
                                              #include <stdlib.h>
                                              #include <string.h>
                                              #include <getopt.h>
                                              
                                              
                                              #define ENCODE  1
                                              #define DECODE  2
                                              
                                              
                                              static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
                                              
                                              
                                              static void encode_b64 (const unsigned char* in, unsigned char* out, size_t len)
                                              {
                                                  out[0] = b64[in[0] >> 2];
                                                  out[1] = b64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
                                                  out[2] = (len > 1) ? b64[((in[1] & 0x0f) << 2) | (in[2] >> 6)] : '=';
                                                  out[3] = (len > 2) ? b64[in[2] & 0x3f] : '=';
                                              }
                                              
                                              static unsigned char val (unsigned char c)
                                              {
                                                  if (c >= 'A' && c <= 'Z')
                                                      return c - 'A';
                                                  else if (c >= 'a' && c <= 'z')
                                                      return 26 + c - 'a';
                                                  else if (c >= '0' && c <= '9')
                                                      return 52 + c - '0';
                                                  else if (c == '+')
                                                      return 62;
                                                  else if (c == '/')
                                                      return 63;
                                                  else
                                                  {
                                                      fprintf(stderr, "Invalid input file\n");
                                                      exit(EXIT_FAILURE);
                                                  }
                                              }
                                              
                                              static size_t decode_b64 (const unsigned char* in, unsigned char* out)  // len == 4
                                              {
                                                  unsigned char v1 = val(in[1]);
                                                  out[0] = (val(in[0]) << 2) | (v1 >> 4);
                                                  if (in[2] == '=')
                                                  {
                                                      if (in[3] == '=')
                                                          return 1;
                                                      else
                                                      {
                                                          fprintf(stderr, "Invalid input file\n");
                                                          exit(EXIT_FAILURE);
                                                      }
                                                  }
                                                  unsigned char v2 = val(in[2]);
                                                  out[1] = (v1 << 4) | (v2 >> 2);
                                                  if (in[3] == '=')
                                                      return 2;
                                                  out[2] = (v2 << 6) | val(in[3]);
                                                  //out[2] = ((v2 & 0x03) << 6) | val(in[3]);
                                                  return 3;
                                              }
                                              
                                              void traitement (const char* infile, const char* outfile, int flag)
                                              {
                                                  if ( strcmp (infile,"-") != 0 )
                                                      if ( freopen (infile, "rb", stdin) == NULL)
                                                      {
                                                          perror("");
                                                          exit(EXIT_FAILURE);
                                                      }
                                                  if ( strcmp (outfile,"-") != 0 )
                                                      if ( freopen (outfile, "wb", stdout) == NULL)
                                                      {
                                                          perror("");
                                                          fclose(stdin);
                                                          exit(EXIT_FAILURE);
                                                      }
                                              
                                                  if (flag == ENCODE)
                                                  {
                                                      unsigned char ibuffer[4], obuffer[4];
                                                      size_t n;
                                                      while ( (n = fread(ibuffer, sizeof(char), 3, stdin)) != 0 )
                                                      {
                                                          ibuffer[n] = 0;
                                                          encode_b64(ibuffer, obuffer, n);
                                                          fwrite(obuffer, sizeof(char), 4, stdout);
                                                      }
                                                  }
                                                  else if (flag == DECODE)
                                                  {
                                                      unsigned char ibuffer[4], obuffer[4];
                                                      size_t n, le;
                                                      while ( (n = fread(ibuffer, sizeof(char), 4, stdin)) == 4 )
                                                      {
                                                          le = decode_b64(ibuffer, obuffer);
                                                          fwrite(obuffer, sizeof(char), le, stdout);
                                                      }
                                                      if (n != 0)
                                                      {
                                                          fprintf(stderr, "Invalid input file\n");
                                                          exit(EXIT_FAILURE);
                                                      }
                                                  }
                                              
                                              
                                                  if ( strcmp (infile,"-") != 0 )
                                                      fclose(stdin);
                                                  if ( strcmp (outfile,"-") != 0 )
                                                      fclose(stdout);
                                              }
                                              
                                              int main(int argc, char** argv)
                                              {
                                                  int flag = 0, opt;
                                                  const char *file[2];
                                                  file[0] = file[1] = "-"; /* valeurs par défaut */
                                              
                                                  while ((opt = getopt(argc, argv, "edi:o:")) != -1)
                                                  {
                                                      switch (opt)
                                                      {
                                                      case 'e':
                                                          if (flag != 0)
                                                          {
                                                              fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                                      argv[0]);
                                                              exit(EXIT_FAILURE);
                                                          }
                                                          flag = ENCODE;
                                                          break;
                                                      case 'd':
                                                          if (flag != 0)
                                                          {
                                                              fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                                      argv[0]);
                                                              exit(EXIT_FAILURE);
                                                          }
                                                          flag = DECODE;
                                                          break;
                                                      case 'i':
                                                          if (strcmp(file[0],"-") != 0)
                                                          {
                                                              fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                                      argv[0]);
                                                              exit(EXIT_FAILURE);
                                                          }
                                                          file[0] = optarg;
                                                          break;
                                                      case 'o':
                                                          if (strcmp(file[1],"-") != 0)
                                                          {
                                                              fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                                      argv[0]);
                                                              exit(EXIT_FAILURE);
                                                          }
                                                          file[1] = optarg;
                                                          break;
                                                      default: /* '?' */
                                                          fprintf(stderr, "Usage: %s [-i filename] [-o filename] name\n",
                                                                  argv[0]);
                                                          exit(EXIT_FAILURE);
                                                      }
                                                  }
                                              
                                                  if (flag == 0)
                                                  {
                                                      fprintf(stderr, "Expected argument after options\n");
                                                      exit(EXIT_FAILURE);
                                                  }
                                              
                                                  traitement (file[0], file[1], flag);
                                              
                                                  return EXIT_SUCCESS;
                                              }
                                              
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                14 décembre 2011 à 12:55:33

                                                en tout cas c'est bien vu pour les paramettre de encod64 et decod64 il faut utiliser un unsign char* sinon au decodage d'un fichier autre que du texte celui-ci ne s'ouvrirait pas. je l'ai testé
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  14 décembre 2011 à 16:50:09

                                                  Voici mon code pour le niveau 2:


                                                  #include <stdio.h>
                                                  #include <stdlib.h>
                                                  #include <string.h>
                                                  
                                                  #define ENCODE 1
                                                  #define DECODE 0
                                                  
                                                  static char b64_e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs"
                                                                        "tuvwxyz0123456789+/=";
                                                  
                                                  static int b64_d[] = {
                                                  	['A'] =  0, ['B'] =  1, ['C'] =  2, ['D'] =  3, ['E'] =  4,
                                                  	['F'] =  5, ['G'] =  6, ['H'] =  7, ['I'] =  8, ['J'] =  9,
                                                  	['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14,
                                                  	['P'] = 15, ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19,
                                                  	['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24,
                                                  	['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29,
                                                  	['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34,
                                                  	['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
                                                  	['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44,
                                                  	['t'] = 45, ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49,
                                                  	['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54,
                                                  	['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59,
                                                  	['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63, ['='] = 64
                                                  };
                                                  
                                                  
                                                  static int
                                                  isbase64(unsigned char const *s, int n)
                                                  {
                                                  	while (n-- > 0)
                                                  		if (strchr(b64_e, s[n]) == NULL)
                                                  			return 0;
                                                  	return 1;
                                                  }
                                                  
                                                  
                                                  static void
                                                  delete_newline(char *s)
                                                  {
                                                  	char *p;
                                                  
                                                  	if ((p = strchr(s, '\n')) != NULL)
                                                  		*p = '\0';
                                                  }
                                                  
                                                  
                                                  static void
                                                  delete_b64(char *s)
                                                  {
                                                  	char *p;
                                                  
                                                  	if ((p = strstr(s, ".b64")) != NULL)
                                                  		*p = '\0';
                                                  }
                                                  
                                                  
                                                  static void
                                                  drain_stdin(void)
                                                  {
                                                  	while (getchar() != '\n')
                                                  		;
                                                  }
                                                  
                                                  
                                                  static int
                                                  get_nbytes(unsigned char *byte, int n, FILE *fp)
                                                  {
                                                  	int i;
                                                  	int end = (fp == stdin) ? '\n' : EOF;
                                                  
                                                  	memset(byte, 0, n);
                                                  	for (i = 0; i < n; i++) {
                                                  		int c;
                                                  
                                                  		if ((c = getc(fp)) != EOF && c != end)
                                                  			byte[i] = c;
                                                  		else
                                                  			break;
                                                  	}
                                                  
                                                  	return (ferror(fp)) ? -1 : i;
                                                  }
                                                  
                                                  
                                                  static FILE *
                                                  base64_encode(FILE *fp)
                                                  {
                                                  	unsigned char byte[3];
                                                  	FILE *tmp;
                                                  	int n;
                                                  
                                                  	if ((tmp = tmpfile()) == NULL)
                                                  		return NULL;
                                                  
                                                  	do {
                                                  		unsigned char pkg[4];
                                                  
                                                  		if ((n = get_nbytes(byte, 3, fp)) <= 0)
                                                  			break;
                                                  
                                                  		pkg[0] = (byte[0] >> 2);
                                                  		pkg[1] = (byte[0] << 4 | byte[1] >> 4) & 0x3f;
                                                  		pkg[2] = (byte[1] << 2 | byte[2] >> 6) & 0x3f;
                                                  		pkg[3] = (byte[2] & 0x3f);
                                                  
                                                  		putc(b64_e[pkg[0]], tmp);
                                                  		putc(b64_e[pkg[1]], tmp);
                                                  		putc((n >= 2) ? b64_e[pkg[2]] : '=', tmp);
                                                  		putc((n >= 3) ? b64_e[pkg[3]] : '=', tmp);
                                                  	} while (n == 3);
                                                  
                                                  	rewind(tmp);
                                                  	return (n >= 0) ? tmp : NULL;
                                                  }
                                                  
                                                  
                                                  static FILE *
                                                  base64_decode(FILE *fp)
                                                  {
                                                  	unsigned char pkg[4];
                                                  	FILE *tmp;
                                                  	int n;
                                                  
                                                  	if ((tmp = tmpfile()) == NULL)
                                                  		return NULL;
                                                  
                                                  	while ((n = get_nbytes(pkg, 4, fp)) == 4) {
                                                  		unsigned char byte[4];
                                                  
                                                  		if (!isbase64(pkg, 4))
                                                  			return NULL;
                                                  
                                                  		byte[0] = (b64_d[pkg[0]] << 2 | b64_d[pkg[1]] >> 4);
                                                  		byte[1] = (b64_d[pkg[1]] << 4 | b64_d[pkg[2]] >> 2);
                                                  		byte[2] = (b64_d[pkg[2]] << 6 | b64_d[pkg[3]]);
                                                  
                                                  		putc(byte[0], tmp);
                                                  		(pkg[2] != '=') ? putc(byte[1], tmp) : 0;
                                                  		(pkg[3] != '=') ? putc(byte[2], tmp) : 0;
                                                  	}
                                                  
                                                  	rewind(tmp);
                                                  	return (n >= 0) ? tmp : NULL;
                                                  }
                                                  
                                                  
                                                  static void
                                                  copy(FILE *src, FILE *dst, int end)
                                                  {
                                                  	int c;
                                                  
                                                  	while ((c = getc(src)) != EOF)
                                                  		putc(c, dst);
                                                  
                                                  	if (end)
                                                  		putc(end, dst);
                                                  }
                                                  
                                                  
                                                  static int
                                                  menu(int *action, FILE **in, FILE **out)
                                                  {
                                                  	static char tmp[FILENAME_MAX];
                                                  
                                                  	printf("Do you want to encode(1) or decode(0)? ");
                                                  	fflush(stdout);
                                                  
                                                  	if (scanf("%d", action) != 1)
                                                  		return 0;
                                                  	drain_stdin();
                                                  
                                                  	printf("Which file do you want to %scode('-' for stdin)?\n",
                                                  	       (*action) ? "en" : "de");
                                                  
                                                  	fgets(tmp, FILENAME_MAX, stdin);
                                                  	delete_newline(tmp);
                                                  
                                                  	if (strcmp(tmp, "-") == 0) {
                                                  		*in = stdin;
                                                  		*out = stdout;
                                                  		return 1;
                                                  	}
                                                  
                                                  	if ((*in = fopen(tmp, "r")) == NULL)
                                                  		return 0;
                                                  
                                                  	if (*action == DECODE)
                                                  		delete_b64(tmp);
                                                  
                                                  	strncat(tmp, (*action) ? ".b64" : ".orig", FILENAME_MAX);
                                                  	tmp[FILENAME_MAX - 1] = '\0';
                                                  
                                                  	if ((*out = fopen(tmp, "w")) == NULL) {
                                                  		fclose(*in);
                                                  		return 0;
                                                  	}
                                                  
                                                  	printf("Result saved in %s", tmp);
                                                  	return 1;
                                                  }
                                                  
                                                  
                                                  int
                                                  main(void)
                                                  {
                                                  	int action;
                                                  	FILE *in, *out, *tmp;
                                                  
                                                  	if (!menu(&action, &in, &out)) {
                                                  		fputs("Invalid entry!\n", stderr);
                                                  		return EXIT_FAILURE;
                                                  	}
                                                  
                                                  	if (action == ENCODE)
                                                  		tmp = base64_encode(in);
                                                  	else
                                                  		tmp = base64_decode(in);
                                                  
                                                  	if (tmp == NULL) {
                                                  		fprintf(stderr, "Error when %scoding\n",
                                                  		        (action) ? "en" : "de");
                                                  		fclose(in);
                                                  		fclose(out);
                                                  		return EXIT_FAILURE;
                                                  	}
                                                  
                                                  	copy(tmp, out, (out == stdout) ? '\n' : 0);
                                                  	fclose(in);
                                                  	fclose(out);
                                                  	return EXIT_SUCCESS;
                                                  }
                                                  



                                                  J'utilise un tableau statique pour le décodage et un fichier temporaire afin de stocker les données encodées ou décodées. Je n'aime pas trop la fonction menu qui fait un peu "fourre-tout", mais bon, je ne vois pas trop comment faire autrement si l'on suit l'énoncé :)
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    14 décembre 2011 à 18:11:18

                                                    Je n'ai pas encore tout vu, juste 2/3 trucs qui m'ont frappés :

                                                    static int b64_d[] = {
                                                    	['A'] =  0, ['B'] =  1, ['C'] =  2, ['D'] =  3, ['E'] =  4,
                                                    	['F'] =  5, ['G'] =  6, ['H'] =  7, ['I'] =  8, ['J'] =  9,
                                                    	['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14,
                                                    	['P'] = 15, ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19,
                                                    	['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24,
                                                    	['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29,
                                                    	['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34,
                                                    	['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
                                                    	['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44,
                                                    	['t'] = 45, ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49,
                                                    	['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54,
                                                    	['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59,
                                                    	['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63, ['='] = 64
                                                    };
                                                    

                                                    Je ne connaissais pas cette façon de déclarer et initialiser un tableau, tu pourrais donner une référence, s'il te plait ?

                                                    Citation : Taurre

                                                    J'utilise un tableau statique pour le décodage et un fichier temporaire afin de stocker les données encodées ou décodées.



                                                    A priori, l'utilisation d'un tel tableau pour le décodage est excellente pour les perfs. Sauf que ton implémentation de isbase64 n'est malgré tout pas très efficace, car tu utilise strchr pour chaque caractère).

                                                    Perso, j'ai imaginé faire comme ça :
                                                    #include <stdio.h>
                                                    #include <stdlib.h>
                                                    #include <string.h>
                                                    #include <getopt.h>
                                                    
                                                    
                                                    #define ENCODE  1
                                                    #define DECODE  2
                                                    
                                                    
                                                    static const unsigned char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
                                                    static unsigned char b64_decode[256];
                                                    
                                                    
                                                    static void encode_b64 (const unsigned char* in, unsigned char* out, size_t len)
                                                    {
                                                        out[0] = b64[in[0] >> 2];
                                                        out[1] = b64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
                                                        out[2] = (len > 1) ? b64[((in[1] & 0x0f) << 2) | (in[2] >> 6)] : '=';
                                                        out[3] = (len > 2) ? b64[in[2] & 0x3f] : '=';
                                                    }
                                                    
                                                    static size_t decode_b64 (const unsigned char* in, unsigned char* out)  // len == 4
                                                    {
                                                        unsigned char v0 = b64_decode[in[0]];
                                                        unsigned char v1 = b64_decode[in[1]];
                                                        unsigned char v2 = b64_decode[in[2]];
                                                        unsigned char v3 = b64_decode[in[3]];
                                                    
                                                        if (   ((v0 | v1 | v2 | v3) & 0x80)     /* Invalids characters */
                                                            || (in[2] == '=' && in[3] != '=')   /* Valid character after '=' */
                                                           )
                                                        {
                                                            fprintf(stderr, "Invalid input file\n");
                                                            exit(EXIT_FAILURE);
                                                        }
                                                    
                                                        out[0] = (v0 << 2) | (v1 >> 4);
                                                        if (in[2] == '=')
                                                            return 1;
                                                    
                                                        out[1] = (v1 << 4) | (v2 >> 2);
                                                        if (in[3] == '=')
                                                            return 2;
                                                    
                                                        out[2] = (v2 << 6) | v3;
                                                        return 3;
                                                    }
                                                    
                                                    void init_decode_array (void)
                                                    {
                                                        size_t i;
                                                        for (i = 0; i < sizeof b64_decode / sizeof *b64_decode; i++)
                                                            b64_decode[i] = 0x80;
                                                        for (i = 0; i < sizeof b64 / sizeof *b64; i++)
                                                            b64_decode[b64[i]] = i;
                                                        b64_decode['='] = 0x40;
                                                    }
                                                    
                                                    void traitement (const char* infile, const char* outfile, int flag)
                                                    {
                                                        if ( strcmp (infile,"-") != 0 )
                                                            if ( freopen (infile, "rb", stdin) == NULL)
                                                            {
                                                                perror("");
                                                                exit(EXIT_FAILURE);
                                                            }
                                                        if ( strcmp (outfile,"-") != 0 )
                                                            if ( freopen (outfile, "wb", stdout) == NULL)
                                                            {
                                                                perror("");
                                                                fclose(stdin);
                                                                exit(EXIT_FAILURE);
                                                            }
                                                    
                                                        if (flag == ENCODE)
                                                        {
                                                            unsigned char ibuffer[4], obuffer[4];
                                                            size_t n;
                                                            while ( (n = fread(ibuffer, sizeof(char), 3, stdin)) != 0 )
                                                            {
                                                                ibuffer[n] = 0;
                                                                encode_b64(ibuffer, obuffer, n);
                                                                fwrite(obuffer, sizeof(char), 4, stdout);
                                                            }
                                                        }
                                                        else if (flag == DECODE)
                                                        {
                                                            init_decode_array();
                                                    
                                                            unsigned char ibuffer[4], obuffer[4];
                                                            size_t n, le;
                                                            while ( (n = fread(ibuffer, sizeof(char), 4, stdin)) == 4 )
                                                            {
                                                                le = decode_b64(ibuffer, obuffer);
                                                                fwrite(obuffer, sizeof(char), le, stdout);
                                                            }
                                                            if (n != 0)
                                                            {
                                                                fprintf(stderr, "Invalid input file\n");
                                                                exit(EXIT_FAILURE);
                                                            }
                                                        }
                                                    
                                                    
                                                        if ( strcmp (infile,"-") != 0 )
                                                            fclose(stdin);
                                                        if ( strcmp (outfile,"-") != 0 )
                                                            fclose(stdout);
                                                    }
                                                    
                                                    
                                                    int main(int argc, char** argv)
                                                    {
                                                        int flag = 0, opt;
                                                        const char *file[2];
                                                        file[0] = file[1] = "-"; /* valeurs par défaut */
                                                    
                                                        while ((opt = getopt(argc, argv, "edi:o:")) != -1)
                                                        {
                                                            switch (opt)
                                                            {
                                                            case 'e':
                                                                if (flag != 0)
                                                                {
                                                                    fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                                            argv[0]);
                                                                    exit(EXIT_FAILURE);
                                                                }
                                                                flag = ENCODE;
                                                                break;
                                                            case 'd':
                                                                if (flag != 0)
                                                                {
                                                                    fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                                            argv[0]);
                                                                    exit(EXIT_FAILURE);
                                                                }
                                                                flag = DECODE;
                                                                break;
                                                            case 'i':
                                                                if (strcmp(file[0],"-") != 0)
                                                                {
                                                                    fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                                            argv[0]);
                                                                    exit(EXIT_FAILURE);
                                                                }
                                                                file[0] = optarg;
                                                                break;
                                                            case 'o':
                                                                if (strcmp(file[1],"-") != 0)
                                                                {
                                                                    fprintf(stderr, "Usage: %s [-e : -d] [-i filename] [-o filename] name\n",
                                                                            argv[0]);
                                                                    exit(EXIT_FAILURE);
                                                                }
                                                                file[1] = optarg;
                                                                break;
                                                            default: /* '?' */
                                                                fprintf(stderr, "Usage: %s [-i filename] [-o filename] name\n",
                                                                        argv[0]);
                                                                exit(EXIT_FAILURE);
                                                            }
                                                        }
                                                    
                                                        if (flag == 0)
                                                        {
                                                            fprintf(stderr, "Expected argument after options\n");
                                                            exit(EXIT_FAILURE);
                                                        }
                                                    
                                                        traitement (file[0], file[1], flag);
                                                    
                                                        return EXIT_SUCCESS;
                                                    }
                                                    
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      14 décembre 2011 à 18:57:17

                                                      Citation : yoch

                                                      static int b64_d[] = {
                                                      	['A'] =  0, ['B'] =  1, ['C'] =  2, ['D'] =  3, ['E'] =  4,
                                                      	['F'] =  5, ['G'] =  6, ['H'] =  7, ['I'] =  8, ['J'] =  9,
                                                      	['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14,
                                                      	['P'] = 15, ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19,
                                                      	['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24,
                                                      	['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29,
                                                      	['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34,
                                                      	['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
                                                      	['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44,
                                                      	['t'] = 45, ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49,
                                                      	['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54,
                                                      	['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59,
                                                      	['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63, ['='] = 64
                                                      };
                                                      

                                                      Ah bah voilà ce que je cherchais !
                                                      J'ai fait une table d'équivalence en tapant sur la table ASCII (ASCII obligatoire pour ce code :p ). Je cherchais un moyen de faire comme toi, bah merci de m'avoir montré ça. J'avais carrément oublié ! ^^

                                                      yoch > C'est marqué dans la norme 6.7.8. :)
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        14 décembre 2011 à 19:36:07

                                                        Citation : yoch


                                                        Je n'ai pas encore tout vu, juste 2/3 trucs qui m'ont frappés :


                                                        static int b64_d[] = {
                                                        	['A'] =  0, ['B'] =  1, ['C'] =  2, ['D'] =  3, ['E'] =  4,
                                                        	['F'] =  5, ['G'] =  6, ['H'] =  7, ['I'] =  8, ['J'] =  9,
                                                        	['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14,
                                                        	['P'] = 15, ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19,
                                                        	['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24,
                                                        	['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29,
                                                        	['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34,
                                                        	['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
                                                        	['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44,
                                                        	['t'] = 45, ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49,
                                                        	['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54,
                                                        	['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59,
                                                        	['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63, ['='] = 64
                                                        };
                                                        


                                                        Je ne connaissais pas cette façon de déclarer et initialiser un tableau, tu pourrais donner une référence, s'il te plait ?



                                                        Ce type d'initialisation n'existe que depuis le C99, il y a d'ailleurs un mécanisme similaire pour initialiser certains champs d'une structure/union. Comme l'a dit Pouet_forever, c'est au point 6.7.8 de la Norme. Le paragraphe en question:

                                                        Citation : Norme C99 6.7.8 § 6 p 125


                                                        If a designator has the form

                                                        [ constant-expression ]

                                                        then the current object (defined below) shall have array type and the expression shall be
                                                        an integer constant expression. If the array is of unknown size, any nonnegative value is
                                                        valid.



                                                        Citation : yoch


                                                        Sauf que ton implémentation de isbase64 n'est malgré tout pas très efficace, car tu utilise strchr pour chaque caractère).



                                                        En fait, mon but est d'être certains que les caractères lus correspondent à des cases du tableau b64_d histoire d'éviter tout dépassement. Or, je ne vois pas d'autres solutions pour l'instant.

                                                        Sinon, dans le code que tu montres, à cette condition:

                                                        if (   ((v0 | v1 | v2 | v3) & 0x80)     /* Invalids characters */
                                                            || (in[2] == '=' && in[3] != '=')   /* Valid character after '=' */
                                                           )
                                                        


                                                        le masque utilisé ne devrait pas plutôt être 0xc0 puisque l'encodage en base64 n'utilise que 6 bits?
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          14 décembre 2011 à 19:48:03

                                                          Merci pour ces précisions ! :)

                                                          Citation : Taurre

                                                          En fait, mon but est d'être certains que les caractères lus correspondent à des cases du tableau b64_d histoire d'éviter tout dépassement.


                                                          Oui, j'ai bien compris ça. ;)

                                                          Citation : Taurre

                                                          Sinon, dans le code que tu montres, à cette condition:

                                                          if (   ((v0 | v1 | v2 | v3) & 0x80)     /* Invalids characters */
                                                              || (in[2] == '=' && in[3] != '=')   /* Valid character after '=' */
                                                             )
                                                          



                                                          le masque utilisé ne devrait pas plutôt être 0xc0 puisque l'encodage en base64 n'utilise que 6 bits?


                                                          Non, car comme toi, je donne la valeur 64 (0x40) pour '=', et j'utilise la valeur 128 (0x80) pour tous les caractères non reconnus (cf. fonction init_decode_array), ce qui me permet justement d'avoir un test performant pour les caractères inconnus. (si 0 <= v_ <= 64, ok, sinon v_ == 128 ce qui signifie que le caractère rencontré est invalide).
                                                          Cependant, je n'ai pas trouvé comment définir ça en dur dans le code, je suis obligé de passer par une initialisation dynamique.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            14 décembre 2011 à 20:29:27

                                                            Citation : yoch

                                                            Merci pour ces précisions ! :)

                                                            Citation : Taurre

                                                            En fait, mon but est d'être certains que les caractères lus correspondent à des cases du tableau b64_d histoire d'éviter tout dépassement.


                                                            Oui, j'ai bien compris ça. ;)

                                                            Citation : Taurre

                                                            Sinon, dans le code que tu montres, à cette condition:

                                                            if (   ((v0 | v1 | v2 | v3) & 0x80)     /* Invalids characters */
                                                                || (in[2] == '=' && in[3] != '=')   /* Valid character after '=' */
                                                               )
                                                            



                                                            le masque utilisé ne devrait pas plutôt être 0xc0 puisque l'encodage en base64 n'utilise que 6 bits?


                                                            Non, car comme toi, je donne la valeur 64 (0x40) pour '=', et j'utilise la valeur 128 (0x80) pour tous les caractères non reconnus (cf. fonction init_decode_array), ce qui me permet justement d'avoir un test performant pour les caractères inconnus. (si 0 <= v_ <= 64, ok, sinon v_ == 128 ce qui signifie que le caractère rencontré était invalide).
                                                            Cependant, je n'ai pas trouvé comment définir ça en dur dans le code, je suis obligé de passer par une initialisation dynamique.



                                                            Ah oui, pardon, j'avais lu le code un peu vite. :honte:
                                                            Je mettrais juste UCHAR_MAX comme taille maximale de b64_decode, mais sinon c'est effectivement nettement plus performant que ma solution. :)
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              15 décembre 2011 à 21:42:57

                                                              Bon, voilà mon code. J'ai voulu faire un truc, mais je suis pas trop fier de ce que j'ai fait. :(
                                                              Comme j'ai dit plus bas, j'ai utilisé un tableau qui tape sur l'ascii, donc non portable sur un système non ascii. :)
                                                              Je ne gère pas non plus les caractères invalides pour le b64 (bon, c'est pas méchant à rajouter).

                                                              #include <stdio.h>
                                                              #include <stdlib.h>
                                                              
                                                              enum state_e {
                                                                M_ENCODE = 1,
                                                                M_DECODE,
                                                                M_EXIT
                                                              };
                                                              
                                                              unsigned char ascii[] = {
                                                                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
                                                                0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
                                                                0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x3E, 0x2C, 0x2D, 0x2E, 0x3F,
                                                                0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3A, 0x3B, 0x3C, 0x00, 0x3E, 0x3F,
                                                                0x40, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
                                                                0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
                                                                0x60, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
                                                                0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
                                                                0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
                                                                0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
                                                                0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
                                                                0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
                                                                0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
                                                                0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
                                                                0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
                                                                0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
                                                              };
                                                              
                                                              char const b64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
                                                              
                                                              /* base 64 to ascii */
                                                              int b64toa_getbits(FILE * in, char * s) {
                                                                return fread(s, sizeof *s, 4, in);
                                                              }
                                                              
                                                              int b64toa_setbits(char * s, int c, char * t) {
                                                                (void) c;
                                                                t[0] = (char) (ascii[s[0]] << 2) | (ascii[s[1]] >> 4);
                                                                t[1] = (char) (ascii[s[1]] << 4) | (ascii[s[2]] >> 2);
                                                                t[2] = (char) (ascii[s[2]] << 6) | (ascii[s[3]] >> 0);
                                                                
                                                                return (s[2] == '=') + (s[3] == '=');
                                                              }
                                                              
                                                              int b64toa_writebits(FILE * in, char * s, int off) {
                                                                return fwrite(s, sizeof *s, 3 - off, in);
                                                              }
                                                              
                                                              /* ascii to base64 */
                                                              int atob64_getbits(FILE * in, char * s) {
                                                                int c, i;
                                                                
                                                                i = 0;
                                                                do {
                                                                  c = fgetc(in);
                                                                  if ((in == stdin && c == '\n') || c == EOF) {
                                                                    ungetc(c, in);
                                                                    break;
                                                                  }
                                                                  s[i++] = (char) c;
                                                                } while (i < 3);
                                                                
                                                                return i;
                                                              }
                                                              
                                                              int atob64_setbits(char * s, int c, char * t) {
                                                                t[0] = b64[s[0] >> 2];
                                                                t[1] = (char) ((s[0] & 0x3) << 4);
                                                                t[2] = '=';
                                                                t[3] = '=';
                                                                
                                                                if (c > 1) {
                                                                  t[1] = b64[t[1] | (s[1] >> 4)];
                                                                  t[2] = (char) ((s[1] & 0xF) << 2);
                                                                }
                                                                else
                                                                  t[1] = b64[t[1]];
                                                                
                                                                if (c > 2) {
                                                                  t[2] = b64[t[2] | (s[2] >> 6)];
                                                                  t[3] = b64[s[2] & 0x3F];
                                                                }
                                                                else if (c > 1)
                                                                  t[2] = b64[t[2]];
                                                                
                                                                return 0;
                                                              }
                                                              
                                                              int atob64_writebits(FILE * in, char * s, int off) {
                                                                (void) off;
                                                                return fwrite(s, sizeof *s, 4, in);
                                                              }
                                                              
                                                              void clearbuff(void) {
                                                                int c;
                                                                
                                                                do {
                                                                  c = getchar();
                                                                  if (c != '\n' && c != EOF) {
                                                                    ungetc(c, stdin);
                                                                    break;
                                                                  }
                                                                } while (c != '\n' && c != EOF);
                                                              }
                                                              
                                                              int process(FILE * in, FILE * out,
                                                                       int (*getbits)(FILE *, char *),
                                                                       int (*setbits)(char *, int, char *),
                                                                       int (*writebits)(FILE *, char *, int)) {
                                                                char s[6] = "";
                                                                char t[6] = "";
                                                                int c, n;
                                                                
                                                                while ((c = getbits(in, s)) != 0) {
                                                                  if (in == stdin)
                                                                    clearbuff();
                                                                  n = setbits(s, c, t);
                                                                  writebits(out, t, n);
                                                                  if (out == stdout) {
                                                                    fflush(stdout);
                                                                  }
                                                                }
                                                                
                                                                return 0;
                                                              }
                                                              
                                                              void loop(FILE * in, FILE * out) {
                                                                int done;
                                                                int c;
                                                                
                                                                done = 0;
                                                                while (!done) {
                                                                  printf("1 - Encode\n");
                                                                  printf("2 - Decode\n");
                                                                  printf("3 - Quit\n");
                                                                  scanf("%d", &c);
                                                                  clearbuff();
                                                                  
                                                                  switch (c) {
                                                                    case M_ENCODE:
                                                                      process(in, out, atob64_getbits, atob64_setbits, atob64_writebits);
                                                                      break;
                                                                    case M_DECODE:
                                                                      process(in, out, b64toa_getbits, b64toa_setbits, b64toa_writebits);
                                                                      break;
                                                                    case M_EXIT:
                                                                      done = 1;
                                                                      break;
                                                                    default:
                                                                      fprintf(stderr, "Erreur de saisie.\n");
                                                                      break;
                                                                  }
                                                                }
                                                              }
                                                              
                                                              int main(int argc, char ** argv) {
                                                                FILE * in = stdin;
                                                                FILE * out = stdout;
                                                                
                                                                if (argc == 2 || argc > 3) {
                                                                  fprintf(stderr, "usage : b64 [source_file target_file]\n");
                                                                  return EXIT_FAILURE;
                                                                }
                                                                if (argc == 3) {
                                                                  in = fopen(argv[1], "r");
                                                                  if (in == NULL) {
                                                                    perror("fopen ag1");
                                                                    return EXIT_FAILURE;
                                                                  }
                                                                  out = fopen(argv[2], "w");
                                                                  if (out == NULL) {
                                                                    perror("fopen ag2");
                                                                    return EXIT_FAILURE;
                                                                  }
                                                                }
                                                                
                                                                loop(in, out);
                                                                return EXIT_SUCCESS;
                                                              }
                                                              
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              [Défis] #8 : Tout en Base64

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown