/*
Fichier base64.c
Auteur Bernard Chardonneau
Logiciel libre, droits d'utilisation précisés en français
dans le fichier : licence.fr
Traductions des droits d'utilisation dans les fichiers :
licence.de , licence.en , licence.es , licence.it
licence.nl , licence.pt , licence.eo , licence.eo-utf
Bibliothèque de fonctions permettant d'encoder et de
décoder le contenu d'un tableau en base64.
*/
#include "base64.h"
#define octet unsigned char
/* encode base64 nbcar caractères mémorisés
dans orig et met le résultat dans dest */
void encode64 (char *orig, char *dest, int nbcar)
{
octet triplet [3]; // groupe de 3 caractères à convertir en base 64
int cartriplet; // nombre de caractères du triplet récupérés
octet valcode [4]; // valeur des 4 caractères en base 64
int posorig; // position dans la ligne passée en paramètre
int posdest; // position dans la ligne contenant le résultat
char valcar [] = // tableau d'encodage
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
// initialisations
posorig = 0;
posdest = 0;
// tant que non fin de ligne
while (posorig < nbcar)
{
// initialisation
cartriplet = 0;
// récupérer un groupe de 3 caractères
do
{
triplet [cartriplet++] = orig [posorig++];
}
while (cartriplet < 3 && posorig < nbcar);
// encodage des 4 caractères du résultat
// prise en compte du premier caractère du triplet
valcode [0] = triplet [0] >> 2;
valcode [1] = (triplet [0] & 3) << 4;
// si 2ème caractère du triplet présent
if (cartriplet > 1)
{
// le prendre en compte
valcode [1] = valcode [1] | (triplet [1] >> 4);
valcode [2] = (triplet [1] & 0x0F) << 2;
}
else
// sinon, on mettra un caractère de padding à la place
valcode [2] = 64;
// traitement similaire pour le 3ème caractère du triplet
if (cartriplet == 3)
{
valcode [2] = valcode [2] | (triplet [2] >> 6);
valcode [3] = triplet [2] & 0x3F;
}
else
valcode [3] = 64;
// affichage des données encodées
dest [posdest++] = valcar [valcode [0]];
dest [posdest++] = valcar [valcode [1]];
dest [posdest++] = valcar [valcode [2]];
dest [posdest++] = valcar [valcode [3]];
}
// fin de l'encodage
dest [posdest] = '\0';
}
/* décode le contenu de buffer encodé base64, met le résultat
dans buffer et retourne le nombre de caractères convertis */
int decode64 (char *buffer)
{
int car; // caractère du fichier
char valcar [4]; // valeur après conversion des caractères
int i; // compteur
int posorig; // position dans la ligne passée en paramètre
int posdest; // position dans la nouvelle ligne générée
// initialisations
posorig = 0;
posdest = 0;
// tant que non fin de ligne
while (buffer [posorig] > ' ' && buffer [posorig] != '=')
{
// décoder la valeur de 4 caractères
for (i = 0; i < 4 && buffer [posorig] != '='; i++)
{
// récupérer un caractère dans la ligne
car = buffer [posorig++];
// décoder ce caractère
if ('A' <= car && car <= 'Z')
valcar [i] = car - 'A';
else if ('a' <= car && car <= 'z')
valcar [i] = car + 26 - 'a';
else if ('0' <= car && car <= '9')
valcar [i] = car + 52 - '0';
else if (car == '+')
valcar [i] = 62;
else if (car == '/')
valcar [i] = 63;
}
// recopier les caractères correspondants dans le buffer
buffer [posdest++] = (valcar [0] << 2) | (valcar [1] >> 4);
// sauf si indicateur de fin de message
if (i > 2)
{
buffer [posdest++] = (valcar [1] << 4) | (valcar [2] >> 2);
if (i > 3)
buffer [posdest++] = (valcar [2] << 6) | (valcar [3]);
}
}
// terminer le buffer
buffer [posdest] = '\0';
// et retourner le nombre de caractères obtenus
return (posdest);
}