1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
/* This file is part of the YAZ toolkit.
* Copyright (C) Index Data
* See the file LICENSE for details.
*/
/**
* \file base64.c
* \brief Base64 encode/decode utilities
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <yaz/base64.h>
void yaz_base64encode(const char *in, char *out)
{
static char encoding[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char buf[3];
long n;
while (*in != 0)
{
const char *pad = 0;
buf[0] = in[0];
buf[1] = in[1];
if (in[1] == 0)
{
buf[2] = 0;
pad = "==";
}
else
{
buf[2] = in[2];
if (in[2] == 0)
pad = "=";
}
/* Treat three eight-bit numbers as on 24-bit number */
n = (buf[0] << 16) + (buf[1] << 8) + buf[2];
/* Write the six-bit chunks out as four encoded characters */
*out++ = encoding[(n >> 18) & 63];
*out++ = encoding[(n >> 12) & 63];
if (in[1] != 0)
*out++ = encoding[(n >> 6) & 63];
if (in[1] != 0 && in[2] != 0)
*out++ = encoding[n & 63];
if (pad != 0) {
while (*pad != 0)
*out++ = *pad++;
break;
}
in += 3;
}
*out++ = 0;
}
static int next_char(const char **in, size_t *len)
{
const char *map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz0123456789+/";
const char *p;
while (*len > 0 && strchr("\r\n\t\f ", **in))
{
(*len)--;
(*in)++;
}
if (*len > 0 && **in == '=')
return -2;
if (*len > 0 && (p = strchr(map, **in)))
{
(*len)--;
(*in)++;
return p - map;
}
return -1;
}
int yaz_base64decode(const char *in, char *out)
{
size_t len = strlen(in);
while (len >= 4)
{
int i0, i1, i2, i3;
i0 = next_char(&in, &len);
if (i0 < 0)
return -1;
i1 = next_char(&in, &len);
if (i1 < 0)
return -1;
*(out++) = i0 << 2 | i1 >> 4;
i2 = next_char(&in, &len);
if (i2 == -2)
break;
if (i2 == -1)
return -1;
*(out++) = i1 << 4 | i2 >> 2;
i3 = next_char(&in, &len);
if (i3 == -2)
break;
if (i3 == -1)
return -1;
*(out++) = i2 << 6 | i3;
}
*out = '\0';
return 0;
}
/*
* Local variables:
* c-basic-offset: 4
* c-file-style: "Stroustrup"
* indent-tabs-mode: nil
* End:
* vim: shiftwidth=4 tabstop=8 expandtab
*/
|